URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [rtl/] [ethlib/] [grethaxi.vhd] - Rev 5
Compare with Previous | Blame | View Log
----------------------------------------------------------------------------- --! @file --! @copyright Copyright 2015 GNSS Sensor Ltd. All right reserved. --! @author Sergey Khabarov - sergeykhbr@gmail.com --! @brief Implementation of the grethaxi device. --! @details This is Ethernet MAC device with the AMBA AXI inteface --! and EDCL debugging functionality. ------------------------------------------------------------------------------ --! Standard library library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library commonlib; use commonlib.types_common.all; --! AMBA system bus specific library. library ambalib; --! AXI4 configuration constants. use ambalib.types_amba4.all; --! Ethernet specific declarations. library ethlib; use ethlib.types_eth.all; entity grethaxi is generic( xaddr : integer := 0; xmask : integer := 16#FFFFF#; xirq : integer := 0; memtech : integer := 0; ifg_gap : integer := 24; attempt_limit : integer := 16; backoff_limit : integer := 10; slot_time : integer := 128; mdcscaler : integer range 0 to 255 := 25; enable_mdio : integer range 0 to 1 := 0; fifosize : integer range 4 to 512 := 8; nsync : integer range 1 to 2 := 2; edcl : integer range 0 to 3 := 0; edclbufsz : integer range 1 to 64 := 1; macaddrh : integer := 16#00005E#; macaddrl : integer := 16#000000#; ipaddrh : integer := 16#c0a8#; ipaddrl : integer := 16#0135#; phyrstadr : integer range 0 to 32 := 0; rmii : integer range 0 to 1 := 0; oepol : integer range 0 to 1 := 0; scanen : integer range 0 to 1 := 0; ft : integer range 0 to 2 := 0; edclft : integer range 0 to 2 := 0; mdint_pol : integer range 0 to 1 := 0; enable_mdint : integer range 0 to 1 := 0; multicast : integer range 0 to 1 := 0; edclsepahbg : integer range 0 to 1 := 0; ramdebug : integer range 0 to 2 := 0; mdiohold : integer := 1; maxsize : integer := 1500; gmiimode : integer range 0 to 1 := 0 ); port( rst : in std_ulogic; clk : in std_ulogic; msti : in nasti_master_in_type; msto : out nasti_master_out_type; mstcfg : out nasti_master_config_type; msto2 : out nasti_master_out_type; mstcfg2 : out nasti_master_config_type; slvi : in nasti_slave_in_type; slvo : out nasti_slave_out_type; slvcfg : out nasti_slave_config_type; ethi : in eth_in_type; etho : out eth_out_type; irq : out std_logic ); end entity; architecture arch_grethaxi of grethaxi is constant bufsize : std_logic_vector(2 downto 0) := conv_std_logic_vector(log2(edclbufsz), 3); constant xslvconfig : nasti_slave_config_type := ( descrtype => PNP_CFG_TYPE_SLAVE, descrsize => PNP_CFG_SLAVE_DESCR_BYTES, irq_idx => xirq, xaddr => conv_std_logic_vector(xaddr, CFG_NASTI_CFG_ADDR_BITS), xmask => conv_std_logic_vector(xmask, CFG_NASTI_CFG_ADDR_BITS), vid => VENDOR_GNSSSENSOR, did => GNSSSENSOR_ETHMAC ); constant xmstconfig : nasti_master_config_type := ( descrsize => PNP_CFG_MASTER_DESCR_BYTES, descrtype => PNP_CFG_TYPE_MASTER, vid => VENDOR_GNSSSENSOR, did => GAISLER_ETH_MAC_MASTER ); constant xmstconfig2 : nasti_master_config_type := ( descrsize => PNP_CFG_MASTER_DESCR_BYTES, descrtype => PNP_CFG_TYPE_MASTER, vid => VENDOR_GNSSSENSOR, did => GAISLER_ETH_EDCL_MASTER ); type local_addr_array_type is array (0 to CFG_WORDS_ON_BUS-1) of std_logic_vector(15 downto 0); type registers is record bank_slv : nasti_slave_bank_type; ctrl : eth_control_type; end record; signal r, rin : registers; signal imac_cmd : eth_command_type; signal omac_status : eth_mac_status_type; signal omac_rdbgdata : std_logic_vector(31 downto 0); signal omac_tmsto : eth_tx_ahb_in_type; signal imac_tmsti : eth_tx_ahb_out_type; signal omac_tmsto2 : eth_tx_ahb_in_type; signal imac_tmsti2 : eth_tx_ahb_out_type; signal omac_rmsto : eth_rx_ahb_in_type; signal imac_rmsti : eth_rx_ahb_out_type; begin comb : process(r, ethi, slvi, omac_rdbgdata, omac_status, rst) is variable v : registers; variable vcmd : eth_command_type; variable raddr_reg : local_addr_array_type; variable waddr_reg : local_addr_array_type; variable rdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); variable wdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); variable wdata32 : std_logic_vector(31 downto 0); variable wstrb : std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); variable val : std_logic_vector(8*CFG_ALIGN_BYTES-1 downto 0); begin v := r; vcmd := eth_command_none; procedureAxi4(slvi, xslvconfig, r.bank_slv, v.bank_slv); for n in 0 to CFG_WORDS_ON_BUS-1 loop raddr_reg(n) := r.bank_slv.raddr(n)(17 downto log2(CFG_ALIGN_BYTES)); val := (others => '0'); if (ramdebug = 0) or (raddr_reg(n)(15 downto 14) = "00") then case raddr_reg(n)(3 downto 0) is when "0000" => --ctrl reg if ramdebug /= 0 then val(13) := r.ctrl.ramdebugen; end if; if (edcl /= 0) then val(31) := '1'; val(30 downto 28) := bufsize; val(14) := r.ctrl.edcldis; val(12) := r.ctrl.disableduplex; end if; if enable_mdint = 1 then val(26) := '1'; val(10) := r.ctrl.pstatirqen; end if; if multicast = 1 then val(25) := '1'; val(11) := r.ctrl.mcasten; end if; if rmii = 1 then val(7) := omac_status.speed; end if; val(6) := omac_status.reset; val(5) := r.ctrl.prom; val(4) := omac_status.full_duplex; val(3) := r.ctrl.rx_irqen; val(2) := r.ctrl.tx_irqen; val(1) := omac_status.rxen; val(0) := omac_status.txen; when "0001" => --status/int source reg val(9) := not (omac_status.edcltx_idle or omac_status.edclrx_idle); if enable_mdint = 1 then val(8) := omac_status.phystat; end if; val(7) := omac_status.invaddr; val(6) := omac_status.toosmall; val(5) := omac_status.txahberr; val(4) := omac_status.rxahberr; val(3) := omac_status.tx_int; val(2) := omac_status.rx_int; val(1) := omac_status.tx_err; val(0) := omac_status.rx_err; when "0010" => --mac addr lsb val := r.ctrl.mac_addr(31 downto 0); when "0011" => --mac addr msb/mdio address val(15 downto 0) := r.ctrl.mac_addr(47 downto 32); when "0100" => --mdio ctrl/status val(31 downto 16) := omac_status.mdio.cmd.data; val(15 downto 11) := r.ctrl.mdio_phyadr; val(10 downto 6) := omac_status.mdio.cmd.regadr; val(3) := omac_status.mdio.busy; val(2) := omac_status.mdio.linkfail; val(1) := omac_status.mdio.cmd.read; val(0) := omac_status.mdio.cmd.write; when "0101" => --tx descriptor val(31 downto 10) := r.ctrl.txdesc; val(9 downto 3) := omac_status.txdsel; when "0110" => --rx descriptor val(31 downto 10) := r.ctrl.rxdesc; val(9 downto 3) := omac_status.rxdsel; when "0111" => --edcl ip if (edcl /= 0) then val := r.ctrl.edclip; end if; when "1000" => if multicast = 1 then val := r.ctrl.hash(63 downto 32); end if; when "1001" => if multicast = 1 then val := r.ctrl.hash(31 downto 0); end if; when "1010" => if edcl /= 0 then val(15 downto 0) := r.ctrl.emacaddr(47 downto 32); end if; when "1011" => if edcl /= 0 then val := r.ctrl.emacaddr(31 downto 0); end if; when others => null; end case; elsif raddr_reg(n)(15 downto 14) = "01" then if ramdebug /= 0 then vcmd.dbg_access_id := DBG_ACCESS_TX_BUFFER; vcmd.dbg_rd_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := raddr_reg(n)(13 downto 0); val := omac_rdbgdata; end if; elsif raddr_reg(n)(15 downto 14) = "10" then if ramdebug /= 0 then vcmd.dbg_access_id := DBG_ACCESS_RX_BUFFER; vcmd.dbg_rd_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := raddr_reg(n)(13 downto 0); val := omac_rdbgdata; end if; elsif raddr_reg(n)(15 downto 14) = "11" then if (ramdebug = 2) and (edcl /= 0) then vcmd.dbg_access_id := DBG_ACCESS_EDCL_BUFFER; vcmd.dbg_rd_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := raddr_reg(n)(13 downto 0); val := omac_rdbgdata; end if; end if; rdata(8*CFG_ALIGN_BYTES*(n+1)-1 downto 8*CFG_ALIGN_BYTES*n) := val; end loop; if slvi.w_valid = '1' and r.bank_slv.wstate = wtrans and r.bank_slv.wresp = NASTI_RESP_OKAY then wdata := slvi.w_data; wstrb := slvi.w_strb; for n in 0 to CFG_WORDS_ON_BUS-1 loop waddr_reg(n) := r.bank_slv.waddr(n)(17 downto 2); wdata32 := wdata(8*CFG_ALIGN_BYTES*(n+1)-1 downto 8*CFG_ALIGN_BYTES*n); if wstrb(CFG_ALIGN_BYTES*(n+1)-1 downto CFG_ALIGN_BYTES*n) /= "0000" then if (ramdebug = 0) or (waddr_reg(n)(15 downto 14) = "00") then case waddr_reg(n)(3 downto 0) is when "0000" => --ctrl reg if ramdebug /= 0 then v.ctrl.ramdebugen := wdata32(13); end if; if edcl /= 0 then v.ctrl.edcldis := wdata32(14); v.ctrl.disableduplex := wdata32(12); end if; if multicast = 1 then v.ctrl.mcasten := wdata32(11); end if; if enable_mdint = 1 then v.ctrl.pstatirqen := wdata32(10); end if; if rmii = 1 then vcmd.set_speed := wdata32(7); vcmd.clr_speed := not wdata32(7); end if; vcmd.set_reset := wdata32(6); vcmd.clr_reset := not wdata32(6); v.ctrl.prom := wdata32(5); vcmd.set_full_duplex := wdata32(4); vcmd.clr_full_duplex := not wdata32(4); v.ctrl.rx_irqen := wdata32(3); v.ctrl.tx_irqen := wdata32(2); vcmd.set_rxena := wdata32(1); vcmd.clr_rxena := not wdata32(1); vcmd.set_txena := wdata32(0); vcmd.clr_txena := not wdata32(0); when "0001" => --status/int source reg if enable_mdint = 1 then vcmd.clr_status_phystat := wdata32(8); end if; vcmd.clr_status_invaddr := wdata32(7); vcmd.clr_status_toosmall := wdata32(6); vcmd.clr_status_txahberr := wdata32(5); vcmd.clr_status_rxahberr := wdata32(4); vcmd.clr_status_tx_int := wdata32(3); vcmd.clr_status_rx_int := wdata32(2); vcmd.clr_status_tx_err := wdata32(1); vcmd.clr_status_rx_err := wdata32(0); when "0010" => --mac addr lsb v.ctrl.mac_addr(31 downto 0) := wdata32(31 downto 0); when "0011" => --mac addr msb v.ctrl.mac_addr(47 downto 32) := wdata32(15 downto 0); when "0100" => --mdio ctrl/status if enable_mdio = 1 then vcmd.mdio_cmd.valid := not omac_status.mdio.busy; if omac_status.mdio.busy = '0' then v.ctrl.mdio_phyadr := wdata32(15 downto 11); end if; vcmd.mdio_cmd.data := wdata32(31 downto 16); vcmd.mdio_cmd.regadr := wdata32(10 downto 6); vcmd.mdio_cmd.read := wdata32(1); vcmd.mdio_cmd.write := wdata32(0); end if; when "0101" => --tx descriptor vcmd.set_txdsel := '1'; vcmd.txdsel := wdata32(9 downto 3); v.ctrl.txdesc := wdata32(31 downto 10); when "0110" => --rx descriptor vcmd.set_rxdsel := '1'; vcmd.rxdsel := wdata32(9 downto 3); v.ctrl.rxdesc := wdata32(31 downto 10); when "0111" => --edcl ip if (edcl /= 0) then v.ctrl.edclip := wdata32; end if; when "1000" => --hash msb if multicast = 1 then v.ctrl.hash(63 downto 32) := wdata32; end if; when "1001" => --hash lsb if multicast = 1 then v.ctrl.hash(31 downto 0) := wdata32; end if; when "1010" => if edcl /= 0 then v.ctrl.emacaddr(47 downto 32) := wdata32(15 downto 0); end if; when "1011" => if edcl /= 0 then v.ctrl.emacaddr(31 downto 0) := wdata32; end if; when others => null; end case; elsif waddr_reg(n)(15 downto 14) = "01" then if ramdebug /= 0 then vcmd.dbg_access_id := DBG_ACCESS_TX_BUFFER; vcmd.dbg_wr_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := waddr_reg(n)(13 downto 0); vcmd.dbg_wdata := wdata32; end if; elsif waddr_reg(n)(15 downto 14) = "10" then if ramdebug /= 0 then vcmd.dbg_access_id := DBG_ACCESS_RX_BUFFER; vcmd.dbg_wr_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := waddr_reg(n)(13 downto 0); vcmd.dbg_wdata := wdata32; end if; elsif waddr_reg(n)(15 downto 14) = "11" then if (ramdebug = 2) and (edcl /= 0) then vcmd.dbg_access_id := DBG_ACCESS_EDCL_BUFFER; vcmd.dbg_wr_ena := r.ctrl.ramdebugen; vcmd.dbg_addr := waddr_reg(n)(13 downto 0); vcmd.dbg_wdata := wdata32; end if; end if; end if; end loop; end if; slvo <= functionAxi4Output(r.bank_slv, rdata); ------------------------------------------------------------------------------ -- RESET ---------------------------------------------------------------------- ------------------------------------------------------------------------------- if rst = '0' then v.bank_slv := NASTI_SLAVE_BANK_RESET; v.ctrl.tx_irqen := '0'; v.ctrl.rx_irqen := '0'; v.ctrl.prom := '0'; v.ctrl.pstatirqen := '0'; v.ctrl.mcasten := '0'; v.ctrl.ramdebugen := '0'; if edcl = 3 then v.ctrl.edcldis := ethi.edcldisable; elsif edcl /= 0 then v.ctrl.edcldis := '0'; end if; v.ctrl.disableduplex := '0'; if phyrstadr /= 32 then v.ctrl.mdio_phyadr := conv_std_logic_vector(phyrstadr, 5); else v.ctrl.mdio_phyadr := ethi.phyrstaddr; end if; v.ctrl.mac_addr := (others => '0'); v.ctrl.txdesc := (others => '0'); v.ctrl.rxdesc := (others => '0'); v.ctrl.hash := (others => '0'); v.ctrl.edclip := conv_std_logic_vector(ipaddrh, 16) & conv_std_logic_vector(ipaddrl, 16); v.ctrl.emacaddr := conv_std_logic_vector(macaddrh, 24) & conv_std_logic_vector(macaddrl, 24); if edcl > 1 then v.ctrl.edclip(3 downto 0) := ethi.edcladdr; v.ctrl.emacaddr(3 downto 0) := ethi.edcladdr; end if; end if; rin <= v; imac_cmd <= vcmd; end process; slvcfg <= xslvconfig; mstcfg <= xmstconfig; mstcfg2 <= xmstconfig2; eth64 : grethc64 generic map ( memtech => memtech, ifg_gap => ifg_gap, attempt_limit => attempt_limit, backoff_limit => backoff_limit, mdcscaler => mdcscaler, enable_mdio => enable_mdio, fifosize => fifosize, nsync => nsync, edcl => edcl, edclbufsz => edclbufsz, macaddrh => macaddrh, macaddrl => macaddrl, ipaddrh => ipaddrh, ipaddrl => ipaddrl, phyrstadr => phyrstadr, rmii => rmii, oepol => oepol, scanen => scanen, mdint_pol => mdint_pol, enable_mdint => enable_mdint, multicast => multicast, edclsepahbg => edclsepahbg, ramdebug => ramdebug, mdiohold => mdiohold, maxsize => maxsize, gmiimode => gmiimode ) port map ( rst => rst, clk => clk, ctrli => r.ctrl, cmdi => imac_cmd, statuso => omac_status, rdbgdatao => omac_rdbgdata, --irq irq => irq, --ethernet input signals rmii_clk => ethi.rmii_clk, tx_clk => ethi.tx_clk, rx_clk => ethi.rx_clk, tx_dv => ethi.tx_dv, rxd => ethi.rxd, rx_dv => ethi.rx_dv, rx_er => ethi.rx_er, rx_col => ethi.rx_col, rx_en => ethi.rx_en, rx_crs => ethi.rx_crs, mdio_i => ethi.mdio_i, phyrstaddr => ethi.phyrstaddr, mdint => ethi.mdint, --ethernet output signals reset => etho.reset, txd => etho.txd, tx_en => etho.tx_en, tx_er => etho.tx_er, mdc => etho.mdc, mdio_o => etho.mdio_o, mdio_oe => etho.mdio_oe, testrst => '0', testen => '0', testoen => '0', edcladdr => ethi.edcladdr, edclsepahb => ethi.edclsepahb, edcldisable => ethi.edcldisable, speed => etho.speed, tmsto => omac_tmsto, tmsti => imac_tmsti, tmsto2 => omac_tmsto2, tmsti2 => imac_tmsti2, rmsto => omac_rmsto, rmsti => imac_rmsti ); etho.tx_clk <= '0'; etho.gbit <= '0'; --! AXI Master interface providing DMA access axi0 : eth_axi_mst port map ( rst, clk, msti, msto, omac_tmsto, imac_tmsti, omac_rmsto, imac_rmsti ); edclmst_on : if edclsepahbg = 1 generate axi1 : eth_axi_mst port map ( rst, clk, msti, msto2, omac_tmsto2, imac_tmsti2, eth_rx_in_none, open ); end generate; edclmst_off : if edclsepahbg = 0 generate msto2 <= nasti_master_out_none; imac_tmsti2.grant <= '0'; imac_tmsti2.data <= (others => '0'); imac_tmsti2.ready <= '0'; imac_tmsti2.error <= '0'; imac_tmsti2.retry <= '0'; end generate; regs : process(clk) is begin if rising_edge(clk) then r <= rin; end if; end process; end architecture;