---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 09/30/2025 05:40:20 PM -- Design Name: -- Module Name: eth_frame_packer - Behavioral -- Project Name: -- Target Devices: -- Tool Versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity eth_frame_packer is port ( clk : in std_logic; resetn : in std_logic; pause : in std_logic := '0'; cfg_dst_mac : in std_logic_vector(47 downto 0); -- DA cfg_src_mac : in std_logic_vector(47 downto 0); -- SA cfg_eth_type : in std_logic_vector(15 downto 0); -- EtherType/Length -- AXIS payload in (512-bit, 64B beats; multiples of 64B, aligned) s_axis_tdata : in std_logic_vector(511 downto 0); s_axis_tvalid : in std_logic; s_axis_tready : out std_logic; s_axis_tlast : in std_logic; -- AXIS to CMAC TX client (512-bit) m_axis_tdata : out std_logic_vector(511 downto 0); m_axis_tkeep : out std_logic_vector(63 downto 0); m_axis_tvalid : out std_logic; m_axis_tready : in std_logic; m_axis_tlast : out std_logic; m_axis_tuser : out std_logic; -- error flag to CMAC tx_cnt : out std_logic_vector(31 downto 0); underrun_cnt : out std_logic_vector(31 downto 0) := (others => '0') ); end entity; architecture rtl of eth_frame_packer is --------------------------------------------------------------------------- -- Functions (VHDL-93 safe) --------------------------------------------------------------------------- function mk_header( da : std_logic_vector(47 downto 0); sa : std_logic_vector(47 downto 0); ety : std_logic_vector(15 downto 0) ) return std_logic_vector is variable h : std_logic_vector(111 downto 0); begin -- DA [0..5] h( 7 downto 0) := da(47 downto 40); h( 15 downto 8) := da(39 downto 32); h( 23 downto 16) := da(31 downto 24); h( 31 downto 24) := da(23 downto 16); h( 39 downto 32) := da(15 downto 8); h( 47 downto 40) := da( 7 downto 0); -- SA [6..11] h( 55 downto 48) := sa(47 downto 40); h( 63 downto 56) := sa(39 downto 32); h( 71 downto 64) := sa(31 downto 24); h( 79 downto 72) := sa(23 downto 16); h( 87 downto 80) := sa(15 downto 8); h( 95 downto 88) := sa( 7 downto 0); -- Type/Len [12..13] h(103 downto 96) := ety(15 downto 8); h(111 downto 104) := ety( 7 downto 0); return h; end function; --------------------------------------------------------------------------- -- --------------------------------------------------------------------------- type state_type is (IDLE, RUN, FLUSH); signal state : state_type; signal state_r : state_type := IDLE; signal carry_r : std_logic_vector(111 downto 0) := (others => '0'); signal carry : std_logic_vector(111 downto 0); signal m_tdata_r : std_logic_vector(511 downto 0) := (others => '0'); signal m_tdata : std_logic_vector(511 downto 0); signal m_tkeep_r : std_logic_vector(63 downto 0) := (others => '1'); signal m_tkeep : std_logic_vector(63 downto 0); signal m_tlast_r : std_logic := '0'; signal m_tlast : std_logic; signal m_tvalid_r : std_logic := '0'; signal m_tvalid : std_logic; signal m_tuser_r : std_logic := '0'; signal m_tuser : std_logic; signal header : std_logic_vector(111 downto 0); signal underrun_cnt_r : std_logic_vector(31 downto 0) := (others => '0'); signal tx_cnt_r : std_logic_vector(31 downto 0) := (others => '0'); begin header <= mk_header(cfg_dst_mac, cfg_src_mac, cfg_eth_type); --------------------------------------------------------------------------- -- Drive Outputs --------------------------------------------------------------------------- m_axis_tuser <= m_tuser_r; m_axis_tdata <= m_tdata_r; m_axis_tkeep <= m_tkeep_r; m_axis_tlast <= m_tlast_r; m_axis_tvalid <= m_tvalid_r; underrun_cnt <= underrun_cnt_r; tx_cnt <= tx_cnt_r; --------------------------------------------------------------------------- -- Combinational next-state / next-data --------------------------------------------------------------------------- process(state_r, carry_r, s_axis_tlast, s_axis_tvalid, m_axis_tready, m_tvalid_r, m_tdata_r, m_tkeep_r, m_tlast_r, m_tuser_r, header, s_axis_tdata, pause) begin -- Defaults state <= state_r; carry <= carry_r; m_tdata <= m_tdata_r; m_tkeep <= m_tkeep_r; m_tlast <= m_tlast_r; m_tuser <= m_tuser_r; m_tvalid <= m_tvalid_r; s_axis_tready <= '0'; case state_r is ----------------------------------------------------------------------- when IDLE => --s_axis_tready <= m_axis_tready or not(m_tvalid_r); --m_tvalid <= (s_axis_tvalid = '1' and (m_axis_tready = '1' or m_tvalid_r = '0')) or (not(m_axis_tready) and m_tvalid_r); if(m_axis_tready = '1')then m_tvalid <= '0'; end if; if (s_axis_tvalid = '1' and (m_axis_tready = '1' or m_tvalid_r = '0') and pause = '0') then s_axis_tready <= '1'; -- Emit first beat = [14B header] ++ [first 50B payload] m_tdata <= s_axis_tdata(399 downto 0) & header; m_tkeep <= (others => '1'); m_tvalid <= '1'; m_tuser <= '0'; m_tlast <= '0'; -- Next carry = bytes 50..63 carry <= s_axis_tdata(511 downto 400); if s_axis_tlast = '1' then state <= FLUSH; else state <= RUN; end if; end if; ----------------------------------------------------------------------- when RUN => s_axis_tready <= m_axis_tready; if(s_axis_tvalid = '0')then m_tuser <= '1'; -- s_axis_tvalid must be '1' or else this is an error condition, tx data underrun. end if; if (m_axis_tready = '1') then -- Steady-state emit = [prev carry 14B] ++ [new payload 0..49] m_tdata <= s_axis_tdata(399 downto 0) & carry_r; --m_tkeep <= (others => '1'); --m_tvalid <= '1'; --m_tlast <= '0'; -- Next carry = bytes 50..63 carry <= s_axis_tdata(511 downto 400); if s_axis_tlast = '1' then state <= FLUSH; else state <= RUN; end if; end if; ----------------------------------------------------------------------- when FLUSH => --s_axis_tready <= '0'; -- if(s_axis_tvalid = '0')then -- m_tuser <= '1'; -- end if; if (m_axis_tready = '1') then -- Emit the final 14B tail m_tdata <= std_logic_vector(to_unsigned(0, 400)) & carry_r; m_tkeep <= x"0000000000003FFF"; m_tlast <= '1'; --m_tvalid <= '1'; state <= IDLE; end if; --when others => end case; end process; --------------------------------------------------------------------------- -- Registers --------------------------------------------------------------------------- seq_proc : process(clk) begin if rising_edge(clk) then if resetn = '0' then state_r <= IDLE; m_tvalid_r <= '0'; underrun_cnt_r <= (others => '0'); tx_cnt_r <= (others => '0'); else state_r <= state; m_tvalid_r <= m_tvalid; if(m_tlast_r = '1' and m_tvalid_r = '1' and m_tuser_r = '1' and m_axis_tready = '1')then underrun_cnt_r <= std_logic_vector(unsigned(underrun_cnt_r) +1); end if; if(m_tlast_r = '1' and m_tvalid_r = '1' and m_axis_tready = '1')then tx_cnt_r <= std_logic_vector(unsigned(tx_cnt_r) +1); end if; end if; carry_r <= carry; m_tdata_r <= m_tdata; m_tkeep_r <= m_tkeep; m_tlast_r <= m_tlast; m_tuser_r <= m_tuser; end if; end process; end architecture;