259 lines
8.6 KiB
VHDL
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;
|
|
|