Refactor testbench for bram_writer: update description, increase image size, and enhance signal handling for improved simulation accuracy
This commit is contained in:
@@ -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,13 +23,36 @@ 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
|
||||||
|
|
||||||
|
-- Component declaration for bram_writer
|
||||||
|
COMPONENT bram_writer IS
|
||||||
|
GENERIC (
|
||||||
|
ADDR_WIDTH : POSITIVE;
|
||||||
|
IMG_SIZE : POSITIVE
|
||||||
|
);
|
||||||
|
PORT (
|
||||||
|
clk : IN STD_LOGIC;
|
||||||
|
aresetn : IN STD_LOGIC;
|
||||||
|
s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||||
|
s_axis_tvalid : IN STD_LOGIC;
|
||||||
|
s_axis_tready : OUT STD_LOGIC;
|
||||||
|
s_axis_tlast : IN STD_LOGIC;
|
||||||
|
conv_addr : IN STD_LOGIC_VECTOR(ADDR_WIDTH-1 DOWNTO 0);
|
||||||
|
conv_data : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
|
||||||
|
start_conv : OUT STD_LOGIC;
|
||||||
|
done_conv : IN STD_LOGIC;
|
||||||
|
write_ok : OUT STD_LOGIC;
|
||||||
|
overflow : OUT STD_LOGIC;
|
||||||
|
underflow : OUT STD_LOGIC
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
-- Signals for DUT
|
-- Signals for DUT
|
||||||
SIGNAL clk : STD_LOGIC := '0';
|
SIGNAL clk : STD_LOGIC := '0';
|
||||||
@@ -46,36 +69,34 @@ ARCHITECTURE sim OF tb_bram_writer IS
|
|||||||
SIGNAL overflow : STD_LOGIC;
|
SIGNAL overflow : STD_LOGIC;
|
||||||
SIGNAL underflow : STD_LOGIC;
|
SIGNAL underflow : STD_LOGIC;
|
||||||
|
|
||||||
-- Instantiate DUT
|
-- Stimulus memory for input data
|
||||||
COMPONENT bram_writer IS
|
TYPE mem_type IS ARRAY(0 TO (IMG_SIZE*IMG_SIZE)-1) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||||
GENERIC (
|
SIGNAL mem : mem_type := (
|
||||||
ADDR_WIDTH : POSITIVE := 4;
|
0 => x"3A",
|
||||||
IMG_SIZE : POSITIVE := 2
|
1 => x"7F",
|
||||||
);
|
2 => x"12",
|
||||||
PORT (
|
3 => x"9C",
|
||||||
clk : IN STD_LOGIC;
|
4 => x"55",
|
||||||
aresetn : IN STD_LOGIC;
|
5 => x"2B",
|
||||||
s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
6 => x"81",
|
||||||
s_axis_tvalid : IN STD_LOGIC;
|
7 => x"04",
|
||||||
s_axis_tready : OUT STD_LOGIC;
|
8 => x"6E",
|
||||||
s_axis_tlast : IN STD_LOGIC;
|
9 => x"F2",
|
||||||
conv_addr : IN STD_LOGIC_VECTOR(ADDR_WIDTH-1 DOWNTO 0);
|
10 => x"1D",
|
||||||
conv_data : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
|
11 => x"C7",
|
||||||
start_conv : OUT STD_LOGIC;
|
12 => x"99",
|
||||||
done_conv : IN STD_LOGIC;
|
13 => x"0A",
|
||||||
write_ok : OUT STD_LOGIC;
|
14 => x"B3",
|
||||||
overflow : OUT STD_LOGIC;
|
15 => x"5D"
|
||||||
underflow : OUT STD_LOGIC
|
);
|
||||||
);
|
|
||||||
END COMPONENT;
|
|
||||||
|
|
||||||
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
|
s_axis_tvalid <= '0';
|
||||||
wait until rising_edge(clk);
|
END LOOP;
|
||||||
end loop;
|
s_axis_tlast <= '0';
|
||||||
end loop;
|
|
||||||
s_axis_tvalid <= '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;
|
||||||
@@ -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';
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
trigger <= '0';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Back?pressure: blocca ingresso finch<63> non hai trasmesso
|
-- State machine for R, G, B values buffering
|
||||||
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;
|
|
||||||
|
|
||||||
-- FSM per ricezione R, G, B
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user