From e8deef86a6fa7c821f07b71d4ccea326e1fb725b Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 4 Apr 2010 09:55:22 +0000 Subject: [PATCH] - added preamble genration - simplified design 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@853 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/emac/src/emac_tx.vhd | 357 ++++++++++++++++++++++++--------------- lib/emac/src/pkt_gen.vhd | 305 +++++++++++++++++++++------------ 2 files changed, 413 insertions(+), 249 deletions(-) diff --git a/lib/emac/src/emac_tx.vhd b/lib/emac/src/emac_tx.vhd index c8cd4ec..5d72565 100644 --- a/lib/emac/src/emac_tx.vhd +++ b/lib/emac/src/emac_tx.vhd @@ -41,8 +41,8 @@ ARCHITECTURE behavior OF emac_tx IS 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_din : unsigned(2*word_ptr_t'length-1 downto 0); + signal cmd_fifo_dout : unsigned(2*word_ptr_t'length-1 downto 0); signal cmd_fifo_we : std_logic; signal cmd_fifo_re : std_logic; signal cmd_fifo_empty : std_logic; @@ -54,12 +54,12 @@ ARCHITECTURE behavior OF emac_tx IS 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_pre_rdy : std_logic; + signal fill_bsy : std_logic; signal fill_remain : unsigned(1 downto 0); + signal fill_set : std_logic; + signal fill_en : std_logic; + signal fill_cnt_en : std_logic; signal alloc_OK : std_logic; signal alloc_req : std_logic; @@ -67,59 +67,61 @@ ARCHITECTURE behavior OF emac_tx IS signal alloc_size : word_ptr_t; signal alloc_remain : unsigned(1 downto 0); - signal nwords_free : word_ptr_t; - signal mem_alloc_en : std_logic; - - signal mem_free_en : std_logic; signal commit_en : std_logic; signal uncommit_en : std_logic; + signal mem_alloc_en : std_logic; + signal mem_free_en : std_logic; + signal nwords_free : word_ptr_t; signal xfer_size : word_ptr_t; signal xfer_ptr : 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 xfer_set : std_logic; + signal xfer_en : std_logic; + signal xfer_sync : unsigned(1 downto 0); + signal xfer_cnt_en : std_logic; + signal xfer_bsy : 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(31 downto 0); - signal ram_dout_a : unsigned(31 downto 0); + signal ram_din_a : unsigned(35 downto 0); + signal ram_dout_a : unsigned(35 downto 0); signal ram_en_b : std_logic; signal ram_addr_b : word_ptr_t; - signal ram_din_b : unsigned(31 downto 0); - signal ram_dout_b : unsigned(31 downto 0); + signal ram_din_b : unsigned(35 downto 0); + signal ram_dout_b : unsigned(35 downto 0); - signal piso_din_be : unsigned(3 downto 0); - signal piso_din_rdy : std_logic; - signal data_vld : std_logic; + signal piso8_din : unsigned(31 downto 0); + signal piso8_din_be : unsigned(3 downto 0); + signal piso8_din_rdy : std_logic; + signal piso8_din_vld : std_logic; - signal piso_dout : unsigned(7 downto 0); - signal piso_dout_vld : std_logic; - signal piso_10mbps_din_rdy : std_logic; - signal tx_en : std_logic; + signal piso8_dout : unsigned(7 downto 0); + signal piso8_dout_vld : std_logic; + signal piso8_dout_en : std_logic; - signal reset_pipe : unsigned(31 downto 0); + signal piso4_dout_vld : std_logic; + signal piso4_din_rdy : std_logic; + signal piso4_dout : unsigned(3 downto 0); + + signal reset_pipe : unsigned(31 downto 0); subtype ifg_cnt_t is natural range 0 to 23; -- 10/100 mbps -- subtype ifg_cnt_t is natural range 0 to 11; -- 1000 mbps - signal ifg_cnt : ifg_cnt_t; - signal ifg_rdy : std_logic; - signal ifg_idle : std_logic; - - type host_state_t is (host_init, host_flush, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit); + + signal ifg_cnt : ifg_cnt_t; + signal ifg_idle : std_logic; + + type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit); signal host_s, host_sn : host_state_t; - type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_arm, xfer_active, xfer_uncommit, xfer_free, xfer_wait); + type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_arm, xfer_active, xfer_uncommit, xfer_free); signal xfer_s, xfer_sn : xfer_state_t; + type stream_state_t is (stream_init, stream_idle, stream_start, stream_preamble0, stream_preamble1, stream_active, stream_crc, stream_stop, stream_finish); + signal stream_s, stream_sn : stream_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 := ( @@ -129,7 +131,16 @@ ARCHITECTURE behavior OF emac_tx IS "1110" ); + signal preamble_en : std_logic; + signal preamble_addr : natural range 0 to 1; + type preamble_t is array (0 to 1) of unsigned(31 downto 0); + constant preamble : preamble_t := + ( + X"55555555", + X"555555D5" + ); + begin ctrl_out.pkt_alloc_req <= alloc_req; @@ -138,26 +149,29 @@ begin mii_tx_er <= ctrl_in.tx_er; - ram_en_a <= '1'; - ram_we_a <= fill_ptr_adv; - ram_din_a <= din; + ram_en_a <= din_vld; + ram_we_a <= fill_bsy; + ram_din_a(31 downto 0) <= din; + ram_din_a(35 downto 32) <= piso_byte_mask_rom(to_integer(fill_remain)) when fill_pre_rdy = '1' else "1111"; ram_addr_a <= fill_ptr; - piso_din_be <= mii_fifo_dout(35 downto 32); - mii_fifo_re <= piso_din_rdy; - data_vld <= not mii_fifo_empty; - - 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; + mii_fifo_din <= ram_dout_b; + piso8_din <= preamble(preamble_addr) when preamble_en = '1' else mii_fifo_dout(31 downto 0); + piso8_din_be <= "1111" when preamble_en = '1' else mii_fifo_dout(35 downto 32); + cmd_fifo_we <= commit_en; cmd_fifo_re <= uncommit_en; - cmd_fifo_din <= fill_remain & "01" & resize(fill_size, 16) & resize(fill_base, 16); + cmd_fifo_din <= fill_size & fill_base; ram_en_b <= not mii_fifo_full; ram_addr_b <= xfer_ptr; - xfer_tag <= cmd_fifo_dout(35 downto 32); reset_en <= reset_pipe(reset_pipe'left); + + mii_fifo_we <= xfer_bsy; + xfer_cnt_en <= xfer_bsy and not mii_fifo_full; + fill_cnt_en <= fill_bsy and din_vld; + ------------------------------------------------------------------ reset_gen: process(clk) @@ -185,13 +199,11 @@ host_state_next: end process; host_state: - process(host_s, alloc_OK, fill_rdy, din_vld, ctrl_in.pkt_commit_en, alloc_req) + process(host_s, alloc_OK, fill_bsy, ctrl_in.pkt_commit_en, alloc_req) begin - fill_cnt_set <= '0'; - fill_cnt_adv <= '0'; - fill_ptr_set <= '0'; - fill_ptr_adv <= '0'; + fill_set <= '0'; + fill_en <= '0'; commit_en <= '0'; alloc_ack <= '0'; mem_alloc_en <= '0'; @@ -217,18 +229,16 @@ host_state: end if; when host_setup => + fill_set <= '1'; host_sn <= host_arm; - fill_cnt_set <= '1'; - fill_ptr_set <= '1'; when host_arm => + fill_en <= '1'; alloc_ack <= '1'; - fill_cnt_adv <= '1'; host_sn <= host_fill; when host_fill => - fill_cnt_adv <= din_vld; - fill_ptr_adv <= not fill_rdy and din_vld; + fill_en <= '1'; if alloc_req = '1' then host_sn <= host_alloc; elsif ctrl_in.pkt_commit_en = '1' then @@ -265,10 +275,6 @@ alloc_request_logic: ctrl_out.tx_size <= resize(ctrl_in.tx_size(word_ptr_t'left downto 0), 16); elsif alloc_ack = '1' then alloc_req <= '0'; - if alloc_OK = '1' then - fill_size <= alloc_size; - fill_remain <= alloc_remain; - end if; end if; end if; end process; @@ -333,14 +339,23 @@ fill_counter: process(clk) begin if rising_edge(clk) then - if fill_cnt_set = '1' then - fill_rdy <= '0'; - fill_cnt <= fill_size; - elsif fill_cnt_adv = '1' then - if fill_cnt /= 0 then - fill_cnt <= fill_cnt - 1; - else - fill_rdy <= '1'; + if fill_set = '1' then + fill_bsy <= '0'; + fill_pre_rdy <= '0'; + fill_cnt <= alloc_size; + fill_size <= alloc_size; + fill_remain <= alloc_remain; + elsif fill_en = '1' then + fill_bsy <= '1'; + if fill_cnt_en = '1' or fill_bsy = '0' then + if fill_cnt /= 1 then + fill_cnt <= fill_cnt - 1; + else + fill_pre_rdy <= '1'; + end if; + if fill_pre_rdy = '1' then + fill_bsy <= '0'; + end if; end if; end if; end if; @@ -350,9 +365,9 @@ fill_pointer: process(clk) begin if rising_edge(clk) then - if fill_ptr_set = '1' then + if fill_set = '1' then fill_ptr <= fill_base; - elsif fill_ptr_adv = '1' then + elsif fill_cnt_en = '1' then fill_ptr <= fill_ptr + 1; end if; end if; @@ -374,15 +389,11 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, cmd_fifo_empty, xfer_odd, xfer_rdy, ifg_rdy, mem_alloc_en, mii_fifo_full) + process(xfer_s, cmd_fifo_empty, xfer_bsy, xfer_sync, mem_alloc_en) begin - xfer_cnt_set <= '0'; - xfer_cnt_adv <= '0'; - xfer_ptr_set <= '0'; - xfer_ptr_adv <= '0'; - xfer_remain_en <= '0'; - mii_fifo_we <= '0'; + xfer_set <= '0'; + xfer_en <= '0'; mem_free_en <= '0'; uncommit_en <= '0'; @@ -399,32 +410,17 @@ xfer_state: end if; when xfer_setup => - xfer_ptr_set <= '1'; - xfer_cnt_set <= '1'; + xfer_set <= '1'; xfer_sn <= xfer_arm; when xfer_arm => - xfer_cnt_adv <= '1'; - xfer_sn <= xfer_wait; + xfer_en <= '1'; + xfer_sn <= xfer_active; - when xfer_wait => - if ifg_rdy = '1' then - xfer_sn <= xfer_active; - xfer_cnt_adv <= '1'; - xfer_ptr_adv <= '1'; - end if; - when xfer_active => - 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 mii_fifo_full = '0' then - xfer_sn <= xfer_uncommit; - end if; + xfer_en <= '1'; + if xfer_bsy = '0' then + xfer_sn <= xfer_uncommit; end if; when xfer_uncommit => @@ -435,7 +431,7 @@ xfer_state: end if; when xfer_free => - if ifg_rdy = '0' then + if xfer_sync(1) = '1' then xfer_sn <= xfer_idle; end if; @@ -450,7 +446,8 @@ interframe_gap_ready: process(clk) begin if rising_edge(clk) then - ifg_rdy <= ifg_idle; + xfer_sync(1) <= xfer_sync(0); + xfer_sync(0) <= mii_fifo_empty; end if; end process; @@ -460,8 +457,9 @@ interframe_gap_counter: begin if rising_edge(mii_tx_clk) then ifg_idle <= '0'; - if reset_en = '1' or tx_en = '1' then - ifg_cnt <= ifg_cnt_t'high; + if reset_en = '1' or piso8_dout_vld = '1' then + ifg_cnt <= ifg_cnt_t'high; + ifg_idle <= '1'; elsif ifg_cnt /= 0 then ifg_cnt <= ifg_cnt - 1; else @@ -475,16 +473,19 @@ xfer_counter: process(clk) begin if rising_edge(clk) then - if xfer_cnt_set = '1' then + xfer_bsy <= '0'; + if xfer_set = '1' then + xfer_cnt <= cmd_fifo_dout(cmd_fifo_dout'left downto word_ptr_t'length); xfer_size <= (others => '0'); - xfer_rdy <= '0'; - 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; - xfer_size <= xfer_size + 1; - else - xfer_rdy <= '1'; + elsif xfer_en = '1' then + xfer_bsy <= '1'; + if xfer_cnt_en = '1' or xfer_bsy = '0' then + if xfer_cnt /= 0 then + xfer_cnt <= xfer_cnt - 1; + xfer_size <= xfer_size + 1; + else + xfer_bsy <= '0'; + end if; end if; end if; end if; @@ -495,26 +496,104 @@ xfer_pointer: process(clk) begin if rising_edge(clk) then - if xfer_ptr_set = '1' then + if xfer_set = '1' then 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 - xfer_odd <= '1'; + elsif xfer_en = '1' then + if xfer_bsy = '0' or xfer_cnt_en = '1' then + xfer_ptr <= xfer_ptr + 1; end if; - elsif xfer_ptr_adv = '1' then - xfer_ptr <= xfer_ptr + 1; end if; end if; end process; +------------------------------------------------------------------ +stream_state_next: + process(mii_tx_clk) + begin + if rising_edge(mii_tx_clk) then + if reset_en = '1' then + stream_s <= stream_init; + else + stream_s <= stream_sn; + end if; + end if; + end process; + +stream_state: + process(stream_s, ifg_idle, mii_fifo_empty, piso8_din_rdy, piso8_dout_vld) + begin + + piso8_din_vld <= '0'; + mii_fifo_re <= '0'; + preamble_en <= '0'; + preamble_addr <= 0; + + stream_sn <= stream_s; + + case stream_s is + + when stream_init => + if mii_fifo_empty = '1' then + stream_sn <= stream_idle; + end if; + + when stream_idle => + if mii_fifo_empty = '0' and piso8_din_rdy = '1' then + stream_sn <= stream_start; + end if; + + when stream_start => + stream_sn <= stream_preamble0; + + when stream_preamble0 => + preamble_addr <= 0; + preamble_en <= '1'; + piso8_din_vld <= '1'; + if piso8_din_rdy = '1' then + stream_sn <= stream_preamble1; + end if; + + when stream_preamble1 => + preamble_addr <= 1; + preamble_en <= '1'; + piso8_din_vld <= '1'; + if piso8_din_rdy = '1' then + stream_sn <= stream_active; + end if; + + when stream_active => + piso8_din_vld <= not mii_fifo_empty; + mii_fifo_re <= piso8_din_rdy; + if mii_fifo_empty = '1' then + stream_sn <= stream_crc; + end if; + + when stream_crc => + stream_sn <= stream_stop; + + when stream_stop => + if piso8_dout_vld = '0' then + stream_sn <= stream_finish; + end if; + + when stream_finish => + if ifg_idle = '0' then + stream_sn <= stream_idle; + end if; + + when others => + stream_sn <= stream_idle; + end case; + + end process; + ------------------------------------------------------------------ inst_ram : entity work.dpram_1w1r GENERIC MAP ( addr_width => RAM_ADDR_WIDTH, - data_width => 32 + data_width => ram_din_a'length ) PORT MAP ( @@ -574,7 +653,7 @@ inst_mii_fifo: entity work.fifo_async data_r => mii_fifo_dout ); -inst_piso : entity work.piso +inst_piso8 : entity work.piso GENERIC MAP ( data_width_in => 32, @@ -585,17 +664,19 @@ inst_piso : entity work.piso ( rst => reset_en, clk => mii_tx_clk, - din_vld => data_vld, - din_rdy => piso_din_rdy, - din_be => piso_din_be, - din => mii_fifo_dout(31 downto 0), - dout_vld => piso_dout_vld, - dout_en => piso_10mbps_din_rdy, - dout => piso_dout + din_vld => piso8_din_vld, + din_rdy => piso8_din_rdy, + din_be => piso8_din_be, + din => piso8_din, + dout_vld => piso8_dout_vld, + dout_en => piso8_dout_en, + dout => piso8_dout ); -inst_piso_10mbps : entity work.piso + piso8_dout_en <= piso4_din_rdy and ifg_idle; + +inst_piso4 : entity work.piso GENERIC MAP ( data_width_in => 8, @@ -606,17 +687,17 @@ inst_piso_10mbps : entity work.piso ( rst => reset_en, clk => mii_tx_clk, - din_vld => piso_dout_vld, - din_rdy => piso_10mbps_din_rdy, + din_vld => piso8_dout_vld, + din_rdy => piso4_din_rdy, din_be => "11", - din => piso_dout, - dout_vld => tx_en, + din => piso8_dout, + dout_vld => piso4_dout_vld, dout_en => '1', - dout => mii_tx(3 downto 0) + dout => piso4_dout ); - mii_tx_en <= tx_en; - mii_tx(7 downto 4) <= "0000"; + mii_tx_en <= piso4_dout_vld; + mii_tx <= "0000" & piso4_dout; end behavior; diff --git a/lib/emac/src/pkt_gen.vhd b/lib/emac/src/pkt_gen.vhd index 8b8ee60..389f294 100644 --- a/lib/emac/src/pkt_gen.vhd +++ b/lib/emac/src/pkt_gen.vhd @@ -51,33 +51,37 @@ ARCHITECTURE behavior OF pkt_gen IS signal xfer_size : word_ptr_t; signal xfer_ptr : 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 commit_en : std_logic; + signal xfer_set : std_logic; + signal xfer_en : std_logic; + signal xfer_sync : unsigned(1 downto 0); + signal xfer_cnt_en : std_logic; + signal xfer_bsy : std_logic; + signal xfer_pre_rdy : std_logic; + signal uncommit_en : std_logic; - signal piso_din_be : unsigned(3 downto 0); - signal piso_din_rdy : std_logic; - signal data_vld : std_logic; + signal piso8_din : unsigned(31 downto 0); + signal piso8_din_be : unsigned(3 downto 0); + signal piso8_din_rdy : std_logic; + signal piso8_din_vld : std_logic; - signal piso_dout : unsigned(7 downto 0); - signal piso_dout_vld : std_logic; - signal piso_10mbps_din_rdy : std_logic; + signal piso8_dout : unsigned(7 downto 0); + signal piso8_dout_vld : std_logic; + signal piso8_dout_en : std_logic; + signal piso4_din_rdy : std_logic; signal tx_en : std_logic; - subtype inter_frame_gap_cnt_t is natural; - signal inter_frame_gap_cnt : inter_frame_gap_cnt_t; - signal inter_frame_gap_rdy : std_logic; + subtype ifg_cnt_t is natural range 0 to 23; -- 10/100 mbps +-- subtype ifg_cnt_t is natural range 0 to 11; -- 1000 mbps + + signal ifg_cnt : ifg_cnt_t; + signal ifg_idle : std_logic; - type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_wait, xfer_active, xfer_uncommit, xfer_free); + type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_arm, xfer_active, xfer_uncommit, xfer_free); signal xfer_s, xfer_sn : xfer_state_t; + type stream_state_t is (stream_init, stream_idle, stream_start, stream_preamble0, stream_preamble1, stream_active, stream_crc, stream_stop, stream_finish); + signal stream_s, stream_sn : stream_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 := ( @@ -87,17 +91,28 @@ ARCHITECTURE behavior OF pkt_gen IS "1110" ); + signal preamble_en : std_logic; + signal preamble_addr : natural range 0 to 1; + type preamble_t is array (0 to 1) of unsigned(31 downto 0); + constant preamble : preamble_t := + ( + X"55555555", + X"555555D5" + ); begin mii_tx_er <= '0'; - piso_din_be <= mii_fifo_dout(35 downto 32); - mii_fifo_re <= piso_din_rdy; - data_vld <= not mii_fifo_empty; - - mii_fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(xfer_remain)) when xfer_remain_en = '1' else "1111"; + piso8_din <= preamble(preamble_addr) when preamble_en = '1' else mii_fifo_dout(31 downto 0); + piso8_din_be <= "1111" when preamble_en = '1' else mii_fifo_dout(35 downto 32); + + mii_fifo_we <= xfer_bsy; + xfer_cnt_en <= xfer_bsy and not mii_fifo_full; + + mii_fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(pkt_nbytes(1 downto 0))) when xfer_pre_rdy = '1' else "1111"; mii_fifo_din(31 downto 0) <= pkt_data; + ------------------------------------------------------------------ -- Transfer stuff @@ -115,16 +130,12 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, xfer_odd, xfer_rdy, inter_frame_gap_rdy, mii_fifo_full) + process(xfer_s, xfer_bsy, xfer_sync) begin - xfer_cnt_set <= '0'; - xfer_cnt_adv <= '0'; - xfer_ptr_set <= '0'; - xfer_ptr_adv <= '0'; - xfer_remain_en <= '0'; - mii_fifo_we <= '0'; - commit_en <= '0'; + uncommit_en <= '0'; + xfer_set <= '0'; + xfer_en <= '0'; xfer_sn <= xfer_s; @@ -134,40 +145,28 @@ xfer_state: xfer_sn <= xfer_idle; when xfer_idle => - xfer_ptr_set <= '1'; - xfer_cnt_set <= '1'; - xfer_sn <= xfer_wait; + xfer_sn <= xfer_setup; - when xfer_wait => - if inter_frame_gap_rdy = '1' then - xfer_sn <= xfer_setup; - xfer_cnt_adv <= '1'; - end if; - when xfer_setup => - xfer_cnt_adv <= '1'; - xfer_ptr_adv <= '1'; + xfer_set <= '1'; + xfer_sn <= xfer_arm; + + when xfer_arm => + xfer_en <= '1'; xfer_sn <= xfer_active; when xfer_active => - 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 mii_fifo_full = '0' then - xfer_sn <= xfer_uncommit; - end if; + xfer_en <= '1'; + if xfer_bsy = '0' then + xfer_sn <= xfer_uncommit; end if; when xfer_uncommit => - commit_en <= '1'; + uncommit_en <= '1'; xfer_sn <= xfer_free; when xfer_free => - if inter_frame_gap_rdy = '0' then + if xfer_sync(1) = '1' then xfer_sn <= xfer_idle; end if; @@ -177,6 +176,33 @@ xfer_state: end process; +------------------------------------------------------------------ +interframe_gap_ready: + process(clk) + begin + if rising_edge(clk) then + xfer_sync(1) <= xfer_sync(0); + xfer_sync(0) <= mii_fifo_empty; + end if; + end process; + +------------------------------------------------------------------ +interframe_gap_counter: + process(mii_tx_clk) + begin + if rising_edge(mii_tx_clk) then + ifg_idle <= '0'; + if rst = '1' or piso8_dout_vld = '1' then + ifg_cnt <= ifg_cnt_t'high; + ifg_idle <= '1'; + elsif ifg_cnt /= 0 then + ifg_cnt <= ifg_cnt - 1; + else + ifg_idle <= '1'; + end if; + end if; + end process; + ------------------------------------------------------------------ pkt_params: process(clk) @@ -195,7 +221,7 @@ pkt_params: seed2 := 12586901; tx_packets <= 0; tx_bytes <= 0; - elsif commit_en = '1' then + elsif uncommit_en = '1' then uniform(seed1, seed2, krand); size := to_unsigned(PKT_SIZE_MIN + natural(real(PKT_SIZE_MAX-PKT_SIZE_MIN)*krand), word_ptr_t'length); delay := natural(1.0E6*f_sysclk*(PKT_DLY_MIN + (PKT_DLY_MAX-PKT_DLY_MIN)*krand)); @@ -212,54 +238,28 @@ pkt_params: end if; end process; ------------------------------------------------------------------- -interframe_gap_counter: - process(mii_tx_clk) - begin - if rising_edge(mii_tx_clk) then - if rst = '1' then - inter_frame_gap_rdy <= '1'; - elsif tx_en = '1' then - inter_frame_gap_rdy <= '0'; - inter_frame_gap_cnt <= pkt_delay; - 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; - ------------------------------------------------------------------ xfer_counter: process(clk) begin if rising_edge(clk) then - if xfer_cnt_set = '1' then - xfer_size <= (others => '0'); - xfer_rdy <= '0'; + if xfer_set = '1' then xfer_cnt <= pkt_nwords; - elsif xfer_cnt_adv = '1' then - if xfer_cnt /= 0 then - xfer_cnt <= xfer_cnt - 1; - xfer_size <= xfer_size + 1; - else - xfer_rdy <= '1'; - end if; - end if; - end if; - - end process; - -xfer_pointer: - process(clk) - begin - if rising_edge(clk) then - if xfer_ptr_set = '1' then - xfer_remain <= pkt_nbytes(1 downto 0); - xfer_odd <= '0'; - if xfer_tag(3 downto 2) /= "00" then - xfer_odd <= '1'; + xfer_size <= (others => '0'); + xfer_bsy <= '0'; + xfer_pre_rdy <= '0'; + elsif xfer_en = '1' then + xfer_bsy <= '1'; + if xfer_cnt_en = '1' or xfer_bsy = '0' then + if xfer_cnt /= 1 then + xfer_cnt <= xfer_cnt - 1; + xfer_size <= xfer_size + 1; + else + xfer_pre_rdy <= '1'; + end if; + if xfer_pre_rdy = '1' then + xfer_bsy <= '0'; + end if; end if; end if; end if; @@ -272,9 +272,9 @@ pkt_data_gen: variable data : unsigned(7 downto 0); begin if rising_edge(clk) then - if rst = '1' then + if xfer_set = '1' then data := (others => '0'); - elsif xfer_cnt_adv = '1' then + elsif xfer_cnt_en = '1' or xfer_bsy = '0' then pkt_data(7 downto 0) <= data; data := data + 1; pkt_data(15 downto 8) <= data; @@ -288,6 +288,87 @@ pkt_data_gen: end process; +------------------------------------------------------------------ +stream_state_next: + process(mii_tx_clk) + begin + if rising_edge(mii_tx_clk) then + if rst = '1' then + stream_s <= stream_init; + else + stream_s <= stream_sn; + end if; + end if; + end process; + +stream_state: + process(stream_s, ifg_idle, mii_fifo_empty, piso8_din_rdy, piso8_dout_vld) + begin + + piso8_din_vld <= '0'; + mii_fifo_re <= '0'; + preamble_en <= '0'; + preamble_addr <= 0; + + stream_sn <= stream_s; + + case stream_s is + + when stream_init => + if mii_fifo_empty = '1' then + stream_sn <= stream_idle; + end if; + + when stream_idle => + if mii_fifo_empty = '0' and piso8_din_rdy = '1' then + stream_sn <= stream_start; + end if; + + when stream_start => + stream_sn <= stream_preamble0; + + when stream_preamble0 => + preamble_addr <= 0; + preamble_en <= '1'; + piso8_din_vld <= '1'; + if piso8_din_rdy = '1' then + stream_sn <= stream_preamble1; + end if; + + when stream_preamble1 => + preamble_addr <= 1; + preamble_en <= '1'; + piso8_din_vld <= '1'; + if piso8_din_rdy = '1' then + stream_sn <= stream_active; + end if; + + when stream_active => + piso8_din_vld <= not mii_fifo_empty; + mii_fifo_re <= piso8_din_rdy; + if mii_fifo_empty = '1' then + stream_sn <= stream_crc; + end if; + + when stream_crc => + stream_sn <= stream_stop; + + when stream_stop => + if piso8_dout_vld = '0' then + stream_sn <= stream_finish; + end if; + + when stream_finish => + if ifg_idle = '0' then + stream_sn <= stream_idle; + end if; + + when others => + stream_sn <= stream_idle; + end case; + + end process; + ------------------------------------------------------------------ -- Instantiate synchronous FIFO inst_mii_fifo: entity work.fifo_async @@ -323,16 +404,18 @@ inst_piso : entity work.piso ( rst => rst, clk => mii_tx_clk, - din_vld => data_vld, - din_rdy => piso_din_rdy, - din_be => piso_din_be, - din => mii_fifo_dout(31 downto 0), - dout_vld => piso_dout_vld, - dout_en => piso_10mbps_din_rdy, - dout => piso_dout + din_vld => piso8_din_vld, + din_rdy => piso8_din_rdy, + din_be => piso8_din_be, + din => piso8_din, + dout_vld => piso8_dout_vld, + dout_en => piso8_dout_en, + dout => piso8_dout ); + piso8_dout_en <= piso4_din_rdy and ifg_idle; + inst_piso_10mbps : entity work.piso GENERIC MAP ( @@ -344,10 +427,10 @@ inst_piso_10mbps : entity work.piso ( rst => rst, clk => mii_tx_clk, - din_vld => piso_dout_vld, - din_rdy => piso_10mbps_din_rdy, + din_vld => piso8_dout_vld, + din_rdy => piso4_din_rdy, din_be => "11", - din => piso_dout, + din => piso8_dout, dout_vld => tx_en, dout_en => '1', dout => mii_tx(3 downto 0)