www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Mysteriös ignorierter if-zweig


Autor: Florian Rems (flo0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo VHDL Gemeinde,

habe ein ein seltsames Problem: In folgender FSM im Zustand prepCalc_MOD 
wird der elsif und der else zweig der äußeren bedingten Verzweigung 
anstandslos und korrekt ausgeführt. Der if-zweig jedoch wird regelrecht 
ignoriert. Ich kann das insofern nicht nachvollziehen, da if und elsif 
zweig quasi identisch sind.

Wäre schön, wenn jemandem dazu was einfällt. Hier der Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

--------------------------------------------------------------------
entity CALC is
--------------------------------------------------------------------
  Port ( ETrigger_C       : in  STD_LOGIC;
       SWDTTrigger_C      : in  STD_LOGIC;
       clk_C          : in  STD_LOGIC;
       Dir_C          : in  STD_LOGIC;
       Resetr_C        : in  STD_LOGIC;
       ResetN_C        : in  STD_LOGIC;
       ResetMOD_C        : in  STD_LOGIC;
       EnableMOD_C      : in  STD_LOGIC;
       EnableAdapt_C      : in  STD_LOGIC;
       AzimuthType_C      : in  STD_LOGIC;
       WE_C            : in  STD_LOGIC;
       DIN_C          : in  STD_LOGIC;
       ADDRW_C          : in  STD_LOGIC_VECTOR (12 downto 0);
       CounterValue_C    : in  STD_LOGIC_VECTOR (16 downto 0);
       rmax_C          : in  UNSIGNED(15 downto 0);
       MODref_C        : in  UNSIGNED(31 downto 0);
       NT_C            : in  SIGNED(19 downto 0);
       h_times_g_C      : in  UNSIGNED(19 downto 0);
       
       Reset_C          : out STD_LOGIC;
       Busy_C          : out STD_LOGIC;
       DirOut_C        : out STD_LOGIC;
       N_C            : out SIGNED(19 downto 0);
       dN_C            : out UNSIGNED(15 downto 0);
       ND_C            : out UNSIGNED(15 downto 0);
       r_C            : out UNSIGNED(15 downto 0);
       MOD_C          : out UNSIGNED(31 downto 0));
  end CALC;
--------------------------------------------------------------------

--------------------------------------------------------------------
architecture Behavioral of CALC is
--------------------------------------------------------------------                                    
  component DIVROM is
    Port ( Clk_R  : in  STD_LOGIC;
         count_R  : in  STD_LOGIC_VECTOR(15 downto 0);
         dN_R    : out STD_LOGIC_VECTOR(15 downto 0));
  end component;
  
  component PSTableRAM is
  Port ( Clk_PS     : in  STD_LOGIC;
       RE_PS     : in  STD_LOGIC;
       WE_PS     : in  STD_LOGIC;
       ADDRR_PS   : in  STD_LOGIC_VECTOR(12 downto 0);
       ADDRW_PS   : in  STD_LOGIC_VECTOR(12 downto 0);
       DIN_PS     : in  STD_LOGIC;
       DOUT_PS    : out STD_LOGIC);       
  end component;
  
  component Multiplier32x32 is
    Port ( In1Mult_M   : in  STD_LOGIC_VECTOR (31 downto 0);
         In2Mult_M   : in  STD_LOGIC_VECTOR (31 downto 0);
         OutMult_M   : out STD_LOGIC_VECTOR (63 downto 0));
  end component;
---------------------------------------------------------------------
  type state is (Init, Idle, WaitForPSRAM, prepCalc_N, Calc_N, Calc_dN, Calc_dNsquare, prepCalc_MOD, Calc_MOD, prepCalc_ND, Calc_ND);
  signal s         : state;
  signal countervalue   : STD_LOGIC_VECTOR(15 downto 0);
  signal Esr        : STD_LOGIC_VECTOR(2 downto 0);
  signal SWDTsr      : STD_LOGIC_VECTOR(2 downto 0);
  signal dN_ROM      : STD_LOGIC_VECTOR(15 downto 0);
  signal RE        : STD_LOGIC;
  signal ADDRR      : STD_LOGIC_VECTOR(12 downto 0);
  signal DOUT        : STD_LOGIC;
  signal In1Mult      : STD_LOGIC_VECTOR(31 downto 0);
  signal In2Mult      : STD_LOGIC_VECTOR(31 downto 0);
  signal OutMult      : STD_LOGIC_VECTOR(63 downto 0);
  signal DOUTreg      : STD_LOGIC_VECTOR(2 downto 0);
  signal rdir        : STD_LOGIC_VECTOR(1 downto 0);
  signal dir        : STD_LOGIC_VECTOR(3 downto 0);
---------------------------------------------------------------------  
  begin
  
    instDIVROM : DIVROM
      Port Map ( Clk_R     => clk_c,
              count_R   => countervalue,
              dN_R    => dN_ROM);
              
    instPSTableRAM : PSTableRAM
      Port Map ( Clk_PS   => clk_C,
              RE_PS    =>  RE,
              WE_PS    =>  WE_C,   
              ADDRR_PS   =>  ADDRR,
              ADDRW_PS   => ADDRW_C,
              DIN_PS     => DIN_C,
              DOUT_PS    => DOUT);
              
    instMultiplier32x32 : Multiplier32x32
      Port Map ( In1Mult_M => In1Mult,
              In2Mult_M => In2Mult,
              OutMult_M => OutMult);
              
---------------------------------------------------------------------  
    FSM : process 
---------------------------------------------------------------------
    type NTArray is array (3 downto 0) of SIGNED(19 downto 0);
    variable NT        : NTArray;
    variable dNsquare    : UNSIGNED(31 downto 0);
    variable ND64bitfp  : UNSIGNED(63 downto 0);
    variable r         : UNSIGNED(15 downto 0):=to_unsigned(1,16);
    variable N         : SIGNED(19 downto 0):=to_signed(0,20);
    variable dN        : UNSIGNED(15 downto 0):=to_unsigned(0,16);
    variable ND        : UNSIGNED(15 downto 0):=to_unsigned(0,16);
    --variable dir      : STD_LOGIC_VECTOR(3 downto 0);
    variable Modifier    : UNSIGNED(31 downto 0);
    variable Modifier64b  : UNSIGNED(63 downto 0); 
    variable absDeltaN  : UNSIGNED(19 downto 0);
    variable factor    : UNSIGNED(7 downto 0);
    
    begin
    
      wait until rising_edge(clk_c);
      
      If Resetr_C = '1'   then r := to_unsigned(1,16); else r := r;            end if;
      If ResetN_C = '1'   then N := to_signed(0,20);   else N := N;             end if;
      If ResetMOD_C = '1' then Modifier := MODref_C;   else Modifier := Modifier; end if;
      
      -------------------------------------------------------
      case s is 
      -------------------------------------------------------
        ----------------------------------------------------
        when Init    =>
        ----------------------------------------------------
          Modifier := MODref_C;
          s <= Idle;
        
         ----------------------------------------------------
        when Idle    =>
         ----------------------------------------------------  
          if Esr(2 downto 1)="01" then
            Busy_C  <= '1';
            Reset_C <= '0';
            If Dir_C='1' then r := r + 1; else r := r - 1; end if;
            If r = 0 then r := rmax_C; elsif r > rmax_C then r := r - rmax_C; end if;
            rdir <= rdir(0)&Dir_C;
            RE <= '1';
            ADDRR <= std_logic_vector(r(12 downto 0)-1);
            s <= WaitForPSRAM;
          elsif SWDTsr(2 downto 1)="01" then
            Busy_C <= '1';
            Reset_C <= '1';
            dN := to_unsigned(0,16);
            ND := to_unsigned(0,16);
            RE <= '0';
            s  <= Idle;
          else
            Busy_C <= '0';
            Reset_C <= '0';
            RE <= '0';
            s <= Idle;
          end if;
        
        ------------------------------------------------------  
        when WaitForPSRAM  =>
         ------------------------------------------------------
          s <= prepCalc_N;
        
        ------------------------------------------------------  
        when prepCalc_N  =>
         ------------------------------------------------------
          DOUTreg <= DOUTreg(1 downto 0)&DOUT;
          s <= Calc_N;
          
         ------------------------------------------------------  
        when Calc_N    =>
         ------------------------------------------------------
          If DOUT='1' OR (DOUTreg="010" AND (rdir(0)/=rdir(1))) then
            If Dir_C='1' then N := N + 1; else N := N - 1; end if;
            If AzimuthType_C = '1' then
              If   N < 0                then N := N + signed(h_times_g_C); 
              elsif N > signed(h_times_g_C-1) then N := N - signed(h_times_g_C);
              end if;
            end if;
            countervalue <= CounterValue_C(15 downto 0);
            dir(3 downto 0) <= dir(2 downto 0)&Dir_C;
            --dir(0) := Dir_C;
            NT(3 downto 0):=NT(2 downto 0)&NT_C;
            --NT(0) := NT_C;
            Reset_C <= '1';
            s <= Calc_dN; 
          else 
            s <= Idle; 
          end if;
          Busy_C  <= '1';
  
         ------------------------------------------------------  
        when Calc_dN  =>
        ------------------------------------------------------
          if dir(0)=dir(1) then
            dN := unsigned(dN_ROM);
            In1Mult <= std_logic_vector("0000000000000000"&dN);
            In2Mult <= std_logic_vector("0000000000000000"&dN);
            s <= Calc_dNsquare;
          else
            dN := to_unsigned(0,16);
            ND := to_unsigned(0,16);
            s  <= Idle;
          end if;
          Busy_C  <= '1';
          Reset_C <= '1';
          
        -------------------------------------------------------
        when Calc_dNsquare  =>
        -------------------------------------------------------
          dNsquare := unsigned(OutMult(31 downto 0)); 
          If EnableAdapt_C = '1' and NT(3)=NT(2) and NT(2)=NT(1) and NT(1)=NT(0) then
            s <= prepCalc_MOD;
          else
            s <= prepCalc_ND;
          end if;
          Busy_C  <= '1';
          Reset_C <= '1';
          
        -------------------------------------------------------
        when prepCalc_MOD  =>
        -------------------------------------------------------
          absDeltaN := unsigned(abs(NT_C - N));
            If ((dir = "1101") or (dir = "0010")) then   --(dir(3)=dir(2) and dir(2)/=dir(1) and dir(1)/=dir(0)) then  -- reduce  Modifier
              If absDeltaN > to_unsigned(64,20) then 
                factor := to_unsigned(64,8);
              else
                factor := 128 - absDeltaN(7 downto 0);
              end if;  
            elsif (dir(3)=dir(2) and dir(2)/=dir(1) and dir(1)=dir(0)) then  -- enlarge Modifier
              If absDeltaN > to_unsigned(64,20) then
                factor := to_unsigned(255,8);
              else
                factor := 128 + absDeltaN(7 downto 0);
              end if;
            else
              factor := to_unsigned(128,8);
            end if;
          In1Mult <= std_logic_vector(Modifier);
          In2Mult <= std_logic_vector("000000000000000000000000"&factor);
          Busy_C  <= '1';
          Reset_C <= '1';
          s <= Calc_MOD;
          
        -------------------------------------------------------
        when Calc_MOD =>
        -------------------------------------------------------
          Modifier64b := unsigned(OutMult) / 128;
          --Modifier64b := (Modifier * ("000000000000000000000000"&factor)) / 128;
          Modifier := Modifier64b(31 downto 0);
          Busy_C  <= '1';
          Reset_C <= '1';
          s <= prepCalc_ND;
          
        -------------------------------------------------------
        when prepCalc_ND =>
        -------------------------------------------------------
          If EnableMOD_C = '0' then
            In1Mult <= std_logic_vector(MODref_C);
            In2Mult <= std_logic_vector(dNSquare);
            --ND64bitfp := MODref_C * dNsquare(31 downto 0);
          else
            In1Mult <= std_logic_vector(Modifier);
            In2Mult <= std_logic_vector(dNSquare);
            --ND64bitfp := Modifier * dNsquare(31 downto 0);
          end if;
          Busy_C  <= '1';
          Reset_C <= '1';
          s <= Calc_ND;
              
        -------------------------------------------------------
        when Calc_ND  =>
        -------------------------------------------------------
          --dNsquare := dN * dN;
          ND64bitfp := unsigned(OutMult);
          ND := ND64bitfp(47 downto 32);
          Busy_C  <= '1';
          Reset_C <= '1';
          s <= Idle;
      
      ----------------------------------------------------------
      end case;
      ----------------------------------------------------------
    
      r_C <= r;
      N_C <= N;
      dN_C <= dN;
      ND_C <= ND;
      DirOut_C <= dir(0);
      MOD_C  <= Modifier;
    
    end process;
    
-------------------------------------------------------------------        
    SyncETrigger : process
-------------------------------------------------------------------
    begin
      wait until rising_edge(clk_C);
      Esr <= Esr(1 downto 0) & ETrigger_C;
    end process;
    
-------------------------------------------------------------------        
    SyncSWDTTrigger : process
-------------------------------------------------------------------
    begin
      wait until rising_edge(clk_C);
      SWDTsr <= SWDTsr(1 downto 0) & SWDTTrigger_C;
    end process;
    
  end Behavioral;

Schonmal Danke!!!

Gruß
Flo

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat dir überhaupt einmal einen Wert, der das Ausführen des if-Zweigs 
erfordern würde?

Autor: Florian Rems (flo0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, eindeutig. Ich gebe dieses "Muster" für dir manuell ein, und kann 
die Variable N beobachten. Bei N = N+1 wird in dir von rechts eine 1 
reingeschoben, bei N = N -1 eine 0. Über ein Terminalprogramm SEHE ich 
das Muster regelrecht auf dem Bildschirm. Bei 1100 oder 0011 
funktioniert alles wie gewünscht, bei 1101 bzw. 0010 jedoch nicht, da 
wird praktisch der else Zweig abgearbeitet.

Gruß
Flo

Autor: Florian Rems (flo0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Problem gefunden. Der Zustand wird erst garnicht erreicht, wenn 
"1101" oder "0010" auftritt...

Gruß
Flo

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.