I have finished my router and would like your thoughts about my code. I think it works well, but I'm not sure since I'm new to the VHDL world. Could someone please help me? Is my code correct?
SOURCE CODE
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
-- -------------------------
-- Entity
-- -------------------------
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- Reset asincrono attivo basso
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
-- -------------------------
architecture arch of mini_router is
-- signal for req control
signal request : std_logic_vector (1 downto 0);
-- Signals to check the parity bits
signal a : std_logic; -- '1' se A < B altrimenti '0'
signal b : std_logic; -- '1' se A = B altrimenti '0'
signal c : std_logic; -- '1' se A > B altrimenti '0'
-- Signal for round robin algoritm
signal r : std_logic;
-- Comparator to check the parity bits
component comparator is
port (
A : in std_logic_vector(1 downto 0);
B : in std_logic_vector(1 downto 0);
A_less_B : out std_logic;
A_equal_B : out std_logic;
A_greater_B : out std_logic
);
end component;
begin
request <= req1&req2;
COMPARATORE: comparator
port map (
A => data1 (1 downto 0),
B => data2 (1 downto 0),
A_less_B => a,
A_equal_B => b,
A_greater_B => c
);
mini_router: process(clk,reset)
begin
if reset = '0' then
data_out <= (others => '0');
grant1 <= '0';
grant2 <= '0';
valid <= '0';
r <= '0';
elsif rising_edge(clk) then
-- One req high
if request = "10" then
data_out <= data1(9 downto 2);
grant1 <= '1';
grant2 <= '0';
valid <= '1';
elsif request = "01" then
data_out <= data2(9 downto 2);
grant1 <= '0';
grant2 <= '1';
valid <= '1';
-- both req signals low
elsif request = "00" then
data_out <= (others => '0');
grant1 <= '0';
grant2 <= '0';
valid <= '0';
-- both req signals high
elsif request = "11" then
-- link 1 has higher priority
if c='1' then
data_out <= data1(9 downto 2);
grant1 <= '1';
grant2 <= '0';
valid <= '1';
-- link 2 has higher priority
elsif a='1' then
data_out <= data2(9 downto 2);
grant1 <= '0';
grant2 <= '1';
valid <= '1';
-- Data conflict
elsif b='1' then
-- Round Robin arbiter
if r = '0' then
data_out <= data1(9 downto 2);
grant1 <= '1';
grant2 <= '0';
valid <= '1';
r <= '1';
else
data_out <= data2(9 downto 2);
grant1 <= '0';
grant2 <= '1';
valid <= '1';
r <= '0';
end if;
end if;
end if;
end if;
end process;
end architecture;
TESTBENCH
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
-- -------------------------
-- Entity
-- -------------------------
entity mini_router_tb is
end mini_router_tb;
-- -------------------------
-- Architecture
-- -------------------------
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns;
signal clk_tb : std_logic := '0';
signal reset_tb : std_logic := '0';
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';
component mini_router is
port (
clk : in std_logic;
reset : in std_logic;
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;
-----------------------------------------------------------------------------------
-- Mini - Router instantiation
-----------------------------------------------------------------------------------
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
);
stimuli_process: process(clk_tb, reset_tb)
variable t : integer := 0; -- variable used to count clock cicles
begin
if (rising_edge(clk_tb)) then
case (t) is
-- CASE 1:
-- data1 = 5; req1=1
-- data2 = 5; req2=0
-- data_out = 0; valid=0
-- grant1 = 0;
-- grant2 = 0;
when 1 => data1_tb <= (9 downto 3 => '0') & "101";
data2_tb <= (9 downto 4 => '0') & "0101";
req1_tb <= '1' ; req2_tb<= '0';
-- CASE 2:
-- data1 = 4; req1=1
-- data2 = 13; req2=0
-- data_out = 1; valid=1
-- grant1 = 1;
-- grant2 = 0;
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100";
data2_tb <= (9 downto 4 => '0') & "1101";
req1_tb <= '1' ; req2_tb<= '0';
-- CASE 3:
-- data1 = 4; req1=0
-- data2 = 13; req2=1
-- data_out = 3; valid=1
-- grant1 = 0;
-- grant2 = 1;
when 3 => data1_tb <= (9 downto 3 => '0') & "100";
data2_tb <= (9 downto 4 => '0') & "1101";
req1_tb <= '0' ; req2_tb<= '1';
-- CASE 4:
--
-- data1 = 7; req1=1
-- data2 = 31; req2=1
-- data_out = 1; valid=1
-- grant1 = 1;
-- grant2 = 0;
when 4 => data1_tb <= (9 downto 5 => '0') & "00111";
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '1' ; req2_tb<= '1';
-- CASE 5:
-- data1 CHOSEN
-- data1 = 23; req1=1
-- data2 = 29; req2=1
-- data_out = 5; valid=1
-- grant1 = 1;
-- grant2 = 0;
when 5 => data1_tb <= (9 downto 5 => '0') & "10111";
data2_tb <= (9 downto 5 => '0') & "11101";
req1_tb <= '1' ; req2_tb<= '1';
-- CASE 6:
--
-- data2 chosen
-- data1 = 22; req1=1
-- data2 = 30; req2=1
-- data_out = 7; valid=1
-- grant1 = 0;
-- grant2 = 1;
when 6 => data1_tb <= (9 downto 5 => '0') & "10110";
data2_tb <= (9 downto 5 => '0') & "11110";
req1_tb <= '1' ; req2_tb<= '1';
-- CASE 7:
-- data1 = 7; req1=0
-- data2 = 31; req2=0
-- data_out = 0; valid=0
-- grant1 = 0;
-- grant2 = 0;
when 7 => data1_tb <= (9 downto 5 => '0') & "00111";
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
-- CASE 8:
-- data2 chosen
-- data1 = 28; req1=1
-- data2 = 13; req2=1
-- data_out = 3; valid=1
-- grant1 = 0;
-- grant2 = 1;
when 8 => data1_tb <= (9 downto 5 => '0') & "11100";
data2_tb <= (9 downto 4 => '0') & "1101";
req1_tb <= '1' ; req2_tb <= '1';
-- CASE 9:
--
-- data1 chosen
-- data1 = 22; req1=1
-- data2 = 30; req2=1
-- data_out = 5; valid=1
-- grant1 = 1;
-- grant2 = 0;
when 9 => data1_tb <= (9 downto 5 => '0') & "10110"; --data1=22; data_out =5
data2_tb <= (9 downto 5 => '0') & "11110"; -- data2= 30; data_out non assunto=7
req1_tb <= '1' ; req2_tb<= '1';
-- CASE 10:
--
-- data2 chosen
-- data1 = 22; req1=1
-- data2 = 30; req2=1
-- data_out = 7; valid=1
-- grant1 = 0;
-- grant2 = 1;
when 10 => data1_tb <= (9 downto 5 => '0') & "10110"; --data1=22; data_out non assunto =5
data2_tb <= (9 downto 5 => '0') & "11110"; -- data2= 30; data_out =7
req1_tb <= '1' ; req2_tb<= '1';
when 11 => end_sim <= '0'; -- end of the simulation
when others => null;
end case;
t := t + 1;
end if;
end process;
end architecture;
SOURCE FILE FOR COMPARATOR
library IEEE;
use IEEE.std_logic_1164.all;
-- -------------------------
-- Entity
-- -------------------------
entity comparator is
port (
A : in std_logic_vector(1 downto 0);
B : in std_logic_vector(1 downto 0);
A_less_B : out std_logic; -- '1' IF A < B
A_equal_B : out std_logic; -- '1' IF A = B
A_greater_B: out std_logic -- '1' IF A > B
);
end entity;
-- -------------------------
-- Architecture
-- -------------------------
architecture arc of comparator is
signal aux1: std_logic;
signal aux2: std_logic;
signal aux3: std_logic;
signal aux4: std_logic;
signal aux5: std_logic;
signal aux6: std_logic;
signal aux7: std_logic;
signal aux8: std_logic;
begin
-- A_equal_B combinational logic circuit
aux1 <= A(1) xnor B(1);
aux2 <= A(0) xnor B(0);
A_equal_B <= aux1 and aux2;
-- A_less_B combinational logic circuit
aux3 <= (not A(0)) and (not A(1)) and B(0);
aux4 <= (not A(1)) and B(1);
aux5 <= (not A(0)) and B(1) and B(0);
A_less_B <= aux3 or aux4 or aux5;
-- A_greater_B combinational logic circuit
aux6 <= (not B(0)) and (not B(1)) and A(0);
aux7 <= (not B(1)) and A(1);
aux8 <= (not B(0)) and A(1) and A(0);
A_greater_B <= aux6 or aux7 or aux8;
end architecture;
-
\$\begingroup\$ What book is this exercise from? It appears to be a variation of this. \$\endgroup\$Mast– Mast ♦2022年11月29日 16:11:34 +00:00Commented Nov 29, 2022 at 16:11
1 Answer 1
Testing
The testbench covers a nice variety of input combinations. The next step is to add
VHDL code to the testbench to make it self-checking. You could add a process
which is triggered on the falling_edge
of the clock, when the output signals
are stable. It looks like you already have the expected output values in the
comments in the case
statement.
You could encapsulate each case
item into a procedure
, where you pass in the
input data, the requests and expected output. This way, you can easily add
many more input combinations.
Comments
Several of the comments are not needed, such as these:
-- Entity
-- Architecture
They just repeat the VHDL keywords of the same name. It would be better to add comments which describe the functionality of the design.
Tabs
The code mixes tab characters with single spaces on the same line. This can cause the code to appear with inconsistent indentation by different code viewers (editors, source code browsers, etc.). Replace the tabs with spaces.
Indentation
Indentation is inconsistent; some lines have 2 spaces, some 3, some 4, etc. I recommend 4 spaces for each level of indentation.
Blank lines
There are too many blank lines in the code. There is no need to use groups of blank lines (2 or more together).
Typo
algoritm
should be algorithm
:
-- Signal for round robin algoritm
In the testbench, cicles
should be cycles
.
variable t : integer := 0; -- variable used to count clock cicles