From aede06ea9e93fdacdd37c87e0c74a2a7d0d608d4 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 28 Mar 2010 08:28:48 +0000 Subject: [PATCH] Initial version 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@833 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/emac/src/pkt_gen.vhd | 354 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 lib/emac/src/pkt_gen.vhd diff --git a/lib/emac/src/pkt_gen.vhd b/lib/emac/src/pkt_gen.vhd new file mode 100644 index 0000000..70e606f --- /dev/null +++ b/lib/emac/src/pkt_gen.vhd @@ -0,0 +1,354 @@ +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE IEEE.MATH_REAL.ALL; +use std.textio.all; -- Imports the standard textio package. + +use work.emac_types.all; +use work.utils_pkg.all; + +ENTITY pkt_gen IS + Generic + ( + f_sysclk : real := 100.0; + PKT_DLY_MIN : real := 1.0E-6; + PKT_DLY_MAX : real := 100.0E-6; + PKT_SIZE_MIN : natural := 64; + PKT_SIZE_MAX : natural := 1518 + + ); + Port + ( + clk : in STD_LOGIC; + rst : in STD_LOGIC; + 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) + + ); +END pkt_gen; + +ARCHITECTURE behavior OF pkt_gen IS + + subtype word_ptr_t is unsigned(15 downto 0); + + signal pkt_data : unsigned(31 downto 0); + signal pkt_nbytes : word_ptr_t := X"0040"; + signal pkt_nwords : word_ptr_t := X"0010"; + signal pkt_delay : natural := natural(1.0*f_sysclk); + + signal tx_packets : natural; + signal tx_bytes : natural; + + 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 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 piso_din_be : unsigned(3 downto 0); + signal piso_din_rdy : std_logic; + signal data_vld : std_logic; + + signal piso_dout : unsigned(7 downto 0); + signal piso_dout_vld : std_logic; + signal piso_10mbps_din_rdy : 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; + + 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; + + 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", + "1000", + "1100", + "1110" + ); + + +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"; + mii_fifo_din(31 downto 0) <= pkt_data; + +------------------------------------------------------------------ +-- Transfer stuff +------------------------------------------------------------------ +xfer_state_next: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + xfer_s <= xfer_init; + else + xfer_s <= xfer_sn; + end if; + end if; + end process; + +xfer_state: + process(xfer_s, xfer_odd, xfer_rdy, inter_frame_gap_rdy, mii_fifo_full) + 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'; + + xfer_sn <= xfer_s; + + case xfer_s is + + when xfer_init => + xfer_sn <= xfer_idle; + + when xfer_idle => + xfer_ptr_set <= '1'; + xfer_cnt_set <= '1'; + xfer_sn <= xfer_wait; + + 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_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_free; + end if; + end if; + + when xfer_free => + commit_en <= '1'; + xfer_sn <= xfer_idle; + + when others => + xfer_sn <= xfer_idle; + end case; + + end process; + +------------------------------------------------------------------ +pkt_params: + process(clk) + variable size : word_ptr_t; + variable delay : natural; + variable krand : real; + variable seed1 : integer; + variable seed2 : integer; + + begin + if rising_edge(clk) then + if rst = '1' then + size := to_unsigned(PKT_SIZE_MIN, word_ptr_t'length); + delay := natural(1.0E6*PKT_DLY_MIN*f_sysclk); + seed1 := 31101970; + seed2 := 12586901; + tx_packets <= 0; + tx_bytes <= 0; + elsif commit_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(PKT_DLY_MIN + real(PKT_DLY_MAX-PKT_DLY_MIN)*1.0E6*f_sysclk*krand); + tx_packets <= tx_packets + 1; + tx_bytes <= tx_bytes + to_integer(pkt_nbytes); + end if; + pkt_delay <= delay; + pkt_nbytes <= size; + if size(1 downto 0) = 0 then + pkt_nwords <= "00" & size(word_ptr_t'left downto 2); + else + pkt_nwords <= "00" & size(word_ptr_t'left downto 2) + 1; + end if; + end if; + end process; + +------------------------------------------------------------------ +interframe_gap_counter: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + inter_frame_gap_rdy <= '1'; + elsif mii_fifo_empty = '0' then + inter_frame_gap_rdy <= '0'; + inter_frame_gap_cnt <= pkt_delay; + end if; + if 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'; + 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'; + end if; + end if; + end if; + + end process; + +------------------------------------------------------------------ +pkt_data_gen: + process(clk) + variable data : unsigned(7 downto 0); + begin + if rising_edge(clk) then + if rst = '1' then + data := (others => '0'); + elsif xfer_cnt_adv = '1' then + pkt_data(7 downto 0) <= data; + data := data + 1; + pkt_data(15 downto 8) <= data; + data := data + 1; + pkt_data(23 downto 16) <= data; + data := data + 1; + pkt_data(31 downto 24) <= data; + data := data + 1; + end if; + end if; + + end process; + +------------------------------------------------------------------ +-- Instantiate synchronous FIFO +inst_mii_fifo: entity work.fifo_async + GENERIC MAP + ( + addr_width => 4, + data_width => mii_fifo_din'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => rst, + clk_w => clk, + clk_r => mii_tx_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 => mii_fifo_din, + data_r => mii_fifo_dout + ); + +inst_piso : entity work.piso + GENERIC MAP + ( + data_width_in => 32, + data_width_out => 8, + msb_first => true + ) + PORT MAP + ( + 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 + + ); + +inst_piso_10mbps : entity work.piso + GENERIC MAP + ( + data_width_in => 8, + data_width_out => 4, + msb_first => false + ) + PORT MAP + ( + rst => rst, + clk => mii_tx_clk, + din_vld => piso_dout_vld, + din_rdy => piso_10mbps_din_rdy, + din_be => "11", + din => piso_dout, + dout_vld => mii_tx_en, + dout_en => '1', + dout => mii_tx(3 downto 0) + + ); + + mii_tx(7 downto 4) <= "0000"; + +end behavior;