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

📄 eth_tx.vhd

📁 The GRLIB IP Library is an integrated set of reusable IP cores, designed for system-on-chip (SOC) de
💻 VHD
字号:
--------------------------------------------------------------------------------- Entity:	eth_tx-- File:        eth_tx.vhd-- Author:      Marko Isomaki-- Description: Ethernet Media Access Controller Transmitter Module-------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library gaisler;use gaisler.net.all;use gaisler.ethernet_mac.all;library grlib;use grlib.stdlib.all;   entity eth_tx is  generic(    nsync            : integer := 2;   --number sync registers     attempt_limit    : integer := 16;  --max nbr of transmit attempts    backoff_limit    : integer := 10;  --max nbr of times to backoff    slot_time        : integer := 128; --number of nibbles for slot time    interframe_space : integer := 24   --interframe gap  );  port(    rst        : in  std_ulogic;    eth_clk    : in  std_ulogic;     eth_tx_in  : in  eth_tx_in_type;    eth_tx_out : out eth_tx_out_type  );end entity;architecture rtl of eth_tx is  constant ifg_bits : integer := log2(interframe_space);  constant ifg_val : std_logic_vector(ifg_bits-1 downto 0) :=    conv_std_logic_vector(interframe_space-1, ifg_bits);  constant ifg_part1 : std_logic_vector(ifg_bits-1 downto 0) :=    conv_std_logic_vector((interframe_space*2)/3, ifg_bits);  constant maxattempts : std_logic_vector(4 downto 0) :=    conv_std_logic_vector(attempt_limit, 5);  constant delay_zero : std_logic_vector(9 downto 0) := (others => '0');  constant slot_zero  : std_logic_vector(6 downto 0) := (others => '0');  function mirror(din : in std_logic_vector(3 downto 0))                        return std_logic_vector is    variable do : std_logic_vector(3 downto 0);  begin    do(3) := din(0); do(2) := din(1);    do(1) := din(2); do(0) := din(3);    return do;  end function;   type tx_state_type is (idle, preamble, sfd, data1, data2, pad1, pad2, fcs,    finish, calc_backoff, wait_backoff, send_jam, send_jam2, check_attempts);  type def_state_type is (monitor, def_on, ifg1, ifg2, frame_waitingst);  type reg_type is record    --deference process    def_state        : def_state_type;     ifg_cycls        : std_logic_vector(4 downto 0);    deferring        : std_ulogic;     was_transmitting : std_ulogic;     --tx process    main_state   : tx_state_type;    transmitting : std_ulogic;    tx_en        : std_ulogic;    txd          : std_logic_vector(3 downto 0);    cnt          : std_logic_vector(3 downto 0);    icnt         : std_logic_vector(1 downto 0);    crc          : std_logic_vector(31 downto 0);    crc_en       : std_ulogic;     byte_count   : std_logic_vector(10 downto 0);    slot_count   : std_logic_vector(6 downto 0);    random       : std_logic_vector(9 downto 0);    delay_val    : std_logic_vector(9 downto 0);    retry_cnt    : std_logic_vector(4 downto 0);    status       : std_logic_vector(1 downto 0);     data         : std_logic_vector(31 downto 0);    --synchronization    read         : std_ulogic;    done         : std_ulogic;    restart      : std_ulogic;    start        : std_logic_vector(nsync downto 0);    read_ack     : std_logic_vector(nsync downto 0);    crs          : std_logic_vector(1 downto 0);    col          : std_logic_vector(1 downto 0);    fullduplex   : std_logic_vector(1 downto 0);  end record;    signal r, rin   : reg_type; begin  comb : process(rst, eth_tx_in, r) is  variable collision     : std_ulogic;   variable frame_waiting : std_ulogic;  variable index         : integer range 0 to 7;  variable start         : std_ulogic;  variable read_ack      : std_ulogic;  variable tc0, tc1, tc2 , tc3 : std_ulogic;   variable v : reg_type;  begin    v := r;     frame_waiting := '0'; collision := r.col(1) and not r.fullduplex(1);     --synchronization    v.col(1) := r.col(0); v.col(0) := eth_tx_in.col;    v.crs(1) := r.crs(0); v.crs(0) := eth_tx_in.crs;    v.fullduplex(1) := r.fullduplex(0);    v.fullduplex(0) := eth_tx_in.full_duplex;    v.start(0)       := eth_tx_in.start;    v.read_ack(0)    := eth_tx_in.read_ack;         if nsync = 2 then      v.start(1)       := r.start(0);      v.read_ack(1)    := r.read_ack(0);    end if;    start       := r.start(nsync)       xor r.start(nsync-1);    read_ack    := r.read_ack(nsync)    xor r.read_ack(nsync-1);    --crc generation     if r.crc_en = '1' then      --xor top nibble in crc reg with data to determine which      --offsets should be xored       tc0 := r.txd(0) xor r.crc(31); tc1 := r.txd(1) xor r.crc(30);      tc2 := r.txd(2) xor r.crc(29); tc3 := r.txd(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;           --main fsm    case r.main_state is    when idle =>      v.transmitting := '0'; v.read_ack(nsync) := r.read_ack(nsync-1);      if (start and not r.deferring) = '1' then        v.main_state := preamble; v.transmitting := '1'; v.tx_en := '1';	v.byte_count := (others => '1'); v.status := (others => '0');	v.read := not r.read; v.start(nsync) := r.start(nsync-1);      elsif start = '1' then	frame_waiting := '1';       end if;      v.txd := "0101"; v.cnt := "1110";    when preamble =>      v.cnt := r.cnt - 1;       if r.cnt = "0000" then	v.txd := "1101"; v.main_state := sfd;       end if;      if collision = '1' then v.main_state := send_jam; end if;     when sfd =>      v.main_state := data1; v.icnt := (others => '0'); v.crc_en := '1';      v.crc := (others => '1'); v.byte_count := (others => '0');      v.txd := eth_tx_in.data(27 downto 24);       if collision = '1' then v.main_state := send_jam; end if;      if (read_ack and eth_tx_in.valid) = '0' then        v.status(0) := '1'; v.main_state := finish; v.tx_en := '0';        else        v.data := eth_tx_in.data; v.read := not r.read;        v.read_ack(nsync) := r.read_ack(nsync-1);      end if;    when data1 =>      index := conv_integer(r.icnt); v.byte_count := r.byte_count + 1;      v.main_state := data2; v.icnt := r.icnt + 1;      case index is      when 0 => v.txd := r.data(31 downto 28);      when 1 => v.txd := r.data(23 downto 20);      when 2 => v.txd := r.data(15 downto 12);      when 3 => v.txd := r.data(7 downto 4);      when others => null;      end case;      if index = 3 then        if (read_ack and eth_tx_in.valid) = '0' then          v.status(0) := '1'; v.main_state := finish; v.tx_en := '0';          else          v.data := eth_tx_in.data; v.read := not r.read;          v.read_ack(nsync) := r.read_ack(nsync-1);        end if;      end if;      if v.byte_count = eth_tx_in.length then        v.tx_en := '1';	if conv_integer(v.byte_count) >= 60 then	  v.main_state := fcs; v.cnt := (others => '0'); 	else	  v.main_state := pad1; 	end if;      end if;      if collision = '1' then v.main_state := send_jam; end if;    when data2 =>      index := conv_integer(r.icnt); v.main_state := data1;      case index is      when 0 => v.txd := r.data(27 downto 24);      when 1 => v.txd := r.data(19 downto 16);      when 2 => v.txd := r.data(11 downto 8);      when 3 => v.txd := r.data(3 downto 0);      when others => null;      end case;      if collision = '1' then v.main_state := send_jam; end if;    when pad1 =>      v.main_state := pad2;       if collision = '1' then v.main_state := send_jam; end if;    when pad2 =>      v.byte_count := r.byte_count + 1;       if conv_integer(v.byte_count) = 60 then	v.main_state := fcs; v.cnt := (others => '0');      else	v.main_state := pad1;      end if;       if collision = '1' then v.main_state := send_jam; end if;     when fcs =>      v.cnt := r.cnt + 1; v.crc_en := '0'; index := conv_integer(r.cnt);      case index is      when 0 => v.txd := mirror(not v.crc(31 downto 28));      when 1 => v.txd := mirror(not r.crc(27 downto 24));      when 2 => v.txd := mirror(not r.crc(23 downto 20));      when 3 => v.txd := mirror(not r.crc(19 downto 16));      when 4 => v.txd := mirror(not r.crc(15 downto 12));      when 5 => v.txd := mirror(not r.crc(11 downto 8));      when 6 => v.txd := mirror(not r.crc(7 downto 4));      when 7 => v.txd := mirror(not r.crc(3 downto 0));                v.main_state := finish;      when others => null;      end case;    when finish =>      v.tx_en := '0'; v.transmitting := '0'; v.main_state := idle;      v.retry_cnt := (others => '0'); v.done := not r.done;     when send_jam =>      v.cnt := "0110"; v.main_state := send_jam2; v.crc_en := '0';    when send_jam2 =>      v.cnt := r.cnt - 1;      if r.cnt = "0000" then	v.main_state := check_attempts; v.retry_cnt := r.retry_cnt + 1;       end if;     when check_attempts =>      if r.retry_cnt = maxattempts then        v.main_state := finish; v.status(1) := '1';        else        v.main_state := calc_backoff; v.restart := not r.restart;      end if;      v.tx_en := '0';    when calc_backoff =>      v.delay_val := (others => '0');      for i in 1 to backoff_limit-1 loop	if i < conv_integer(r.retry_cnt)+1 then	  v.delay_val(i) := r.random(i);	end if;       end loop;      v.main_state := wait_backoff; v.slot_count := (others => '1');     when wait_backoff =>      if r.delay_val = delay_zero then	v.main_state := idle;       end if;      v.slot_count := r.slot_count - 1;      if r.slot_count = slot_zero then	v.slot_count := (others => '1'); v.delay_val := r.delay_val - 1;       end if;    when others =>      v.main_state := idle;    end case;        --random values;     v.random := r.random(8 downto 0) & (not (r.random(2) xor r.random(9)));       --deference    case r.def_state is    when monitor =>      v.was_transmitting := '0';       if ( (r.crs(1) and not r.fullduplex(1)) or	   (r.transmitting and r.fullduplex(1)) ) = '1' then	v.deferring := '1'; v.def_state := def_on;	v.was_transmitting := r.transmitting;       end if;    when def_on =>      v.was_transmitting := r.was_transmitting or r.transmitting;       if r.fullduplex(1) = '1' then	if r.transmitting = '0' then v.def_state := ifg1; end if;	v.ifg_cycls := ifg_val;       else	if (r.transmitting or r.crs(1)) = '0' then	  v.def_state := ifg1; v.ifg_cycls := (others => '0');	end if;       end if;     when ifg1 =>      v.ifg_cycls := r.ifg_cycls + 1;      if r.ifg_cycls = ifg_part1 then v.def_state := ifg2;      elsif r.crs(1) = '1' then        v.ifg_cycls := (others => '0');      end if;     when ifg2 =>      v.ifg_cycls := r.ifg_cycls + 1;      if r.ifg_cycls = ifg_val then	v.deferring := '0'; 	if (r.fullduplex(1) or not frame_waiting) = '1' then	  v.def_state := monitor;        elsif frame_waiting = '1' then	  v.def_state := frame_waitingst;	end if;       end if;    when frame_waitingst =>       if frame_waiting = '0' then v.def_state := monitor; end if;     when others => v.def_state := monitor;     end case;        if rst = '0' then      v.main_state := idle; v.random := (others => '0');      v.def_state := monitor; v.deferring := '0'; v.tx_en := '0';       v.done := '0'; v.restart := '0'; v.read := '0';      v.start := (others => '0'); v.read_ack := (others => '0');    end if;    rin                      <= v;    eth_tx_out.done          <= r.done;    eth_tx_out.restart       <= r.restart;    eth_tx_out.read          <= r.read;    eth_tx_out.status        <= r.status;     eth_tx_out.tx_er         <= '0';    eth_tx_out.tx_en         <= r.tx_en;    eth_tx_out.txd           <= r.txd;   end process;  regs : process(eth_clk) is  begin    if rising_edge(eth_clk) then r <= rin; end if;  end process;end architecture; 

⌨️ 快捷键说明

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