diff --git a/LAB2/sim/tb_packetizer.vhd b/LAB2/sim/tb_packetizer.vhd new file mode 100644 index 0000000..9269669 --- /dev/null +++ b/LAB2/sim/tb_packetizer.vhd @@ -0,0 +1,208 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 04/21/2025 +-- Design Name: +-- Module Name: tb_packetizer - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: Testbench for packetizer +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +ENTITY tb_packetizer IS +END tb_packetizer; + +ARCHITECTURE Behavioral OF tb_packetizer IS + + COMPONENT packetizer IS + GENERIC ( + HEADER : INTEGER := 16#FF#; + FOOTER : INTEGER := 16#F1# + ); + 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; + + m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + m_axis_tvalid : OUT STD_LOGIC; + m_axis_tready : IN STD_LOGIC + ); + END COMPONENT; + + 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 m_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL m_axis_tvalid : STD_LOGIC; + SIGNAL m_axis_tready : STD_LOGIC := '1'; + + -- Stimulus memory + TYPE mem_type IS ARRAY(0 TO 7) OF STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL mem : mem_type := ( + 0 => x"10", + 1 => x"20", + 2 => x"30", + 3 => x"4", + 4 => x"54", + 5 => x"65", + 6 => x"73", + 7 => x"90" + ); + + SIGNAL data_index : INTEGER := 0; + + SIGNAL tready_block_req : STD_LOGIC := '0'; + +BEGIN + + -- Clock generation + clk <= NOT clk AFTER 5 ns; + + -- Asynchronous tready block process + PROCESS (clk) + VARIABLE block_counter : INTEGER := 0; + VARIABLE tready_blocked : BOOLEAN := FALSE; + BEGIN + IF rising_edge(clk) THEN + IF tready_block_req = '1' AND NOT tready_blocked THEN + tready_blocked := TRUE; + block_counter := 0; + END IF; + + IF tready_blocked THEN + IF block_counter < 9 THEN + m_axis_tready <= '0'; + block_counter := block_counter + 1; + ELSE + m_axis_tready <= '1'; + tready_blocked := FALSE; + block_counter := 0; + END IF; + ELSE + m_axis_tready <= '1'; + END IF; + END IF; + END PROCESS; + + -- DUT instantiation + uut: packetizer + 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, + + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tready => m_axis_tready + ); + + -- Stimulus process + PROCESS + BEGIN + -- Reset + aresetn <= '0'; + WAIT FOR 20 ns; + aresetn <= '1'; + WAIT UNTIL rising_edge(clk); + + -- Start tready block asynchronously after 60 ns + WAIT FOR 60 ns; + tready_block_req <= '1'; + WAIT UNTIL rising_edge(clk); + tready_block_req <= '0'; + + -- Send 4 data words as a packet + FOR i IN 0 TO 3 LOOP + s_axis_tdata <= mem(i); + s_axis_tvalid <= '1'; + IF i = 3 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + -- Wait for handshake + WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk); + s_axis_tvalid <= '0'; + END LOOP; + s_axis_tlast <= '0'; + + -- Wait a bit, then send another packet of 2 words + WAIT FOR 50 ns; + FOR i IN 4 TO 5 LOOP + s_axis_tdata <= mem(i); + s_axis_tvalid <= '1'; + IF i = 5 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk); + s_axis_tvalid <= '0'; + END LOOP; + s_axis_tlast <= '0'; + + -- Start another tready block asynchronously + WAIT FOR 40 ns; + tready_block_req <= '1'; + WAIT UNTIL rising_edge(clk); + tready_block_req <= '0'; + + -- Send packet of 3 words + WAIT FOR 30 ns; + FOR i IN 5 TO 7 LOOP + s_axis_tdata <= mem(i); + s_axis_tvalid <= '1'; + IF i = 7 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk); + s_axis_tvalid <= '0'; + END LOOP; + s_axis_tlast <= '0'; + + -- Send packet of 4 words without initial waiting + FOR i IN 2 TO 6 LOOP + s_axis_tdata <= mem(i); + s_axis_tvalid <= '1'; + IF i = 6 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + WAIT UNTIL s_axis_tvalid = '1' AND s_axis_tready = '1' AND rising_edge(clk); + s_axis_tvalid <= '0'; + END LOOP; + s_axis_tlast <= '0'; + + WAIT; + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB2/src/packetizer.vhd b/LAB2/src/packetizer.vhd index 7161607..9572529 100644 --- a/LAB2/src/packetizer.vhd +++ b/LAB2/src/packetizer.vhd @@ -18,22 +18,21 @@ ENTITY packetizer IS m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); m_axis_tvalid : OUT STD_LOGIC; - m_axis_tready : IN STD_LOGIC; - m_axis_tlast : OUT STD_LOGIC + m_axis_tready : IN STD_LOGIC ); END ENTITY packetizer; ARCHITECTURE rtl OF packetizer IS - TYPE state_type IS (IDLE, SENDING_HEADER, SENDING_DATA, SENDING_FOOTER); - SIGNAL state : state_type := IDLE; + TYPE state_type IS (SENDING_HEADER, STREAMING, SENDING_FOOTER); + SIGNAL state : state_type := SENDING_HEADER; SIGNAL data_buffer : STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL s_axis_tready_int : STD_LOGIC; SIGNAL m_axis_tvalid_int : STD_LOGIC; - SIGNAL last_seen : STD_LOGIC := '0'; + SIGNAL trigger : STD_LOGIC := '0'; BEGIN @@ -41,75 +40,22 @@ BEGIN m_axis_tvalid <= m_axis_tvalid_int; PROCESS (clk) - VARIABLE trigger : STD_LOGIC := '0'; BEGIN IF rising_edge(clk) THEN IF aresetn = '0' THEN + state <= SENDING_HEADER; data_buffer <= (OTHERS => '0'); + m_axis_tdata <= (OTHERS => '0'); + m_axis_tvalid_int <= '0'; + s_axis_tready_int <= '0'; m_axis_tvalid_int <= '0'; - m_axis_tlast <= '0'; ELSE - m_axis_tlast <= '0'; - - IF m_axis_tready = '1' THEN - m_axis_tvalid_int <= '0'; - END IF; - - CASE state IS - WHEN IDLE => - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - state <= SENDING_HEADER; - END IF; - - WHEN SENDING_HEADER => - IF m_axis_tvalid_int = '0' OR m_axis_tready = '1' THEN - m_axis_tvalid_int <= '1'; - m_axis_tdata <= STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)); - - state <= SENDING_DATA; - END IF; - - WHEN SENDING_DATA => - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - IF s_axis_tlast = '1' THEN - last_seen <= '1'; - END IF; - - trigger := '1'; - END IF; - - IF last_seen = '1' THEN - state <= SENDING_FOOTER; - last_seen <= '0'; - - trigger := '1'; - END IF; - - WHEN SENDING_FOOTER => - IF m_axis_tvalid_int = '0' OR m_axis_tready = '1' THEN - m_axis_tvalid_int <= '1'; - m_axis_tlast <= '1'; - m_axis_tdata <= STD_LOGIC_VECTOR(to_unsigned(FOOTER, 8)); - - state <= IDLE; - END IF; - - END CASE; - - -- Output data - master - IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN - m_axis_tvalid_int <= '1'; - m_axis_tdata <= data_buffer; - - trigger := '0'; - END IF; - -- Input data - slave s_axis_tready_int <= m_axis_tready; @@ -117,6 +63,52 @@ BEGIN data_buffer <= s_axis_tdata; END IF; + -- Output data - master + IF m_axis_tready = '1' THEN + m_axis_tvalid_int <= '0'; + END IF; + + IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tvalid_int <= '1'; + m_axis_tdata <= data_buffer; + + trigger <= '0'; + END IF; + + -- State machine for packetization + CASE state IS + + WHEN SENDING_HEADER => + IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN + m_axis_tdata <= STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)); -- Prepare header + m_axis_tvalid_int <= '1'; --Send header + + trigger <= '1'; + state <= STREAMING; + END IF; + + WHEN STREAMING => + IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN + IF s_axis_tlast = '1' THEN + s_axis_tready_int <= '0'; -- Block the slave interface to avoid data loss + state <= SENDING_FOOTER; + END IF; + + trigger <= '1'; + END IF; + + WHEN SENDING_FOOTER => + IF m_axis_tvalid_int = '0' OR m_axis_tready = '1' THEN + s_axis_tready_int <= '0'; -- Block the slave interface to avoid data loss + + data_buffer <= STD_LOGIC_VECTOR(to_unsigned(FOOTER, 8)); -- Send footer + m_axis_tvalid_int <= '1'; + + trigger <= '1'; + state <= SENDING_HEADER; + END IF; + + END CASE; END IF; END IF; diff --git a/LAB2/vivado/packetizer_test/packetizer_test.xpr b/LAB2/vivado/packetizer_test/packetizer_test.xpr new file mode 100644 index 0000000..092d185 --- /dev/null +++ b/LAB2/vivado/packetizer_test/packetizer_test.xpr @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vivado Synthesis Defaults + + + + + + + + + + + Default settings for Implementation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default_dashboard + + + diff --git a/LAB2/vivado/packetizer_test/tb_packetizer_behav.wcfg b/LAB2/vivado/packetizer_test/tb_packetizer_behav.wcfg new file mode 100644 index 0000000..74e1646 --- /dev/null +++ b/LAB2/vivado/packetizer_test/tb_packetizer_behav.wcfg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + mem[0:7][7:0] + mem[0:7][7:0] + + + clk + clk + + + aresetn + aresetn + + + state + state + #00FFFF + true + + + data_buffer[7:0] + data_buffer[7:0] + + + s_axis + label + + + s_axis_tdata[7:0] + s_axis_tdata[7:0] + + + s_axis_tvalid + s_axis_tvalid + + + s_axis_tready + s_axis_tready + #FFD700 + true + + + s_axis_tlast + s_axis_tlast + #0000FF + true + + + m_axis + label + + + m_axis_tdata[7:0] + m_axis_tdata[7:0] + + + m_axis_tvalid + m_axis_tvalid + + + m_axis_tready + m_axis_tready + #FFD700 + true + + + m_axis_tlast + m_axis_tlast + #0000FF + true + +