Refactor testbench for bram_writer: update description, increase image size, and enhance signal handling for improved simulation accuracy

This commit is contained in:
2025-04-23 01:49:46 +02:00
parent 722b479811
commit 5995a532f5
5 changed files with 124 additions and 95 deletions

View File

@@ -8,7 +8,7 @@
-- Project Name: -- Project Name:
-- Target Devices: -- Target Devices:
-- Tool Versions: -- Tool Versions:
-- Description: Testbench for bram_writer, stimulus and timing inspired by tb_img_conv.vhd -- Description: Testbench for bram_writer, rewritten in the style of tb_packetizer.vhd
-- --
-- Dependencies: -- Dependencies:
-- --
@@ -23,34 +23,19 @@ USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL; USE ieee.numeric_std.ALL;
ENTITY tb_bram_writer IS ENTITY tb_bram_writer IS
END ENTITY; END tb_bram_writer;
ARCHITECTURE sim OF tb_bram_writer IS ARCHITECTURE sim OF tb_bram_writer IS
-- Testbench constants -- Testbench constants
CONSTANT ADDR_WIDTH : POSITIVE := 4; CONSTANT ADDR_WIDTH : POSITIVE := 4;
CONSTANT IMG_SIZE : POSITIVE := 2; -- Small size for quick simulation CONSTANT IMG_SIZE : POSITIVE := 4; -- Increased size for more memory
-- Signals for DUT -- Component declaration for bram_writer
SIGNAL clk : STD_LOGIC := '0';
SIGNAL aresetn : STD_LOGIC := '0';
SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0');
SIGNAL s_axis_tvalid : STD_LOGIC := '0';
SIGNAL s_axis_tready : STD_LOGIC;
SIGNAL s_axis_tlast : STD_LOGIC := '0';
SIGNAL conv_addr : STD_LOGIC_VECTOR(ADDR_WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL conv_data : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL start_conv : STD_LOGIC;
SIGNAL done_conv : STD_LOGIC := '0';
SIGNAL write_ok : STD_LOGIC;
SIGNAL overflow : STD_LOGIC;
SIGNAL underflow : STD_LOGIC;
-- Instantiate DUT
COMPONENT bram_writer IS COMPONENT bram_writer IS
GENERIC ( GENERIC (
ADDR_WIDTH : POSITIVE := 4; ADDR_WIDTH : POSITIVE;
IMG_SIZE : POSITIVE := 2 IMG_SIZE : POSITIVE
); );
PORT ( PORT (
clk : IN STD_LOGIC; clk : IN STD_LOGIC;
@@ -69,13 +54,49 @@ ARCHITECTURE sim OF tb_bram_writer IS
); );
END COMPONENT; END COMPONENT;
-- Signals for DUT
SIGNAL clk : STD_LOGIC := '0';
SIGNAL aresetn : STD_LOGIC := '0';
SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0');
SIGNAL s_axis_tvalid : STD_LOGIC := '0';
SIGNAL s_axis_tready : STD_LOGIC;
SIGNAL s_axis_tlast : STD_LOGIC := '0';
SIGNAL conv_addr : STD_LOGIC_VECTOR(ADDR_WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL conv_data : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL start_conv : STD_LOGIC;
SIGNAL done_conv : STD_LOGIC := '0';
SIGNAL write_ok : STD_LOGIC;
SIGNAL overflow : STD_LOGIC;
SIGNAL underflow : STD_LOGIC;
-- Stimulus memory for input data
TYPE mem_type IS ARRAY(0 TO (IMG_SIZE*IMG_SIZE)-1) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL mem : mem_type := (
0 => x"3A",
1 => x"7F",
2 => x"12",
3 => x"9C",
4 => x"55",
5 => x"2B",
6 => x"81",
7 => x"04",
8 => x"6E",
9 => x"F2",
10 => x"1D",
11 => x"C7",
12 => x"99",
13 => x"0A",
14 => x"B3",
15 => x"5D"
);
BEGIN BEGIN
-- Clock generation -- Clock generation
clk <= not clk after 5 ns; clk <= NOT clk AFTER 5 ns;
-- Instantiate DUT -- DUT instantiation
bram_writer_inst: bram_writer uut: bram_writer
GENERIC MAP ( GENERIC MAP (
ADDR_WIDTH => ADDR_WIDTH, ADDR_WIDTH => ADDR_WIDTH,
IMG_SIZE => IMG_SIZE IMG_SIZE => IMG_SIZE
@@ -97,51 +118,46 @@ BEGIN
); );
-- Stimulus process -- Stimulus process
stimulus : process stimulus : PROCESS
begin BEGIN
-- Initial reset -- Reset
aresetn <= '0'; aresetn <= '0';
wait for 10 ns; WAIT FOR 20 ns;
aresetn <= '1'; aresetn <= '1';
wait until rising_edge(clk); WAIT UNTIL rising_edge(clk);
-- Send IMG_SIZE*IMG_SIZE data words -- Send IMG_SIZE*IMG_SIZE data words
for i in 0 to IMG_SIZE*IMG_SIZE-1 loop FOR i IN 0 TO IMG_SIZE*IMG_SIZE-1 LOOP
s_axis_tdata <= std_logic_vector(to_unsigned(i, 8)); s_axis_tdata <= mem(i);
s_axis_tvalid <= '1'; s_axis_tvalid <= '1';
if i = IMG_SIZE*IMG_SIZE-1 then IF i = IMG_SIZE*IMG_SIZE-1 THEN
s_axis_tlast <= '1'; s_axis_tlast <= '1';
else ELSE
s_axis_tlast <= '0'; s_axis_tlast <= '0';
end if; END IF;
wait until rising_edge(clk); -- Wait for handshake
-- Wait for ready WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk);
while s_axis_tready /= '1' loop
wait until rising_edge(clk);
end loop;
end loop;
s_axis_tvalid <= '0'; s_axis_tvalid <= '0';
END LOOP;
s_axis_tlast <= '0'; s_axis_tlast <= '0';
-- Wait for write_ok and start_conv -- Wait for write_ok and start_conv
wait until write_ok = '1'; WAIT UNTIL write_ok = '1';
wait until rising_edge(clk); WAIT UNTIL rising_edge(clk);
-- Require data -- Read out data using conv_addr
for i in 0 to IMG_SIZE*IMG_SIZE-1 loop FOR i IN 0 TO IMG_SIZE*IMG_SIZE-1 LOOP
conv_addr <= std_logic_vector(to_unsigned(i, ADDR_WIDTH)); conv_addr <= std_logic_vector(to_unsigned(i, ADDR_WIDTH));
wait until rising_edge(clk); WAIT UNTIL rising_edge(clk);
end loop; END LOOP;
-- Simulate convolution done -- Simulate convolution done
done_conv <= '1'; done_conv <= '1';
wait until rising_edge(clk); WAIT UNTIL rising_edge(clk);
done_conv <= '0'; done_conv <= '0';
-- Wait and finish -- Wait and finish
wait for 20 ns; WAIT;
assert false report "Simulation finished." severity note; END PROCESS;
wait;
end process;
END ARCHITECTURE; END sim;

View File

@@ -56,11 +56,9 @@ ARCHITECTURE Behavioral OF rgb2gray_tb IS
SIGNAL tready_block_req : STD_LOGIC := '0'; SIGNAL tready_block_req : STD_LOGIC := '0';
CONSTANT clk_period : TIME := 10 ns;
BEGIN BEGIN
clk <= NOT clk AFTER clk_period / 2; -- Clock generation clk <= NOT clk AFTER 5 ns; -- Clock generation
-- Asynchronous tready block process (simulate downstream backpressure) -- Asynchronous tready block process (simulate downstream backpressure)
PROCESS (clk) PROCESS (clk)
@@ -123,12 +121,12 @@ BEGIN
FOR j IN 0 TO 2 LOOP FOR j IN 0 TO 2 LOOP
s_axis_tdata <= rgb_mem(i, j); s_axis_tdata <= rgb_mem(i, j);
s_axis_tvalid <= '1'; s_axis_tvalid <= '1';
IF i = 2 AND j = 2 THEN -- Assert tlast at the end of the first group (i=2, j=2)
IF (i = 2 AND j = 2) THEN
s_axis_tlast <= '1'; s_axis_tlast <= '1';
ELSE ELSE
s_axis_tlast <= '0'; s_axis_tlast <= '0';
END IF; END IF;
-- Wait for handshake
WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk); WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk);
s_axis_tvalid <= '0'; s_axis_tvalid <= '0';
END LOOP; END LOOP;
@@ -141,7 +139,8 @@ BEGIN
FOR j IN 0 TO 2 LOOP FOR j IN 0 TO 2 LOOP
s_axis_tdata <= rgb_mem(i, j); s_axis_tdata <= rgb_mem(i, j);
s_axis_tvalid <= '1'; s_axis_tvalid <= '1';
IF i = 4 AND j = 2 THEN -- Assert tlast at the end of this group (i=4, j=2)
IF (i = 4 AND j = 2) THEN
s_axis_tlast <= '1'; s_axis_tlast <= '1';
ELSE ELSE
s_axis_tlast <= '0'; s_axis_tlast <= '0';
@@ -164,7 +163,8 @@ BEGIN
FOR j IN 0 TO 2 LOOP FOR j IN 0 TO 2 LOOP
s_axis_tdata <= rgb_mem(i, j); s_axis_tdata <= rgb_mem(i, j);
s_axis_tvalid <= '1'; s_axis_tvalid <= '1';
IF i = 6 AND j = 2 THEN -- Assert tlast at the end of this group (i=6, j=2)
IF (i = 6 AND j = 2) THEN
s_axis_tlast <= '1'; s_axis_tlast <= '1';
ELSE ELSE
s_axis_tlast <= '0'; s_axis_tlast <= '0';
@@ -180,7 +180,8 @@ BEGIN
FOR j IN 0 TO 2 LOOP FOR j IN 0 TO 2 LOOP
s_axis_tdata <= rgb_mem(i, j); s_axis_tdata <= rgb_mem(i, j);
s_axis_tvalid <= '1'; s_axis_tvalid <= '1';
IF i = 8 AND j = 2 THEN -- Assert tlast at the very end (i=8, j=2)
IF (i = 8 AND j = 2) THEN
s_axis_tlast <= '1'; s_axis_tlast <= '1';
ELSE ELSE
s_axis_tlast <= '0'; s_axis_tlast <= '0';

View File

@@ -37,18 +37,17 @@ ARCHITECTURE Behavioral OF rgb2gray IS
SIGNAL r_val, g_val : UNSIGNED(7 DOWNTO 0); SIGNAL r_val, g_val : UNSIGNED(7 DOWNTO 0);
SIGNAL sum : UNSIGNED(8 DOWNTO 0); SIGNAL sum : UNSIGNED(8 DOWNTO 0);
SIGNAL gray : UNSIGNED(6 DOWNTO 0); SIGNAL gray : UNSIGNED(6 DOWNTO 0);
SIGNAL send_data : STD_LOGIC := '0';
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
SIGNAL m_axis_tdata_int : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0'); SIGNAL s_axis_tready_int : STD_LOGIC := '0';
SIGNAL s_axis_tready_int : STD_LOGIC := '1';
SIGNAL trigger : STD_LOGIC := '0';
SIGNAL last_seen : STD_LOGIC := '0';
BEGIN BEGIN
-- Port mappings
m_axis_tvalid <= m_axis_tvalid_int;
m_axis_tdata <= m_axis_tdata_int;
s_axis_tready <= s_axis_tready_int; s_axis_tready <= s_axis_tready_int;
m_axis_tvalid <= m_axis_tvalid_int;
-- Divider instance -- Divider instance
DIVIDER : divider_by_3 DIVIDER : divider_by_3
@@ -66,56 +65,69 @@ BEGIN
IF resetn = '0' THEN IF resetn = '0' THEN
-- Reset all signals -- Reset all signals
state <= WAIT_R; state <= WAIT_R;
s_axis_tready_int <= '1';
s_axis_tready_int <= '0';
m_axis_tvalid_int <= '0'; m_axis_tvalid_int <= '0';
m_axis_tdata <= (OTHERS => '0');
m_axis_tlast <= '0'; m_axis_tlast <= '0';
m_axis_tdata_int <= (OTHERS => '0');
r_val <= (OTHERS => '0'); r_val <= (OTHERS => '0');
g_val <= (OTHERS => '0'); g_val <= (OTHERS => '0');
sum <= (OTHERS => '0'); sum <= (OTHERS => '0');
send_data <= '0';
trigger <= '0';
ELSE ELSE
-- Propagate TLAST
m_axis_tlast <= s_axis_tlast;
-- Clear valid once data has been accepted -- Input data - slave
IF m_axis_tvalid_int = '1' AND m_axis_tready = '1' THEN s_axis_tready_int <= m_axis_tready;
IF s_axis_tlast = '1' THEN
last_seen <= '1';
ELSE
m_axis_tlast <= '0';
END IF;
-- Output data - master
IF m_axis_tready = '1' THEN
m_axis_tvalid_int <= '0'; m_axis_tvalid_int <= '0';
END IF; END IF;
-- Issue new output only when back?pressure is released IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
IF send_data = '1' AND m_axis_tready = '1' THEN
m_axis_tdata_int <= '0' & STD_LOGIC_VECTOR(gray); -- MSB zero + 7?bit gray
m_axis_tvalid_int <= '1'; m_axis_tvalid_int <= '1';
send_data <= '0'; m_axis_tdata <= '0' & STD_LOGIC_VECTOR(gray); -- MSB zero + 7bit gray
IF last_seen = '1' THEN
m_axis_tlast <= '1';
last_seen <= '0';
END IF; END IF;
-- Back?pressure: blocca ingresso finch<63> non hai trasmesso trigger <= '0';
IF send_data = '1' OR (m_axis_tvalid_int = '1' AND m_axis_tready = '0') THEN
s_axis_tready_int <= '0';
ELSE
s_axis_tready_int <= '1';
END IF; END IF;
-- FSM per ricezione R, G, B -- State machine for R, G, B values buffering
CASE state IS CASE state IS
WHEN WAIT_R => WHEN WAIT_R =>
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
r_val <= unsigned(s_axis_tdata); r_val <= unsigned(s_axis_tdata);
state <= WAIT_G; state <= WAIT_G;
END IF; END IF;
WHEN WAIT_G => WHEN WAIT_G =>
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
g_val <= unsigned(s_axis_tdata); g_val <= unsigned(s_axis_tdata);
state <= WAIT_B; state <= WAIT_B;
END IF; END IF;
WHEN WAIT_B => WHEN WAIT_B =>
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
sum <= RESIZE(r_val + g_val + unsigned(s_axis_tdata), 9); sum <= RESIZE(r_val + g_val + unsigned(s_axis_tdata), sum'length);
send_data <= '1'; trigger <= '1';
state <= WAIT_R; state <= WAIT_R;
END IF; END IF;
END CASE; END CASE;

View File

@@ -47,7 +47,7 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/> <Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/> <Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="basys3"/> <Option Name="DSABoardId" Val="basys3"/>
<Option Name="WTXSimLaunchSim" Val="31"/> <Option Name="WTXSimLaunchSim" Val="40"/>
<Option Name="WTModelSimLaunchSim" Val="0"/> <Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/> <Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/> <Option Name="WTIesLaunchSim" Val="0"/>

View File

@@ -47,7 +47,7 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/> <Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/> <Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="basys3"/> <Option Name="DSABoardId" Val="basys3"/>
<Option Name="WTXSimLaunchSim" Val="93"/> <Option Name="WTXSimLaunchSim" Val="106"/>
<Option Name="WTModelSimLaunchSim" Val="0"/> <Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/> <Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/> <Option Name="WTIesLaunchSim" Val="0"/>