Reputation: 9
I have to implement a mini-router in VHDL. The design requirements for this are:
I've written the implementation, and a testbench. However, looking at the simulation waveform, some of my initial signals are undefined and I'm not sure why.
This is the source code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end entity;
architecture arch of mini_router is
signal aux : std_logic_vector(9 downto 0);
signal aux1 : std_logic_vector(1 downto 0);
signal aux2 : std_logic_vector(1 downto 0);
signal aux_valid : std_logic;
signal aux_grant1 : std_logic;
signal aux_grant2 : std_logic;
begin
mini_router: process(clk)
variable r : std_logic:= '1';
begin
-- conta le volte in cui c'è stato data conflict
if rising_edge(clk) then -- chiuso
if reset = '0' then
aux <= (others => '0');
aux_valid <= '0';
aux_grant1 <= '0';
aux_grant2 <= '0';
elsif reset = '1' then
if (req1 xor req2) = '1' then --chiuso -- un solo req è alto
if req1 ='1' then --chiuso
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
else
aux <= data2;
aux_grant1 <= '0';
aux_grant2 <= '1';
aux_valid <= '1';
end if;
----entrambi i req sono alti
elsif (req1 and req2) = '1' then -- chiuso
if ((unsigned(aux1)) > (unsigned(aux2))) then
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) < (unsigned(aux2))) then
aux <= data2;
aux_grant2 <= '1';
aux_grant1 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) = (unsigned(aux2))) then -- stesso livello di priorità -- alternativa:(aux1 xnor aux2)="11"
if r = '1' then
aux <= data1;
aux_grant1<= '1';
aux_grant2 <= '0';
aux_valid <= '1';
r := not (r);
else
aux <= data2;
aux_grant2 <= '1';
aux_grant1<= '0';
aux_valid <= '1';
r := not (r);
end if;
end if;
elsif (req1 nor req2) = '1' then
aux_valid <= '0';
aux <= (others => '0');
aux_grant1 <= '0';
aux_grant2 <= '0';
end if;
end if; -- if del reset
end if; -- if del clock
end process;
data_out <= aux(9 downto 2);
aux1 <= data1 (1 downto 0);
aux2 <= data2 (1 downto 0);
valid <= aux_valid;
grant1 <= aux_grant1;
grant2 <= aux_grant2;
end architecture;
This is the testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mini_router_tb is
end mini_router_tb;
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns; --- frequenza di clock: 125 MHz
signal clk_tb : std_logic := '1';
signal reset_tb : std_logic := '0'; -- reset attivo basso sincrono
signal data1_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req1_tb : std_logic:= '0';
signal grant1_tb : std_logic;
signal data2_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req2_tb : std_logic:= '0';
signal grant2_tb : std_logic;
signal data_out_tb : std_logic_vector(7 downto 0);
signal valid_tb : std_logic;
signal end_sim : std_logic := '1'; -- signal to use to stop the simulation when there is nothing else to test
component mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end component;
begin
clk_tb <= (not(clk_tb)and(end_sim)) after T_CLK/2;
DUT : mini_router
port map (
clk => clk_tb,
reset => reset_tb,
data1 => data1_tb,
req1 => req1_tb,
grant1 => grant1_tb,
data2 => data2_tb,
req2 => req2_tb,
grant2 => grant2_tb,
data_out => data_out_tb,
valid => valid_tb
);
-- process used to make the testbench signals change synchronously with the rising edge of the clock
stimuli_process: process(clk_tb,reset_tb)
variable t : integer := 0; -- variabile che conta i cicli di clock
begin
if (rising_edge(clk_tb)) then
case (t) is
when 1 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=0 per il reset
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=1
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 3 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4;
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13; data_out=3
req1_tb <= '0' ; req2_tb<= '1';
when 4 => data1_tb <= (9 downto 5 => '0') & "11100"; --data1=28
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13; data_out=3 priorità maggiore
req1_tb <= '1' ; req2_tb<= '1';
when 5 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1 priorità maggiore
data2_tb <= (9 downto 5 => '0') & "11101"; -- data2= 29;
req1_tb <= '1' ; req2_tb<= '1';
when 6 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31;
req1_tb <= '1' ; req2_tb<= '1';
when 7 => data1_tb <= (9 downto 5 => '0') & "00111"; --data_out=0;
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
when 8 => data1_tb <= (9 downto 5 => '0') & "10111"; --data1=7; data_out non assunto=5
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31; data_out=7
req1_tb <= '1' ; req2_tb<= '1';
when 9 => end_sim <= '0'; -- stops the simulation when t = 10
when others => null; -- non accade nulla negli altri casi
end case;
t := t + 1;
end if;
end process;
end architecture;
Upvotes: 1
Views: 712
Reputation: 1138
The reason your signals are initially set to U
or X
is because the values of all signals, variables, etc. are initialized to the left hand side of the type definition.
From the IEEE 1076 code (see here):
-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
type STD_ULOGIC is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
--------------------------------
And std_logic
is just a resolved version of std_ulogic
. So any signal of type std_logic
will have its default value be U
, unless set otherwise.
Consider the following code:
signal A : std_logic;
signal B : std_logic := '1';
Signal A
would be U
until set otherwise. Signal B
will be 0
until set otherwise.
This is why you are seeing U
in your simulation. (As for X
you see in your waveform window, many simulators that collapse vectors into a single value in the waveform view treat collections with U
as X
. Expand that vector and I suspect you will see several U
's.)
Upvotes: 0
Reputation: 12600
Your reset logic is synchronous, because the outmost condition is rising_edge(clk)
. Therefore the internal signals are undefined until the first raising edge of the clock.
Change to an asynchronous reset like this (excerpt):
if reset = '0' then
-- reset statements
elsif rising_edge(clk) then
-- work statements
end if;
Please be aware that even with an asynchronous reset the signals will be undefined until reset is activated or the clock raises. This reflects the actual behavior of a real device.
Upvotes: 1