---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 01:28:13 01/29/2011 -- Design Name: -- Module Name: EthernetTXWrapped - EthernetTransmitter -- 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.STD_LOGIC_UNSIGNED.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity EthernetTXWrapped is port ( clk : in std_logic; tx_clk : in std_logic; rst : in std_logic; ethTXStart : in std_logic; ethTXBusy : out std_logic; ethTXDone : out std_logic; ethTXLength : in std_logic_vector(15 downto 0); ethTXProtocol : in std_logic_vector (15 downto 0); ethTXSrcMAC : in std_logic_vector (47 downto 0); ethTXDstMAC : in std_logic_vector (47 downto 0); ethTXStrobe : out std_logic; ethTXData : in std_logic_vector (7 downto 0); tx_en : out std_logic; txd : out std_logic_vector (3 downto 0) ); end EthernetTXWrapped; architecture EthernetTransmitter of EthernetTXWrapped is component asyncFifo port ( rst: IN std_logic; wr_clk: IN std_logic; rd_clk: IN std_logic; din: IN std_logic_vector(7 downto 0); wr_en: IN std_logic; rd_en: IN std_logic; dout: OUT std_logic_vector(7 downto 0); full: OUT std_logic; empty: OUT std_logic); end component; component ethernetTX port ( tx_clk : in std_logic; rst : in std_logic; ethTXStart : in std_logic; ethTXStrobe : out std_logic; ethTXData : in std_logic_vector(7 downto 0); ethTXDone : out std_logic; tx_en : out std_logic; txd : out std_logic_vector(3 downto 0) ); end component; component taskSync port ( clkA : in std_logic; clkB : in std_logic; rst : in std_logic; taskStartA : in std_logic; taskBusyA : out std_logic; taskDoneA : out std_logic; taskStartB : out std_logic; taskBusyB : out std_logic; taskDoneB : in std_logic ); end component; signal fifoWrite : std_logic; signal fifoIn : std_logic_vector(7 downto 0); signal fifoEmpty, fifoFull : std_logic; signal startRawTX : std_logic; signal doneRawTX : std_logic; signal ethRawTXStart : std_logic; signal ethRawTXData : std_logic_vector(7 downto 0); signal ethRawTXStrobe : std_logic; signal ethRawTXDone : std_logic; type TState is (stIdle, stPushLength, stPushHeader, stHeaderClockDivision, stPushPayload, stPayloadClockDivision, stDone); signal state : TState := stIdle; signal counter : std_logic_vector(15 downto 0); signal payloadLength : std_logic_vector(15 downto 0); signal frameLength : std_logic_vector(15 downto 0); signal dstMAC, srcMAC : std_logic_vector(47 downto 0); signal protocol : std_logic_vector(15 downto 0); signal clockDivider : std_logic_vector(1 downto 0); begin fifo : asyncFifo port map ( rst => rst, wr_clk => clk, rd_clk => tx_clk, din => fifoIn, wr_en => fifoWrite, rd_en => ethRawTXStrobe, dout => ethRawTXData, full => fifoFull, empty => fifoEmpty); ethernetTXRaw : ethernetTX port map ( tx_clk => tx_clk, rst => rst, ethTXStart => ethRawTXStart, ethTXStrobe => ethRawTXStrobe, ethTXData => ethRawTXData, ethTXDone => ethRawTXDone, tx_en => tx_en, txd => txd ); sync : taskSync port map ( clkA => clk, clkB => tx_clk, rst => rst, taskStartA => startRawTX, taskBusyA => open, taskDoneA => doneRawTX, taskStartB => ethRawTXStart, taskBusyB => open, taskDoneB => ethRawTXDone ); process (clk, rst) begin if rst = '1' then state <= stIdle; fifoWrite <= '0'; srcMAC <= (others => '0'); dstMAC <= (others => '0'); protocol <= (others => '0'); payloadLength <= (others => '0'); frameLength <= (others => '0'); ethTXStrobe <= '0'; counter <= x"0000"; ethTXBusy <= '0'; ethTXDone <= '0'; elsif rising_edge(clk) then fifoWrite <= '1'; state <= state; protocol <= protocol; dstMAC <= dstMAC; srcMAC <= srcMAC; frameLength <= frameLength; payloadLength <= payloadLength; startRawTX <= '0'; ethTXStrobe <= '0'; ethTXBusy <= '1'; ethTXDone <= '0'; clockdivider <= clockdivider; counter <= counter; case state is when stIdle => fifoWrite <= '0'; ethTXBusy <= '0'; if ethTXStart = '1' then state <= stPushLength; payloadLength <= ethTXLength; frameLength <= ethTXLength + 14; dstMAC <= ethTXDstMAC; srcMAC <= ethTXSrcMAC; protocol <= ethTXProtocol; counter <= x"0000"; end if; when stPushLength => case counter(0) is when '0' => fifoIn <= frameLength(15 downto 8); counter(0) <= '1'; when '1' => fifoIn <= frameLength(7 downto 0); counter(0) <= '0'; state <= stPushHeader; when others => end case; when stPushHeader => counter <= counter + 1; clockdivider <= "00"; state <= stHeaderClockDivision; case counter(3 downto 0) is when x"0" => fifoIn <= dstMAC(47 downto 40); when x"1" => fifoIn <= dstMAC(39 downto 32); when x"2" => fifoIn <= dstMAC(31 downto 24); -- lets start actual TX here. We push data with the -- quadruple rate -- we must hope that tx starts early enough so that -- clock division can kick in at the right time startRawTX <= '1'; when x"3" => fifoIn <= dstMAC(23 downto 16); when x"4" => fifoIn <= dstMAC(15 downto 8); when x"5" => fifoIn <= dstMAC(7 downto 0); when x"6" => fifoIn <= srcMAC(47 downto 40); when x"7" => fifoIn <= srcMAC(39 downto 32); when x"8" => fifoIn <= srcMAC(31 downto 24); when x"9" => fifoIn <= srcMAC(23 downto 16); when x"A" => fifoIn <= srcMAC(15 downto 8); when x"B" => fifoIn <= srcMAC(7 downto 0); when x"C" => fifoIn <= protocol(15 downto 8); when x"D" => fifoIn <= protocol(7 downto 0); counter <= payloadLength; state <= stPushPayload; ethTXStrobe <= '1'; when others => end case; when stHeaderClockDivision => clockdivider <= clockdivider + 1; fifoWrite <= '0'; if clockdivider = "10" then state <= stPushHeader; end if; when stPushPayload => state <= stPayloadClockDivision; clockdivider <= "00"; counter <= counter - 1; if counter = x"0000" then state <= stDone; fifoWrite <= '0'; elsif counter = x"0001" then fifoIn <= counter(7 downto 0); state <= stPushPayload; else fifoIn <= counter(7 downto 0); end if; when stPayloadClockDivision => fifoWrite <= '0'; clockdivider <= clockdivider + 1; if clockdivider = "10" then state <= stPushPayload; ethTXStrobe <= '1'; end if; when stDone => fifoWrite <= '0'; if doneRawTX = '1' then ethTXDone <= '1'; state <= stIdle; end if; end case; end if; end process; end EthernetTransmitter;