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

📄 eth_mac.vhd

📁 The GRLIB IP Library is an integrated set of reusable IP cores, designed for system-on-chip (SOC) de
💻 VHD
📖 第 1 页 / 共 2 页
字号:
       end case; 
     end if;
   when check_desc =>
     v.txrenable := '1'; v.txstart := '0'; 
     v.txburstcnt := (others => '0'); v.txdstate := req;
     if r.txden = '1' then
       if r.txlength > maxSize then
         v.txrenable := '0'; v.txdstate := idle;
         if r.txwrap = '1' then v.txdsel := (others => '0');
         else v.txdsel := r.txdsel + 8; end if;
       elsif r.txlength /= zero11 then
         v.tmsto.addr := r.txaddr; v.txcnt(10 downto 0) := r.txlength;
       else
         v.txrenable := '0'; v.txdstate := idle;
         if r.txwrap = '1' then v.txdsel := (others => '0');
         else v.txdsel := r.txdsel + 8; end if;
       end if;
     else
       v.txdstate := idle;
     end if;
   when req =>
     if r.tfcnt(fabits-1) = '0' then
       v.tmsto.req := '1'; v.txdstate := fill_fifo;
     end if;
     if r.txcnt = zero11 then
       v.txdstate := check_result; v.tmsto.req := '0'; 
     end if;
     v.txburstcnt := (others => '0');
     if txrestart = '1' then
       v.txdstate := idle; v.txstart := '0'; 
       v.txrestart(nsync) := r.txrestart(nsync-1);
     end if;
   when fill_fifo =>
     if tmsti.grant = '1' then
       v.txburstcnt := r.txburstcnt + 1;  
       if (conv_integer(r.txcnt) <= 8) or
         (conv_integer(r.txburstcnt) = burstlength-1) then
         v.tmsto.req := '0'; v.tmsto.addr := r.tmsto.addr + 4;
       end if;
     end if;
     if tmsti.ready = '1' then
       v.tfwpnt := r.tfwpnt + 1; v.tfcnt := r.tfcnt + 1; vtxfi.write := '1';
       if conv_integer(r.txcnt) > 4 then
         v.txcnt := r.txcnt - 4;
       else
         v.txcnt := (others => '0');
         v.txdstate := req;
       end if;
       if r.txburstcnt(burstbits) = '1' or conv_integer(r.txcnt) <= 4 then
         v.txdstate := req;
         if r.txstart = '0' then
           v.txstart := '1'; v.txstart_sync := not r.txstart_sync; 
         end if;
       end if;
     end if;
   when check_result =>
     if txdone = '1' then
       v.txdstate := write_result; v.tmsto.req := '1';
       v.tmsto.write := '1'; v.tmsto.addr := r.txdesc & r.txdsel;
       v.tmsto.data(31 downto 2) := (others => '0');
       v.tmsto.data(1 downto 0) := v.txstatus;
       v.txdone(nsync) := r.txdone(nsync-1);
     elsif txrestart = '1' then
       v.txdstate := idle; v.txstart := '0'; 
       v.txrestart(nsync) := r.txrestart(nsync-1);
     end if;
   when write_result =>
     if tmsti.grant = '1' then v.tmsto.req := '0'; end if;
     if tmsti.ready = '1' then
       v.txdstate := idle; 
       v.txirqgen := r.ctrl.tx_irqen; 
       if r.txwrap = '0' then v.txdsel := r.txdsel + 8;
       else v.txdsel := (others => '0'); end if;
     end if;
   end case;

   if tmsti.retry = '1' then
     v.tmsto.req := '1'; v.tmsto.addr := r.tmsto.addr - 4; 
   end if;
    
   --tx fifo read
   if txread = '1' then
     v.txread_ack := not r.txread_ack; v.txread(nsync) := r.txread(nsync-1);
     if conv_integer(r.tfcnt) /= 0 then
       v.txvalid := '1';
       v.tfcnt := v.tfcnt - 1; v.tfrpnt := r.tfrpnt + 1;
     else
       v.txvalid := '0';
     end if;
     v.txdata := txfo.data;
   end if;

   --rx dataflow fsm
   case r.rxdstate is
   when idle =>
     v.rmsto.req := '0'; v.rmsto.write := '0'; v.addrnok := '0'; 
     v.rxoverrun := '0'; v.rxcnt := (others => '0'); v.rxdoneold := '0';
     v.ctrlpkt := '0';
     if r.ctrl.rxen = '1' then
       v.rxdstate := desc_read; v.rmsto.req := '1';
       v.rmsto.addr := r.rxdesc & r.rxdsel; 
     end if;
   when desc_read =>
     v.rxstatus := (others => '0');
     if rmsti.grant = '1' then
       v.rmsto.addr := r.rmsto.addr + 4;
     end if;
     if rmsti.ready = '1' then
       v.rxcnt := r.rxcnt + 1; v.rmsto.req := '0';
       case r.rxcnt(1 downto 0) is
       when "00" => v.ctrl.rxen := rmsti.data(11);
                    v.rxwrap    := rmsti.data(12);
       when "01" => v.rxaddr    := rmsti.data;
                    v.rxdstate  := check_desc;
       when others => null;
       end case; 
     end if;
   when check_desc =>
     v.rxcnt := (others => '0'); v.usesizefield := '0';
     v.rmsto.write := '1'; 
     if r.ctrl.rxen = '1' then
       if rxstart = '1' then
         v.rxdstate := read_req; v.rxstart(nsync) := r.rxstart(nsync-1);
       end if; 
     else
       v.rxdstate := idle;
     end if;
     v.rmsto.addr := r.rxaddr;
   when read_req =>
     if r.rfcnt(fabits-1) = '1' or
       (lengthav = '1' and r.rxcnt > (r.rxlength - burstlength)) then
       v.rmsto.req := '1'; v.rxdstate := read_fifo;
       v.rfrpnt := r.rfrpnt + 1; v.rfcnt := r.rfcnt - 1;
     end if;
     if lengthav = '1' and r.rxcnt >= r.rxlength then
       v.rxdstate := write_status; v.rmsto.req := '0'; 
     end if;
     v.rxburstcnt := (others => '0'); v.rmsto.data := rxfo.data; 
     if (r.addrnok or r.ctrlpkt) = '1' then v.rxdstate := discard; end if;
   when read_fifo =>
     if rmsti.grant = '1' then
       v.rxburstcnt := r.rxburstcnt + 1; 
       if (lengthav = '1' and
           conv_integer(r.rxcnt) > (conv_integer(r.rxlength) - 8)) or
         conv_integer(r.rxburstcnt) = burstlength-1 then
         v.rmsto.req := '0'; v.rmsto.addr := r.rmsto.addr + 4;
       end if;
     end if;
     if rmsti.ready = '1' then
       v.rmsto.data := rxfo.data; 
       v.rfcnt := r.rfcnt - 1; v.rfrpnt := r.rfrpnt + 1;
       v.rxcnt := r.rxcnt + 4;  
       if r.rxburstcnt(burstbits) = '1' or
         (lengthav = '1' and r.rxcnt >= (r.rxlength - 4)) then
         v.rxdstate := read_req;
       end if;
       v.check := '1'; v.checkdata := r.rmsto.data; 
     end if;
   when write_status =>
     v.rmsto.req := '1'; v.rmsto.addr := r.rxdesc & r.rxdsel;
     v.rxdstate := write_status2;
     v.rmsto.data := X"0000" & r.rxstatus & "00" & r.rxlength;  
   when write_status2 =>
     if rmsti.grant = '1' then v.rmsto.req := '0'; end if;
     if rmsti.ready = '1' then
       v.rxdsel := r.rxdsel + 8; v.rxdstate := idle;
       if r.ctrl.rx_irqen = '1' then
         vpirq(pirq) := '1';
         if r.rxstatus = receiveOK then v.status.rx_int := '1';
         else v.status.rx_err := '1'; end if;
       end if; 
     end if;
     if (r.rxstatus = overrun) or (r.rxoverrun = '1') then
       v.rfcnt := (others => '0'); v.rfwpnt := (others => '0');
       v.rfrpnt := (others => '0'); 
     end if;
   when discard =>
     if r.rxdoneold = '1' then
       v.rfrpnt := r.rfwpnt; v.rfcnt := (others => '0');
       v.rxdstate := idle; v.ctrlpkt := '0';
     end if; 
   when others => null;
   end case;

   if rmsti.retry = '1' then
     v.rmsto.req := '1'; v.rmsto.addr := r.rmsto.addr - 4;
   end if;

   --rx address/type check
   if r.check = '1' and r.rxcnt(10 downto 5) = "000000" then 
     case r.rxcnt(4 downto 2) is
     when "001" =>
       if r.checkdata /= broadcast(47 downto 16) and
          r.checkdata /= r.mac_addr(47 downto 16) and
          (not r.ctrl.prom) = '1'then
         v.addrnok := '1'; 
       end if;
     when "010" =>
       if r.checkdata(31 downto 16) /= broadcast(15 downto 0) and
          r.checkdata(31 downto 16) /= r.mac_addr(15 downto 0) and
          (not r.ctrl.prom) = '1' then
         v.addrnok := '1';
       end if;
     when "011" =>
       null;
     when "100" =>
       if r.checkdata(31 downto 16) = ctrlopcode then v.ctrlpkt := '1'; end if;
       if r.checkdata(31 downto 16) <= maxSize then
         v.usesizefield := '1'; v.rxlength := r.checkdata(31 downto 21);
       end if;
     when others =>
       null;
     end case; 
   end if;
    
   --rx packet overrun
   if rxdone = '1' then
     if r.rxdoneold = '1' then
       v.rxoverrun := '1';
     else  
       v.rxstatus := erxo.status; 
       if r.usesizefield = '0' then v.rxlength := erxo.length; end if;
     end if;
     v.rxdone(nsync) := r.rxdone(nsync-1);
     v.rxdoneack := not r.rxdoneack; 
   end if; 
     
   --rx fifo write
   if rxwrite = '1' then
     v.rxwriteack := not r.rxwriteack; v.rxwrite(nsync) := r.rxwrite(nsync-1);
     if (not r.rfcnt(fabits) and rxactive) = '1' then 
       v.rfwpnt := r.rfwpnt + 1; v.rfcnt := r.rfcnt + 1; v.writeok := '1'; 
       vrxfi.write := '1'; 
     else
       v.writeok := '0'; 
     end if; 
   end if;  

   --must be placed here because it uses variable  
   vrxfi.raddress := v.rfrpnt;

   --mdio commands
   if enable_mdio = 1 then
     if r.mdio_ctrl.busy = '1' then
       if emdio_done = '1' then
         v.mdio_ctrl.busy := '0'; v.mdio_ctrl.read := '0';
         v.mdio_ctrl.write := '0';
         v.emdio_done(nsync) := r.emdio_done(nsync-1);
         if emdioo.error = '1' then
           v.mdio_ctrl.nvalid := '0'; v.mdio_ctrl.linkfail := '1';  
         else
           v.mdio_ctrl.linkfail := '0';  
           if r.mdio_ctrl.read = '1' then
             v.mdio_ctrl.nvalid := '1'; v.mdio_ctrl.data := emdioo.data; 
           else
             v.mdio_ctrl.nvalid := '0';
           end if;
         end if; 
       end if; 
     end if;
   end if;
------------------------------------------------------------------------------
-- RESET ----------------------------------------------------------------------
-------------------------------------------------------------------------------
    if rst = '0' then
      v.txdstate := idle; v.rxdstate := idle; v.rfrpnt := (others => '0');
      v.tmsto.req := '0'; v.tmsto.req := '0'; v.rfwpnt := (others => '0'); 
      v.rfcnt := (others => '0'); v.mdiostart := '0';
      v.mdio_ctrl.read := '0'; v.mdio_ctrl.write := '0'; v.ctrl.txen := '0';
      v.mdio_ctrl.busy := '0'; v.txirqgen := '0'; v.ctrl.rxen := '0';
      v.txdsel := (others => '0'); v.txstart_sync := '0';
      v.txread := (others => '0'); v.txrestart := (others => '0');
      v.txdone := (others => '0'); v.txread_ack := '0'; 
      v.rxdsel := (others => '0'); v.rxdone := (others => '0');
      v.rxdoneold := '0'; v.rxdoneack := '0'; v.rxwriteack := '0';
      v.rxstart := (others => '0'); v.emdio_done := (others => '0');
      v.rxwrite := (others => '0');
    end if;
-------------------------------------------------------------------------------
-- SIGNAL ASSIGNMENTS ---------------------------------------------------------
-------------------------------------------------------------------------------
    rin           <= v;
    apbo.prdata   <= prdata;                          	
    apbo.pirq     <= vpirq;
    tmsto         <= r.tmsto;
    rmsto         <= r.rmsto;

    --tx fifo synced signals
    etxi.full_duplex <= r.ctrl.full_duplex;
    etxi.length      <= r.txlength;
    etxi.start       <= r.txstart_sync;
    etxi.valid       <= r.txvalid;
    etxi.data        <= r.txdata;
    etxi.read_ack    <= r.txread_ack;
    etxi.crs         <= ethi.rx_crs;
    etxi.col         <= ethi.rx_col;

    etho.tx_er       <= etxo.tx_er;
    etho.tx_en       <= etxo.tx_en;
    etho.txd         <= etxo.txd;

    erxi.rxen        <= r.ctrl.rxen;
    erxi.writeok     <= r.writeok;
    erxi.rx_er       <= ethi.rx_er;
    erxi.rx_dv       <= ethi.rx_dv;
    erxi.rxd         <= ethi.rxd;
    erxi.write_ack   <= r.rxwriteack;
    erxi.done_ack    <= r.rxdoneack;
    
    emdioi.mdioi     <= ethi.mdio_i;
    etho.mdio_o      <= emdioo.mdioo;
    etho.mdio_oe     <= emdioo.mdioen;
    etho.mdc         <= emdioo.mdc;

    txfi             <= vtxfi;
    rxfi             <= vrxfi;
  end process;

  apbo.pindex    <= pindex;
  apbo.pconfig   <= pconfig; 	

  regs : process(clk) is
  begin
    if rising_edge(clk) then r <= rin; end if;
  end process;

-------------------------------------------------------------------------------
-- TX UNIT --------------------------------------------------------------------
-------------------------------------------------------------------------------
   tx0 : eth_tx generic map(nsync => nsync, slot_time => slot_time,
     attempt_limit => attempt_limit, backoff_limit => backoff_limit,
     interframe_space => ifg_gap)
     port map(rst, ethi.tx_clk, etxi, etxo);
-------------------------------------------------------------------------------
-- RX UNIT --------------------------------------------------------------------
-------------------------------------------------------------------------------
   rx0 : eth_rx generic map(nsync => nsync)
     port map(rst, ethi.rx_clk, erxi, erxo);
-------------------------------------------------------------------------------
-- MDIO INTERFACE -------------------------------------------------------------
-------------------------------------------------------------------------------
   mdio0 : if enable_mdio = 1 generate 
     md0 : eth_mdio generic map(nsync => nsync, scaler => mdcscaler)
       port map(rst, clk, emdioi, emdioo);
   end generate;
-------------------------------------------------------------------------------
-- AHB MST INTERFACE ----------------------------------------------------------
-------------------------------------------------------------------------------
   ahb0 : eth_ahb_mst generic map (hindex => hindex) 
     port map(rst, clk, ahbmi, ahbmo, tmsto, tmsti, rmsto, rmsti);
-------------------------------------------------------------------------------
-- FIFOS ----------------------------------------------------------------------
-------------------------------------------------------------------------------
  tx_fifo0 : syncram_2p generic map(tech => memtech, abits => fabits,
    dbits => 32, sepclk => 0)
    port map(clk, txfi.renable, txfi.raddress, txfo.data, clk,
    txfi.write, txfi.waddress, txfi.datain);

  rx_fifo0 : syncram_2p generic map(tech => memtech, abits => fabits,
    dbits => 32, sepclk => 0)
    port map(clk, rxfi.renable, rxfi.raddress, rxfo.data, clk,
    rxfi.write, rxfi.waddress, rxfi.datain);
  
end architecture;

⌨️ 快捷键说明

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