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

Subversion Repositories etherlab

[/] [etherlab/] [trunk/] [vhdl/] [mac_rcv.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.common.all;
 
entity mac_rcv is
   port(
      E_RX_CLK : in  std_logic;                      -- Receiver Clock.
      E_RX_DV  : in  std_logic;                      -- Received Data Valid.
      E_RXD    : in  std_logic_vector(3 downto 0);   -- Received Nibble.
      el_chnl  : out std_logic_vector(7 downto 0);   -- EtherLab channels.
      el_data  : out data_t;                         -- EtherLab channel data.
      el_dv    : out std_logic;                      -- EtherLab data valid.
      el_ack   : in  std_logic                       -- Packet reception ACK.
   );
end mac_rcv;
 
architecture rtl of mac_rcv is
 
   type state_t is (
      Preamble, StartOfFrame,             -- 7 Bytes 0x55, 1 Byte 0x5d.
      MACS,                               -- 12 Byte MAC addresses.
      EtherTypeCheck,                     -- Next Protocol EtherLab?
      Version,                            -- EtherLab - Version.
      Channel,                            -- EtherLab - Channel.
      DataU, DataL,                       -- EtherLab - Channel data.
      Notify                              -- Inform other hardware components.
   );
 
   type rcv_t is record
      s    : state_t;
      chnl : std_logic_vector(7 downto 0);   -- EtherLab channel field.
      d    : data_t;                         -- Channel data.
      c    : natural range 0 to 23;
      a    : natural range 0 to 7;
   end record;
 
   signal r, rin : rcv_t 
      := rcv_t'(Preamble, x"00", (others => (others => '0')), 0, 0);
begin
 
   rcv_nsl : process(r, E_RX_DV, E_RXD, el_ack)
   begin
 
      rin   <= r;
      el_dv <= '0';
 
      if E_RX_DV = '1' then
         case r.s is
 
            --------------------------------------------------------------------
            -- Ethernet II - Preamble and Start Of Frame.                     --
            --------------------------------------------------------------------
            when Preamble =>
               if E_RXD = x"5" then
                  if r.c = 14 then
                     rin.c <= 0;
                     rin.s <= StartOfFrame;
                  else
                     rin.c <= r.c + 1;
                  end if;
               else
                  rin.c <= 0;
               end if;
 
            when StartOfFrame =>
               if E_RXD = x"d" then
                  rin.s <= MACS;
               else
                  rin.s <= Preamble;
               end if;
 
            --------------------------------------------------------------------
            -- Ethernet II - 12 Byte MAC addresses.                           --
            --------------------------------------------------------------------
            when MACS =>
               if r.c = 23 then
                  rin.c <= 0;
                  rin.s <= EtherTypeCheck;
               else
                  rin.c <= r.c + 1;
               end if;
 
            --------------------------------------------------------------------
            -- Ethernet II - Next Layer EtherLab?                             --
            --------------------------------------------------------------------
            when EtherTypeCheck =>
               if E_RXD = x"0" then
                  if r.c = 3 then
                     rin.c <= 0;
                     rin.s <= Version;
                  else
                     rin.c <= r.c + 1;
                  end if;
               else
                  rin.c <= 0;
                  rin.s <= Preamble;
               end if;
 
            --------------------------------------------------------------------
            -- EtherLab - Version                                             --
            --------------------------------------------------------------------
            when Version =>
               if r.c = 1 then
                  rin.c <= 0;
                  rin.s <= Channel;
               else
                  rin.c <= r.c + 1;
               end if;
 
            --------------------------------------------------------------------
            -- EtherLab - Channel Flags.                                       --
            --------------------------------------------------------------------
            when Channel =>
               rin.chnl(7 downto 0) <= E_RXD & r.chnl(7 downto 4);
               if r.c = 1 then
                  rin.c <= 0;
                  rin.a <= 0;
                  rin.s <= DataU;
               else
                  rin.c <= r.c + 1;
               end if;
 
            --------------------------------------------------------------------
            -- EtherLab - Data. 8 channels á 16 bit.                          --
            --------------------------------------------------------------------
            when DataU =>
               rin.d(r.a)(15 downto 8) <= E_RXD & r.d(r.a)(15 downto 12);
               if r.c = 1 then
                  rin.c <= 0;
                  rin.s <= DataL;
               else
                  rin.c <= r.c + 1;
               end if;
 
            when DataL =>
               rin.d(r.a)(7 downto 0) <= E_RXD & r.d(r.a)(7 downto 4);
               if r.c = 1 then
                  rin.c <= 0;
                  if r.a = 7 then
                     rin.a <= 0;
                     rin.s <= Notify;
                  else
                     rin.a <= r.a + 1;
                     rin.s <= DataU;
                  end if;
               else
                  rin.c <= r.c + 1;
               end if;
 
            --------------------------------------------------------------------
            -- Notification                                                   --
            --------------------------------------------------------------------
            when Notify =>
               el_dv <= '1';
               rin.s <= Preamble;
 
         end case;
      end if;
   end process;
 
   snd_reg : process(E_RX_CLK)
   begin
      if rising_edge(E_RX_CLK) then
         r <= rin;
      end if;
   end process;
 
   el_chnl <= r.chnl;
   el_data <= r.d;
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.