📄 eth_mac.vhd
字号:
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 + -