OpenCores
URL https://opencores.org/ocsvn/etherlab/etherlab/trunk

Subversion Repositories etherlab

[/] [etherlab/] [trunk/] [vhdl/] [mac_snd.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
-- ETHERLAB - FPGA To C# To LABVIEW Bridge                                    --
--------------------------------------------------------------------------------
-- REFERENCES                                                                 --
--  [1] http://tools.ietf.org/html/rfc2460                                    --
--  [2] https://en.wikipedia.org/wiki/Ethernet_frame                          --
--  [5] http://outputlogic.com/my-stuff/circuit-cellar-january-2010-crc.pdf   --
--  [6] OPB Ethernet Lite Media Access Controller (v1.01b)                    --
--  [7] LAN83C185 - 10/100 Ethernet PHY                                       --
--  [8] Xilinx UG230                                                          --
--------------------------------------------------------------------------------
-- Copyright (C)2012  Mathias Hörtnagl <mathias.hoertnagl@gmail.com>          --
--                                                                            --
-- This program is free software: you can redistribute it and/or modify       --
-- it under the terms of the GNU General Public License as published by       --
-- the Free Software Foundation, either version 3 of the License, or          --
-- (at your option) any later version.                                        --
--                                                                            --
-- This program is distributed in the hope that it will be useful,            --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              --
-- GNU General Public License for more details.                               --
--                                                                            --
-- You should have received a copy of the GNU General Public License          --
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.      --
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library work;
use work.PCK_CRC32_D4.all;
use work.common.all;
 
entity mac_snd is
   port(     
      E_TX_CLK : in  std_logic;                       -- Sender Clock.
      E_TX_EN  : out std_logic;                       -- Sender Enable.
      E_TXD    : out std_logic_vector(3 downto 0);    -- Sent Data.
      E_TX_ER  : out std_logic;                       -- Sent Data Error.
      el_chnl  : in  std_logic_vector(7 downto 0);    -- EtherLab channels.
      el_data  : in  data_t;                          -- EtherLab data.
      en       : in  std_logic                        -- User Start Send. 
   );
end mac_snd;
 
architecture rtl of mac_snd is
 
   type mem_t is array(0 to 14) of std_logic_vector(7 downto 0);
 
   signal mem : mem_t := (
      --------------------------------------------------------------------------
      -- Host PC MAC Address                                                  --
      --------------------------------------------------------------------------
      -- 0x0 - 0x5
      x"00", x"1f", x"16", x"01", x"95", x"5a",
 
      --------------------------------------------------------------------------
      -- FPGA MAC Address (Xilinx OUI)                                        --
      --------------------------------------------------------------------------
      -- 0x6 - 0xb
      x"00", x"0a", x"35", x"00", x"00", x"00",
 
      --------------------------------------------------------------------------
      -- EtherType Field: 0x0000 (EtherLab)                                   --
      --------------------------------------------------------------------------
      -- 0xc - 0xd
      x"00", x"00",
 
      --------------------------------------------------------------------------
      -- EtherLab Header                                                      --
      --------------------------------------------------------------------------
      -- EtherLab Version. 
      -- Hardware returns Version 2 packets to distinguish them from Version 1 
      -- packets sent by the host who captures in promiscuous mode only. This
      -- would cause the host to read it's own Version 1 packets as well.
      -- 0xe
      x"02"
   );
 
   attribute RAM_STYLE : string;
   attribute RAM_STYLE of mem: signal is "BLOCK";
 
   type state_t is (
      Idle,                      -- Wait for signal en.
      Preamble,                  -- 55 55 55 55 55 55 55 5
      StartOfFrame,              -- d
      Upper,                     -- Send upper Nibble.
      Lower,                     -- Send lower Nibble.
      Channel,                   -- Send EtherLab channel.
      DataU, DataL,              -- Send EtherLab data.
      FrameCheck,                -- No Frame Check for now.
      InterframeGap              -- Gap between two cosecutive frames (93 Bit).
   );
 
   type snd_t is record
      s   : state_t;
      crc : std_logic_vector(31 downto 0);   -- CRC32 latch.
      c   : natural range 0 to 63;
      a   : natural range 0 to 7;
   end record;
 
   signal s, sin : snd_t := snd_t'(Idle, x"ffffffff", 0, 0);  
begin
 
   snd_nsl : process(s, mem, en, el_chnl, el_data)
   begin
 
      sin     <= s;
      E_TX_EN <= '0';
      E_TXD   <= x"0";     
      E_TX_ER <= '0';
 
      case s.s is
         when Idle =>
            if en = '1' then
               sin.c <= 0;
               sin.s <= Preamble;
            end if;
 
         -----------------------------------------------------------------------
         -- Ethernet II - Preamble and Start Of Frame.                        --
         -----------------------------------------------------------------------            
         when Preamble =>
            E_TXD   <= x"5";
            E_TX_EN <= '1';
            if s.c = 14 then
               sin.c <= 0;
               sin.s <= StartOfFrame;
            else
               sin.c <= s.c + 1;
            end if;
 
         when StartOfFrame =>
            E_TXD   <= x"d";
            E_TX_EN <= '1';
            sin.crc <= x"ffffffff";
            sin.s   <= Upper;
 
         -----------------------------------------------------------------------
         -- Custom Protocol Transmit.                                         --
         -----------------------------------------------------------------------            
         when Upper =>
            E_TXD   <= mem(s.c)(3 downto 0);
            E_TX_EN <= '1';
            sin.crc <= nextCRC32_D4(mem(s.c)(3 downto 0), s.crc);
            sin.s   <= Lower;
 
         when Lower =>
            E_TXD   <= mem(s.c)(7 downto 4);
            E_TX_EN <= '1';
            sin.crc <= nextCRC32_D4(mem(s.c)(7 downto 4), s.crc);   
            if s.c = 14 then
               sin.c <= 0;
               sin.s <= Channel;
            else
               sin.c <= s.c + 1;
               sin.s <= Upper;
            end if;            
 
         -----------------------------------------------------------------------
         -- EtherLab - Channel Flags.                                         --
         -----------------------------------------------------------------------
         when Channel =>
            E_TXD   <= el_chnl(4*s.c+3 downto 4*s.c);
            E_TX_EN <= '1';
            sin.crc <= nextCRC32_D4(el_chnl(4*s.c+3 downto 4*s.c), s.crc);  
            if s.c = 1 then
               sin.c <= 0;
               sin.a <= 0;
               sin.s <= DataU;
            else
               sin.c <= s.c + 1;
            end if;
 
         -----------------------------------------------------------------------
         -- EtherLab - Data. 8 channels á 16 bit.                             --
         -----------------------------------------------------------------------
         when DataU =>
            E_TXD   <= el_data(s.a)(4*s.c+11 downto 4*s.c+8);
            E_TX_EN <= '1';
            sin.crc <= nextCRC32_D4(el_data(s.a)(4*s.c+11 downto 4*s.c+8), s.crc); 
            if s.c = 1 then
               sin.c <= 0;
               sin.s <= DataL;
            else
               sin.c <= s.c + 1;
            end if;            
 
         when DataL =>
            E_TXD   <= el_data(s.a)(4*s.c+3 downto 4*s.c);
            E_TX_EN <= '1';
            sin.crc <= nextCRC32_D4(el_data(s.a)(4*s.c+3 downto 4*s.c), s.crc); 
            if s.c = 1 then
               sin.c <= 0;
               if s.a = 7 then
                  sin.a <= 0;
                  sin.s <= FrameCheck;
               else
                  sin.a <= s.a + 1;
                  sin.s <= DataU;
               end if;
            else
               sin.c <= s.c + 1;
            end if;
 
         -----------------------------------------------------------------------
         -- Ethernet II - Frame Check.                                        --
         -----------------------------------------------------------------------            
         when FrameCheck =>
            E_TXD   <= not s.crc(4*s.c+3 downto 4*s.c);
            E_TX_EN <= '1';
            if s.c = 7 then
               sin.c <= 0;
               sin.s <= InterframeGap;
            else
               sin.c <= s.c + 1;
            end if;
 
         -----------------------------------------------------------------------
         -- Ethernet II - Interframe Gap.                                     --
         -----------------------------------------------------------------------            
         when InterframeGap =>
            if s.c = 23 then
               sin.c <= 0;
               sin.s <= Idle;
            else
               sin.c <= s.c + 1;
            end if;
      end case;
   end process;
 
   snd_reg : process(E_TX_CLK)
   begin
      if rising_edge(E_TX_CLK) then
         s <= sin;
      end if;
   end process;
end rtl;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.