⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eth_rx.vhd

📁 The GRLIB IP Library is an integrated set of reusable IP cores, designed for system-on-chip (SOC) de
💻 VHD
字号:
--------------------------------------------------------------------------------- Entity:	eth_rx-- File:        eth_rx.vhd-- Author:      Marko Isomaki-- Description: Ethernet Media Access Controller receiver module-------------------------------------------------------------------------------library ieee;library grlib;library gaisler; use ieee.std_logic_1164.all;use gaisler.ethernet_mac.all; use grlib.stdlib.all;entity eth_rx is  generic(    nsync       : integer := 2);    port(    rst         : in  std_ulogic;    eth_clk     : in  std_ulogic;    eth_rx_in   : in  eth_rx_in_type;    eth_rx_out  : out eth_rx_out_type  );end entity; architecture rtl of eth_rx is  constant maxSize : std_logic_vector(10 downto 0) :=    conv_std_logic_vector(1518,11);  constant minSize : std_logic_vector(10 downto 0) :=    conv_std_logic_vector(64,11);    type rx_state_type is (idle, wait_sfd, data1, data2, errorst, report_status,                         wait_report, check_crc, discard_packet);    type reg_type is record    er              : std_ulogic;    en              : std_ulogic;    rxd             : std_logic_vector(3 downto 0);                     crc             : std_logic_vector(31 downto 0);    sync_start      : std_ulogic;    start           : std_ulogic;    write           : std_ulogic;     done            : std_ulogic;     odd_nibble      : std_ulogic;    byte_count      : std_logic_vector(10 downto 0);    data            : std_logic_vector(31 downto 0);    dataout         : std_logic_vector(31 downto 0);    rx_state        : rx_state_type;    status          : std_logic_vector(2 downto 0);    writeerror      : std_ulogic;    write_ack       : std_logic_vector(nsync downto 0);    done_ack        : std_logic_vector(nsync downto 0);    rxen            : std_logic_vector(1 downto 0);  end record;  signal r, rin : reg_type;begin    comb : process(rst, eth_rx_in, r) is  variable v         : reg_type;  variable index     : integer range 0 to 3;  variable crc_en    : std_ulogic;  variable write_req : std_ulogic;  variable write_ack : std_ulogic;  variable done_ack  : std_ulogic;   variable tc0, tc1, tc2, tc3 : std_ulogic;   begin    v := r; v.rxd := eth_rx_in.rxd; v.en := eth_rx_in.rx_dv;    v.er := eth_rx_in.rx_er; write_req := '0'; crc_en := '0';    index := conv_integer(r.byte_count(1 downto 0));        --synchronization    v.rxen(1) := r.rxen(0); v.rxen(0) := eth_rx_in.rxen;        v.write_ack(0) := eth_rx_in.write_ack;    v.done_ack(0)  := eth_rx_in.done_ack;         if nsync = 2 then      v.write_ack(1) := r.write_ack(0);      v.done_ack(1)  := r.done_ack(0);    end if;    write_ack := r.write_ack(nsync) xor r.write_ack(nsync-1);    done_ack  := r.done_ack(nsync)  xor r.done_ack(nsync-1);    case r.rx_state is    when idle =>      v.writeerror := '0'; v.status := receiveOk;      v.byte_count := (others => '0'); v.odd_nibble := '0';      if (r.en and r.rxen(1)) = '1' then        v.rx_state := wait_sfd; v.sync_start := not r.sync_start;       elsif r.en = '1' then  v.rx_state := discard_packet; end if;    when discard_packet =>      if r.en = '0' then v.rx_state := idle; end if;     when wait_sfd =>      if r.en = '0' then v.rx_state := idle;       elsif r.rxd = "1101" then        v.rx_state := data1;       end if;      v.start := '0'; v.crc := (others => '1');      if r.er = '1' then v.status := frameCheckError; end if;    when data1 =>      if r.en = '1' then         crc_en := '1';        v.odd_nibble := not r.odd_nibble; v.rx_state := data2;        case index is        when 0 => v.data(27 downto 24) := r.rxd;        when 1 => v.data(19 downto 16) := r.rxd;        when 2 => v.data(11 downto 8)  := r.rxd;        when 3 => v.data(3 downto 0)   := r.rxd;         end case;      else        v.rx_state := check_crc;      end if;      if (r.byte_count(1 downto 0) = "00" and r.start = '1') or        (r.en = '0') then        write_req := '1';      end if;      if r.er = '1' then v.status := frameCheckError; end if;      if r.writeerror = '1' then        v.rx_state := errorst; v.status := overrun;       end if;      if r.byte_count > maxSize then        v.rx_state := errorst; v.status := frameTooLong;       end if;    when data2 =>      if r.en = '1' then        crc_en := '1';        v.odd_nibble := not r.odd_nibble; v.rx_state := data1;        v.byte_count := r.byte_count + 1; v.start := '1';        case index is        when 0 => v.data(31 downto 28) := r.rxd;        when 1 => v.data(23 downto 20) := r.rxd;        when 2 => v.data(15 downto 12) := r.rxd;        when 3 => v.data(7 downto 4)   := r.rxd;        end case;      else        v.rx_state := check_crc;      end if;      if r.er = '1' then v.status := frameCheckError; end if;      if r.writeerror = '1' then        v.rx_state := errorst; v.status := overrun;       end if;    when check_crc =>      if r.crc /= X"C704DD7B" then        if r.odd_nibble = '1' then v.status := alignmentError;        else v.status := frameCheckError; end if;      end if;      if write_ack = '1' then v.rx_state := report_status; end if;       if r.writeerror = '1' then v.status := overrun; end if;      if r.byte_count < minSize then v.rx_state := idle; end if;    when errorst =>      if r.en = '0' then        if r.byte_count < minSize then v.rx_state := idle;         else v.rx_state := report_status; end if;       end if;    when report_status =>      v.done := not r.done; v.rx_state := wait_report;    when wait_report =>      if done_ack = '1' then        v.rx_state := idle; v.done_ack(nsync) := r.done_ack(nsync-1);      end if;        when others => null;    end case;    --write to fifo    if write_req = '1' then      if write_ack = '0' then        v.writeerror := '1';      else        v.write_ack(nsync) := r.write_ack(nsync-1);        v.dataout := r.data; v.write := not r.write;       end if;    end if;    if eth_rx_in.write_ack = '1' then       if eth_rx_in.writeok = '0' then v.writeerror := '1'; end if;    end if;    --crc generation     if crc_en = '1' then      --xor top nibble in crc reg with data to determine which      --offsets should be xored       tc0 := r.rxd(0) xor r.crc(31); tc1 := r.rxd(1) xor r.crc(30);      tc2 := r.rxd(2) xor r.crc(29); tc3 := r.rxd(3) xor r.crc(28);      --the lsbit is sent first which means tcd(0) is xored with crc(31) etc       --dont forget to invert the resulting crc before transmitting      --initial value must be 0xFFFFFFFF      v.crc(31) := r.crc(27);      v.crc(30) := r.crc(26);      v.crc(29) := tc0 xor r.crc(25);      v.crc(28) := tc1 xor r.crc(24);      v.crc(27) := tc2 xor r.crc(23);      v.crc(26) := tc0 xor tc3 xor r.crc(22);      v.crc(25) := tc0 xor tc1 xor r.crc(21);      v.crc(24) := tc1 xor tc2 xor r.crc(20);      v.crc(23) := tc2 xor tc3 xor r.crc(19);      v.crc(22) := tc3 xor r.crc(18);      v.crc(21) := r.crc(17);      v.crc(20) := r.crc(16);      v.crc(19) := tc0 xor r.crc(15);      v.crc(18) := tc1 xor r.crc(14);      v.crc(17) := tc2 xor r.crc(13);      v.crc(16) := tc3 xor r.crc(12);      v.crc(15) := tc0 xor r.crc(11);      v.crc(14) := tc0 xor tc1 xor r.crc(10);      v.crc(13) := tc0 xor tc1 xor tc2 xor r.crc(9);      v.crc(12) := tc1 xor tc2 xor tc3 xor r.crc(8);      v.crc(11) := tc0 xor tc2 xor tc3 xor r.crc(7);      v.crc(10) := tc0 xor tc1 xor tc3 xor r.crc(6);      v.crc(9)  := tc1 xor tc2 xor r.crc(5);      v.crc(8)  := tc0 xor tc2 xor tc3 xor r.crc(4);      v.crc(7)  := tc0 xor tc1 xor tc3 xor r.crc(3);      v.crc(6)  := tc1 xor tc2 xor r.crc(2);      v.crc(5)  := tc0 xor tc2 xor tc3 xor r.crc(1);      v.crc(4)  := tc0 xor tc1 xor tc3 xor r.crc(0);      v.crc(3)  := tc0 xor tc1 xor tc2;      v.crc(2)  := tc1 xor tc2 xor tc3;      v.crc(1)  := tc2 xor tc3;      v.crc(0)  := tc3;     end if;        if rst = '0' then      v.rx_state := idle; v.write := '0'; v.done := '0'; v.sync_start := '0';      v.write_ack(nsync) := '1'; v.done_ack := (others => '0');      v.write_ack(nsync-1 downto 0) := (others => '0');    end if;    eth_rx_out.start   <= r.sync_start;     eth_rx_out.done    <= r.done;    eth_rx_out.write   <= r.write;    eth_rx_out.data    <= r.dataout;    eth_rx_out.length  <= r.byte_count;    eth_rx_out.status  <= r.status;    rin <= v;  end process;  regs : process(eth_clk) is  begin    if rising_edge(eth_clk) then r <= rin; end if;  end process;end; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -