Files

259 lines
8.6 KiB
VHDL

----------------------------------------------------------------------------------
-- 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;