Files
Pipeline-AXI-Handshake/tests/Pipeline_tb.vhd
MaxP 75ac016c9a Refines testbench logic and parameter configurations
Updates random seed values and adjusts pipeline configuration constants for improved testing flexibility. Refactors write and read processes for clarity, adding additional checks and error handling. Introduces `stop` function to terminate simulation on critical errors.

Enhances test coverage and simulation reliability.
2025-04-16 17:26:14 +00:00

179 lines
6.1 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use std.env.stop;
entity Pipeline_tb is
-- The testbench does not require any ports
end entity Pipeline_tb;
architecture behavior of Pipeline_tb is
-- Random number generator
--@ Select a random number for `seed1` to generate random numbers
shared variable seed1 : integer := 467;
--@ Select a random number for `seed2` to generate random numbers
shared variable seed2 : integer := 623;
--@ Generate a random number between `min_val` and `max_val`
--@ You must provide the `shared variable seed1` and `shared variable seed2` to generate random numbers.
--@ You need `use ieee.math_real.all;` to use this function.
impure function rand_int(min_val, max_val : integer) return integer is
variable r : real;
begin
uniform(seed1, seed2, r);
return integer(
round(r * real(max_val - min_val + 1) + real(min_val) - 0.5));
end function;
-- Clock signal period
constant period : time := 20 ns;
-- Adjustable wait times
constant write_delay : natural := 40; -- Maximal wait time between write operations in clock cycles
constant read_delay : natural := 60; -- Maximal wait time between read operations in clock cycles
-- Setting constants for the FIFO to be tested
constant K_Width : integer := 32; -- Data width of the FIFO
constant K_PipelineStages : integer := 5; -- Number of pipeline stages
constant K_RegisterBalancing : string := "yes"; -- Register balancing attribute
-- Testbench signals
signal CLK : std_logic := '0';
signal RST : std_logic := '1';
signal CE : std_logic := '1';
signal I_Data : std_logic_vector(K_Width - 1 downto 0) := (others => 'U');
signal I_Valid : std_logic := '0';
signal O_Ready : std_logic;
signal O_Data : std_logic_vector(K_Width - 1 downto 0) := (others => 'U');
signal O_Valid : std_logic;
signal I_Ready : std_logic := '0';
signal PipelineEnable : std_logic;
begin
uut0 : entity work.PipelineController
generic map(
G_PipelineStages => K_PipelineStages,
G_ResetActiveAt => '1'
)
port map(
I_CLK => CLK,
I_RST => RST,
I_CE => CE,
O_Enable => PipelineEnable,
I_Valid => I_Valid,
O_Ready => O_Ready,
O_Valid => O_Valid,
I_Ready => I_Ready
);
uut1 : entity work.PipelineRegister
generic map(
G_PipelineStages => K_PipelineStages,
G_Width => K_Width,
G_RegisterBalancing => K_RegisterBalancing
)
port map(
I_CLK => CLK,
I_Enable => PipelineEnable,
I_Data => I_Data,
O_Data => O_Data
);
-- Clock process
Clocking : process
begin
while true loop
CLK <= '0';
wait for (period / 2);
CLK <= '1';
wait for (period / 2);
end loop;
end process;
-- Clock enable process
-- This process is used to enable the clock signal for a certain amount of time
-- and only for the Pipeline Controller to check if the dataflow is working correctly.
-- ClockEnable : process
-- begin
-- while true loop
-- CE <= '1';
-- wait for 1000 ns;
-- CE <= '0';
-- wait for 500 ns;
-- end loop;
-- end process;
-- 100 ns Reset
RST <= '1', '0' after 100 ns;
-- Write process
Write : process
variable delay : integer := 0;
variable i : integer := 1;
begin
I_Valid <= '0';
I_Data <= (others => 'U');
wait until RST = '0'; -- auf Reset-Ende warten
while true loop
wait until rising_edge(CLK);
if O_Ready = '1' and delay = 0 then
I_Data <= std_logic_vector(to_unsigned(i, K_Width));
I_Valid <= '1';
report "Sende Paket #" & integer'image(i) severity note;
i := i + 1;
delay := rand_int(1, write_delay);
elsif O_Ready = '1' and I_Valid = '1' then
I_Valid <= '0';
end if;
if delay /= 0 then
delay := delay - 1;
end if;
end loop;
end process;
-- Read process
Read : process
variable delay : integer := 0;
variable expected : integer := 1;
variable received : integer;
begin
I_Ready <= '0';
wait until RST = '0'; -- auf Reset-Ende warten
while true loop
wait until rising_edge(CLK);
wait for 1 ns;
if O_Valid = '1' and delay = 0 then
I_Ready <= '1';
received := to_integer(unsigned(O_Data));
if received = expected then
report "Empfange Paket #" & integer'image(expected) severity note;
else
report "Fehler bei Paket #" & integer'image(expected) &
": erwartet " & integer'image(expected) &
", empfangen " & integer'image(received) severity error;
stop(0);
end if;
expected := expected + 1;
delay := rand_int(1, read_delay);
elsif O_Valid = '1' and I_Ready = '1' then
I_Ready <= '0';
end if;
if delay /= 0 then
delay := delay - 1;
end if;
end loop;
end process;
end architecture behavior;