Soy muy nuevo en VHDL y tengo un problema con el tiempo de simulación en Modelsim PE Student Edition 10.4.
Escribí algunos archivos para un modelo RTL como multiplexor, demultiplexor y registro.
Para probar mi código, traté de implementar un banco de pruebas para cada archivo. La simulación para el multiplexor y demultiplexor funciona bastante bien, pero el banco de pruebas para los registros parece simular para siempre. Siempre que trato de simular no pasa nada y la simulación no termina en ningún punto. Traté de mirar las formas de onda pero no cambian.
A continuación te enviaré el código correspondiente a mi 4x1-MUX (que simula bastante bien) y el código de mi registro de 12 bits con reinicio síncrono (que no simula correctamente).
Realmente no puedo encontrar el problema en este código.
-- 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;
Hay algunos errores típicos que debe comprender y evitar primero.
Al crear su proceso instanciando su registro, no especificó ninguna lista de sensibilidad. (Si no sabe qué es, verifique allí ). Dado que su proceso está sincronizado con su reloj, CLK
debe colocarlo en la lista de sensibilidad.
Otra cosa que podría ser útil (es más una sugerencia que un error real) es poner cualquiera de las señales de reinicio de su registro de forma asíncrona (al menos en el proceso) y si lo desea sincrónico, aún puede sincronizarlo en el nivel superior . Se necesitarán menos elementos para implementar esto.
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;
Luego, en su banco de pruebas, como comentó @scary_jeff, no hizo que su reloj cambiara de estado. Entonces su rising_edge
condición solo es válida una vez. Para evitar esto te sugiero que siempre crees un proceso aparte generando tu reloj.
clk_gen : process (CLK)
begin
clk <= not clk after clk_period/2;
end process;
(No olvides inicializar tu reloj)
Como realmente no especificó qué problema tuvo en la simulación, no puedo ayudar más por ahora, pero debería probar esto primero y volver con más información.
miedo_jeff
CLK
en el segundo ejemplo solo se establecería alto? Sería más habitual tener sentencias que lo asignen alternativamente a'0'
y'1'
.leo renk