From ef6b6378f89fe17e033c623a470cdcf375d3f2ec Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sun, 16 Jan 2022 14:44:43 +0100 Subject: [PATCH] mac: tx: Implement automatic padding This also renames the bit_cnt signal to sr_cnt. 97d0905c08549e7e60a1d862360258f777dd5691 was kinda BS. This fixes #4. --- trashernet/trashernet_mac.vhd | 50 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/trashernet/trashernet_mac.vhd b/trashernet/trashernet_mac.vhd index 5e88559..0dc4649 100644 --- a/trashernet/trashernet_mac.vhd +++ b/trashernet/trashernet_mac.vhd @@ -32,7 +32,8 @@ entity trashernet_mac is end entity trashernet_mac; architecture rtl of trashernet_mac is - constant ETH_POLYNOMIAL : std_logic_vector(31 downto 0) := x"04C11DB7"; + constant ETH_POLYNOMIAL : std_logic_vector(31 downto 0) := x"04C11DB7"; + constant ETH_FRAME_MIN_LENGTH : integer := 64; begin rx : block @@ -134,12 +135,14 @@ begin end block rx; tx : block - type tx_state_t is (IDLE, HEADER, DATA, TXCRC); + type tx_state_t is (IDLE, HEADER, DATA, PAD, TXCRC); signal tx_state : tx_state_t; - signal sr : byte_vector(0 to mac_in.tx_header.mac_destination'length + mac_in.tx_header.mac_source'length + mac_in.tx_header.mac_ethertype'length - 1); - constant BIT_CNT_MAX : integer := sr'high; - signal bit_cnt : integer range 0 to BIT_CNT_MAX; + signal sr : byte_vector(0 to mac_in.tx_header.mac_destination'length + mac_in.tx_header.mac_source'length + mac_in.tx_header.mac_ethertype'length - 1); + constant SR_CNT_MAX : integer := sr'high; + signal sr_cnt : integer range 0 to SR_CNT_MAX; + constant BYTE_CNT_MAX : integer := ETH_FRAME_MIN_LENGTH - 4; -- Minus four because the CRC is *after* the PAD + signal byte_cnt : integer range 0 to BYTE_CNT_MAX; signal crc : std_logic_vector(ETH_POLYNOMIAL'range); signal crc_clear : std_logic; @@ -173,40 +176,49 @@ begin if phy_out.tx_data_ack then sr <= sr(sr'low + 1 to sr'high) & x"00"; crc_valid <= '1'; - if bit_cnt /= 0 then - bit_cnt <= bit_cnt - 1; + if sr_cnt /= 0 then + sr_cnt <= sr_cnt - 1; + end if; + if byte_cnt /= 0 then + byte_cnt <= byte_cnt - 1; end if; end if; case tx_state is - when IDLE => + when IDLE => -- Idle + prepare sync header if not phy_out.tx_active and mac_in.tx_mac_data_en then sr(0 to 7) <= byte_vector'(0 to 6 => x"55", 7 => x"D5"); - bit_cnt <= 7; + sr_cnt <= 7; tx_state <= HEADER; end if; - when HEADER => - if (phy_out.tx_data_ack = '1') and (bit_cnt = 0) then -- Sync Header TX complete + when HEADER => -- Wait for sync header + prepare MAC header + if (phy_out.tx_data_ack = '1') and (sr_cnt = 0) then -- Sync Header TX complete sr <= mac_in.tx_header.mac_destination & mac_in.tx_header.mac_source & mac_in.tx_header.mac_ethertype; crc_valid <= '1'; - bit_cnt <= BIT_CNT_MAX; + sr_cnt <= SR_CNT_MAX; tx_state <= DATA; end if; + byte_cnt <= BYTE_CNT_MAX; - when DATA => - if (phy_out.tx_data_ack = '1') and (bit_cnt = 0) then -- MAC Header TX complete + when DATA => -- Wait for MAC header + transmit payload until tx_mac_data_en goes away + if (phy_out.tx_data_ack = '1') and (sr_cnt = 0) then -- MAC Header TX complete if mac_in.tx_mac_data_en then sr(0) <= mac_in.tx_mac_data; mac_out.tx_mac_data_ack <= '1'; else - sr(0 to 3) <= (crc(7 downto 0), crc(15 downto 8), crc(23 downto 16), crc(31 downto 24)); - bit_cnt <= 4 - 1; - tx_state <= TXCRC; + tx_state <= PAD; end if; end if; - when TXCRC => - if (phy_out.tx_data_ack = '1') and (bit_cnt = 0) then -- CRC TX complete + when PAD => -- Wait for PADs / last payload byte + prepare CRC + if (byte_cnt = 0) then + sr(0 to 3) <= (crc(7 downto 0), crc(15 downto 8), crc(23 downto 16), crc(31 downto 24)); + sr_cnt <= 4 - 1; + tx_state <= TXCRC; + end if; + + when TXCRC => -- Wait for CRC + jump back to idle + if (phy_out.tx_data_ack = '1') and (sr_cnt = 0) then -- CRC TX complete tx_state <= IDLE; end if; end case;