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;
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, CLK
mü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_edge
Bedingung 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.
scary_jeff
CLK
im zweiten Beispiel immer nur hoch angesetzt? Es wäre üblicher, Anweisungen zu haben, die es abwechselnd zu'0'
und zuweisen'1'
.Leo Renk