diff --git a/lib/emac/src/emac_rx.vhd b/lib/emac/src/emac_rx.vhd index 5cf8540..0659adf 100644 --- a/lib/emac/src/emac_rx.vhd +++ b/lib/emac/src/emac_rx.vhd @@ -36,43 +36,55 @@ ARCHITECTURE behavior OF emac_rx IS subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0); -- Signals for EMAC connections - signal fifo_din : unsigned(35 downto 0); - signal fifo_dout : unsigned(35 downto 0); - signal fifo_we : std_logic; - signal fifo_re : std_logic; - signal fifo_empty : std_logic; - signal fifo_full : std_logic; + signal mii_fifo_din : unsigned(35 downto 0); + signal mii_fifo_dout : unsigned(35 downto 0); + signal mii_fifo_we : std_logic; + signal mii_fifo_re : std_logic; + signal mii_fifo_empty : std_logic; + signal mii_fifo_full : std_logic; + + signal cmd_fifo_din : unsigned(35 downto 0); + signal cmd_fifo_dout : unsigned(35 downto 0); + signal cmd_fifo_we : std_logic; + signal cmd_fifo_re : std_logic; + signal cmd_fifo_empty : std_logic; + signal cmd_fifo_full : std_logic; signal flush_en : std_logic; - signal flush_rdy : std_logic; - signal flush_ptr_set : std_logic; - signal flush_ptr : word_ptr_t; - signal fill_size : word_ptr_t; - signal fill_cnt : word_ptr_t; signal fill_ptr : word_ptr_t; - signal fill_rdy : std_logic; - signal fill_cnt_set : std_logic; - signal fill_cnt_adv : std_logic; signal fill_ptr_set : std_logic; signal fill_ptr_adv : std_logic; - signal fill_remain : unsigned(1 downto 0); - signal nwords_free : word_ptr_t; - - signal free_en : std_logic; + signal commit_en : std_logic; signal uncommit_en : std_logic; + signal xfer_ram_full : std_logic; + signal xfer_base : word_ptr_t; + signal xfer_size : word_ptr_t; + signal xfer_ptr : word_ptr_t; + signal xfer_ptr_next : word_ptr_t; + signal xfer_cnt : word_ptr_t; + signal xfer_ptr_set : std_logic; + signal xfer_ptr_adv : std_logic; + signal xfer_cnt_set : std_logic; + signal xfer_cnt_adv : std_logic; + signal 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 ram_en_a : std_logic; signal ram_we_a : std_logic; signal ram_addr_a : word_ptr_t; - signal ram_din_a : unsigned(35 downto 0); - signal ram_dout_a : unsigned(35 downto 0); + signal ram_din_a : unsigned(31 downto 0); + signal ram_dout_a : unsigned(31 downto 0); signal ram_en_b : std_logic; signal ram_we_b : std_logic; signal ram_addr_b : word_ptr_t; - signal ram_din_b : unsigned(35 downto 0); - signal ram_dout_b : unsigned(35 downto 0); + signal ram_din_b : unsigned(31 downto 0); + signal ram_dout_b : unsigned(31 downto 0); signal sipo_dout : unsigned(31 downto 0); signal sipo_dout_be : unsigned(3 downto 0); @@ -81,26 +93,125 @@ ARCHITECTURE behavior OF emac_rx IS signal byte_count : word_ptr_t; signal byte_count_reg : word_ptr_t; + signal byte_count_reg_s : word_ptr_t; + + signal word_count : word_ptr_t; + signal word_count_reg : word_ptr_t; + signal word_count_set : std_logic; + signal word_count_clr : std_logic; + signal word_count_ack : std_logic; + signal word_count_vld : std_logic; + signal rx_dv_r : std_logic; + type host_state_t is (host_init, host_flush, host_idle, host_setup, host_arm, host_fill, host_uncommit); + signal host_s, host_sn : host_state_t; + type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_wait, xfer_active, xfer_free); signal xfer_s, xfer_sn : xfer_state_t; - alias ram_data_in_a is ram_din_a(31 downto 0); - alias ram_tag_in_a is ram_din_a(35 downto 32); - alias ram_data_out_a is ram_dout_a(31 downto 0); - alias ram_tag_out_a is ram_dout_a(35 downto 32); - - alias ram_data_in_b is ram_din_b(31 downto 0); - alias ram_tag_in_b is ram_din_b(35 downto 32); - alias ram_data_out_b is ram_dout_b(31 downto 0); - alias ram_tag_out_b is ram_dout_b(35 downto 32); - begin - dout <= sipo_dout; - fifo_din <= sipo_dout_be & sipo_dout; + ctrl_out.rx_size <= cmd_fifo_dout(31 downto 16); + ctrl_out.rx_vld <= not cmd_fifo_empty; + ctrl_out.rx_er <= mii_rx_er; + dout <= ram_dout_a; + mii_fifo_din <= sipo_dout_be & sipo_dout; + mii_fifo_we <= sipo_dout_vld; + + ram_en_a <= ctrl_in.data_read; + ram_din_a <= (others => '-'); + ram_addr_a <= fill_ptr; + ram_we_a <= '0'; + + ram_en_b <= '1'; + ram_din_b <= mii_fifo_dout(31 downto 0); + ram_addr_b <= xfer_ptr; + ram_we_b <= xfer_cnt_adv; + + cmd_fifo_we <= commit_en; + cmd_fifo_re <= uncommit_en; + cmd_fifo_din <= "0000" & resize(byte_count_reg_s, 16) & resize(xfer_base, 16); + +------------------------------------------------------------------ +host_state_next: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + host_s <= host_init; + else + host_s <= host_sn; + end if; + end if; + end process; + +host_state: + process(host_s, cmd_fifo_empty, ctrl_in.data_read, ctrl_in.uncommit) + begin + + flush_en <= '0'; + fill_ptr_set <= '0'; + fill_ptr_adv <= '0'; + uncommit_en <= '0'; + + host_sn <= host_s; + + case host_s is + + when host_init => + flush_en <= '1'; + host_sn <= host_flush; + + when host_flush => + flush_en <= '1'; + host_sn <= host_idle; + + when host_idle => + if cmd_fifo_empty = '0' then + host_sn <= host_setup; + end if; + + when host_setup => + fill_ptr_set <= '1'; + host_sn <= host_arm; + + when host_arm => + host_sn <= host_fill; + + when host_fill => + fill_ptr_adv <= ctrl_in.data_read; + if ctrl_in.uncommit = '1' then + host_sn <= host_uncommit; + end if; + + when host_uncommit => + uncommit_en <= '1'; + host_sn <= host_idle; + + when others => + host_sn <= host_idle; + end case; + + end process; + +------------------------------------------------------------------ +-- Fill stuff +------------------------------------------------------------------ +fill_pointer: + process(clk) + begin + if rising_edge(clk) then + ctrl_out.data_vld <= ctrl_in.data_read; + if fill_ptr_set = '1' then + fill_ptr <= resize(cmd_fifo_dout(15 downto 0), word_ptr_t'length); + elsif fill_ptr_adv = '1' then + fill_ptr <= fill_ptr + 1; + end if; + end if; + end process; + ------------------------------------------------------------------ -- Transfer stuff ------------------------------------------------------------------ @@ -117,34 +228,53 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, mii_rx_dv) + process(xfer_s, mii_fifo_empty, xfer_rdy, xfer_ram_full) begin + commit_en <= '0'; + xfer_ptr_set <= '0'; + xfer_ptr_adv <= '0'; + xfer_cnt_set <= '0'; + xfer_cnt_adv <= '0'; + word_count_ack <= '0'; + mii_fifo_re <= '0'; + xfer_sn <= xfer_s; case xfer_s is when xfer_init => - xfer_sn <= xfer_idle; + xfer_sn <= xfer_idle; when xfer_idle => - xfer_sn <= xfer_setup; + if mii_fifo_empty = '0' then + xfer_sn <= xfer_setup; + end if; when xfer_setup => + xfer_cnt_set <= '1'; + xfer_ptr_set <= '1'; xfer_sn <= xfer_wait; when xfer_wait => - if mii_rx_dv = '1' then - xfer_sn <= xfer_active; - end if; + xfer_sn <= xfer_active; when xfer_active => - if mii_rx_dv = '0' then + mii_fifo_re <= '1'; + xfer_cnt_adv <= not mii_fifo_empty; + xfer_ptr_adv <= not mii_fifo_empty; + if xfer_ram_full = '1' then xfer_sn <= xfer_free; + elsif xfer_rdy = '1' then + if mii_fifo_empty = '1' then + xfer_sn <= xfer_free; + end if; end if; when xfer_free => - xfer_sn <= xfer_init; + word_count_ack <= '1'; + commit_en <= not xfer_ram_full; + xfer_sn <= xfer_idle; when others => xfer_sn <= xfer_idle; @@ -152,6 +282,66 @@ xfer_state: end process; +------------------------------------------------------------------ +xfer_ram_full_detect: + process(clk) + begin + if rising_edge(clk) then + if xfer_ptr_set = '1' or flush_en = '1' then + xfer_ram_full <= '0'; + elsif xfer_ptr_adv = '1' then + if xfer_ptr_next = resize(cmd_fifo_dout(15 downto 0), word_ptr_t'length) then + xfer_ram_full <= '1'; + end if; + end if; + end if; + + end process; + +xfer_counter: + process(clk) + begin + if rising_edge(clk) then + xfer_rdy <= '0'; + if xfer_size = word_count_reg then + xfer_rdy <= word_count_vld; + end if; + if xfer_cnt_set = '1' then + xfer_size <= (others => '0'); + elsif xfer_cnt_adv = '1' then + xfer_size <= xfer_size + 1; + end if; + end if; + + end process; + +xfer_pointer: + process(clk) + begin + if rising_edge(clk) then + if xfer_ptr_set = '1' then + xfer_ptr <= xfer_base; + xfer_ptr_next <= xfer_base + 1; + elsif xfer_ptr_adv = '1' then + xfer_ptr <= xfer_ptr_next; + xfer_ptr_next <= xfer_ptr_next + 1; + end if; + end if; + + end process; + +xfer_base_logic: + process(clk) + begin + if rising_edge(clk) then + if flush_en = '1' then + xfer_base <= (others => '0'); + elsif commit_en = '1' then + xfer_base <= xfer_ptr; + end if; + end if; + end process; + ------------------------------------------------------------------ byte_counter: process(mii_rx_clk) @@ -178,13 +368,91 @@ byte_count_register: end if; end process; +word_counter: + process(mii_rx_clk) + begin + if rising_edge(mii_rx_clk) then + if rst = '1' or word_count_clr = '1' then + word_count <= (others => '0'); + elsif sipo_dout_vld = '1' then + word_count <= word_count + 1; + end if; + end if; + end process; + +-- MII doamin +word_count_set_logic: + process(mii_rx_clk) + begin + if rising_edge(mii_rx_clk) then + if rst = '1' or word_count_clr = '1' then + word_count_set <= '0'; + elsif sipo_dout_vld = '1' and mii_rx_dv = '0' then + word_count_set <= '1'; + end if; + end if; + end process; + +-- Host doamin +word_count_clr_logic: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + word_count_clr <= '0'; + elsif word_count_set = '1' then + if word_count_ack = '1' then + word_count_clr <= '1'; + end if; + else + word_count_clr <= '0'; + end if; + end if; + end process; + +word_count_register: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' or word_count_ack = '1' then + word_count_vld <= '0'; + elsif word_count_set = '1' then + word_count_reg <= word_count; + byte_count_reg_s <= byte_count_reg; + word_count_vld <= '1'; + end if; + end if; + end process; + sipo_rst <= not mii_rx_dv; ------------------------------------------------------------------ +-- Instantiate synchronous FIFO +inst_cmd_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words) + data_width => cmd_fifo_din'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => flush_en, + clk => clk, + we => cmd_fifo_we, + re => cmd_fifo_re, + fifo_full => cmd_fifo_full, + fifo_empty => cmd_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => cmd_fifo_din, + data_r => cmd_fifo_dout + ); + inst_ram : entity work.dpram_2w2r GENERIC MAP ( addr_width => RAM_ADDR_WIDTH, - data_width => 36 + data_width => 32 ) PORT MAP ( @@ -203,7 +471,7 @@ inst_ram : entity work.dpram_2w2r ); -- Instantiate synchronous FIFO -inst_fifo: entity work.fifo_async +inst_mii_fifo: entity work.fifo_async GENERIC MAP ( addr_width => 5, @@ -213,16 +481,16 @@ inst_fifo: entity work.fifo_async PORT MAP ( rst => rst, - clk_w => clk, - clk_r => mii_rx_clk, - we => fifo_we, - re => fifo_re, - fifo_full => fifo_full, - fifo_empty => fifo_empty, + clk_w => mii_rx_clk, + clk_r => clk, + we => mii_fifo_we, + re => mii_fifo_re, + fifo_full => mii_fifo_full, + fifo_empty => mii_fifo_empty, fifo_afull => open, fifo_aempty => open, - data_w => fifo_din, - data_r => fifo_dout + data_w => mii_fifo_din, + data_r => mii_fifo_dout ); inst_sipo : entity work.sipo diff --git a/lib/emac/src/emac_top_jb.vhd b/lib/emac/src/emac_top_jb.vhd index 5cb5924..3e91db3 100644 --- a/lib/emac/src/emac_top_jb.vhd +++ b/lib/emac/src/emac_top_jb.vhd @@ -73,8 +73,9 @@ registers_write: if rising_edge(CLK_I) then if_rdy <= '1'; tx_ctrl_in.data_vld <= '0'; - tx_ctrl_in.alloc_req_size_vld <= '0'; - tx_ctrl_in.alloc_req_en <= '0'; + tx_ctrl_in.tx_size_vld <= '0'; + tx_ctrl_in.tx_req_en <= '0'; + rx_ctrl_in.uncommit <= '0'; if RST_I = '1' then rx_int_en <= '0'; tx_int_en <= '0'; @@ -84,18 +85,19 @@ registers_write: when "0000" => tx_ctrl_in.tx_er <= DAT_I(31); - tx_ctrl_in.alloc_req_en <= DAT_I(16); + tx_ctrl_in.tx_req_en <= DAT_I(17); + rx_ctrl_in.uncommit <= DAT_I(16); tx_int_en <= DAT_I(5); rx_int_en <= DAT_I(4); when "0001" => if_rdy <= '0'; -- allow request size to propagate inside TX module - tx_ctrl_in.alloc_req_size_vld <= '1'; - tx_din <= X"0000" & DAT_I(31 downto 16); + tx_ctrl_in.tx_size_vld <= '1'; + tx_din <= X"0000" & DAT_I(31 downto 16); when "0010" => - tx_ctrl_in.data_vld <= '1'; - tx_din <= DAT_I; + tx_ctrl_in.data_vld <= '1'; + tx_din <= DAT_I; when others => null; end case; @@ -107,26 +109,31 @@ registers_read: process(CLK_I) begin if rising_edge(CLK_I) then - ACK_O <= '0'; + rx_ctrl_in.data_read <= '0'; + ACK_O <= rx_ctrl_out.data_vld; + DAT_O <= rx_dout; 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 <= (others => '0'); + ACK_O <= not WE_I; DAT_O(31) <= tx_ctrl_in.tx_er; DAT_O(30) <= mii_rx_er; DAT_O(29) <= mii_col; DAT_O(28) <= mii_crs; - DAT_O(16) <= tx_ctrl_out.alloc_req; + DAT_O(17) <= tx_ctrl_out.tx_req; + DAT_O(16) <= rx_ctrl_out.rx_vld; DAT_O(5) <= tx_int_en; DAT_O(4) <= rx_int_en; when "0001" => - DAT_O(31 downto 16) <= tx_ctrl_out.alloc_req_size(15 downto 0); + ACK_O <= not WE_I; + DAT_O <= tx_ctrl_out.tx_size & rx_ctrl_out.rx_size; when "0010" => - + rx_ctrl_in.data_read <= not WE_I; + when others => null; end case; end if; diff --git a/lib/emac/src/emac_tx.vhd b/lib/emac/src/emac_tx.vhd index a79fc53..d17af8f 100644 --- a/lib/emac/src/emac_tx.vhd +++ b/lib/emac/src/emac_tx.vhd @@ -33,20 +33,25 @@ ARCHITECTURE behavior OF emac_tx IS subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0); - signal fifo_din : unsigned(35 downto 0); - signal fifo_dout : unsigned(35 downto 0); - signal fifo_we : std_logic; - signal fifo_re : std_logic; - signal fifo_empty : std_logic; - signal fifo_full : std_logic; + signal mii_fifo_din : unsigned(35 downto 0); + signal mii_fifo_dout : unsigned(35 downto 0); + signal mii_fifo_we : std_logic; + signal mii_fifo_re : std_logic; + signal mii_fifo_empty : std_logic; + signal mii_fifo_full : std_logic; + + signal cmd_fifo_din : unsigned(35 downto 0); + signal cmd_fifo_dout : unsigned(35 downto 0); + signal cmd_fifo_we : std_logic; + signal cmd_fifo_re : std_logic; + signal cmd_fifo_empty : std_logic; + signal cmd_fifo_full : std_logic; signal flush_en : std_logic; - signal flush_rdy : std_logic; - signal flush_ptr_set : std_logic; - signal flush_ptr : word_ptr_t; - + signal alloc_req_size : unsigned(15 downto 0); + signal fill_base : word_ptr_t; signal fill_size : word_ptr_t; signal fill_cnt : word_ptr_t; signal fill_ptr : word_ptr_t; @@ -62,7 +67,6 @@ ARCHITECTURE behavior OF emac_tx IS signal alloc_ack : std_logic; signal nwords_free : word_ptr_t; - signal alloc_base : word_ptr_t; signal alloc_size : word_ptr_t; signal alloc_en : std_logic; @@ -86,13 +90,13 @@ ARCHITECTURE behavior OF emac_tx IS signal ram_en_a : std_logic; signal ram_we_a : std_logic; signal ram_addr_a : word_ptr_t; - signal ram_din_a : unsigned(35 downto 0); - signal ram_dout_a : unsigned(35 downto 0); + signal ram_din_a : unsigned(31 downto 0); + signal ram_dout_a : unsigned(31 downto 0); signal ram_en_b : std_logic; signal ram_we_b : std_logic; signal ram_addr_b : word_ptr_t; - signal ram_din_b : unsigned(35 downto 0); - signal ram_dout_b : unsigned(35 downto 0); + signal ram_din_b : unsigned(31 downto 0); + signal ram_dout_b : unsigned(31 downto 0); signal piso_din_be : unsigned(3 downto 0); signal piso_din_rdy : std_logic; @@ -102,16 +106,6 @@ ARCHITECTURE behavior OF emac_tx IS signal inter_frame_gap_cnt : inter_frame_gap_cnt_t; signal inter_frame_gap_rdy : std_logic; - alias ram_data_in_a is ram_din_a(31 downto 0); - alias ram_tag_in_a is ram_din_a(35 downto 32); - alias ram_data_out_a is ram_dout_a(31 downto 0); - alias ram_tag_out_a is ram_dout_a(35 downto 32); - - alias ram_data_in_b is ram_din_b(31 downto 0); - alias ram_tag_in_b is ram_din_b(35 downto 32); - alias ram_data_out_b is ram_dout_b(31 downto 0); - alias ram_tag_out_b is ram_dout_b(35 downto 32); - type host_state_t is (host_init, host_flush, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit); signal host_s, host_sn : host_state_t; @@ -130,28 +124,30 @@ ARCHITECTURE behavior OF emac_tx IS begin - ctrl_out.alloc_req <= alloc_req; + ctrl_out.tx_req <= alloc_req; mii_tx_er <= ctrl_in.tx_er; - ram_tag_in_b <= "0000"; - ram_en_b <= not fifo_full or uncommit_en or flush_en; - ram_we_b <= uncommit_en or flush_en; - ram_addr_b <= flush_ptr when (flush_en = '1' or uncommit_en = '1') else xfer_ptr; - xfer_tag <= ram_tag_out_b; ram_en_a <= '1'; - ram_we_a <= commit_en or fill_cnt_adv; - ram_tag_in_a <= fill_remain & "01" when commit_en = '1' else "0000"; - ram_data_in_a <= resize(fill_size, 16) & resize(alloc_base, 16) when commit_en = '1' else din; - ram_addr_a <= alloc_base when commit_en = '1' else fill_ptr; + ram_we_a <= fill_ptr_adv; + ram_din_a <= din; + ram_addr_a <= fill_ptr; piso_din_be <= (others => '1'); - fifo_re <= piso_din_rdy; - data_vld <= not fifo_empty; + mii_fifo_re <= piso_din_rdy; + data_vld <= not mii_fifo_empty; - fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(xfer_remain)) when xfer_remain_en = '1' else "1111"; - fifo_din(31 downto 0) <= ram_data_out_b; + mii_fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(xfer_remain)) when xfer_remain_en = '1' else "1111"; + mii_fifo_din(31 downto 0) <= ram_dout_b; + + cmd_fifo_we <= commit_en; + cmd_fifo_re <= uncommit_en; + cmd_fifo_din <= fill_remain & "01" & resize(fill_size, 16) & resize(fill_base, 16); + ram_en_b <= not mii_fifo_full or uncommit_en; + ram_we_b <= '0'; + ram_addr_b <= xfer_ptr; + xfer_tag <= cmd_fifo_dout(35 downto 32); ------------------------------------------------------------------ host_state_next: @@ -167,17 +163,16 @@ host_state_next: end process; host_state: - process(host_s, flush_rdy, alloc_req, alloc_OK, fill_rdy, ctrl_in.data_vld) + process(host_s, alloc_req, alloc_OK, fill_rdy, ctrl_in.data_vld) begin flush_en <= '0'; - flush_ptr_set <= '0'; - alloc_ack <= '0'; fill_cnt_set <= '0'; fill_cnt_adv <= '0'; fill_ptr_set <= '0'; fill_ptr_adv <= '0'; commit_en <= '0'; + alloc_ack <= '0'; alloc_en <= '0'; host_sn <= host_s; @@ -185,15 +180,12 @@ host_state: case host_s is when host_init => - flush_ptr_set <= '1'; + flush_en <= '1'; host_sn <= host_flush; when host_flush => flush_en <= '1'; - if flush_rdy = '1' then - flush_en <= '0'; - host_sn <= host_idle; - end if; + host_sn <= host_idle; when host_idle => if alloc_req = '1' then @@ -212,7 +204,6 @@ host_state: host_sn <= host_arm; when host_arm => - fill_ptr_adv <= '1'; fill_cnt_adv <= '1'; host_sn <= host_fill; @@ -243,7 +234,7 @@ alloc_req_size_register: process(clk) begin if rising_edge(clk) then - if ctrl_in.alloc_req_size_vld = '1' then + if ctrl_in.tx_size_vld = '1' then alloc_req_size <= din(15 downto 0); end if; end if; @@ -256,14 +247,14 @@ alloc_request_logic: if rising_edge(clk) then if rst = '1' then alloc_req <= '0'; - elsif ctrl_in.alloc_req_en = '1' and alloc_req = '0' then + elsif ctrl_in.tx_req_en = '1' and alloc_req = '0' then alloc_req <= '1'; fill_remain <= alloc_req_size(1 downto 0); fill_size <= alloc_req_size(word_ptr_t'left+2 downto 2); if din(1 downto 0) /= "00" then fill_size <= alloc_req_size(word_ptr_t'left+2 downto 2) + 1; end if; - ctrl_out.alloc_req_size <= resize(alloc_req_size(word_ptr_t'left downto 0), 16); + ctrl_out.tx_size <= resize(alloc_req_size(word_ptr_t'left downto 0), 16); elsif alloc_ack = '1' then alloc_req <= '0'; @@ -273,14 +264,14 @@ alloc_request_logic: end process; ------------------------------------------------------------------ -alloc_base_logic: +fill_base_logic: process(clk) begin if rising_edge(clk) then if flush_en = '1' then - alloc_base <= (others => '0'); + fill_base <= (others => '0'); elsif commit_en = '1' then - alloc_base <= fill_ptr; + fill_base <= fill_ptr; end if; end if; end process; @@ -314,26 +305,6 @@ nwords_free_counter: end if; end process; ------------------------------------------------------------------- -flush_counter: - process(clk) - begin - if rising_edge(clk) then - if flush_en = '0' then - flush_rdy <= '0'; - if flush_ptr_set = '1' then - flush_ptr <= (others => '1'); - elsif xfer_ptr_set = '1' then - flush_ptr <= ram_data_out_b(flush_ptr'left downto 0); - end if; - elsif flush_ptr /= 0 then - flush_ptr <= flush_ptr - 1; - else - flush_rdy <= '1'; - end if; - end if; - end process; - ------------------------------------------------------------------ -- Fill stuff ------------------------------------------------------------------ @@ -359,7 +330,7 @@ fill_pointer: begin if rising_edge(clk) then if fill_ptr_set = '1' then - fill_ptr <= alloc_base; + fill_ptr <= fill_base; elsif fill_ptr_adv = '1' then fill_ptr <= fill_ptr + 1; end if; @@ -382,7 +353,7 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, xfer_tag, xfer_odd, xfer_rdy, inter_frame_gap_rdy, alloc_en, fifo_full) + process(xfer_s, cmd_fifo_empty, xfer_odd, xfer_rdy, inter_frame_gap_rdy, alloc_en, mii_fifo_full) begin xfer_cnt_set <= '0'; @@ -390,7 +361,7 @@ xfer_state: xfer_ptr_set <= '0'; xfer_ptr_adv <= '0'; xfer_remain_en <= '0'; - fifo_we <= '0'; + mii_fifo_we <= '0'; free_en <= '0'; uncommit_en <= '0'; @@ -402,7 +373,7 @@ xfer_state: xfer_sn <= xfer_idle; when xfer_idle => - if xfer_tag(0) = '1' then + if cmd_fifo_empty = '0' then xfer_ptr_set <= '1'; xfer_cnt_set <= '1'; xfer_sn <= xfer_wait; @@ -411,25 +382,23 @@ xfer_state: when xfer_wait => if inter_frame_gap_rdy = '1' then xfer_sn <= xfer_setup; - xfer_ptr_adv <= '1'; xfer_cnt_adv <= '1'; - uncommit_en <= '1'; end if; when xfer_setup => - xfer_ptr_adv <= '1'; xfer_cnt_adv <= '1'; + xfer_ptr_adv <= '1'; xfer_sn <= xfer_active; when xfer_active => - fifo_we <= '1'; - xfer_cnt_adv <= not fifo_full; - xfer_ptr_adv <= not fifo_full; + mii_fifo_we <= '1'; + xfer_cnt_adv <= not mii_fifo_full; + xfer_ptr_adv <= not mii_fifo_full; if xfer_rdy = '1' then xfer_remain_en <= xfer_odd; xfer_cnt_adv <= '0'; xfer_ptr_adv <= '0'; - if fifo_full = '0' then + if mii_fifo_full = '0' then xfer_sn <= xfer_free; end if; end if; @@ -437,6 +406,7 @@ xfer_state: when xfer_free => free_en <= not alloc_en; if alloc_en = '0' then + uncommit_en <= '1'; xfer_sn <= xfer_idle; end if; @@ -453,7 +423,7 @@ interframe_gap_counter: if rising_edge(clk) then if flush_en = '1' then inter_frame_gap_rdy <= '1'; - elsif fifo_empty = '0' then + elsif mii_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 @@ -472,7 +442,7 @@ xfer_counter: if xfer_cnt_set = '1' then xfer_size <= (others => '0'); xfer_rdy <= '0'; - xfer_cnt <= ram_data_out_b(xfer_ptr'left+16 downto 16); + xfer_cnt <= cmd_fifo_dout(xfer_ptr'left+16 downto 16); elsif xfer_cnt_adv = '1' then if xfer_cnt /= 0 then xfer_cnt <= xfer_cnt - 1; @@ -490,7 +460,7 @@ xfer_pointer: begin if rising_edge(clk) then if xfer_ptr_set = '1' then - xfer_ptr <= ram_data_out_b(xfer_ptr'left downto 0); + xfer_ptr <= cmd_fifo_dout(xfer_ptr'left downto 0); xfer_remain <= xfer_tag(3 downto 2); xfer_odd <= '0'; if xfer_tag(3 downto 2) /= "00" then @@ -503,11 +473,12 @@ xfer_pointer: end process; +------------------------------------------------------------------ inst_ram : entity work.dpram_2w2r GENERIC MAP ( addr_width => RAM_ADDR_WIDTH, - data_width => 36 + data_width => 32 ) PORT MAP ( @@ -526,11 +497,33 @@ inst_ram : entity work.dpram_2w2r ); -- Instantiate synchronous FIFO -inst_fifo: entity work.fifo_async +inst_cmd_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words) + data_width => cmd_fifo_din'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => flush_en, + clk => clk, + we => cmd_fifo_we, + re => cmd_fifo_re, + fifo_full => cmd_fifo_full, + fifo_empty => cmd_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => cmd_fifo_din, + data_r => cmd_fifo_dout + ); + +-- Instantiate synchronous FIFO +inst_mii_fifo: entity work.fifo_async GENERIC MAP ( addr_width => 4, - data_width => 36, + data_width => mii_fifo_din'length, do_last_read_update => true ) PORT MAP @@ -538,14 +531,14 @@ inst_fifo: entity work.fifo_async rst => rst, clk_w => clk, clk_r => mii_tx_clk, - we => fifo_we, - re => fifo_re, - fifo_full => fifo_full, - fifo_empty => fifo_empty, + we => mii_fifo_we, + re => mii_fifo_re, + fifo_full => mii_fifo_full, + fifo_empty => mii_fifo_empty, fifo_afull => open, fifo_aempty => open, - data_w => fifo_din, - data_r => fifo_dout + data_w => mii_fifo_din, + data_r => mii_fifo_dout ); inst_piso : entity work.piso @@ -561,8 +554,8 @@ inst_piso : entity work.piso clk => mii_tx_clk, din_vld => data_vld, din_rdy => piso_din_rdy, - din_be => fifo_dout(35 downto 32), - din => fifo_dout(31 downto 0), + din_be => mii_fifo_dout(35 downto 32), + din => mii_fifo_dout(31 downto 0), dout_en => mii_tx_en, dout => mii_tx diff --git a/lib/emac/src/emac_types.vhd b/lib/emac/src/emac_types.vhd index 979a66e..6e1f276 100644 --- a/lib/emac/src/emac_types.vhd +++ b/lib/emac/src/emac_types.vhd @@ -16,23 +16,26 @@ package emac_types is -- Types type tx_ctrl_in_t is record tx_er : std_logic; - alloc_req_size_vld : std_logic; + tx_size_vld : std_logic; data_vld : std_logic; - alloc_req_en : std_logic; + tx_req_en : std_logic; end record; type tx_ctrl_out_t is record - alloc_req_size : unsigned(15 downto 0); - alloc_req : std_logic; + tx_size : unsigned(15 downto 0); + tx_req : std_logic; end record; type rx_ctrl_in_t is record - dummy : std_logic; + data_read : std_logic; + uncommit : std_logic; end record; type rx_ctrl_out_t is record rx_er : std_logic; + rx_vld : std_logic; data_vld : std_logic; + rx_size : unsigned(15 downto 0); end record; -- Functions diff --git a/lib/emac/src/tb_emac_top_jb.vhd b/lib/emac/src/tb_emac_top_jb.vhd index 5cf347b..861556f 100644 --- a/lib/emac/src/tb_emac_top_jb.vhd +++ b/lib/emac/src/tb_emac_top_jb.vhd @@ -68,7 +68,7 @@ ARCHITECTURE behavior OF tb_emac_top_jb IS signal loop_back_en : std_logic := '0'; - type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_read); + type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_read, emac_free); signal emac_action : emac_action_t; BEGIN @@ -163,7 +163,7 @@ STIMULUS: process -- set alloc request CYC_I <= '1'; wait until rising_edge(CLK) and SRDY_O = '1'; - DAT_I <= X"0001_0000"; + DAT_I <= X"0002_0000"; STB_I <= '1'; WE_I <= '1'; ADDR_I <= X"0000_0000"; @@ -183,7 +183,7 @@ STIMULUS: process STB_I <= '0'; wait until rising_edge(CLK) and ACK_O = '1'; wait until rising_edge(CLK); - if DAT_O_reg(16) = '0' then + if DAT_O_reg(17) = '0' then exit check_bsy; end if; end loop; @@ -228,6 +228,90 @@ STIMULUS: process end procedure emac_write; + procedure emac_read (size_in : natural) is + variable data : unsigned (7 downto 0); + variable size, num_words : natural; + begin + + emac_action <= emac_read; + + -- check if data available + check_data_avail: + while (true) loop + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + WE_I <= '0'; + STB_I <= '1'; + ADDR_I <= X"0000_0000"; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + wait until rising_edge(CLK); + if DAT_O_reg(16) = '1' then + exit check_data_avail; + end if; + end loop; + + read_size: + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + WE_I <= '0'; + STB_I <= '1'; + ADDR_I <= X"0000_0004"; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + wait until rising_edge(CLK); + + + -- Read RX data + size := size_in; + if (size_in = 0) then + size := to_integer(DAT_O_reg(15 downto 0)); + end if; + + if (size mod 4) = 0 then + num_words := size/4; + else + num_words := size/4 + 1; + end if; + + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + data := X"00"; + ADDR_I <= X"0000_0008"; + WE_I <= '0'; + STB_I <= '1'; + for i in 1 to num_words loop + wait until rising_edge(CLK) and SRDY_O = '1'; + end loop; + STB_I <= '0'; + wait until rising_edge(CLK) and SRDY_O = '1'; + emac_action <= emac_idle; + + end procedure emac_read; + + procedure emac_free is + begin + + -- RX- DEALLOCATION + emac_action <= emac_free; + + -- set free request + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + DAT_I <= X"0001_0000"; + STB_I <= '1'; + WE_I <= '1'; + ADDR_I <= X"0000_0000"; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + WE_I <= '0'; + + emac_action <= emac_idle; + + end procedure emac_free; + begin wait for 6*MII_CLK_PERIOD; @@ -238,49 +322,79 @@ STIMULUS: process emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (64); emac_write (64); + emac_read (0); + emac_free; emac_alloc (512); emac_write (512); + emac_read (0); + emac_free; emac_alloc (1536); emac_write (1536); + emac_read (0); + emac_free; emac_alloc (65); emac_write (65); + emac_read (0); + emac_free; emac_alloc (66); emac_write (66); + emac_read (0); + emac_free; emac_alloc (67); emac_write (67); + emac_read (0); + emac_free; emac_alloc (512); emac_write (64); + emac_read (0); + emac_free; emac_alloc (128); emac_write (128); - + emac_read (0); + emac_free; + wait; end process;