LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; use std.textio.all; -- Imports the standard textio package. use work.emac_types.all; use work.utils_pkg.all; ENTITY emac_top_jb IS Generic ( f_sysclk : real := 100.0; TX_RAM_SIZE : natural := 2048; RX_RAM_SIZE : natural := 2048 ); Port ( CLK_I : in STD_LOGIC; RST_I : in STD_LOGIC; INT_O : out STD_LOGIC; CYC_I : in STD_LOGIC; STB_I : in STD_LOGIC; SEL_I : in unsigned(3 downto 0); WE_I : in STD_LOGIC; ACK_O : out STD_LOGIC; SRDY_O : out STD_LOGIC; MRDY_I : in STD_LOGIC; ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); mii_rx_clk : in STD_LOGIC; mii_rx_dv : in STD_LOGIC; mii_rx_er : in STD_LOGIC; mii_rx : in unsigned(7 downto 0); mii_tx_clk : in STD_LOGIC; mii_tx_en : out STD_LOGIC; mii_tx_er : out STD_LOGIC; mii_tx : out unsigned(7 downto 0); mii_gtx_clk : in STD_LOGIC; mii_crs : in STD_LOGIC; mii_col : in STD_LOGIC ); END emac_top_jb; ARCHITECTURE behavior OF emac_top_jb IS -- Signals for EMAC connections signal tx_ctrl_in : tx_ctrl_in_t; signal tx_ctrl_out : tx_ctrl_out_t; signal tx_din : unsigned(31 downto 0); signal tx_din_vld : std_logic; signal rx_ctrl_in : rx_ctrl_in_t; signal rx_ctrl_out : rx_ctrl_out_t; signal rx_dout : unsigned(31 downto 0); signal rx_dout_re : std_logic; signal rx_int_en : std_logic; signal tx_int_en : std_logic; signal irq_rx : std_logic; signal irq_tx : std_logic; signal ready : std_logic; signal read : std_logic; signal write : std_logic; signal data_read : std_logic; signal data_write : std_logic; signal reg_read : std_logic; signal reg_write : std_logic; signal reg_addr : unsigned(3 downto 0); signal tx_clk : std_logic; begin SRDY_O <= CYC_I and ready; read <= STB_I and CYC_I and not WE_I; write <= STB_I and CYC_I and WE_I; data_read <= read and ADDR_I(15); data_write <= write and ADDR_I(15); reg_read <= read and not ADDR_I(15); reg_write <= write and not ADDR_I(15); reg_addr <= ADDR_I(5 downto 2); ready <= not tx_ctrl_in.pkt_alloc_en; tx_din_vld <= data_write; tx_din <= DAT_I; rx_dout_re <= data_read; tx_clk <= mii_gtx_clk when tx_ctrl_in.Gbps_en = '1' else mii_tx_clk; ------------------------------------------------------------------ registers_write: process(CLK_I) begin if rising_edge(CLK_I) then tx_ctrl_in.pkt_alloc_en <= '0'; tx_ctrl_in.pkt_commit_en <= '0'; tx_ctrl_in.reset <= '0'; rx_ctrl_in.pkt_free_en <= '0'; rx_ctrl_in.pkt_req_en <= '0'; rx_ctrl_in.reset <= '0'; if RST_I = '1' then rx_int_en <= '0'; tx_int_en <= '0'; tx_ctrl_in.tx_size <= (others => '0'); rx_ctrl_in.mac_addr <= (X"03", X"02", X"01", X"00", X"07", X"06"); rx_ctrl_in.promiscious <= '0'; tx_ctrl_in.Gbps_en <= '0'; rx_ctrl_in.Gbps_en <= '0'; tx_ctrl_in.fcs_gen_en <= '0'; rx_ctrl_in.fcs_chk_en <= '0'; elsif reg_write = '1' then -- 0x0000 .. 0x003C case reg_addr is -- 0x0000 when "0000" => rx_ctrl_in.reset <= DAT_I(31); rx_ctrl_in.Gbps_en <= DAT_I(30); rx_ctrl_in.fcs_chk_en <= DAT_I(29); rx_ctrl_in.promiscious <= DAT_I(23); rx_ctrl_in.pkt_req_en <= DAT_I(17); rx_ctrl_in.pkt_free_en <= DAT_I(16); rx_int_en <= DAT_I(4); -- 0x0004 -- rx_size R/O -- 0x0008 when "0010" => tx_ctrl_in.reset <= DAT_I(31); tx_ctrl_in.Gbps_en <= DAT_I(30); tx_ctrl_in.fcs_gen_en <= DAT_I(29); tx_ctrl_in.pkt_alloc_en <= DAT_I(17); tx_ctrl_in.pkt_commit_en <= DAT_I(16); tx_int_en <= DAT_I(4); -- 0x000C when "0011" => tx_ctrl_in.tx_size <= DAT_I(15 downto 0); -- 0x0010 -- Gap -- 0x0014 -- Gap -- 0x0018 when "0110" => rx_ctrl_in.mac_addr(0) <= DAT_I(31 downto 24); rx_ctrl_in.mac_addr(1) <= DAT_I(23 downto 16); rx_ctrl_in.mac_addr(2) <= DAT_I(15 downto 8); rx_ctrl_in.mac_addr(3) <= DAT_I(7 downto 0); -- 0x001C when "0111" => rx_ctrl_in.mac_addr(4) <= DAT_I(31 downto 24); rx_ctrl_in.mac_addr(5) <= DAT_I(23 downto 16); -- 0x0020 .. 0x003C -- Gap when others => null; end case; end if; end if; end process; registers_read: process(CLK_I) begin if rising_edge(CLK_I) then ACK_O <= data_read; DAT_O <= rx_dout; if reg_read = '1' then -- 0x0000 .. 0x003C case reg_addr is -- 0x0000 when "0000" => ACK_O <= ready; DAT_O <= (others => '0'); DAT_O(31) <= rx_ctrl_out.reset_busy; DAT_O(30) <= rx_ctrl_in.Gbps_en; DAT_O(29) <= rx_ctrl_in.fcs_chk_en; DAT_O(23) <= rx_ctrl_in.promiscious; DAT_O(19) <= rx_ctrl_out.pkt_bcast; DAT_O(18) <= rx_ctrl_out.pkt_mac_match; DAT_O(17) <= rx_ctrl_out.pkt_valid; DAT_O(16) <= rx_ctrl_out.pkt_avail; DAT_O(4) <= rx_int_en; -- 0x0004 when "0001" => ACK_O <= '1'; DAT_O <= X"0000" & rx_ctrl_out.rx_size; -- 0x0008 when "0010" => ACK_O <= ready; DAT_O <= (others => '0'); DAT_O(31) <= tx_ctrl_out.reset_busy; DAT_O(30) <= tx_ctrl_in.Gbps_en; DAT_O(29) <= tx_ctrl_in.fcs_gen_en; DAT_O(24) <= tx_ctrl_out.pkt_done; DAT_O(17) <= tx_ctrl_out.pkt_alloc_req; DAT_O(16) <= tx_ctrl_out.pkt_armed; DAT_O(4) <= tx_int_en; -- 0x000C when "0011" => ACK_O <= '1'; DAT_O <= X"0000" & tx_ctrl_out.tx_size; -- 0x0010 -- Gap -- 0x0014 -- Gap -- 0x0018 when "0110" => ACK_O <= '1'; DAT_O <= rx_ctrl_in.mac_addr(0) & rx_ctrl_in.mac_addr(1) & rx_ctrl_in.mac_addr(2) & rx_ctrl_in.mac_addr(3); -- 0x001C when "0111" => ACK_O <= '1'; DAT_O <= rx_ctrl_in.mac_addr(4) & rx_ctrl_in.mac_addr(5) & X"0000"; -- 0x0020 .. 0x003C -- Gap when others => null; end case; end if; end if; end process; irq_register: process(CLK_I) begin if rising_edge(CLK_I) then INT_O <= irq_rx or irq_tx; irq_tx <= tx_int_en and tx_ctrl_out.pkt_done; irq_rx <= rx_int_en and rx_ctrl_out.pkt_avail; end if; end process; inst_emac_rx : entity work.emac_rx GENERIC MAP ( f_sysclk => f_sysclk, RAM_SIZE => RX_RAM_SIZE ) PORT MAP ( clk => CLK_I, rst => RST_I, dout_re => rx_dout_re, dout => rx_dout, ctrl_in => rx_ctrl_in, ctrl_out => rx_ctrl_out, mii_rx_clk => mii_rx_clk, mii_rx_dv => mii_rx_dv, mii_rx_er => mii_rx_er, mii_rx => mii_rx, mii_crs => mii_crs, mii_col => mii_col ); inst_emac_tx : entity work.emac_tx GENERIC MAP ( f_sysclk => f_sysclk, RAM_SIZE => TX_RAM_SIZE ) PORT MAP ( clk => CLK_I, rst => RST_I, din_vld => tx_din_vld, din => tx_din, ctrl_in => tx_ctrl_in, ctrl_out => tx_ctrl_out, mii_tx_clk => tx_clk, mii_tx_en => mii_tx_en, mii_tx_er => mii_tx_er, mii_tx => mii_tx ); end behavior;