GigabitTX

From Hamsterworks Wiki!

Revision as of 04:25, 5 May 2016 by User (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This FPGA Project was completed in May 2016.

Following on from ArtyEthernet, I decided to make the jump to sending data at 'gigabit' speed, this time on the Nexys Video

Four switches control the frequency that packets are sent - from one per second to flat out.

Gigabit test.jpg

Important Note This is just a proof of concept test. It doesn't correctly handle that the PHY can also run at 10Mb/s or 100Mb/s. If you don't see packets, check the speed that your port has negotiated. You may need to disable auto-negotiation on the other end of the cable, fixing the speed at 1Gb/s.

The actual interface is quite different to 100BaseT as RGMII uses a 125MHz clock, and DDR outputs to transfer data to the PHY

Contents

Source

The latest work-in-progress copy is in a GitHub repo at https://github.com/hamsternz/FPGA_GigabitTx

gigabit_test.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: Top level design for sending UDP packets out over the RGMII interface.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

entity gigabit_test is
    Port ( clk100MHz : in    std_logic; -- system clock
           switches  : in    std_logic_vector(3 downto 0);
           
           -- Control signals
           eth_int_b : in    std_logic; -- interrupt
           eth_pme_b : in    std_logic; -- power management event
           eth_rst_b : out   std_logic := '0'; -- reset
           -- Management interface
           eth_mdc   : out   std_logic := '0'; 
           eth_mdio  : inout std_logic := '0';
           -- Receive interface
           eth_rxck  : in    std_logic; 
           eth_rxctl : in    std_logic;
           eth_rxd   : in    std_logic_vector(3 downto 0);
           -- Transmit interface
           eth_txck  : out   std_logic := '0';
           eth_txctl : out   std_logic := '0';
           eth_txd   : out   std_logic_vector(3 downto 0) := (others => '0')
    );
end gigabit_test;

architecture Behavioral of gigabit_test is
    signal max_count     : unsigned(26 downto 0)         := (others => '0');
    signal count         : unsigned(26 downto 0)         := (others => '0');
    signal start_sending : std_logic                     := '0';
    signal reset_counter : unsigned(24 downto 0)         := (others => '0');
    signal debug         : STD_LOGIC_VECTOR (5 downto 0) := (others => '0');
    signal phy_ready     : std_logic                     := '0';
    signal tx_ready_meta : std_logic                     := '0';
    signal tx_ready      : std_logic                     := '0';
    signal ok_to_send    : std_logic                     := '0'; -- change to '1' for simulation
    signal user_data     : std_logic                     := '0';

    component byte_data is
        Port ( clk        : in STD_LOGIC;
               start      : in  STD_LOGIC;
               busy       : out STD_LOGIC;
               data       : out STD_LOGIC_VECTOR (7 downto 0);
               user_data  : out STD_LOGIC;
               data_valid : out STD_LOGIC);
    end component;

    signal raw_byte        : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
    signal raw_byte_valid  : std_logic                     := '0';

    component add_crc32 is
        Port ( clk             : in  STD_LOGIC;
               data_in         : in  STD_LOGIC_VECTOR (7 downto 0);
               data_enable_in  : in  STD_LOGIC;
               data_out        : out STD_LOGIC_VECTOR (7 downto 0);
               data_enable_out : out STD_LOGIC);
    end component;

    signal with_crc        : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
    signal with_crc_valid  : std_logic                     := '0';
    
    component add_preamble is
        Port ( clk             : in  STD_LOGIC;
               data_in         : in  STD_LOGIC_VECTOR (7 downto 0);
               data_enable_in  : in  STD_LOGIC;
               data_out        : out STD_LOGIC_VECTOR (7 downto 0);
               data_enable_out : out STD_LOGIC);
    end component;

    signal fully_framed        : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
    signal fully_framed_valid  : std_logic                     := '0';

    signal dout                : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
    signal doutctl             : STD_LOGIC := '0';
    ATTRIBUTE IOB : STRING ;
    ATTRIBUTE IOB OF dout    : signal IS "TRUE";
    ATTRIBUTE IOB OF doutctl : signal IS "TRUE";

    --------------------------------
    -- Clocking signals 
    -------------------------------- 
    signal clk50MHz    : std_logic;
    signal clk125MHz   : std_logic;
    signal clk125MHz90 : std_logic; -- for the TX clock
    signal clk25MHz    : std_logic;
    signal clkfb       : std_logic;
begin
   ---------------------------------------------------
   -- Strapping signals
   ----------------------------------------------------
   -- No pullups/pulldowns added
 
   ----------------------------------------------------
   -- Data for the packet packet 
   ----------------------------------------------------
data: byte_data port map ( 
      clk        => clk125MHz,
      start      => start_sending,
      busy       => open,
      data       => raw_byte,
      user_data  => user_data,
      Data_valid => raw_byte_valid);

i_add_crc32: add_crc32 port map (
      clk             => clk125MHz,
      data_in         => raw_byte,
      data_enable_in  => raw_byte_valid,
      data_out        => with_crc,
      data_enable_out => with_crc_valid);

i_add_preamble: add_preamble port map (
      clk             => clk125MHz,
      data_in         => with_crc,
      data_enable_in  => with_crc_valid,
      data_out        => fully_framed,
      data_enable_out => fully_framed_valid);
      
   ----------------------------------------------------
   -- Send the data out to the ethernet PHY
   -- But only when it is OK to send after the
   -- PHY has been out of reset for long enough 
   ----------------------------------------------------
send_data_out: process(clk125MHz)
    begin
       if falling_edge(clk125MHz) then
           dout    <= fully_framed;
           doutctl <= fully_framed_valid and ok_to_send;
       end if;
    end process;

   ----------------------------------------------------
   -- DDR output registers 
   ----------------------------------------------------
tx_d0  : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txd(0), C  => clk125MHz, CE => '1', R  => '0', S  => '0', D1 => dout(0), D2 => dout(4));
tx_d1  : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txd(1), C  => clk125MHz, CE => '1', R  => '0', S  => '0', D1 => dout(1), D2 => dout(5));
tx_d2  : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txd(2), C  => clk125MHz, CE => '1', R  => '0', S  => '0', D1 => dout(2), D2 => dout(6));
tx_d3  : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txd(3), C  => clk125MHz, CE => '1', R  => '0', S  => '0', D1 => dout(3), D2 => dout(7));

-- The second bit of this should be tx_enable XOR tx_error, to be in line with the spec.
tx_ctl : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txctl,   C  => clk125MHz, CE => '1', R  => '0', S  => '0', D1 => doutctl, D2 => doutctl);

-- Note that this clock is shifted 90 degrees!
tx_c   : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT         => '0', SRTYPE       => "SYNC")
              port map (Q  => eth_txck,  C  => clk125MHz90, CE => '1', R  => '0', S  => '0', D1 => '1', D2 => '0');
    
monitor_reset_state: process(clk125MHz)
    begin
       if rising_edge(clk125MHz) then
          tx_ready      <= tx_ready_meta;
          tx_ready_meta <= phy_ready;
          if tx_ready = '1' and fully_framed_valid = '0' then
             ok_to_send    <= '1';
          end if;
       end if;
    end process;

    ----------------------------------------
    -- Control reseting the PHY
    ----------------------------------------
control_reset: process(clk125MHz)
    begin
       if rising_edge(clk125MHz) then           
          if reset_counter(reset_counter'high) = '0' then
              reset_counter <= reset_counter + 1;
          end if; 
           eth_rst_b <= reset_counter(reset_counter'high) or reset_counter(reset_counter'high-1);
          phy_ready  <= reset_counter(reset_counter'high);
       end if;
    end process;
    
   -------------------------------------------------------
   -- Generate a 25MHz and 50Mhz clocks from the 100MHz 
   -- system clock 
   ------------------------------------------------------- 
clocking : PLLE2_BASE
   generic map (
      BANDWIDTH          => "OPTIMIZED",
      CLKFBOUT_MULT      => 10,
      CLKFBOUT_PHASE     => 0.0,
      CLKIN1_PERIOD      => 10.0,

      -- CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128)
      CLKOUT0_DIVIDE     => 8,  CLKOUT1_DIVIDE     => 20, CLKOUT2_DIVIDE      => 40, 
      CLKOUT3_DIVIDE     => 8,  CLKOUT4_DIVIDE     => 16, CLKOUT5_DIVIDE      => 16,

      -- CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for each CLKOUT (0.001-0.999).
      CLKOUT0_DUTY_CYCLE => 0.5, CLKOUT1_DUTY_CYCLE => 0.5, CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5, CLKOUT4_DUTY_CYCLE => 0.5, CLKOUT5_DUTY_CYCLE => 0.5,

      -- CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
      CLKOUT0_PHASE      =>  0.0, CLKOUT1_PHASE      => 0.0, CLKOUT2_PHASE      => 0.0,
      CLKOUT3_PHASE      => 90.0, CLKOUT4_PHASE      => 0.0, CLKOUT5_PHASE      => 0.0,

      DIVCLK_DIVIDE      => 1,
      REF_JITTER1        => 0.0,
      STARTUP_WAIT       => "FALSE"
   )
   port map (
      CLKIN1   => CLK100MHz,
      CLKOUT0 => CLK125MHz,   CLKOUT1 => CLK50Mhz,  CLKOUT2 => CLK25MHz,  
      CLKOUT3 => CLK125MHz90, CLKOUT4 => open,      CLKOUT5 => open,
      LOCKED   => open,
      PWRDWN   => '0', 
      RST      => '0',
      CLKFBOUT => clkfb,
      CLKFBIN  => clkfb
   );

 when_to_send: process(clk125MHz) 
    begin  
        if rising_edge(clk125MHz) then
            case switches is
                when "0000" => max_count <= to_unsigned(124_999_999,27);  -- 1 packet per second
                when "0001" => max_count <= to_unsigned( 62_499_999,27);  -- 2 packet per second
                when "0010" => max_count <= to_unsigned( 12_499_999,27);  -- 10 packets per second 
                when "0011" => max_count <= to_unsigned(  6_249_999,27);  -- 20 packet per second
                when "0100" => max_count <= to_unsigned(  2_499_999,27);  -- 50 packets per second 
                when "0101" => max_count <= to_unsigned(  1_249_999,27);  -- 100 packets per second
                when "0110" => max_count <= to_unsigned(    624_999,27);  -- 200 packets per second 
                when "0111" => max_count <= to_unsigned(    249_999,27);  -- 500 packets per second 
                when "1000" => max_count <= to_unsigned(    124_999,27);  -- 1000 packets per second 
                when "1001" => max_count <= to_unsigned(     62_499,27);  -- 2000 packets per second 
                when "1010" => max_count <= to_unsigned(     24_999,27);  -- 5000 packets per second 
                when "1011" => max_count <= to_unsigned(     12_499,27);  -- 10,000 packests per second 
                when "1100" => max_count <= to_unsigned(      6_249,27);  -- 20,000 packets per second
                when "1101" => max_count <= to_unsigned(      2_499,27);  -- 50,000 packets per second 
                when "1110" => max_count <= to_unsigned(      1_249,27);  -- 100,000 packets per second
                when others => max_count <= to_unsigned(          0,27);  -- as fast as possible 152,439 packets
            end case;

            if count = max_count then
                count <= (others => '0');
                start_sending <= '1';
            else
                count <= count + 1;
                start_sending <= '0';
            end if;
        end if;
    end process;

end Behavioral;

byte_data.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: Data for sending an empty UDP packet out over the GMII interface.
--              "user_data" is asserted where you should replace 'byte' with 
--              data that you wish to send.
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity byte_data is
    Port ( clk        : in  STD_LOGIC;
           start      : in  STD_LOGIC;
           busy       : out STD_LOGIC;
           data       : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           user_data  : out STD_LOGIC                     := '0';
           data_valid : out STD_LOGIC                     := '0');
end byte_data;

architecture Behavioral of byte_data is
    constant ip_header_bytes   : integer := 20;
    constant udp_header_bytes  : integer := 8;
    constant data_bytes        : integer := 16+1024;
    constant ip_total_bytes    : integer := ip_header_bytes + udp_header_bytes + data_bytes;
    constant udp_total_bytes   : integer := udp_header_bytes + data_bytes;

    signal counter : unsigned(11 downto 0) := (others => '0');
    
    
    -- Ethernet frame header 
    signal eth_src_mac       : std_logic_vector(47 downto 0) := x"DEADBEEF0123";
    signal eth_dst_mac       : std_logic_vector(47 downto 0) := x"FFFFFFFFFFFF";
    signal eth_type          : std_logic_vector(15 downto 0) := x"0800";

    -- IP header
    signal ip_version        : std_logic_vector( 3 downto 0) := x"4";
    signal ip_header_len     : std_logic_vector( 3 downto 0) := x"5";
    signal ip_dscp_ecn       : std_logic_vector( 7 downto 0) := x"00";
    signal ip_identification : std_logic_vector(15 downto 0) := x"0000";     -- Checksum is optional
    signal ip_length         : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(ip_total_bytes, 16));
    signal ip_flags_and_frag : std_logic_vector(15 downto 0) := x"0000";     -- no flags48 bytes
    signal ip_ttl            : std_logic_vector( 7 downto 0)  := x"80";
    signal ip_protocol       : std_logic_vector( 7 downto 0)  := x"11";
    signal ip_checksum       : std_logic_vector(15 downto 0) := x"0000";   -- Calcuated later on
    signal ip_src_addr       : std_logic_vector(31 downto 0) := x"C0A40140"; -- 192.168.1.64
    signal ip_dst_addr       : std_logic_vector(31 downto 0) := x"FFFFFFFF"; -- 255.255.255.255
    -- for calculating the checksum 
    signal ip_checksum1     : unsigned(31 downto 0) := (others => '0');
    signal ip_checksum2     : unsigned(15 downto 0) := (others => '0');
    
    -- UDP Header
    signal udp_src_port      : std_logic_vector(15 downto 0) := x"1000";     -- port 4096
    signal udp_dst_port      : std_logic_vector(15 downto 0) := x"1000";     -- port 4096
    signal udp_length        : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(udp_total_bytes, 16)); 
    signal udp_checksum      : std_logic_vector(15 downto 0) := x"0000";     -- Checksum is optional, and if presentincludes the data
begin
   ---------------------------------------------
   -- Calutate the TCP checksum using logic
   -- This should all colapse down to a constant
   -- at build-time (example #s found on the web)
   ----------------------------------------------
   --- Step 1) 4500 + 0030 + 4422 + 4000 + 8006 + 0000 + (0410 + 8A0C + FFFF + FFFF) = 0002BBCF (32-bit sum)
   ip_checksum1 <= to_unsigned(0,32) 
                 + unsigned(ip_version & ip_header_len & ip_dscp_ecn)
                 + unsigned(ip_identification)
                 + unsigned(ip_length)
                 + unsigned(ip_flags_and_frag)
                 + unsigned(ip_ttl & ip_protocol)
                 + unsigned(ip_src_addr(31 downto 16))
                 + unsigned(ip_src_addr(15 downto  0))
                 + unsigned(ip_dst_addr(31 downto 16))
                 + unsigned(ip_dst_addr(15 downto  0));
   -- Step 2) 0002 + BBCF = BBD1 = 1011101111010001 (1's complement 16-bit sum, formed by "end around carry" of 32-bit 2's complement sum)
   ip_checksum2 <= ip_checksum1(31 downto 16) + ip_checksum1(15 downto 0);
   -- Step 3) ~BBD1 = 0100010000101110 = 442E (1's complement of 1's complement 16-bit sum)
   ip_checksum  <= NOT std_logic_vector(ip_checksum2);

generate_nibbles: process (clk) 
    begin
        if rising_edge(clk) then
            -- Update the counter of where we are 
            -- in the packet
            if counter /= 0 or start = '1' then
               counter <= counter + 1;
            end if;
            
            -- Note, this uses the current value of counter, not the one assigned above!
            data <= "00000000";
            case counter is 
              -- We pause at 0 count when idle (see below case statement)
              when x"000" => NULL;
              -----------------------------
              -- MAC Header 
              -----------------------------
              -- Ethernet destination
              when x"001" => data <= eth_dst_mac(47 downto 40); data_valid <= '1';
              when x"002" => data <= eth_dst_mac(39 downto 32);
              when x"003" => data <= eth_dst_mac(31 downto 24);
              when x"004" => data <= eth_dst_mac(23 downto 16);
              when x"005" => data <= eth_dst_mac(15 downto  8);
              when x"006" => data <= eth_dst_mac( 7 downto  0);
              -- Ethernet source
              when x"007" => data <= eth_src_mac(47 downto 40);
              when x"008" => data <= eth_src_mac(39 downto 32);
              when x"009" => data <= eth_src_mac(31 downto 24);
              when x"00A" => data <= eth_src_mac(23 downto 16);
              when x"00B" => data <= eth_src_mac(15 downto  8);
              when x"00C" => data <= eth_src_mac( 7 downto  0);
              -- Ether Type 08:00
              when x"00D" => data <= eth_type(15 downto  8);
              when x"00E" => data <= eth_type( 7 downto  0);
              -------------------------
              -- User data packet
              ------------------------------
              -- IPv4 Header
              ----------------------------
              when x"00F" => data <= ip_version & ip_header_len;              
              when x"010" => data <= ip_dscp_ecn( 7 downto  0);
              -- Length of total packet (excludes etherent header and ethernet FCS) = 0x0030
              when x"011" => data <= ip_length(15 downto  8);
              when x"012" => data <= ip_length( 7 downto  0);
              -- all zeros
              when x"013" => data <= ip_identification(15 downto  8);
              when x"014" => data <= ip_identification( 7 downto  0);
              -- No flags, no frament offset.
              when x"015" => data <= ip_flags_and_frag(15 downto  8);
              when x"016" => data <= ip_flags_and_frag( 7 downto  0);
              -- Time to live
              when x"017" => data <= ip_ttl( 7 downto  0);
              -- Protocol (UDP)
              when x"018" => data <= ip_protocol( 7 downto  0);
              -- Header checksum
              when x"019" => data <= ip_checksum(15 downto  8);
              when x"01A" => data <= ip_checksum( 7 downto  0);
              -- source address
              when x"01B" => data <= ip_src_addr(31 downto 24);
              when x"01C" => data <= ip_src_addr(23 downto 16);
              when x"01D" => data <= ip_src_addr(15 downto  8);
              when x"01E" => data <= ip_src_addr( 7 downto  0);
              -- dest address
              when x"01F" => data <= ip_dst_addr(31 downto 24);
              when x"020" => data <= ip_dst_addr(23 downto 16);
              when x"021" => data <= ip_dst_addr(15 downto  8);
              when x"022" => data <= ip_dst_addr( 7 downto  0);
              -- No options in this packet
              
              ------------------------------------------------
              -- UDP/IP Header - from port 4096 to port 4096
              ------------------------------------------------
              -- Source port 4096
              when x"023" => data <= udp_src_port(15 downto  8);
              when x"024" => data <= udp_src_port( 7 downto  0);
              -- Target port 4096
              when x"025" => data <= udp_dst_port(15 downto  8);
              when x"026" => data <= udp_dst_port( 7 downto  0);
              -- UDP Length (header + data) 24 octets
              when x"027" => data <= udp_length(15 downto  8);
              when x"028" => data <= udp_length( 7 downto  0);
              -- UDP Checksum not suppled
              when x"029" => data <= udp_checksum(15 downto  8);
              when x"02A" => data <= udp_checksum( 7 downto  0);
              --------------------------------------------
              -- Finally! 16 bytes of user data (defaults 
              -- to "0000" due to assignement above CASE).
              ---------------------------------------------
              when x"02B" => user_data <= '1';
              when x"02C" => NULL; 
              when x"02D" => NULL; 
              when x"02E" => NULL; 
              when x"02F" => NULL; 
              when x"030" => NULL; 
              when x"031" => NULL; 
              when x"032" => NULL; 
              when x"033" => NULL; 
              when x"034" => NULL; 
              when x"035" => NULL; 
              when x"036" => NULL; 
              when x"037" => NULL; 
              when x"038" => NULL; 
              when x"039" => NULL; 
              when x"03A" => NULL; 
              --------------------------------------------
              -- Ethernet Frame Check Sequence (CRC) will 
              -- be added here, overwriting these nibbles
              --------------------------------------------
              when x"43B" => data_valid <= '0'; user_data <= '0';
              when x"43C" => NULL;
              when x"43D" => NULL;
              when x"43E" => NULL;
              ----------------------------------------------------------------------------------
              -- End of frame - there needs to be at least 20 octets before  sending 
              -- the next packet, (maybe more depending  on medium?) 12 are for the inter packet
              -- gap, 8 allow for the preamble that will be added to the start of this packet.
              --
              -- Note that when the count of 0000 adds one  more nibble, so if start is assigned 
              -- '1' this should be minimum that is  within spec.
              ----------------------------------------------------------------------------------
              when x"451" => counter <= (others => '0'); busy  <= '0';
              when others => data <= "00000000";
            end case;
         end if;    
    end process;
end Behavioral;

add_preamble.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: add_preamble - Behavioral
--
-- Description: Add the required 8 bytes of preamble to the data packet. 
-- 
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity add_preamble is
    Port ( clk             : in  STD_LOGIC;
           data_in         : in  STD_LOGIC_VECTOR (7 downto 0);
           data_enable_in  : in  STD_LOGIC;
           data_out        : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           data_enable_out : out STD_LOGIC                     := '0');
end add_preamble;

architecture Behavioral of add_preamble is
    signal delay_data        : std_logic_vector(8*8-1 downto 0) := (others => '0');
    signal delay_data_enable : std_logic_vector(8-1 downto 0) := (others => '0');
begin

process(clk)
    begin
        if rising_edge(clk) then
            if delay_data_enable(delay_data_enable'high)= '1' then
                -- Passing through data
                data_out        <= delay_data(delay_data'high downto delay_data'high-7);
                data_enable_out <= '1';        
            elsif delay_data_enable(delay_data_enable'high-1)= '1' then
                -- Start Frame Delimiter
                data_out        <= "11010101"; 
                data_enable_out <= '1';
            elsif data_enable_in = '1' then
                -- Preamble nibbles
                data_out        <= "01010101"; 
                data_enable_out <= '1';        
            else
                -- Link idle
                data_out        <= "00000000"; 
                data_enable_out <= '0';                
            end if;
            -- Move the data through the delay line
            delay_data        <= delay_data(delay_data'high-8 downto 0) & data_in;  
            delay_data_enable <= delay_data_enable(delay_data_enable'high-1 downto 0) & data_enable_in;
        end if;
    end process;

end Behavioral;

add_crc32.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: add_crc32 - Behavioral
--
-- Description: Add the required 16 nibbles of preamble to the data packet. 
-- 
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity add_crc32 is
    Port ( clk             : in  STD_LOGIC;
           data_in         : in  STD_LOGIC_VECTOR (7 downto 0);
           data_enable_in  : in  STD_LOGIC;
           data_out        : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           data_enable_out : out STD_LOGIC                     := '0');
end add_crc32;

architecture Behavioral of add_crc32 is
    signal crc               : std_logic_vector(31 downto 0)   := (others => '1');
    signal trailer_left      : std_logic_vector(3 downto 0) := (others => '0');
begin

add_crc_proc: process(clk)
        variable v_crc : std_logic_vector(31 downto 0) := (others => '1');
    begin
        if rising_edge(clk) then
            if data_enable_in = '1' then
                -- Pass the data through
                data_out        <= data_in;
                data_enable_out <= '1';
                -- Flag that we need to output 8 bytes of CRC
                trailer_left    <= (others => '1');
                
                ----------------------------------------
                -- Update the CRC
                --
                -- This uses a variable to make the code 
                -- simple to follow and more compact
                ---------------------------------------- 
                v_crc := crc;
                for i in 0 to 7 loop
                    if data_in(i) = v_crc(31) then
                       v_crc := v_crc(30 downto 0) & '0';
                    else
                       v_crc := (v_crc(30 downto 0)& '0') xor x"04C11DB7";
                    end if;
                end loop;
                crc <= v_crc; 
                
            elsif trailer_left(trailer_left'high)= '1' then
                -- append the CRC
                data_out        <= not (crc(24) & crc(25) & crc(26) & crc(27) & crc(28) & crc(29) & crc(30) & crc(31));
                crc             <= crc(23 downto 0) & "11111111";
                trailer_left    <= trailer_left(trailer_left'high-1 downto 0) & '0';
                data_enable_out <= '1';        
            else
                -- Idle
                data_out        <= "00000000"; 
                data_enable_out <= '0';                
            end if;
        end if;
    end process;
end Behavioral;

nexys_video.xdc

#Clock Signal
set_property -dict { PACKAGE_PIN R4    IOSTANDARD LVCMOS33 } [get_ports { clk100MHz }]; #IO_L13P_T2_MRCC_34 Sch=sysclk
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk100MHz}];

#Switches 
set_property -dict { PACKAGE_PIN E22  IOSTANDARD LVCMOS25 } [get_ports { switches[0] }]; #IO_L22P_T3_16 Sch=sw[0]
set_property -dict { PACKAGE_PIN F21  IOSTANDARD LVCMOS25 } [get_ports { switches[1] }]; #IO_25_16 Sch=sw[1]
set_property -dict { PACKAGE_PIN G21  IOSTANDARD LVCMOS25 } [get_ports { switches[2] }]; #IO_L24P_T3_16 Sch=sw[2]
set_property -dict { PACKAGE_PIN G22  IOSTANDARD LVCMOS25 } [get_ports { switches[3] }]; #IO_L24N_T3_16 Sch=sw[3]

#Ethernet
set_property -dict { PACKAGE_PIN Y14   IOSTANDARD LVCMOS25 } [get_ports { eth_int_b }]; #IO_L6N_T0_VREF_13 Sch=eth_int_b
set_property -dict { PACKAGE_PIN AA16  IOSTANDARD LVCMOS25 } [get_ports { eth_mdc }]; #IO_L1N_T0_13 Sch=eth_mdc
set_property -dict { PACKAGE_PIN Y16   IOSTANDARD LVCMOS25 } [get_ports { eth_mdio }]; #IO_L1P_T0_13 Sch=eth_mdio
set_property -dict { PACKAGE_PIN W14   IOSTANDARD LVCMOS25 } [get_ports { eth_pme_b }]; #IO_L6P_T0_13 Sch=eth_pme_b
set_property -dict { PACKAGE_PIN U7    IOSTANDARD LVCMOS33 } [get_ports { eth_rst_b }]; #IO_25_34 Sch=eth_rst_b
set_property -dict { PACKAGE_PIN V13   IOSTANDARD LVCMOS25 } [get_ports { eth_rxck }]; #IO_L13P_T2_MRCC_13 Sch=eth_rxck
set_property -dict { PACKAGE_PIN W10   IOSTANDARD LVCMOS25 } [get_ports { eth_rxctl }]; #IO_L10N_T1_13 Sch=eth_rxctl
set_property -dict { PACKAGE_PIN AB16  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[0] }]; #IO_L2P_T0_13 Sch=eth_rxd[0]
set_property -dict { PACKAGE_PIN AA15  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[1] }]; #IO_L4P_T0_13 Sch=eth_rxd[1]
set_property -dict { PACKAGE_PIN AB15  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[2] }]; #IO_L4N_T0_13 Sch=eth_rxd[2]
set_property -dict { PACKAGE_PIN AB11  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[3] }]; #IO_L7P_T1_13 Sch=eth_rxd[3]
set_property -dict { PACKAGE_PIN AA14  IOSTANDARD LVCMOS25 } [get_ports { eth_txck }]; #IO_L5N_T0_13 Sch=eth_txck
set_property -dict { PACKAGE_PIN V10   IOSTANDARD LVCMOS25 } [get_ports { eth_txctl }]; #IO_L10P_T1_13 Sch=eth_txctl
set_property -dict { PACKAGE_PIN Y12   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[0] }]; #IO_L11N_T1_SRCC_13 Sch=eth_txd[0]
set_property -dict { PACKAGE_PIN W12   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[1] }]; #IO_L12N_T1_MRCC_13 Sch=eth_txd[1]
set_property -dict { PACKAGE_PIN W11   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[2] }]; #IO_L12P_T1_MRCC_13 Sch=eth_txd[2]
set_property -dict { PACKAGE_PIN Y11   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[3] }]; #IO_L11P_T1_SRCC_13 Sch=eth_txd[3]

Personal tools