Enhance bram_writer: add image size parameter, improve state machine for data handling, and refine signal management for better performance

This commit is contained in:
2025-04-17 19:21:15 +02:00
parent 1d226709ac
commit 7ee12b37fe
2 changed files with 262 additions and 76 deletions

141
LAB2/sim/tb_bram_writer.vhd Normal file
View File

@@ -0,0 +1,141 @@
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 04/17/2025
-- Design Name:
-- Module Name: tb_bram_writer - sim
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description: Testbench for bram_writer, stimulus and timing inspired by tb_img_conv.vhd
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_bram_writer IS
END ENTITY;
ARCHITECTURE sim OF tb_bram_writer IS
-- Testbench constants
CONSTANT ADDR_WIDTH : POSITIVE := 4;
CONSTANT IMG_SIZE : POSITIVE := 2; -- Small size for quick simulation
-- 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;
-- Instantiate DUT
COMPONENT bram_writer IS
GENERIC (
ADDR_WIDTH : POSITIVE := 4;
IMG_SIZE : POSITIVE := 2
);
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;
BEGIN
-- Clock generation
clk <= not clk after 5 ns;
-- Instantiate DUT
bram_writer_inst: bram_writer
GENERIC MAP (
ADDR_WIDTH => ADDR_WIDTH,
IMG_SIZE => IMG_SIZE
)
PORT MAP (
clk => clk,
aresetn => aresetn,
s_axis_tdata => s_axis_tdata,
s_axis_tvalid => s_axis_tvalid,
s_axis_tready => s_axis_tready,
s_axis_tlast => s_axis_tlast,
conv_addr => conv_addr,
conv_data => conv_data,
start_conv => start_conv,
done_conv => done_conv,
write_ok => write_ok,
overflow => overflow,
underflow => underflow
);
-- Stimulus process
stimulus : process
begin
-- Initial reset
aresetn <= '0';
wait for 10 ns;
aresetn <= '1';
wait until rising_edge(clk);
-- Send IMG_SIZE*IMG_SIZE data words
for i in 0 to IMG_SIZE*IMG_SIZE-1 loop
s_axis_tdata <= std_logic_vector(to_unsigned(i, 8));
s_axis_tvalid <= '1';
if i = IMG_SIZE*IMG_SIZE-1 then
s_axis_tlast <= '1';
else
s_axis_tlast <= '0';
end if;
wait until rising_edge(clk);
-- Wait for ready
while s_axis_tready /= '1' loop
wait until rising_edge(clk);
end loop;
end loop;
s_axis_tvalid <= '0';
s_axis_tlast <= '0';
-- Wait for write_ok and start_conv
wait until write_ok = '1';
wait until rising_edge(clk);
-- Simulate convolution done
done_conv <= '1';
wait until rising_edge(clk);
done_conv <= '0';
-- Wait and finish
wait for 20 ns;
assert false report "Simulation finished." severity note;
wait;
end process;
END ARCHITECTURE;

View File

@@ -1,116 +1,161 @@
library ieee; LIBRARY ieee;
use ieee.std_logic_1164.all; USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all; USE ieee.numeric_std.ALL;
entity bram_writer is ENTITY bram_writer IS
generic( GENERIC (
ADDR_WIDTH: POSITIVE :=16 ADDR_WIDTH : POSITIVE := 16;
IMG_SIZE : POSITIVE := 256 -- Image size (256x256)
); );
port ( PORT (
clk : in std_logic; clk : IN STD_LOGIC;
aresetn : in std_logic; aresetn : IN STD_LOGIC;
s_axis_tdata : in std_logic_vector(7 downto 0); s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axis_tvalid : in std_logic; s_axis_tvalid : IN STD_LOGIC;
s_axis_tready : out std_logic; s_axis_tready : OUT STD_LOGIC;
s_axis_tlast : in std_logic; s_axis_tlast : IN STD_LOGIC;
conv_addr: in std_logic_vector(ADDR_WIDTH-1 downto 0); conv_addr : IN STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0);
conv_data: out std_logic_vector(6 downto 0); conv_data : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
start_conv: out std_logic; start_conv : OUT STD_LOGIC;
done_conv: in std_logic; done_conv : IN STD_LOGIC;
write_ok : out std_logic; write_ok : OUT STD_LOGIC;
overflow : out std_logic; overflow : OUT STD_LOGIC;
underflow: out std_logic underflow : OUT STD_LOGIC
); );
end entity bram_writer; END ENTITY bram_writer;
architecture rtl of bram_writer is ARCHITECTURE rtl OF bram_writer IS
component bram_controller is COMPONENT bram_controller IS
generic ( GENERIC (
ADDR_WIDTH: POSITIVE :=16 ADDR_WIDTH : POSITIVE := 16
); );
port ( PORT (
clk : in std_logic; clk : IN STD_LOGIC;
aresetn : in std_logic; aresetn : IN STD_LOGIC;
addr: in std_logic_vector(ADDR_WIDTH-1 downto 0);
dout: out std_logic_vector(7 downto 0);
din: in std_logic_vector(7 downto 0);
we: in std_logic
);
end component;
TYPE state_type is (IDLE, RECEIVING, CONVOLUTION); addr : IN STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
we : IN STD_LOGIC
);
END COMPONENT;
TYPE state_type IS (IDLE, RECEIVING, CONVOLUTION);
SIGNAL state : state_type := IDLE; SIGNAL state : state_type := IDLE;
SIGNAL s_axis_tready_int : std_logic := '0'; SIGNAL s_axis_tready_int : STD_LOGIC := '0';
SIGNAL bram_addr : std_logic_vector(ADDR_WIDTH-1 downto 0) := (others => '0'); -- Indirizzo BRAM SIGNAL bram_addr : STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- BRAM address
SIGNAL bram_we : std_logic := '0'; -- Segnale di scrittura per il BRAM SIGNAL bram_we : STD_LOGIC := '0'; -- Write enable signal for BRAM
SIGNAL wr_addr : std_logic_vector(ADDR_WIDTH-1 downto 0) := (others => '0'); -- Indirizzo di scrittura BRAM SIGNAL wr_addr : STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Write address for BRAM
begin BEGIN
BRAM_CTRL: bram_controller
generic map (
ADDR_WIDTH => ADDR_WIDTH
)
port map (
clk => clk,
aresetn => aresetn,
addr => bram_addr,
dout => conv_data,
din => s_axis_tdata,
we => bram_we
);
-- AXIS -- Instantiate BRAM controller
s_axis_tready <= s_axis_tready_int BRAM_CTRL : bram_controller
GENERIC MAP(
ADDR_WIDTH => ADDR_WIDTH
)
PORT MAP(
clk => clk,
aresetn => aresetn,
addr => bram_addr,
dout => conv_data,
din => s_axis_tdata,
we => bram_we
);
-- Gestione addr BRAM -- Assign AXIS ready signal
with state select bram_addr <= conv_addr when CONVOLUTION, s_axis_tready <= s_axis_tready_int;
wr_addr when Others;
process(clk) -- Select BRAM address based on state
begin WITH state SELECT bram_addr <= conv_addr WHEN CONVOLUTION,
if rising_edge(clk) then wr_addr WHEN OTHERS;
if aresetn = '0' then
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF aresetn = '0' THEN
-- Reset all signals and state
state <= IDLE; state <= IDLE;
s_axis_tready_int <= '0'; s_axis_tready_int <= '0';
bram_we <= '0'; bram_we <= '0';
wr_addr <= (others => '0'); wr_addr <= (OTHERS => '0');
start_conv <= '0'; start_conv <= '0';
write_ok <= '0'; write_ok <= '0';
overflow <= '0'; overflow <= '0';
underflow <= '0'; underflow <= '0';
else ELSE
-- Default assignments for each clock cycle
start_conv <= '0'; start_conv <= '0';
bram_we <= '0';
write_ok <= '0'; write_ok <= '0';
overflow <= '0'; overflow <= '0';
underflow <= '0'; underflow <= '0';
s_axis_tready_int <= '1';
case state is -- State machine for data handling
when IDLE => CASE state IS
s_axis_tready_int <= '1'; WHEN IDLE =>
-- Wait for valid input data
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
-- valid data received, start receiving
wr_addr <= (OTHERS => '0');
bram_we <= '1'; -- Enable write to BRAM
state <= RECEIVING;
END IF;
WHEN RECEIVING =>
-- Receiving data, increment write address
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
-- Check for overflow: if address reaches max image size
IF unsigned(wr_addr) = (IMG_SIZE ** 2 - 1) THEN
overflow <= '1';
state <= IDLE;
ELSE
-- Increment write address and write data to BRAM
wr_addr <= STD_LOGIC_VECTOR(unsigned(wr_addr) + 1);
bram_we <= '1'; -- Enable write to BRAM
when RECEIVING => -- Check for last data signal
IF s_axis_tlast = '1' THEN
-- Check for underflow: if not enough data received
IF unsigned(wr_addr) < (IMG_SIZE ** 2 - 2) THEN
underflow <= '1';
state <= IDLE;
ELSE
-- Data reception complete, start convolution
write_ok <= '1';
s_axis_tready_int <= '0';
start_conv <= '1';
state <= CONVOLUTION;
END IF;
END IF;
END IF;
END IF;
when CONVOLUTION => WHEN CONVOLUTION =>
-- Wait for convolution to finish
s_axis_tready_int <= '0';
end case; IF done_conv = '1' THEN
end if; state <= IDLE;
end if; END IF;
end process;
end architecture; END CASE;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;