diff --git a/LAB2/sim/tb_bram_writer.vhd b/LAB2/sim/tb_bram_writer.vhd new file mode 100644 index 0000000..1c6ee0e --- /dev/null +++ b/LAB2/sim/tb_bram_writer.vhd @@ -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; \ No newline at end of file diff --git a/LAB2/src/bram_writer.vhd b/LAB2/src/bram_writer.vhd index 5cfaae7..00f7cd8 100644 --- a/LAB2/src/bram_writer.vhd +++ b/LAB2/src/bram_writer.vhd @@ -1,116 +1,161 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; -entity bram_writer is - generic( - ADDR_WIDTH: POSITIVE :=16 +ENTITY bram_writer IS + GENERIC ( + ADDR_WIDTH : POSITIVE := 16; + IMG_SIZE : POSITIVE := 256 -- Image size (256x256) ); - port ( - clk : in std_logic; - aresetn : in std_logic; + 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; + 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); + 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; + start_conv : OUT STD_LOGIC; + done_conv : IN STD_LOGIC; - write_ok : out std_logic; - overflow : out std_logic; - underflow: out std_logic + write_ok : OUT STD_LOGIC; + overflow : 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 - generic ( - ADDR_WIDTH: POSITIVE :=16 + COMPONENT bram_controller IS + GENERIC ( + ADDR_WIDTH : POSITIVE := 16 ); - port ( - clk : 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; + PORT ( + clk : IN STD_LOGIC; + aresetn : IN STD_LOGIC; - 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 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_we : std_logic := '0'; -- Segnale di scrittura per il BRAM + SIGNAL bram_addr : STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- BRAM address + 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 - - 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 - ); +BEGIN - -- AXIS - s_axis_tready <= s_axis_tready_int + -- Instantiate BRAM controller + 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 - with state select bram_addr <= conv_addr when CONVOLUTION, - wr_addr when Others; + -- Assign AXIS ready signal + s_axis_tready <= s_axis_tready_int; - process(clk) - begin - if rising_edge(clk) then - if aresetn = '0' then + -- Select BRAM address based on state + WITH state SELECT bram_addr <= conv_addr WHEN CONVOLUTION, + wr_addr WHEN OTHERS; + + PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF aresetn = '0' THEN + -- Reset all signals and state state <= IDLE; s_axis_tready_int <= '0'; bram_we <= '0'; - wr_addr <= (others => '0'); - + wr_addr <= (OTHERS => '0'); + start_conv <= '0'; write_ok <= '0'; overflow <= '0'; underflow <= '0'; - else + ELSE + -- Default assignments for each clock cycle start_conv <= '0'; + bram_we <= '0'; write_ok <= '0'; overflow <= '0'; underflow <= '0'; + s_axis_tready_int <= '1'; - case state is - when IDLE => - s_axis_tready_int <= '1'; + -- State machine for data handling + CASE state IS + 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; - end if; - end if; - end process; + IF done_conv = '1' THEN + state <= IDLE; + END IF; -end architecture; + END CASE; + END IF; + END IF; + END PROCESS; + +END ARCHITECTURE; \ No newline at end of file