diff --git a/lib/emac/.directory_history b/lib/emac/.directory_history new file mode 100644 index 0000000..86afba5 --- /dev/null +++ b/lib/emac/.directory_history @@ -0,0 +1,2 @@ +VHDL/lib/emac/emac_jb.vhd + diff --git a/lib/emac/emac_jb.vhd b/lib/emac/emac_jb.vhd deleted file mode 100644 index b81bd27..0000000 --- a/lib/emac/emac_jb.vhd +++ /dev/null @@ -1,658 +0,0 @@ -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, - dout_en => '1', - 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_vld => 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;