Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@808 cc03376c-175c-47c8-b038-4cd826a8556b
658 lines
16 KiB
VHDL
658 lines
16 KiB
VHDL
LIBRARY IEEE;
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
|
USE IEEE.NUMERIC_STD.ALL;
|
|
use std.textio.all; -- Imports the standard textio package.
|
|
|
|
use work.utils_pkg.all;
|
|
|
|
ENTITY emac_jb IS
|
|
Generic
|
|
(
|
|
f_sysclk : real := 100.0;
|
|
TX_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 : out STD_LOGIC;
|
|
mii_crs : in STD_LOGIC;
|
|
mii_col : in STD_LOGIC
|
|
|
|
);
|
|
END emac_jb;
|
|
|
|
ARCHITECTURE behavior OF emac_jb IS
|
|
|
|
constant TX_RAM_ADDR_WIDTH : natural := NextExpBaseTwo(TX_RAM_SIZE);
|
|
|
|
subtype word_ptr_t is unsigned(TX_RAM_ADDR_WIDTH-1 downto 0);
|
|
|
|
-- Signals for EMAC connections
|
|
signal tx_fifo_din : unsigned(35 downto 0);
|
|
signal tx_fifo_dout : unsigned(35 downto 0);
|
|
signal tx_fifo_we : std_logic;
|
|
signal tx_fifo_re : std_logic;
|
|
signal tx_fifo_empty : std_logic;
|
|
signal tx_fifo_full : 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 tx_err : std_logic;
|
|
|
|
signal tx_flush_en : std_logic;
|
|
signal tx_flush_rdy : std_logic;
|
|
signal tx_flush_ptr_set : std_logic;
|
|
|
|
signal tx_commit_en : std_logic;
|
|
signal tx_flush_ptr : word_ptr_t;
|
|
|
|
signal host_data_we : std_logic;
|
|
signal host_data_reg : unsigned(31 downto 0);
|
|
signal host_tx_size : unsigned(15 downto 0);
|
|
|
|
signal tx_fill_size : word_ptr_t;
|
|
signal tx_fill_cnt : word_ptr_t;
|
|
signal tx_fill_ptr : word_ptr_t;
|
|
signal tx_fill_rdy : std_logic;
|
|
signal tx_fill_cnt_set : std_logic;
|
|
signal tx_fill_cnt_adv : std_logic;
|
|
signal tx_fill_ptr_set : std_logic;
|
|
signal tx_fill_ptr_adv : std_logic;
|
|
|
|
signal tx_alloc_OK : std_logic;
|
|
signal tx_alloc_req_en : std_logic;
|
|
signal tx_alloc_req : std_logic;
|
|
signal tx_alloc_ack : std_logic;
|
|
|
|
signal tx_nwords_free : word_ptr_t;
|
|
signal tx_alloc_base : word_ptr_t;
|
|
signal tx_alloc_size : word_ptr_t;
|
|
signal tx_alloc_en : std_logic;
|
|
|
|
signal tx_free_en : std_logic;
|
|
signal tx_uncommit_en : std_logic;
|
|
signal tx_fill_remain : unsigned(1 downto 0);
|
|
|
|
signal tx_xfer_size : word_ptr_t;
|
|
signal tx_xfer_ptr : word_ptr_t;
|
|
signal tx_xfer_cnt : word_ptr_t;
|
|
signal tx_xfer_en : std_logic;
|
|
signal tx_xfer_ptr_set : std_logic;
|
|
signal tx_xfer_ptr_adv : std_logic;
|
|
signal tx_xfer_cnt_set : std_logic;
|
|
signal tx_xfer_cnt_adv : std_logic;
|
|
signal tx_xfer_rdy : std_logic;
|
|
signal xfer_tag : unsigned(3 downto 0);
|
|
signal xfer_remain : unsigned(1 downto 0);
|
|
signal xfer_odd : std_logic;
|
|
signal xfer_remain_en : std_logic;
|
|
|
|
signal tx_ram_en_a : std_logic;
|
|
signal tx_ram_we_a : std_logic;
|
|
signal tx_ram_addr_a : unsigned(TX_RAM_ADDR_WIDTH-1 downto 0);
|
|
signal tx_ram_din_a : unsigned(35 downto 0);
|
|
signal tx_ram_dout_a : unsigned(35 downto 0);
|
|
signal tx_ram_en_b : std_logic;
|
|
signal tx_ram_we_b : std_logic;
|
|
signal tx_ram_addr_b : unsigned(TX_RAM_ADDR_WIDTH-1 downto 0);
|
|
signal tx_ram_din_b : unsigned(35 downto 0);
|
|
signal tx_ram_dout_b : unsigned(35 downto 0);
|
|
|
|
signal piso_din_be : unsigned(3 downto 0);
|
|
signal piso_din_rdy : std_logic;
|
|
signal tx_data_vld : std_logic;
|
|
|
|
subtype inter_frame_gap_cnt_t is natural range 0 to natural(1.0*f_sysclk)-1;
|
|
signal inter_frame_gap_cnt : inter_frame_gap_cnt_t;
|
|
signal inter_frame_gap_rdy : std_logic;
|
|
|
|
alias tx_ram_data_in_a is tx_ram_din_a(31 downto 0);
|
|
alias tx_ram_tag_in_a is tx_ram_din_a(35 downto 32);
|
|
alias tx_ram_data_out_a is tx_ram_dout_a(31 downto 0);
|
|
alias tx_ram_tag_out_a is tx_ram_dout_a(35 downto 32);
|
|
|
|
alias tx_ram_data_in_b is tx_ram_din_b(31 downto 0);
|
|
alias tx_ram_tag_in_b is tx_ram_din_b(35 downto 32);
|
|
alias tx_ram_data_out_b is tx_ram_dout_b(31 downto 0);
|
|
alias tx_ram_tag_out_b is tx_ram_dout_b(35 downto 32);
|
|
|
|
type host_tx_state_t is (host_tx_init, host_tx_flush, host_tx_idle, host_tx_alloc, host_tx_setup, host_tx_arm, host_tx_fill, host_tx_commit);
|
|
signal host_tx_s, host_tx_sn : host_tx_state_t;
|
|
|
|
type xfer_tx_state_t is (xfer_tx_init, xfer_tx_idle, xfer_tx_setup, xfer_wait, xfer_tx_active, xfer_tx_free);
|
|
signal xfer_tx_s, xfer_tx_sn : xfer_tx_state_t;
|
|
|
|
|
|
type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0);
|
|
constant piso_byte_mask_rom : piso_byte_mask_array_t :=
|
|
(
|
|
"1111",
|
|
"0001",
|
|
"0011",
|
|
"0111"
|
|
);
|
|
|
|
|
|
begin
|
|
|
|
SRDY_O <= CYC_I;
|
|
INT_O <= irq_rx or irq_tx;
|
|
mii_gtx_clk <= '0';
|
|
mii_tx_er <= tx_err;
|
|
|
|
tx_ram_tag_in_b <= "0000";
|
|
tx_ram_en_b <= '1';
|
|
tx_ram_we_b <= tx_uncommit_en or tx_flush_en;
|
|
tx_ram_addr_b <= tx_flush_ptr when (tx_flush_en = '1' or tx_uncommit_en = '1') else tx_xfer_ptr;
|
|
xfer_tag <= tx_ram_tag_out_b;
|
|
|
|
tx_ram_en_a <= '1';
|
|
tx_ram_we_a <= tx_commit_en or tx_fill_cnt_adv;
|
|
tx_ram_tag_in_a <= tx_fill_remain & "01" when tx_commit_en = '1' else "0000";
|
|
tx_ram_data_in_a <= resize(tx_fill_size, 16) & resize(tx_alloc_base, 16) when tx_commit_en = '1' else host_data_reg;
|
|
tx_ram_addr_a <= tx_alloc_base when tx_commit_en = '1' else tx_fill_ptr;
|
|
|
|
piso_din_be <= (others => '1');
|
|
tx_fifo_re <= piso_din_rdy;
|
|
tx_data_vld <= not tx_fifo_empty;
|
|
|
|
tx_fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(xfer_remain)) when xfer_remain_en = '1' else "1111";
|
|
tx_fifo_din(31 downto 0) <= tx_ram_data_out_b;
|
|
|
|
------------------------------------------------------------------
|
|
host_tx_state_next:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if RST_I = '1' then
|
|
host_tx_s <= host_tx_init;
|
|
else
|
|
host_tx_s <= host_tx_sn;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
host_tx_state:
|
|
process(host_tx_s, tx_flush_rdy, tx_alloc_req, tx_alloc_OK, tx_fill_rdy, host_data_we)
|
|
begin
|
|
|
|
tx_flush_en <= '0';
|
|
tx_flush_ptr_set <= '0';
|
|
tx_alloc_ack <= '0';
|
|
tx_fill_cnt_set <= '0';
|
|
tx_fill_cnt_adv <= '0';
|
|
tx_fill_ptr_set <= '0';
|
|
tx_fill_ptr_adv <= '0';
|
|
tx_commit_en <= '0';
|
|
tx_alloc_en <= '0';
|
|
|
|
host_tx_sn <= host_tx_s;
|
|
|
|
case host_tx_s is
|
|
|
|
when host_tx_init =>
|
|
tx_flush_ptr_set <= '1';
|
|
host_tx_sn <= host_tx_flush;
|
|
|
|
when host_tx_flush =>
|
|
tx_flush_en <= '1';
|
|
if tx_flush_rdy = '1' then
|
|
tx_flush_en <= '0';
|
|
host_tx_sn <= host_tx_idle;
|
|
end if;
|
|
|
|
when host_tx_idle =>
|
|
if tx_alloc_req = '1' then
|
|
host_tx_sn <= host_tx_alloc;
|
|
end if;
|
|
|
|
when host_tx_alloc =>
|
|
if tx_alloc_OK = '1' then
|
|
host_tx_sn <= host_tx_setup;
|
|
tx_alloc_ack <= '1';
|
|
end if;
|
|
|
|
when host_tx_setup =>
|
|
tx_fill_cnt_set <= '1';
|
|
tx_fill_ptr_set <= '1';
|
|
host_tx_sn <= host_tx_arm;
|
|
|
|
when host_tx_arm =>
|
|
tx_fill_ptr_adv <= '1';
|
|
tx_fill_cnt_adv <= '1';
|
|
host_tx_sn <= host_tx_fill;
|
|
|
|
when host_tx_fill =>
|
|
tx_fill_cnt_adv <= host_data_we;
|
|
tx_fill_ptr_adv <= not tx_fill_rdy and host_data_we;
|
|
if tx_alloc_req = '1' then
|
|
host_tx_sn <= host_tx_alloc;
|
|
elsif tx_fill_rdy = '1' then
|
|
host_tx_sn <= host_tx_commit;
|
|
end if;
|
|
|
|
when host_tx_commit =>
|
|
tx_commit_en <= '1';
|
|
tx_alloc_en <= '1';
|
|
host_tx_sn <= host_tx_idle;
|
|
|
|
when others =>
|
|
host_tx_sn <= host_tx_idle;
|
|
end case;
|
|
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
-- Allocation stuff
|
|
------------------------------------------------------------------
|
|
alloc_request_logic:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if RST_I = '1' then
|
|
tx_alloc_req <= '0';
|
|
elsif tx_alloc_req_en = '1' and tx_alloc_req = '0' then
|
|
tx_alloc_req <= '1';
|
|
tx_fill_remain <= host_tx_size(1 downto 0);
|
|
tx_fill_size <= host_tx_size(word_ptr_t'left+2 downto 2);
|
|
if host_tx_size(1 downto 0) /= "00" then
|
|
tx_fill_size <= host_tx_size(word_ptr_t'left+2 downto 2) + 1;
|
|
end if;
|
|
elsif tx_alloc_ack = '1' then
|
|
tx_alloc_req <= '0';
|
|
tx_alloc_size <= tx_fill_size;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
alloc_base_logic:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_flush_en = '1' then
|
|
tx_alloc_base <= (others => '0');
|
|
elsif tx_commit_en = '1' then
|
|
tx_alloc_base <= tx_fill_ptr;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
alloc_eval_logic:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
tx_alloc_OK <= '0';
|
|
if tx_alloc_req = '1' then
|
|
if tx_fill_size < tx_nwords_free then
|
|
tx_alloc_OK <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
tx_nwords_free_counter:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_flush_en = '1' then
|
|
tx_nwords_free <= (others => '1');
|
|
elsif tx_alloc_en = '1' then
|
|
tx_nwords_free <= tx_nwords_free - tx_fill_size;
|
|
elsif tx_free_en = '1' then
|
|
tx_nwords_free <= tx_nwords_free + tx_xfer_size;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
tx_flush_counter:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_flush_en = '0' then
|
|
tx_flush_rdy <= '0';
|
|
if tx_flush_ptr_set = '1' then
|
|
tx_flush_ptr <= (others => '1');
|
|
elsif tx_xfer_ptr_set = '1' then
|
|
tx_flush_ptr <= tx_ram_data_out_b(tx_flush_ptr'left downto 0);
|
|
end if;
|
|
elsif tx_flush_ptr /= 0 then
|
|
tx_flush_ptr <= tx_flush_ptr - 1;
|
|
else
|
|
tx_flush_rdy <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
-- Fill stuff
|
|
------------------------------------------------------------------
|
|
tx_fill_counter:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_fill_cnt_set = '1' then
|
|
tx_fill_rdy <= '0';
|
|
tx_fill_cnt <= tx_alloc_size;
|
|
elsif tx_fill_cnt_adv = '1' then
|
|
if tx_fill_cnt /= 0 then
|
|
tx_fill_cnt <= tx_fill_cnt - 1;
|
|
else
|
|
tx_fill_rdy <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
tx_fill_pointer:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_fill_ptr_set = '1' then
|
|
tx_fill_ptr <= tx_alloc_base;
|
|
elsif tx_fill_ptr_adv = '1' then
|
|
tx_fill_ptr <= tx_fill_ptr + 1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
-- Transfer stuff
|
|
------------------------------------------------------------------
|
|
xfer_tx_state_next:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if RST_I = '1' then
|
|
xfer_tx_s <= xfer_tx_init;
|
|
else
|
|
xfer_tx_s <= xfer_tx_sn;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
xfer_tx_state:
|
|
process(xfer_tx_s, xfer_tag, xfer_odd, tx_xfer_rdy, inter_frame_gap_rdy, tx_alloc_en, tx_fifo_full)
|
|
begin
|
|
|
|
tx_xfer_cnt_set <= '0';
|
|
tx_xfer_cnt_adv <= '0';
|
|
tx_xfer_ptr_set <= '0';
|
|
tx_xfer_ptr_adv <= '0';
|
|
tx_xfer_en <= '0';
|
|
xfer_remain_en <= '0';
|
|
tx_free_en <= '0';
|
|
tx_uncommit_en <= '0';
|
|
|
|
xfer_tx_sn <= xfer_tx_s;
|
|
|
|
case xfer_tx_s is
|
|
|
|
when xfer_tx_init =>
|
|
xfer_tx_sn <= xfer_tx_idle;
|
|
|
|
when xfer_tx_idle =>
|
|
if xfer_tag(0) = '1' then
|
|
tx_xfer_ptr_set <= '1';
|
|
tx_xfer_cnt_set <= '1';
|
|
xfer_tx_sn <= xfer_wait;
|
|
end if;
|
|
|
|
when xfer_wait =>
|
|
if inter_frame_gap_rdy = '1' then
|
|
xfer_tx_sn <= xfer_tx_setup;
|
|
end if;
|
|
|
|
when xfer_tx_setup =>
|
|
tx_uncommit_en <= '1';
|
|
tx_xfer_ptr_adv <= '1';
|
|
tx_xfer_cnt_adv <= '1';
|
|
xfer_tx_sn <= xfer_tx_active;
|
|
|
|
when xfer_tx_active =>
|
|
tx_xfer_en <= '1';
|
|
tx_xfer_cnt_adv <= not tx_fifo_full;
|
|
tx_xfer_ptr_adv <= not tx_fifo_full;
|
|
if tx_xfer_rdy = '1' then
|
|
xfer_remain_en <= xfer_odd;
|
|
tx_xfer_en <= '0';
|
|
tx_xfer_cnt_adv <= '0';
|
|
tx_xfer_ptr_adv <= '0';
|
|
xfer_tx_sn <= xfer_tx_free;
|
|
end if;
|
|
|
|
when xfer_tx_free =>
|
|
tx_free_en <= not tx_alloc_en;
|
|
if tx_alloc_en = '0' then
|
|
xfer_tx_sn <= xfer_tx_idle;
|
|
end if;
|
|
|
|
when others =>
|
|
xfer_tx_sn <= xfer_tx_idle;
|
|
end case;
|
|
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
interframe_gap_counter:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_flush_en = '1' then
|
|
inter_frame_gap_rdy <= '1';
|
|
elsif tx_fifo_empty = '0' then
|
|
inter_frame_gap_rdy <= '0';
|
|
inter_frame_gap_cnt <= inter_frame_gap_cnt_t'high;
|
|
elsif inter_frame_gap_cnt /= 0 then
|
|
inter_frame_gap_cnt <= inter_frame_gap_cnt - 1;
|
|
else
|
|
inter_frame_gap_rdy <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
tx_xfer_counter:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if tx_xfer_cnt_set = '1' then
|
|
tx_xfer_size <= (others => '0');
|
|
tx_xfer_rdy <= '0';
|
|
tx_xfer_cnt <= tx_ram_data_out_b(tx_xfer_ptr'left+16 downto 16);
|
|
elsif tx_xfer_cnt_adv = '1' then
|
|
if tx_xfer_cnt /= 0 then
|
|
tx_xfer_cnt <= tx_xfer_cnt - 1;
|
|
tx_xfer_size <= tx_xfer_size + 1;
|
|
else
|
|
tx_xfer_rdy <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
tx_xfer_pointer:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
tx_fifo_we <= tx_xfer_en;
|
|
if tx_xfer_ptr_set = '1' then
|
|
tx_xfer_ptr <= tx_ram_data_out_b(tx_xfer_ptr'left downto 0);
|
|
xfer_remain <= xfer_tag(3 downto 2);
|
|
xfer_odd <= '0';
|
|
if xfer_tag(3 downto 2) /= "00" then
|
|
xfer_odd <= '1';
|
|
end if;
|
|
elsif tx_xfer_ptr_adv = '1' then
|
|
tx_xfer_ptr <= tx_xfer_ptr + 1;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
registers_write:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
host_data_we <= '0';
|
|
tx_alloc_req_en <= '0';
|
|
if RST_I = '1' then
|
|
rx_int_en <= '0';
|
|
tx_int_en <= '0';
|
|
tx_err <= '0';
|
|
elsif (STB_I and CYC_I and WE_I) = '1' then
|
|
case ADDR_I(5 downto 2) is
|
|
|
|
when "0000" =>
|
|
tx_err <= DAT_I(31);
|
|
tx_alloc_req_en <= DAT_I(16);
|
|
tx_int_en <= DAT_I(5);
|
|
rx_int_en <= DAT_I(4);
|
|
|
|
when "0001" =>
|
|
if tx_alloc_req = '0' then
|
|
host_tx_size <= DAT_I(31 downto 16);
|
|
end if;
|
|
|
|
when "0010" =>
|
|
host_data_we <= '1';
|
|
host_data_reg <= DAT_I;
|
|
|
|
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 <= '0';
|
|
if (STB_I and CYC_I) = '1' then
|
|
ACK_O <= not WE_I;
|
|
DAT_O <= (others => '0');
|
|
case ADDR_I(5 downto 2) is
|
|
|
|
when "0000" =>
|
|
DAT_O(31) <= tx_err;
|
|
DAT_O(30) <= mii_rx_er;
|
|
DAT_O(29) <= mii_col;
|
|
DAT_O(28) <= mii_crs;
|
|
DAT_O(16) <= tx_alloc_req;
|
|
DAT_O(5) <= tx_int_en;
|
|
DAT_O(4) <= rx_int_en;
|
|
|
|
when "0001" =>
|
|
DAT_O(31 downto 16) <= host_tx_size;
|
|
|
|
when "0010" =>
|
|
|
|
when others => null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
inst_tx_ram : entity work.dpram_2w2r
|
|
GENERIC MAP
|
|
(
|
|
addr_width => TX_RAM_ADDR_WIDTH,
|
|
data_width => 36
|
|
)
|
|
PORT MAP
|
|
(
|
|
clk_a => CLK_I,
|
|
clk_b => CLK_I,
|
|
en_a => tx_ram_en_a,
|
|
en_b => tx_ram_en_b,
|
|
we_a => tx_ram_we_a,
|
|
we_b => tx_ram_we_b,
|
|
addr_a => tx_ram_addr_a,
|
|
addr_b => tx_ram_addr_b,
|
|
din_a => tx_ram_din_a,
|
|
din_b => tx_ram_din_b,
|
|
dout_a => tx_ram_dout_a,
|
|
dout_b => tx_ram_dout_b
|
|
);
|
|
|
|
-- Instantiate synchronous FIFO
|
|
inst_tx_fifo: entity work.fifo_async
|
|
GENERIC MAP
|
|
(
|
|
addr_width => 5,
|
|
data_width => 36,
|
|
do_last_read_update => true
|
|
)
|
|
PORT MAP
|
|
(
|
|
rst => RST_I,
|
|
clk_w => CLK_I,
|
|
clk_r => mii_tx_clk,
|
|
we => tx_fifo_we,
|
|
re => tx_fifo_re,
|
|
fifo_full => tx_fifo_full,
|
|
fifo_empty => tx_fifo_empty,
|
|
fifo_afull => open,
|
|
fifo_aempty => open,
|
|
data_w => tx_fifo_din,
|
|
data_r => tx_fifo_dout
|
|
);
|
|
|
|
inst_piso : entity work.piso
|
|
GENERIC MAP
|
|
(
|
|
data_width_in => 32,
|
|
data_width_out => 8,
|
|
msb_first => false
|
|
)
|
|
PORT MAP
|
|
(
|
|
rst => RST_I,
|
|
clk => mii_tx_clk,
|
|
din_vld => tx_data_vld,
|
|
din_rdy => piso_din_rdy,
|
|
din_be => tx_fifo_dout(35 downto 32),
|
|
din => tx_fifo_dout(31 downto 0),
|
|
dout_en => mii_tx_en,
|
|
dout => mii_tx
|
|
|
|
);
|
|
|
|
irq_register:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
irq_tx <= tx_int_en;
|
|
irq_rx <= rx_int_en;
|
|
end if;
|
|
end process;
|
|
|
|
end behavior;
|