VHDL - Problem mit Simulation der Testbench - Modelsim PE Student 10.4

Ich bin sehr neu bei VHDL und habe ein Problem mit der Simulationszeit in Modelsim PE Student Edition 10.4.

Ich habe einige Dateien für ein RTL-Modell wie Multiplexer, Demultiplexer und Register geschrieben.

Um meinen Code zu testen, habe ich versucht, für jede Datei eine Testbench zu implementieren. Die Simulation für den Multiplexer und Demultiplexer funktioniert ganz gut, aber die Testbench für die Register scheint für immer zu simulieren. Wenn ich versuche zu simulieren, passiert nichts und die Simulation wird zu keinem Zeitpunkt beendet. Ich habe versucht, die Wellenformen zu betrachten, aber sie ändern sich nicht.

Im Folgenden sende ich Ihnen den entsprechenden Code für meinen 4x1-MUX (der ziemlich gut simuliert) und den Code für mein 12-Bit-Register mit synchronem Reset (der nicht korrekt simuliert).

Ich kann das Problem in diesem Code wirklich nicht finden.

-- multiplexer for 4 inputs with 12 bit data width to 1 output with 12 bit data width
entity MULTIPLEXER_4TO1_12BIT is
       port (
             SELECT_IN: in bit_vector (1 downto 0);
             D_IN_0: in bit_vector (11 downto 0);
             D_IN_1: in bit_vector (11 downto 0);
             D_IN_2: in bit_vector (11 downto 0);
             D_IN_3: in bit_vector (11 downto 0);
             D_OUT: out bit_vector (11 downto 0)
            );
end MULTIPLEXER_4TO1_12BIT;

architecture RTL of MULTIPLEXER_4TO1_12BIT is
       begin 
            D_OUT <= D_IN_0 when SELECT_IN = "00" else
                     D_IN_1 when SELECT_IN = "01" else
                     D_IN_2 when SELECT_IN = "10" else
                     D_IN_3;
end RTL; 



 -- testbench for multiplexer for 4 inputs with 12 bit data width to 1  output with 12 bit data width
entity TESTBENCH_MULTIPLEXER_4TO1_12BIT is
end TESTBENCH_MULTIPLEXER_4TO1_12BIT;

architecture BEHAVIOUR of TESTBENCH_MULTIPLEXER_4TO1_12BIT is
      signal SELECT_IN: bit_vector (1 downto 0) := "00";
      signal D_IN_0, D_IN_1, D_IN_2, D_IN_3, D_OUT : bit_vector (11 downto 0) := B"0000_0000_0000"; 
      begin
           UUT: entity work.MULTIPLEXER_4TO1_12BIT port map (SELECT_IN, D_IN_0, D_IN_1, D_IN_2, D_IN_3, D_OUT); 
           tb: process
               begin 
                    D_IN_0 <= B"0000_0000_0000";
                    D_IN_1 <= B"0001_0001_0001";
                    D_IN_2 <= B"0110_0110_0110";
                    D_IN_3 <= B"1111_1111_1111";

                    SELECT_IN <= "00";
                    wait for 2 ns;
                    SELECT_IN <= "01";
                    wait for 2 ns;
                    SELECT_IN <= "10";
                    wait for 2 ns;
                    SELECT_IN <= "11";
                    wait for 2 ns; 

                    assert false report "end of simulation" severity failure; 
              end process tb;
end BEHAVIOUR;





-- register with 12 bit data width and synchronous reset
entity REG_SYNC_12BIT is
       port (
             D_IN: in bit_vector (11 downto 0);
             CLK: in bit;
             EN: in bit;
             RST: in bit;
             D_OUT: out bit_vector (11 downto 0)
            );
end REG_SYNC_12BIT; 

architecture RTL of REG_SYNC_12BIT is
             begin 
                  process
                         begin 
                              if (rising_edge (CLK)) then 
                                 if (RST = '0') then
                                    D_OUT <= B"0000_0000_0000"; 
                                 else
                                    if (EN = '1') then
                                       D_OUT <= D_IN;
                                    end if;
                                 end if;
                              end if;
                         end process;
end RTL;


-- testbench for register with 12 bit data width and synchronous reset

entity TESTBENCH_REG_SYNC_12BIT is
end TESTBENCH_REG_SYNC_12BIT;

architecture BEHAVIOUR of TESTBENCH_REG_SYNC_12BIT is
             signal D_IN, D_OUT: bit_vector (11 downto 0) := B"0000_0000_0000";
             signal CLK, EN: bit := '0'; 
             signal RST: bit := '1';

             begin
                  UUT: entity work.REG_SYNC_12BIT port map (D_IN, CLK, EN, RST, D_OUT); 
                  tb: process 
                             begin 
                                  EN <= '1'; 
                                  D_IN <= B"1111_1111_1111";
                                  wait for 4 ns;
                                  CLK <= '1';
                                  wait for 2 ns;
                                  D_IN <= B"0000_1111_1111";
                                  wait for 2 ns;
                                  CLK <= '1';
                                  wait for 10 ns; 

                                  assert false report "end of simulation" severity failure; 
                             end process tb;
end BEHAVIOUR;
Meinten Sie für Ihr CLKim zweiten Beispiel immer nur hoch angesetzt? Es wäre üblicher, Anweisungen zu haben, die es abwechselnd zu '0'und zuweisen '1'.
Ich habe CLK nur hoch gesetzt, um zu testen, ob meine Testbench korrekt funktioniert. Aber du hast natürlich recht. Das CLK-Signal muss alternierend sein.

Antworten (1)

Es gibt einige typische Fehler, die Sie zuerst verstehen und vermeiden sollten.

Beim Erstellen Ihres Prozesses zum Instanziieren Ihres Registers haben Sie keine Sensitivitätsliste angegeben. (Wenn Sie nicht wissen, was es ist, überprüfen Sie es dort .) Da Ihr Prozess synchron zu Ihrer Uhr ist, CLKmüssen Sie ihn in die Sensitivitätsliste aufnehmen.

Eine andere Sache, die nützlich sein könnte (es ist eher ein Vorschlag als ein echter Fehler), ist, jedes Reset-Signal Ihres Registers asynchron zu setzen (zumindest im Prozess) und wenn Sie es synchron wollen, können Sie es immer noch auf der obersten Ebene synchronisieren . Es werden weniger Elemente benötigt, um dies umzusetzen.

 process (RST, CLK)
        begin 
             if (RST = '0') then

                D_OUT <= B"0000_0000_0000"; 

             elsif (rising_edge (CLK)) then     

                if (EN = '1') then
                   D_OUT <= D_IN;
                end if;

             end if;
 end process;

Dann haben Sie in Ihrer Testbench, wie @scary_jeff kommentierte, Ihre Uhr nicht dazu gebracht, ihren Zustand zu ändern. Ihre rising_edgeBedingung ist also nur einmal gültig. Um dies zu vermeiden, schlage ich vor, dass Sie immer einen separaten Prozess erstellen, der Ihre Uhr generiert.

clk_gen : process (CLK)
begin

     clk <= not clk after clk_period/2;

end process;

(Vergessen Sie nicht, Ihre Uhr zu initialisieren)

Da Sie nicht wirklich angegeben haben, welches Problem Sie in der Simulation hatten, kann ich im Moment nicht weiter helfen, aber Sie sollten dies zuerst versuchen und mit weiteren Informationen zurückkommen.

Warum verbraucht ein asynchrones Zurücksetzen weniger Ressourcen? Ich bin nur mit Xilinx-FPGAs vertraut, aber bei diesen ist die Verwendung für beide Reset-Typen identisch, mit der Einschränkung, dass asynchrone Resets nicht mit anderer Logik zusammengeführt werden können, wenn die Tools den SR-Pin eines Registers verwenden möchten, um die LUT-Nutzung zu reduzieren. Vielleicht ist es in der ASIC-Welt anders?
Nun, ich denke, dass die meisten Synthesizer es heutzutage vereinfachen können, aber meiner Meinung nach ist es vorzuziehen, diese Syntax zu verwenden, um sicherzustellen, dass der dedizierte Reset-Pin tatsächlich verwendet wird
Ein asynchrones Zurücksetzen kann in einigen Architekturen, die kein dediziertes SET/RST (Xilinx-Jargon für synchrones Setzen/Löschen) haben, weniger Ressourcen verbrauchen. Dies ist jedoch selten, wenn nicht vorhanden für heutige FPGAs (Xilinx und Altera empfehlen beide synchrone Resets). Die FFs auf Xilinx- und Altera-Teilen haben sowohl synchrone als auch asynchrone Resets und Clears (obwohl sie nicht unbedingt alle zusammen verwendet werden müssen). Auch die Set/Rst-Dominanz kann die Logiknutzung vorantreiben.
Vielen Dank für Ihre Tipps. Wie Sie empfohlen haben, habe ich die CLK- und RST-Signale zur Empfindlichkeitsliste hinzugefügt und das Register auf asynchrones Zurücksetzen geändert. Jetzt läuft die Simulation korrekt. Danke, du rockst! :)