Commit ceb462c7 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

WR endpoint: WIP

parent 9b85c4bf
files = [ "endpoint_private_pkg.vhd",
# "ep_rx_pcs_tbi.vhd",
# "ep_tx_pcs_tbi.vhd",
# "ep_autonegotiation.vhd",
# "ep_pcs_tbi_mdio_wb.vhd",
# "ep_1000basex_pcs.vhd",
# "ep_rx_crc_size_check.vhd",
# "ep_crc_bypass_queue.vhd",
# "ep_rx_deframer.vhd",
"ep_rx_pcs_tbi.vhd",
"ep_tx_pcs_tbi.vhd",
"ep_autonegotiation.vhd",
"ep_pcs_tbi_mdio_wb.vhd",
"ep_1000basex_pcs.vhd",
"ep_rx_crc_size_check.vhd",
"ep_rx_vlan_unit.vhd",
"ep_packet_filter.vhd",
"ep_rx_bypass_queue.vhd",
"ep_rx_deframer.vhd",
"ep_tx_framer.vhd",
# "ep_flow_control.vhd",
# "ep_timestamping_unit.vhd",
# "ep_rmon_counters.vhd",
# "ep_rx_buffer.vhd",
# "ep_sync_detect.vhd",
"ep_sync_detect.vhd",
"ep_wishbone_controller.vhd",
# "ep_ts_counter.vhd",
# "wrsw_endpoint.vhd",
"ep_registers_pkg.vhd",
"wr_fabric_pkg.vhd"
"wr_fabric_pkg.vhd",
"wr_endpoint.vhd"
];
......@@ -22,9 +22,9 @@ package endpoint_pkg is
constant c_preamble_char : std_logic_vector(7 downto 0) := "01010101";
constant c_preamble_sfd : std_logic_vector(7 downto 0) := "11010101";
constant c_QMODE_PORT_ACCESS : std_logic_vector(1 downto 0) := "00";
constant c_QMODE_PORT_TRUNK : std_logic_vector(1 downto 0) := "01";
constant c_QMODE_PORT_NONE : std_logic_vector(1 downto 0) := "11";
constant c_QMODE_PORT_ACCESS : std_logic_vector(1 downto 0) := "00";
constant c_QMODE_PORT_TRUNK : std_logic_vector(1 downto 0) := "01";
constant c_QMODE_PORT_UNQUALIFIED : std_logic_vector(1 downto 0) := "11";
constant c_WRF_STATUS : std_logic_vector(1 downto 0) := "11";
......@@ -312,66 +312,7 @@ package endpoint_pkg is
rdisp_err_o : out std_logic;
out_8b_o : out std_logic_vector(7 downto 0));
end component;
component ep_1000basex_pcs
generic (
g_simulation : integer;
g_phy_mode : string);
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
rxpcs_busy_o : out std_logic;
rxpcs_data_o : out std_logic_vector(15 downto 0);
rxpcs_bytesel_o : out std_logic;
rxpcs_sof_o : out std_logic;
rxpcs_eof_o : out std_logic;
rxpcs_error_o : out std_logic;
rxpcs_dreq_i : in std_logic;
rxpcs_valid_o : out std_logic;
rxpcs_timestamp_stb_p_o : out std_logic;
txpcs_data_i : in std_logic_vector(15 downto 0);
txpcs_bytesel_i : in std_logic;
txpcs_sof_i : in std_logic;
txpcs_eof_i : in std_logic;
txpcs_abort_i : in std_logic;
txpcs_error_p_o : out std_logic;
txpcs_busy_o : out std_logic;
txpcs_valid_i : in std_logic;
txpcs_fifo_almostfull_o : out std_logic;
txpcs_timestamp_stb_p_o : out std_logic;
link_ok_o : out std_logic;
tbi_rbclk_i : in std_logic;
tbi_rxdata_i : in std_logic_vector(9 downto 0);
tbi_txclk_i : in std_logic;
tbi_txdata_o : out std_logic_vector(9 downto 0);
tbi_syncen_o : out std_logic;
tbi_loopen_o : out std_logic;
tbi_prbsen_o : out std_logic;
tbi_enable_o : out std_logic;
gtp_tx_clk_i : in std_logic;
gtp_tx_data_o : out std_logic_vector(7 downto 0);
gtp_tx_k_o : out std_logic;
gtp_tx_disparity_i : in std_logic;
gtp_tx_enc_err_i : in std_logic;
gtp_rx_data_i : in std_logic_vector(7 downto 0);
gtp_rx_clk_i : in std_logic;
gtp_rx_k_i : in std_logic;
gtp_rx_enc_err_i : in std_logic;
gtp_rx_bitslide_i : in std_logic_vector(3 downto 0);
gtp_rst_o : out std_logic;
gtp_loopen_o : out std_logic;
rmon_syncloss_p_o : out std_logic;
rmon_invalid_code_p_o : out std_logic;
rmon_rx_overrun_p_o : out std_logic;
rmon_tx_underrun_o : out std_logic;
mdio_addr_i : in std_logic_vector(7 downto 0);
mdio_data_i : in std_logic_vector(15 downto 0);
mdio_data_o : out std_logic_vector(15 downto 0);
mdio_stb_i : in std_logic;
mdio_rw_i : in std_logic;
mdio_ready_o : out std_logic);
end component;
component wrsw_endpoint
generic (
g_simulation : integer := 0;
......
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2010-11-18
-- Last update: 2011-08-14
-- Last update: 2011-08-22
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -50,7 +50,7 @@ use work.endpoint_private_pkg.all;
entity ep_1000basex_pcs is
generic (
g_simulation : integer);
g_simulation : boolean);
port (
rst_n_i : in std_logic;
......@@ -58,16 +58,14 @@ entity ep_1000basex_pcs is
-- PCS <-> MAC Interface
rxpcs_fab_o: out t_ep_internal_fabric;
rxpcs_busy_o : out std_logic;
rxpcs_data_o : out std_logic_vector(17 downto 0);
rxpcs_dreq_i : in std_logic;
rxpcs_valid_o : out std_logic;
rxpcs_timestamp_stb_p_o : out std_logic;
txpcs_data_i : in std_logic_vector(17 downto 0);
txpcs_fab_i: in t_ep_internal_fabric;
txpcs_error_o : out std_logic;
txpcs_busy_o : out std_logic;
txpcs_valid_i : in std_logic;
txpcs_dreq_o : out std_logic;
txpcs_timestamp_stb_p_o : out std_logic;
......@@ -111,14 +109,14 @@ end ep_1000basex_pcs;
architecture rtl of ep_1000basex_pcs is
component ep_tx_pcs_tbi
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
pcs_data_i : in std_logic_vector(17 downto 0);
pcs_fab_i : in t_ep_internal_fabric;
pcs_error_o : out std_logic;
pcs_busy_o : out std_logic;
pcs_valid_i : in std_logic;
pcs_dreq_o : out std_logic;
mdio_mcr_pdown_i : in std_logic;
mdio_wr_spec_tx_cal_i : in std_logic;
......@@ -135,14 +133,13 @@ architecture rtl of ep_1000basex_pcs is
component ep_rx_pcs_tbi
generic (
g_simulation : integer);
g_simulation : boolean);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
pcs_busy_o : out std_logic;
pcs_data_o : out std_logic_vector(17 downto 0);
pcs_dreq_i : in std_logic;
pcs_valid_o : out std_logic;
pcs_busy_o : out std_logic;
pcs_fab_o : out t_ep_internal_fabric;
timestamp_stb_p_o : out std_logic;
phy_rx_clk_i : in std_logic;
phy_rx_data_i : in std_logic_vector(7 downto 0);
......@@ -160,7 +157,6 @@ architecture rtl of ep_1000basex_pcs is
rmon_o : inout t_rmon_triggers);
end component;
component ep_pcs_tbi_mdio_wb
port (
rst_n_i : in std_logic;
......@@ -203,7 +199,7 @@ architecture rtl of ep_1000basex_pcs is
component ep_autonegotiation
generic (
g_simulation : integer);
g_simulation : boolean);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
......@@ -288,10 +284,10 @@ begin -- rtl
port map (
rst_n_i => pcs_reset_n,
clk_sys_i => clk_sys_i,
pcs_data_i => txpcs_data_i,
pcs_fab_i => txpcs_fab_i,
pcs_error_o => txpcs_error_o,
pcs_busy_o => txpcs_busy_int,
pcs_valid_i => txpcs_valid_i,
pcs_dreq_o => txpcs_dreq_o,
mdio_mcr_pdown_i => mdio_mcr_pdown,
......@@ -316,10 +312,10 @@ begin -- rtl
port map (
clk_sys_i => clk_sys_i,
rst_n_i => pcs_reset_n,
pcs_busy_o => rxpcs_busy_o,
pcs_data_o => rxpcs_data_o,
pcs_fab_o => rxpcs_fab_o,
pcs_dreq_i => rxpcs_dreq_i,
pcs_valid_o => rxpcs_valid_o,
timestamp_stb_p_o => rxpcs_timestamp_stb_p_o,
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.endpoint_pkg.all;
entity ep_address_compare is
generic(
g_userval_match_offset : integer := 0;
g_userval_match_enable : boolean := false;
g_userval_extract_offset : integer := 0;
g_userval_extract_enable : boolean := false
);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
snk_data_i : in std_logic_vector(15 downto 0);
snk_sof_p1_i : in std_logic;
snk_valid_i : in std_logic;
dmac_en_i : in std_logic;
dmac_i : in std_logic_vector(47 downto 0);
vid_en_i : in std_logic;
vid_i : in std_logic_vector(11 downto 0);
etype_en_i : in std_logic;
etype_i : in std_logic_vector(15 downto 0);
user_val_i : in std_logic_vector(15 downto 0);
user_en_i : in std_logic;
done_o : out std_logic;
match_o : out std_logic;
user_extracted_o : out std_logic_vector(15 downto 0)
);
end ep_address_compare;
architecture behavioral of ep_address_compare is
function to_sl(x : boolean) return std_logic is
begin
if(x = true) then
return '1';
else
return '0';
end if;
end function to_sl;
function f_eval_match (matches : std_logic; enable_matching : std_logic) return std_logic is
begin
if(enable_matching = '0') then
return '1';
else
return matches;
end if;
end function f_eval_match;
function f_max(x : integer; y : integer) return integer is
begin
if(x > y) then
return x;
else
return y;
end if;
end function f_max;
signal offset_sreg : unsigned(f_max(9, g_userval_extract_offset + 1) downto 0);
signal is_802_1q : std_logic;
signal matches_dmac : std_logic_vector(2 downto 0);
signal matches_vid : std_logic;
signal matches_etype : std_logic;
signal matches_user : std_logic;
begin -- behavioral
main_fsm : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or enable_i = '0' then
done_o <= '0';
match_o <= '0';
offset_sreg <= (others => '0');
is_802_1q <= '0';
else
if (snk_sof_p1_i = '1') then
offset_sreg(0) <= '1';
done_o <= '0';
match_o <= '0';
elsif(offset_sreg /= 0) then
if(snk_valid_i = '1') then
if(offset_sreg(0) = '1') then
matches_dmac(0) <= to_sl(snk_data_i = dmac_i(47 downto 32));
end if;
if(offset_sreg(1) = '1') then
matches_dmac(1) <= to_sl(snk_data_i = dmac_i(31 downto 16));
end if;
if(offset_sreg(2) = '1') then
matches_dmac(2) <= to_sl(snk_data_i = dmac_i(15 downto 0));
end if;
if(offset_sreg(6) = '1') then
is_802_1q <= to_sl(snk_data_i = x"8100");
matches_etype <= to_sl(snk_data_i = etype_i);
end if;
if(offset_sreg(7) = '1' and is_802_1q = '1') then
matches_etype <= to_sl(snk_data_i = etype_i);
end if;
if(offset_sreg(8) = '1') then
if(is_802_1q = '1') then
matches_vid <= to_sl(snk_data_i(11 downto 0) = vid_i);
else
matches_vid <= to_sl((vid_i = x"fff") or (vid_i = x"000"));
end if;
end if;
if(g_userval_extract_enable) then
if(offset_sreg(g_userval_extract_offset) = '1') then
user_extracted_o <= snk_data_i;
end if;
end if;
if(offset_sreg(offset_sreg'left) = '1') then
done_o <= '1';
match_o <= f_eval_match(to_sl(matches_dmac = "111"), dmac_en_i)
and f_eval_match(matches_etype, etype_en_i)
and f_eval_match(matches_vid, vid_en_i)
and f_eval_match(matches_user, user_en_i);
offset_sreg <= (others => '0');
else
offset_sreg <= offset_sreg sll 1;
end if;
end if;
end if;
end if;
end if;
end process;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.global_defs.all;
use work.endpoint_pkg.all;
entity ep_address_match is
generic(
g_num_matching_rules : integer := 4
);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
snk_data_i : in std_logic_vector(15 downto 0);
snk_sof_p1_i : in std_logic;
snk_valid_i : in std_logic;
ep_macl_i : in std_logic_vector(31 downto 0);
ep_mach_i : in std_logic_vector(15 downto 0);
ep_afcr_enable : in std_logic;
ep_afcr_rule_sel_i : in std_logic_vector(2 downto 0);
ep_afcr_matrix_addr_i : in std_logic_vector(7 downto 0);
ep_afcr_matrix_data_i : in std_logic_vector(7 downto 0);
ep_afcr_matrix_write_p_i : in std_logic;
ep_afr0_load_i : in std_logic;
ep_afr0_dmac_en_i : in std_logic;
ep_afr0_vid_en_i : in std_logic;
ep_afr0_etype_en_i : in std_logic;
ep_afr0_vid_i : in std_logic_vector(11 downto 0);
ep_afr1_load_i : in std_logic;
ep_afr1_dmac_lo_i : in std_logic_vector(31 downto 0);
ep_afr2_load_i : in std_logic;
ep_afr2_dmac_hi_i : in std_logic_vector(15 downto 0);
ep_afr2_etype_i : in std_logic_vector(15 downto 0);
r_done_o : out std_logic;
r_drop_o : out std_logic;
r_match_o : out std_logic_vector(g_num_matching_rules+1 downto 0);
r_is_pause_o : out std_logic;
r_pause_quanta_o : out std_logic_vector(15 downto 0)
);
end ep_address_match;
architecture behavioral of ep_address_match is
component ep_address_compare
generic (
g_userval_match_offset : integer := 0;
g_userval_match_enable : boolean := false;
g_userval_extract_offset : integer := 0;
g_userval_extract_enable : boolean := false);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
snk_data_i : in std_logic_vector(15 downto 0);
snk_sof_p1_i : in std_logic;
snk_valid_i : in std_logic;
dmac_en_i : in std_logic := '0';
dmac_i : in std_logic_vector(47 downto 0) := x"000000000000";
vid_en_i : in std_logic := '0';
vid_i : in std_logic_vector(11 downto 0) := x"000";
etype_en_i : in std_logic := '0';
etype_i : in std_logic_vector(15 downto 0) := x"0000";
user_val_i : in std_logic_vector(15 downto 0) := x"0000";
user_en_i : in std_logic := '0';
done_o : out std_logic;
match_o : out std_logic;
user_extracted_o : out std_logic_vector(15 downto 0));
end component;
-- rule array layout:
-- slot 0: broadcast
-- slot 1: own MAC address
-- slot 2: user rule 0
-- slot 3: user rule 1
-- slot 4: user rule 2
-- slot 5: user rule 3
-- slot N: user rule g_num_matching_rules-1
type t_matching_rule is record
dmac_en : std_logic;
dmac : std_logic_vector(47 downto 0);
vid_en : std_logic;
vid : std_logic_vector(11 downto 0);
etype_en : std_logic;
etype : std_logic_vector(15 downto 0);
end record;
type t_rule_array is array(0 to g_num_matching_rules+1) of t_matching_rule;
type t_matching_matrix is array(0 to g_num_matching_rules+1) of std_logic_vector(g_num_matching_rules+1 downto 0);
signal user_rules : t_rule_array;
signal matrix : t_matching_matrix;
signal match_pause : std_logic;
signal compare_done : std_logic;
signal own_mac : std_logic_vector(47 downto 0);
signal matrix_out : std_logic_vector(g_num_matching_rules+1 downto 0);
signal user_match : std_logic_vector(g_num_matching_rules+1 downto 0);
signal enable_int : std_logic;
signal rule_addr : integer;
begin -- behavioral
enable_int <= ep_afcr_enable and enable_i;
own_mac <= ep_mach_i & ep_macl_i;
-- special case for PAUSE frames
U_Compare_PAUSE : ep_address_compare
generic map (
g_userval_match_offset => 9,
g_userval_match_enable => true,
g_userval_extract_offset => 10,
g_userval_extract_enable => true)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
enable_i => enable_int,
snk_data_i => snk_data_i,
snk_sof_p1_i => snk_sof_p1_i,
snk_valid_i => snk_valid_i,
dmac_en_i => '1',
dmac_i => x"0180c2000001",
etype_en_i => '1',
etype_i => x"8808",
user_en_i => '1',
user_val_i => x"0001",
done_o => compare_done,
match_o => match_pause,
user_extracted_o => r_pause_quanta_o
);
U_Compare_BCAST : ep_address_compare
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
enable_i => enable_int,
snk_data_i => snk_data_i,
snk_sof_p1_i => snk_sof_p1_i,
snk_valid_i => snk_valid_i,
dmac_en_i => '1',
dmac_i => x"ffffffffffff",
vid_en_i => user_rules(0).vid_en,
vid_i => user_rules(0).vid,
done_o => open,
match_o => user_match(0),
user_extracted_o => open);
U_Compare_OWN_MAC : ep_address_compare
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
enable_i => enable_int,
snk_data_i => snk_data_i,
snk_sof_p1_i => snk_sof_p1_i,
snk_valid_i => snk_valid_i,
dmac_en_i => '1',
dmac_i => own_mac,
vid_en_i => user_rules(1).vid_en,
vid_i => user_rules(1).vid,
done_o => open,
match_o => user_match(1),
user_extracted_o => open);
gen_user_rules : for i in 0 to g_num_matching_rules-1 generate
U_Compare_USER : ep_address_compare
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
enable_i => enable_i,
snk_data_i => snk_data_i,
snk_sof_p1_i => snk_sof_p1_i,
snk_valid_i => snk_valid_i,
dmac_en_i => user_rules(2+i).dmac_en,
dmac_i => user_rules(2+i).dmac,
vid_en_i => user_rules(2+i).vid_en,
vid_i => user_rules(2+i).vid,
etype_en_i => user_rules(2+i).etype_en,
etype_i => user_rules(2+i).etype,
done_o => open,
match_o => user_match(2+i),
user_extracted_o => open);
end generate gen_user_rules;
rule_addr <= to_integer(unsigned(ep_afcr_rule_sel_i));
p_update_rules : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0') then
for i in 0 to g_num_matching_rules+1 loop
user_rules(i).dmac <= (others => '0');
user_rules(i).dmac_en <= '0';
user_rules(i).vid <= (others => '0');
user_rules(i).vid_en <= '0';
user_rules(i).etype <= (others => '0');
user_rules(i).etype_en <= '0';
end loop; -- i
else
-- handle writes to the rule table
if(ep_afr0_load_i = '1') then
user_rules(rule_addr).dmac_en <= ep_afr0_dmac_en_i;
user_rules(rule_addr).vid_en <= ep_afr0_vid_en_i;
user_rules(rule_addr).etype_en <= ep_afr0_etype_en_i;
user_rules(rule_addr).vid <= ep_afr0_vid_i;
end if;
if(ep_afr1_load_i = '1') then
user_rules(rule_addr).dmac(31 downto 0) <= ep_afr1_dmac_lo_i;
end if;
if(ep_afr2_load_i = '1') then
user_rules(rule_addr).dmac(47 downto 32) <= ep_afr2_dmac_hi_i;
user_rules(rule_addr).etype <= ep_afr2_etype_i;
end if;
end if;
end if;
end process;
p_update_matrix : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(ep_afcr_matrix_write_p_i = '1') then
matrix(to_integer(unsigned(ep_afcr_matrix_addr_i(g_num_matching_rules+1 downto 0)))) <=
ep_afcr_matrix_data_i(g_num_matching_rules+1 downto 0);
end if;
end if;
end process;
matrix_out <= matrix(to_integer(unsigned(user_match)));
p_decision_output : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0' or enable_int = '0') then
r_done_o <= '0';
r_drop_o <= '0';
r_match_o <= (others => '0');
else
r_done_o <= compare_done;
if(unsigned(matrix_out) = 0) then
r_drop_o <= '1';
else
r_drop_o <= '0';
end if;
r_match_o <= matrix_out;
r_is_pause_o <= match_pause;
end if;
end if;
end process;
end behavioral;
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2010-11-18
-- Last update: 2011-05-27
-- Last update: 2011-08-22
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -50,7 +50,7 @@ use work.endpoint_private_pkg.all;
entity ep_autonegotiation is
generic (
g_simulation : integer);
g_simulation : boolean);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
......@@ -96,7 +96,7 @@ architecture syn of ep_autonegotiation is
function f_eval_link_timer_size
return integer is
begin -- f_eval_link_timer_size
if(g_simulation = 0) then
if(g_simulation = false) then
return 20;
else
return 11;
......@@ -131,12 +131,10 @@ begin -- syn
p_link_timer : process(clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
if rst_n_i = '0' or link_timer_restart ='1' then
link_timer <= (others => '0');
else
if(link_timer_restart = '1') then
link_timer <= (others => '0');
elsif(link_timer_expired = '0') then
if(link_timer_expired = '0') then
link_timer <= link_timer + 1;
end if;
end if;
......
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,8 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.wr_fabric_pkg.all;
use work.endpoint_private_pkg.all;
use work.ep_wbgen2_pkg.all;
entity ep_packet_filter is
......@@ -11,67 +12,262 @@ entity ep_packet_filter is
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
snk_data_i: in std_logic_vector(17 downto 0);
snk_valid_i: in std_logic;
snk_dreq_o: out std_logic;
snk_fab_i : in t_ep_internal_fabric;
snk_dreq_o : out std_logic;
src_data_o: out std_logic_vector(17 downto 0);
src_valid_o : out std_logic(17 downto 0);
src_dreq_i: in std_logic;
src_fab_o : out t_ep_internal_fabric;
src_dreq_i : in std_logic;
match_done_o: out std_logic;
match_class_o: out std_logic_vector(7 downto 0);
done_o : out std_logic;
pclass_o : out std_logic_vector(7 downto 0);
drop_o : out std_logic;
regs_b: inout t_ep_registers
regs_b : inout t_ep_registers
);
end ep_packet_filter;
architecture behavioral of ep_packet_filter is
constant c_BACKLOG_SIZE : integer := 128;
constant c_BACKLOG_SIZE_LOG2 : integer := 7;
constant c_PC_SIZE : integer := 6;
constant c_OPC_AND : std_logic_vector(1 downto 0) : = "00";
constant c_OPC_OR : std_logic_vector(1 downto 0) : = "01";
constant c_OPC_XOR : std_logic_vector(1 downto 0) : = "10";
constant c_OPC_FIN : std_logic_vector(1 downto 0) := "11";
constant c_MODE_LOGIC : std_logic := '1';
constant c_MODE_COMPARE : std_logic := '0';
type t_microcode_instruction is record
-- comparison value
cmp_val : std_logic_vector(15 downto 0);
-- comparison mask (nibbles)
cmp_mask : std_logic_vector(3 downto 0);
-- comparison offset (0 = 1st word of the frame)
cmp_offset : std_logic_vector(5 downto 0); -- 26
-- opcode
cmp_en: std_logic;
opcode : std_logic_vector(1 downto 0);
op_b : std_logic_vector(4 downto 0);
op_dst : std_logic_vector(4 downto 0);
fin : std_logic;
mode : std_logic;
cmp_bit : std_logic;
cmp_mask : std_logic_vector(3 downto 0);
cmp_value : std_logic_vector(15 downto 0);
offset : std_logic_vector(5 downto 0);
op : std_logic_vector(2 downto 0);
op2 : std_logic_vector(2 downto 0);
rd : std_logic_vector(4 downto 0);
ra : std_logic_vector(4 downto 0);
rb : std_logic_vector(4 downto 0);
rc : std_logic_vector(4 downto 0);
end record;
signal fifo_wr_ptr : unsigned(c_BACKLOG_SIZE_LOG2 - 1 downto 0);
signal fifo_rd_ptr : unsigned(c_BACKLOG_SIZE_LOG2 - 1 downto 0);
signal fifo_full : std_logic;
signal fifo_next_wr_ptr : unsigned(c_BACKLOG_SIZE_LOG2 -1 downto 0);
signal fifo_next_rd_ptr : unsigned(c_BACKLOG_SIZE_LOG2 -1 downto 0);
signal pc : unsigned(c_BACKLOG_SIZE_LOG2-1 downto 0);
signal op : t_microcode_instruction;
signal R : std_logic_vector(31 downto 0);
function f_decode_insn
(ir : std_logic_vector) return t_microcode_instruction is
variable insn : t_microcode_instruction;
begin
insn.fin := ir(35);
insn.mode := ir(34);
insn.cmp_bit := ir(33);
insn.cmp_mask := ir(32 downto 29);
insn.cmp_value := ir(28 downto 13);
insn.offset := ir(12 downto 7);
insn.rd(3 downto 0) := ir(6 downto 3);
insn.op := ir(2 downto 0);
insn.rd(4) := ir(34) and ir(7);
insn.ra := ir(12 downto 8);
insn.rb := ir(17 downto 13);
insn.rc := ir(22 downto 18);
insn.op2 := ir(25 downto 23);
return insn;
end f_decode_insn;
function f_eval
(
a, b : std_logic;
op : std_logic_vector
) return std_logic is
variable r : std_logic;
variable op_t : std_logic_vector(2 downto 0);
begin
op_t := op;
case op_t is
when "000" => r := a and b;
when "100" => r := a nand b;
when "001" => r := a or b;
when "101" => r := a nor b;
when "010" => r := a xor b;
when "110" => r := a xnor b;
when "011" => r := a;
when "111" => r := not a;
when others => null;
end case;
return r;
end f_eval;
function f_pick_reg(regs : std_logic_vector; index : std_logic_vector)return std_logic is
variable idx_int : integer;
begin
idx_int := to_integer(unsigned(index));
return regs(idx_int);
end f_pick_reg;
signal pc : unsigned(c_PC_SIZE-1 downto 0);
signal ir : std_logic_vector(35 downto 0);
signal insn : t_microcode_instruction;
signal done_int : std_logic;
signal regs : std_logic_vector(31 downto 0);
signal result_cmp : std_logic;
signal mask : std_logic_vector(15 downto 0);
signal ra, rb, rc, result1, result2, rd : std_logic;
signal pmem_addr : unsigned(c_PC_SIZE-1 downto 0);
signal pmem_rdata : std_logic_vector(15 downto 0);
signal mm_write : std_logic;
signal mm_rdata, mm_wdata : std_logic_vector(35 downto 0);
type t_state is (WAIT_FRAME, PROCESS_FRAME, GEN_OUTPUT);
signal stage1, stage2 : std_logic;
begin -- behavioral
R(0) <= '0';
R(1) <= '1';
regs_b <= c_ep_registers_init_value;
snk_o.stall <= src_i.stall or fifo_full;
mm_write <= not regs_b.ecr_rx_en_o and regs_b.pfcr0_mm_write_o and regs_b.pfcr0_mm_write_wr_o;
mm_wdata <= regs_b.pfcr0_mm_data_msb_o & regs_b.pfcr1_mm_data_lsb_o;
U_microcode_ram : generic_spram
generic map (
g_data_width => 36,
g_size => 2**c_PC_SIZE)
port map (
rst_n_i => rst_n_i,
clk_i => clk_sys_i,
bwe_i => "11111",
we_i => mm_write,
a_i => regs_b.pfcr0_mm_addr_o,
d_i => mm_wdata,
q_o => mm_rdata);
fifo_next_rd_ptr <= fifo_rd_ptr + 1;
fifo_next_wr_ptr <= fifo_wr_ptr + 1;
fifo_full <= '1' when fifo_next_wr_ptr = fifo_rd_ptr else '0';
U_backlog_ram : generic_dpram
generic map (
g_data_width => 16,
g_size => 2**c_PC_SIZE,
g_with_byte_enable => false,
g_dual_clock => false)
port map (
rst_n_i => rst_n_i,
clka_i => clk_sys_i,
bwea_i => "11",
wea_i => snk_fab_i.dvalid,
aa_i => std_logic_vector(pc),
da_i => snk_fab_i.data,
qa_o => open,
clkb_i => clk_sys_i,
bweb_i => "00",
web_i => '0',
ab_i => insn.offset,
db_i => x"0000",
qb_o => pmem_rdata);
snk_dreq_o <= src_dreq_i;
src_fab_o <= snk_fab_i;
p_pc_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or snk_fab_i.eof = '1' or snk_fab_i.error = '1' or done_int = '1' then
pc <= (others => '0');
stage1 <= '0';
elsif(snk_fab_i.dvalid = '1') then
pc <= pc + 1;
stage1 <= '1';
else
stage1 <= '0';
end if;
end if;
end process;
p_stage2 : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or done_int = '1' then
stage2 <= '0';
else
stage2 <= stage1;
ir <= mm_rdata;
end if;
end if;
end process;
p_gen_mask : process(insn)
begin
if(insn.cmp_bit = '0') then
mask(3 downto 0) <= (insn.cmp_mask(0) & insn.cmp_mask(0) & insn.cmp_mask(0) & insn.cmp_mask(0));
mask(7 downto 4) <= (insn.cmp_mask(1) & insn.cmp_mask(1) & insn.cmp_mask(1) & insn.cmp_mask(1));
mask(11 downto 8) <= (insn.cmp_mask(2) & insn.cmp_mask(2) & insn.cmp_mask(2) & insn.cmp_mask(2));
mask(15 downto 12) <= (insn.cmp_mask(3) & insn.cmp_mask(3) & insn.cmp_mask(3) & insn.cmp_mask(3));
else
case insn.cmp_mask is
when x"0" => mask <= x"0001";
when x"1" => mask <= x"0002";
when x"2" => mask <= x"0004";
when x"3" => mask <= x"0008";
when x"4" => mask <= x"0010";
when x"5" => mask <= x"0020";
when x"6" => mask <= x"0040";
when x"7" => mask <= x"0080";
when x"8" => mask <= x"0100";
when x"9" => mask <= x"0200";
when x"a" => mask <= x"0400";
when x"b" => mask <= x"0800";
when x"c" => mask <= x"1000";
when x"d" => mask <= x"2000";
when x"e" => mask <= x"4000";
when x"f" => mask <= x"8000";
when others => mask <= (others => 'X');
end case;
end if;
end process;
result_cmp <= '1' when ((pmem_rdata and mask) xor mask) = x"0000" else '0';
insn <= f_decode_insn(ir);
ra <= f_pick_reg(regs, insn.ra) when insn.mode = c_MODE_LOGIC else result_cmp;
rb <= f_pick_reg(regs, insn.rb) when insn.mode = c_MODE_LOGIC else f_pick_reg(regs, insn.rd);
rc <= f_pick_reg(regs, insn.rc);
result1 <= f_eval(ra, rb, insn.op);
result2 <= f_eval(result1, rc, insn.op2);
rd <= result1 when insn.mode = c_MODE_LOGIC else result2;
p_execute : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or snk_fab_i.eof = '1' or snk_fab_i.error = '1' or done_int = '1' then
regs <= (others => '0');
else
if(stage2 = '1') then
regs(to_integer(unsigned(insn.rd))) <= rd;
end if;
end if;
end if;
end process;
p_gen_status : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or snk_fab_i.eof = '1' or snk_fab_i.error = '1' then
done_int <= '0';
drop_o <= '0';
else
if(stage2 = '1' and insn.fin = '1') then
done_int <= '1';
pclass_o <= regs(31 downto 24);
drop_o <= regs(23);
end if;
end if;
end if;
end process;
done_o <= done_int;
end behavioral;
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : ep_pcs_tbi_mdio_wb.vhd
-- Author : auto-generated by wbgen2 from pcs_regs.wb
-- Created : Thu Jun 9 00:58:47 2011
-- Created : Mon Aug 22 16:14:10 2011
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE pcs_regs.wb
......
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : ep_registers_pkg.vhd
-- Author : auto-generated by wbgen2 from ep_wishbone_controller.wb
-- Created : Wed Aug 10 16:10:21 2011
-- Created : Mon Aug 22 16:14:10 2011
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE ep_wishbone_controller.wb
......@@ -37,18 +37,20 @@ package ep_wbgen2_pkg is
vcr0_qmode_o : std_logic_vector(1 downto 0);
vcr0_fix_prio_o : std_logic;
vcr0_prio_val_o : std_logic_vector(2 downto 0);
vcr0_vid_val_o : std_logic_vector(11 downto 0);
vcr0_pvid_o : std_logic_vector(11 downto 0);
vcr1_vid_o : std_logic_vector(11 downto 0);
vcr1_vid_wr_o : std_logic;
vcr1_value_o : std_logic;
vcr1_value_wr_o : std_logic;
pfcr_mm_addr_o : std_logic_vector(6 downto 0);
pfcr_mm_addr_wr_o : std_logic;
pfcr_mm_data_o : std_logic_vector(17 downto 0);
pfcr_mm_data_wr_o : std_logic;
pfcr_mm_write_o : std_logic;
pfcr_mm_write_wr_o : std_logic;
pfcr_enable_o : std_logic;
pfcr0_mm_addr_o : std_logic_vector(5 downto 0);
pfcr0_mm_addr_wr_o : std_logic;
pfcr0_mm_write_o : std_logic;
pfcr0_mm_write_wr_o : std_logic;
pfcr0_enable_o : std_logic;
pfcr0_mm_data_msb_o : std_logic_vector(23 downto 0);
pfcr0_mm_data_msb_wr_o : std_logic;
pfcr1_mm_data_lsb_o : std_logic_vector(11 downto 0);
tcar_pcp_map_o : std_logic_vector(23 downto 0);
fcr_rxpause_o : std_logic;
fcr_txpause_o : std_logic;
fcr_tx_thr_o : std_logic_vector(7 downto 0);
......@@ -95,18 +97,20 @@ package ep_wbgen2_pkg is
vcr0_qmode_o => (others => 'Z'),
vcr0_fix_prio_o => 'Z',
vcr0_prio_val_o => (others => 'Z'),
vcr0_vid_val_o => (others => 'Z'),
vcr0_pvid_o => (others => 'Z'),
vcr1_vid_o => (others => 'Z'),
vcr1_vid_wr_o => 'Z',
vcr1_value_o => 'Z',
vcr1_value_wr_o => 'Z',
pfcr_mm_addr_o => (others => 'Z'),
pfcr_mm_addr_wr_o => 'Z',
pfcr_mm_data_o => (others => 'Z'),
pfcr_mm_data_wr_o => 'Z',
pfcr_mm_write_o => 'Z',
pfcr_mm_write_wr_o => 'Z',
pfcr_enable_o => 'Z',
pfcr0_mm_addr_o => (others => 'Z'),
pfcr0_mm_addr_wr_o => 'Z',
pfcr0_mm_write_o => 'Z',
pfcr0_mm_write_wr_o => 'Z',
pfcr0_enable_o => 'Z',
pfcr0_mm_data_msb_o => (others => 'Z'),
pfcr0_mm_data_msb_wr_o => 'Z',
pfcr1_mm_data_lsb_o => (others => 'Z'),
tcar_pcp_map_o => (others => 'Z'),
fcr_rxpause_o => 'Z',
fcr_txpause_o => 'Z',
fcr_tx_thr_o => (others => 'Z'),
......
library ieee;
use ieee.std_logic_1164.all;
entity ep_crc_bypass_queue is
entity ep_rx_bypass_queue is
generic(
g_size : integer := 3;
g_width: integer := 18);
......@@ -22,9 +22,9 @@ entity ep_crc_bypass_queue is
purge_i : in std_logic
);
end ep_crc_bypass_queue;
end ep_rx_bypass_queue;
architecture behavioral of ep_crc_bypass_queue is
architecture behavioral of ep_rx_bypass_queue is
type t_queue_entry is record
d : std_logic_vector(g_width-1 downto 0);
......
......@@ -13,16 +13,12 @@ entity ep_rx_crc_size_check is
port(clk_sys_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
snk_data_i : in std_logic_vector(17 downto 0);
snk_valid_i : in std_logic;
snk_fab_i:in t_ep_internal_fabric;
snk_dreq_o : out std_logic;
src_data_o : out std_logic_vector(17 downto 0);
src_valid_o : out std_logic;
src_fab_o:out t_ep_internal_fabric;
src_dreq_i : in std_logic;
rmon_o : inout t_rmon_triggers;
regs_b : inout t_ep_registers
);
......@@ -33,7 +29,7 @@ architecture behavioral of ep_rx_crc_size_check is
constant c_MIN_FRAME_SIZE : integer := 64;
component ep_crc_bypass_queue
component ep_rx_bypass_queue
generic (
g_size : integer;
g_width : integer);
......@@ -63,28 +59,20 @@ architecture behavioral of ep_rx_crc_size_check is
signal state : t_state;
signal snk_sof, snk_eof, snk_bytesel, snk_error, snk_dvalid : std_logic;
signal q_flush : std_logic;
signal q_purge : std_logic;
signal q_valid : std_logic;
signal q_data : std_logic_vector(17 downto 0);
signal src_eof, src_bytesel, src_error : std_logic;
signal valid_mask : std_logic;
signal last_bytesel : std_logic;
signal q_data : std_logic_vector(15 downto 0);
signal q_bytesel : std_logic;
signal q_dvalid : std_logic;
begin -- behavioral
snk_sof <= f_is_sof(snk_data_i, snk_valid_i);
snk_eof <= f_is_eof(snk_data_i, snk_valid_i);
snk_bytesel <= f_is_single_byte(snk_data_i, snk_valid_i);
snk_error <= f_is_error(snk_data_i, snk_valid_i);
snk_dvalid <= f_is_data(snk_data_i, snk_valid_i);
crc_gen_reset <= snk_sof or (not rst_n_i);
regs_b <= c_ep_registers_init_value;
crc_gen_reset <= snk_fab_i.sof or (not rst_n_i);
U_rx_crc_generator : gc_crc_gen
generic map (
g_polynomial => x"04C11DB7",
......@@ -98,21 +86,21 @@ begin -- behavioral
port map (
clk_i => clk_sys_i,
rst_i => crc_gen_reset,
en_i => snk_dvalid,
half_i => snk_bytesel,
data_i => snk_data_i(15 downto 0),
en_i => snk_fab_i.dvalid,
half_i => snk_fab_i.bytesel,
data_i => snk_fab_i.data(15 downto 0),
match_o => crc_match,
crc_o => open);
U_bypass_queue : ep_crc_bypass_queue
U_bypass_queue : ep_rx_bypass_queue
generic map (
g_size => 3,
g_width => 18)
g_size => 2,
g_width => 16)
port map (
rst_n_i => rst_n_i,
clk_i => clk_sys_i,
d_i => snk_data_i,
valid_i => snk_dvalid,
d_i => snk_fab_i.data,
valid_i => snk_fab_i.dvalid,
dreq_o => snk_dreq_o,
q_o => q_data,
valid_o => q_valid,
......@@ -124,17 +112,17 @@ begin -- behavioral
p_count_bytes : process (clk_sys_i, rst_n_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_i = '0' or enable_i = '0') then
if (rst_n_i = '0' or regs_b.ecr_rx_en_o = '0') then
byte_cntr <= (others => '0');
is_runt <= '0';
is_giant <= '0';
else
if(snk_sof = '1') then
if(snk_fab_i.sof = '1') then
byte_cntr <= (others => '0');
end if;
if(snk_dvalid = '1') then
if(snk_bytesel = '1') then
if(snk_fab_i.dvalid = '1') then
if(snk_fab_i.bytesel = '1') then
byte_cntr <= byte_cntr + 1;
else
byte_cntr <= byte_cntr + 2;
......@@ -165,11 +153,11 @@ begin -- behavioral
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or enable_i = '0' then
if rst_n_i = '0' or regs_b.ecr_rx_en_o = '0' then
q_flush <= '0';
q_purge <= '0';
valid_mask <= '0';
q_bytesel <= '0';
state <= ST_WAIT_FRAME;
......@@ -181,64 +169,67 @@ begin -- behavioral
else
case state is
when ST_WAIT_FRAME =>
q_flush <= '0';
q_purge <= '0';
valid_mask <= '1';
q_flush <= '0';
q_purge <= '0';
rmon_o.rx_pcs_err <= '0';
rmon_o.rx_giant <= '0';
rmon_o.rx_runt <= '0';
rmon_o.rx_crc_err <= '0';
q_bytesel <='0';
src_fab_o.eof <= '0';
src_fab_o.error <= '0';
src_eof <= '0';
src_error <= '0';
src_bytesel <= '0';
if(snk_sof = '1') then
state <= ST_DATA;
if(snk_fab_i.sof = '1') then
state <= ST_DATA;
end if;
when ST_DATA =>
if (snk_dvalid = '1') then
last_bytesel <= snk_bytesel;
valid_mask <= '1';
if(snk_fab_i.dvalid= '1') then
q_bytesel<=snk_fab_i.bytesel;
end if;
if(snk_fab_i.error = '1') then -- an error from the source?
if(snk_error = '1') then -- an error from the source?
src_error <= '1';
src_fab_o.error <= '1';
rmon_o.rx_pcs_err <= '1';
state <= ST_WAIT_FRAME;
q_purge <= '1';
state <= ST_WAIT_FRAME;
q_purge <= '1';
end if;
if(snk_eof = '1') then -- we've got a valid frame
state <= ST_WAIT_FRAME;
if(size_check_ok = '0' or crc_match = '0') then -- bad frame?
src_error <= '1';
else
src_eof <= '1';
end if;
if(snk_fab_i.eof = '1') then
if(regs_b.rfcr_keep_crc_o = '0') then
valid_mask <= '0';
q_purge <= '1';
else
q_flush <= '1';
end if;
state <= ST_WAIT_FRAME;
if(size_check_ok = '0' or crc_match = '0') then -- bad frame?
src_fab_o.error <= '1';
else
src_fab_o.eof <= '1';
end if;
rmon_o.rx_runt <= is_runt and (not regs_b.rfcr_a_runt_o);
rmon_o.rx_giant <= is_giant and (not regs_b.rfcr_a_giant_o);
rmon_o.rx_crc_err <= not crc_match;
rmon_o.rx_runt <= is_runt and (not regs_b.rfcr_a_runt_o);
rmon_o.rx_giant <= is_giant and (not regs_b.rfcr_a_giant_o);
rmon_o.rx_crc_err <= not crc_match;
end if;
end case;
end if;
end if;
end process;
src_fab_o.sof <= regs_b.ecr_rx_en_o and snk_fab_i.sof;
src_fab_o.dvalid<=q_valid;
src_fab_o.data <=q_data;
src_fab_o.bytesel<=snk_fab_i.bytesel or q_bytesel;
end behavioral;
......
This diff is collapsed.
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2009-06-16
-- Last update: 2011-05-27
-- Last update: 2011-08-22
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -56,7 +56,7 @@ use work.endpoint_private_pkg.all;
entity ep_rx_pcs_tbi is
generic (
g_simulation : integer);
g_simulation : boolean);
port (
-- 62.5 MHz refclk divided by 2
clk_sys_i : in std_logic;
......@@ -64,16 +64,12 @@ entity ep_rx_pcs_tbi is
-- reset (refclk2-synchronous)
rst_n_i : in std_logic;
-- RX path busy indicator (active HI),
-- asserted means that receiver is in the middle of reception
-- of a frame
pcs_busy_o : out std_logic;
-- data FIFO output
pcs_data_o : out std_logic_vector(17 downto 0);
-- HI requests a single word from RX FIFO
pcs_dreq_i : in std_logic;
-- HI indicates that there is valid data present on pcs_data_o
pcs_valid_o : out std_logic;
-- RX path busy indicator (active HI).
-- When asserted, the receiver is in the middle of reception of a frame
pcs_busy_o : out std_logic;
-- data FIFO output
pcs_fab_o: out t_ep_internal_fabric;
timestamp_stb_p_o : out std_logic; -- strobe for RX timestamping
......@@ -124,7 +120,7 @@ architecture behavioral of ep_rx_pcs_tbi is
function f_calc_pattern_counter_bits
return integer is
begin -- f_calc_pattern_counter_bits
if(g_simulation /= 0) then
if(g_simulation) then
return 8; -- use smaller calibration counter to
-- speed up the simulation
else
......@@ -337,26 +333,31 @@ begin
-- FIFO input data formatting
fifo_wrreq <= fifo_wr_toggle and fifo_mask_write;
fifo_in <= f_encode_fabric_int(fifo_rx_data, fifo_sof, fifo_eof, fifo_bytesel, fifo_error);
fifo_in <= f_pack_fifo_contents (
fifo_rx_data,
fifo_sof,
fifo_eof,
fifo_bytesel,
fifo_error);
-- Clock adjustment FIFO
U_RX_FIFO : generic_async_fifo
U_Rx_FIFO : generic_async_fifo
generic map (
g_data_width => 18,
g_size => 32,
g_with_wr_almost_full => true,
g_with_rd_almost_empty => true,
g_almost_empty_threshold => 4,
g_almost_full_threshold => 30)
g_with_wr_almost_full => false,
g_with_rd_almost_empty => false)
-- g_almost_empty_threshold => 4,
-- g_almost_full_threshold => 26)
port map (
rst_n_i => fifo_clear_n,
clk_wr_i => phy_rx_clk_i,
d_i => fifo_in,
we_i => fifo_wrreq,
wr_empty_o => open,
wr_full_o => open,
wr_full_o => fifo_almostfull,
wr_almost_empty_o => open,
wr_almost_full_o => fifo_almostfull,
wr_almost_full_o => open,
wr_count_o => open,
clk_rd_i => clk_sys_i,
q_o => fifo_out,
......@@ -382,9 +383,13 @@ begin
end process;
-- FIFO output data formatting
pcs_data_o <= fifo_out;
pcs_valid_o <= pcs_valid_int;
pcs_fab_o.sof <= f_fifo_is_sof(fifo_out, pcs_valid_int);
pcs_fab_o.eof <= f_fifo_is_eof(fifo_out, pcs_valid_int);
pcs_fab_o.error <= f_fifo_is_error(fifo_out, pcs_valid_int);
pcs_fab_o.dvalid <= f_fifo_is_data(fifo_out, pcs_valid_int);
pcs_fab_o.bytesel <= f_fifo_is_single_byte(fifo_out, pcs_valid_int);
pcs_fab_o.data <= fifo_out(15 downto 0);
-- FIFO control signals
rx_rdreq <= (not fifo_empty) and pcs_dreq_i;
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all; -- for gc_crc_gen
use work.endpoint_private_pkg.all;
use work.ep_wbgen2_pkg.all;
-- 3rd deframing pipeline stage - VLAN Unit
entity ep_rx_vlan_unit is
port(clk_sys_i : in std_logic;
rst_n_i : in std_logic;
snk_fab_i : in t_ep_internal_fabric;
snk_dreq_o : out std_logic;
src_fab_o : out t_ep_internal_fabric;
src_dreq_i : in std_logic;
tclass_o : out std_logic_vector(2 downto 0);
tclass_valid_o : out std_logic;
rmon_o : inout t_rmon_triggers;
regs_b : inout t_ep_registers
);
end ep_rx_vlan_unit;
architecture behavioral of ep_rx_vlan_unit is
type t_tag_type is (NONE, PRIO, VLAN, NULL_VLAN);
type t_state is (WAIT_FRAME, DATA, DISCARD_FRAME, INSERT_TAG);
signal dreq_mask : std_logic;
signal hdr_offset : std_logic_vector(11 downto 0);
signal comb_tag_type : t_tag_type;
signal tag_type : t_tag_type;
signal state : t_state;
signal at_ethertype : std_logic;
signal at_vid : std_logic;
signal at_tpid : std_logic;
signal is_tagged : std_logic;
signal stored_ethertype : std_logic_vector(15 downto 0);
signal prio_int : std_logic_vector(2 downto 0);
procedure f_vlan_decision
(tag_type : t_tag_type;
qmode : in std_logic_vector(1 downto 0);
admit : out std_logic;
use_pvid : out std_logic;
use_fixed_prio : out std_logic) is
begin
use_pvid := 'X';
use_fixed_prio := 'X';
admit := '0';
-- From Jose's table. Thanks a lot!
case (qmode) is
when c_QMODE_PORT_ACCESS =>
case tag_type is
when NONE =>
admit := '1'; use_pvid := '1'; use_fixed_prio := '1';
when PRIO =>
admit := '1'; use_pvid := '1'; use_fixed_prio := '0';
when VLAN =>
admit := '0'; use_pvid := '0';
when NULL_VLAN =>
admit := '0';
end case;
when c_QMODE_PORT_TRUNK =>
case tag_type is
when NONE =>
admit := '0';
when PRIO=>
admit := '0';
when VLAN=>
admit := '1';
use_pvid := '0';
use_fixed_prio := '0';
when NULL_VLAN =>
admit := '0';
end case;
when c_QMODE_PORT_UNQUALIFIED =>
case tag_type is
when NONE =>
admit := '1';
use_pvid := '1'; use_fixed_prio := '1';
when PRIO=>
admit := '1';
use_pvid := '1'; use_fixed_prio := '0';
when VLAN=>
admit := '1';
use_pvid := '0'; use_fixed_prio := '0';
when NULL_VLAN =>
admit := '0';
end case;
when others => null;
end case;
end procedure;
begin -- behavioral
at_ethertype <= hdr_offset(5) and snk_fab_i.dvalid and src_dreq_i;
at_tpid <= hdr_offset(6) and snk_fab_i.dvalid and is_tagged and src_dreq_i;
at_vid <= hdr_offset(7) and snk_fab_i.dvalid and is_tagged and src_dreq_i;
regs_b <= c_ep_registers_init_value;
snk_dreq_o <= src_dreq_i and dreq_mask;
p_decode_tag_type : process(snk_fab_i, is_tagged)
begin
if(is_tagged = '0') then
comb_tag_type <= NONE;
else
case snk_fab_i.data(11 downto 0) is
when x"000" => comb_tag_type <= PRIO;
when x"fff" => comb_tag_type <= NULL_VLAN;
when others => comb_tag_type <= VLAN;
end case;
end if;
end process;
p_tag_untag : process(clk_sys_i)
variable admit, use_pvid, use_fixed_prio : std_logic;
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or regs_b.ecr_rx_en_o = '0' then
hdr_offset(hdr_offset'left downto 1) <= (others => '0');
hdr_offset(0) <= '1';
state <= WAIT_FRAME;
dreq_mask <= '0';
else
if(snk_fab_i.error = '1') then
state <= DISCARD_FRAME;
else
case state is
when WAIT_FRAME =>
dreq_mask <= '1';
src_fab_o.eof <= '0';
src_fab_o.error <= '0';
if(snk_fab_i.sof = '1') then
hdr_offset(hdr_offset'left downto 1) <= (others => '0');
hdr_offset(0) <= '1';
state <= DATA;
end if;
when DATA =>
dreq_mask <= '1';
-- pass the data through the pipeline
src_fab_o.data <= snk_fab_i.data;
src_fab_o.dvalid <= snk_fab_i.dvalid;
if(at_ethertype = '1') then
if(snk_fab_i.data = x"8100") then -- got a 802.1q tagged frame
is_tagged <= '1';
else
is_tagged <= '0';
-- if the packet has to be VLAN-tagged on ingress, do it as
-- early as possible (i.e. right after identifying the Ethertype)
-- to avoid increasing latency
if(regs_b.vcr0_qmode_o = c_QMODE_PORT_ACCESS) then
-- fix to Jose's table: UNQUALIFIED ports don't tag untagged
-- frames with PVID
src_fab_o.dvalid <= '0';
src_fab_o.data <= x"8100";
prio_int <= regs_b.vcr0_prio_val_o;
state <= INSERT_TAG;
dreq_mask <= '0';
end if;
end if;
-- remember the Ethertype, as it is needed for producing an
-- 802.1q header
stored_ethertype <= snk_fab_i.data;
end if;
-- we are at the VID field in the header. Most of the VLAN logic lives
-- here :)
if(at_vid = '1') then
-- decide what to do with the frame, basing on the port mode
-- (ACCESS, TRUNK, UNQUALIFIED), and whether the frame is tagged
-- or not.
f_vlan_decision(comb_tag_type, regs_b.vcr0_qmode_o, admit, use_pvid, use_fixed_prio);
if(admit = '0') then -- oops...
state <= DISCARD_FRAME;
end if;
-- assign the VID
if(use_pvid = '1')then
src_fab_o.data(11 downto 0) <= regs_b.vcr0_pvid_o;
end if;
-- assign the priority
if(regs_b.vcr0_fix_prio_o = '1' or use_fixed_prio = '1') then
-- Forced priority (or a non-priority tagged frame)? Take the priority
-- value from VCR0 register
prio_int <= regs_b.vcr0_prio_val_o;
else
-- Got a priority tag - use the value from the VLAN tag
prio_int <= snk_fab_i.data(15 downto 13);
end if;
end if;
if(snk_fab_i.eof = '1') then
state <= WAIT_FRAME;
src_fab_o.eof <= '1';
end if;
if(snk_fab_i.dvalid = '1') then
hdr_offset <= hdr_offset(hdr_offset'left-1 downto 0) & '0';
end if;
when INSERT_TAG =>
src_fab_o.dvalid <= '0';
if(src_dreq_i = '1') then
-- we are at 7th word from the beginning of the frame, but the sink reception
-- is disabled, so we can insert the original ethertype as the TPID
if(hdr_offset(6) = '1') then
src_fab_o.data <= stored_ethertype;
src_fab_o.dvalid <= '1';
end if;
if(hdr_offset(7) = '1') then
src_fab_o.data <= regs_b.vcr0_prio_val_o & '0' & regs_b.vcr0_pvid_o;
state <= DATA;
src_fab_o.dvalid <= '1';
end if;
hdr_offset <= hdr_offset(hdr_offset'left-1 downto 0) & '0';
end if;
when DISCARD_FRAME =>
if(src_dreq_i = '1') then
src_fab_o.error <= '1';
state <= WAIT_FRAME;
end if;
end case;
end if;
end if;
end if;
end process;
-- Process: p_map_prio_to_tc
-- Maps the PCP value from the 802.1q header into a traffic class for further
-- processing. The mapping table is stored in TCAR register.
p_map_prio_to_tc : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0' or regs_b.ecr_rx_en_o = '0' or snk_fab_i.sof = '1')then
tclass_valid_o <= '0';
elsif(hdr_offset(8) = '1') then
-- we're already after the headers, so prio_int is
-- certainly valid
tclass_valid_o <= '1';
case prio_int is
when "000" => tclass_o <= regs_b.tcar_pcp_map_o(2 downto 0);
when "001" => tclass_o <= regs_b.tcar_pcp_map_o(5 downto 3);
when "010" => tclass_o <= regs_b.tcar_pcp_map_o(8 downto 6);
when "011" => tclass_o <= regs_b.tcar_pcp_map_o(11 downto 9);
when "100" => tclass_o <= regs_b.tcar_pcp_map_o(14 downto 12);
when "101" => tclass_o <= regs_b.tcar_pcp_map_o(17 downto 15);
when "110" => tclass_o <= regs_b.tcar_pcp_map_o(20 downto 18);
when "111" => tclass_o <= regs_b.tcar_pcp_map_o(23 downto 21);
when others => tclass_o <= "XXX"; -- packet probably contains porn
end case;
end if;
end if;
end process;
src_fab_o.sof <= regs_b.ecr_rx_en_o and snk_fab_i.sof;
end behavioral;
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2009-06-22
-- Last update: 2011-08-15
-- Last update: 2011-08-22
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
......@@ -51,11 +51,10 @@ entity ep_tx_framer is
-- Physical Coding Sublayer (PCS) interface
------------------------------------------------------------------------------
pcs_fab_o : out t_ep_internal_fabric;
pcs_error_i : in std_logic;
pcs_busy_i : in std_logic;
pcs_data_o : out std_logic_vector(17 downto 0);
pcs_dreq_i : in std_logic;
pcs_valid_o : out std_logic;
-------------------------------------------------------------------------------
-- WRF Sink (see WRF specification for the details)
......@@ -68,17 +67,18 @@ entity ep_tx_framer is
-- Flow Control Unit signals
-------------------------------------------------------------------------------
-- TX send pause frame - when active, the framer will send a PAUSE frame
-- as soon as possible. The pause quanta must be provided on tx_pause_delay_i input.
tx_pause_i : in std_logic;
tx_pause_delay_i : in std_logic_vector(15 downto 0);
fc_pause_p_i : in std_logic;
fc_pause_delay_i : in std_logic_vector(15 downto 0);
-- TX send pause acknowledge - active after the current pause send request has
-- been completed
tx_pause_ack_o : out std_logic;
fc_pause_ack_o : out std_logic;
-- When active, the framer will allow for packet transmission.
tx_flow_enable_i : in std_logic;
fc_flow_enable_i : in std_logic;
-------------------------------------------------------------------------------
-- OOB/TSU signals
......@@ -318,7 +318,7 @@ begin -- behavioral
snk_out.err <= '0';
snk_out.rty <= '0';
tx_pause_ack_o <= '0';
fc_pause_ack_o <= '0';
crc_gen_enable_mask <= '1';
crc_gen_force_reset <= '0';
......@@ -357,27 +357,27 @@ begin -- behavioral
q_abort <= '0';
tx_ready <= tx_flow_enable_i;
tx_ready <= fc_flow_enable_i;
-- Check start-of-frame and send-pause signals and eventually
-- commence frame transmission
if(pcs_dreq_i = '1' and (sof_p1 = '1' or tx_pause_i = '1') and regs_b.ecr_tx_en_o = '1') then
if(pcs_dreq_i = '1' and (sof_p1 = '1' or fc_pause_p_i = '1') and regs_b.ecr_tx_en_o = '1') then
-- enable writing to PCS FIFO
q_sof <= '1';
q_eof <= '0';
write_mask <= '1';
tx_pause_ack_o <= tx_pause_i;
tx_pause_mode <= tx_pause_i;
tx_pause_delay <= tx_pause_delay_i;
fc_pause_ack_o <= fc_pause_p_i;
tx_pause_mode <= fc_pause_p_i;
tx_pause_delay <= fc_pause_delay_i;
crc_gen_force_reset <= '1';
crc_gen_enable_mask <= '1';
counter <= (others => '0');
if(tx_pause_i = '1') then
if(fc_pause_p_i = '1') then
state <= TXF_PAUSE;
else
state <= TXF_ADDR;
......@@ -396,7 +396,7 @@ begin -- behavioral
-------------------------------------------------------------------------------
when TXF_PAUSE =>
tx_ready <= '0';
tx_pause_ack_o <= '0';
fc_pause_ack_o <= '0';
q_sof <= '0';
crc_gen_force_reset <= '0';
......@@ -684,14 +684,12 @@ begin -- behavioral
snk_o <= snk_out;
pcs_data_o <= f_encode_fabric_int(
q_data,
q_sof,
q_eof,
q_bytesel,
q_abort);
pcs_valid_o <= q_sof or q_eof or (q_valid and write_mask);
pcs_fab_o.data <= q_data;
pcs_fab_o.sof <= q_sof;
pcs_fab_o.eof <= q_eof;
pcs_fab_o.bytesel <= q_bytesel;
pcs_fab_o.error <= q_abort;
pcs_fab_o.dvalid <= (q_valid and write_mask);
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.endpoint_private_pkg.all;
use work.ep_wbgen2_pkg.all;
entity ep_tx_header_processor is
generic (
g_with_vlans : boolean);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
sof_p1_i : in std_logic;
has_mac_i : in std_logic;
is_pause_i : in std_logic;
pause_delay_i : in std_logic_vector(15 downto 0);
en_i :in std_logic;
d_i : in std_logic_vector(15 downto 0);
q_o : out std_logic_vector(15 downto 0);
valid_o : out std_logic;
done_o : out std_logic;
send_pad_o : out std_logic;
stall_o : out std_logic;
regs_b : inout t_ep_registers
);
end ep_tx_header_processor;
architecture behavioral of ep_tx_header_processor is
signal vut_rd_vid : integer;
signal vut_wr_vid : integer;
signal vut_untag : std_logic;
signal vut_is_802_1q : std_logic;
signal prev_word0 : std_logic_vector(15 downto 0);
signal prev_word1 : std_logic_vector(15 downto 0);
signal prev_word2 : std_logic_vector(15 downto 0);
signal comb_is_802_1q : std_logic;
signal offset : unsigned(3 downto 0);
signal stall_int : std_logic;
begin -- behavioral
regs_b <= c_ep_registers_init_value;
p_process_packet_header : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
valid_o <= '0';
q_o <= (others => 'X');
done_o <= '0';
send_pad_o <= '0';
stall_int <= '0';
else
if(is_pause_i = '1') then
case offset_i is
when x"0" =>
q_o <= x"0180";
when x"1"=>
q_o <= x"c200";
when x"2" =>
q_o <= x"0001";
when x"3" =>
q_o <= regs_b.mach_o;
when x"4" =>
q_o <= regs_b.macl_o(31 downto 16);
when x"5" =>
q_o <= regs_b.macl_o(15 downto 0);
when x"6" =>
q_o <= x"8808";
when x"7" =>
q_o <= pause_delay_i;
done_o <= '1';
send_pad_o <= '1';
when others => null;
end case;
end if;
else
case offset_i is
when x"0" =>
q_o <= d_i;
valid_o <= en_i;
when x"1" =>
q_o <= d_i;
valid_o <= en_i;
when x"2" =>
q_o <= d_i;
valid_o <= en_i;
when x"3" =>
if(has_mac_i = '0') then
q_o <= regs_b.mach_o;
else
q_o <= d_i;
end if;
valid_o <= en_i;
when x"4" =>
if(has_mac_i = '0') then
q_o <= regs_b.macl_o(31 downto 16);
else
q_o <= d_i;
end if;
valid_o <= en_i;
when x"5" =>
if(has_mac_i = '0') then
q_o <= regs_b.macl_o(15 downto 0);
else
q_o <= d_i;
end if;
valid_o <= en_i;
-- no VLAN tagging support - just treat the eventual 802.1q header as
-- a payload
if (not g_with_vlans) then
done_o <= '1';
end if;
when x"6" =>
if(d_i = x"8100" and g_with_vlans = true) then
comb_is_802_1q <= '1';
valid_o <= '0';
else
q_o <= d_i;
valid_o <= en_i;
done_o <= '1';
end if;
when x"7" => -- prev0 = 0x8100,
valid_o <= '0';
when x"8" => -- prev0 = TPID, prev1 = 0x8100
valid_o <= '0';
when x"9" => -- prev0 = VID, prev1 = TPID, prev2 = 0x8100
if(vut_untag = '1') then
stall_int <= '1';
done_o <= '0';
valid_o <= '0';
else
stall_int <= '1';
valid_o <= '1';
q_o <= prev_word1; -- output the TPID as ethertype
end if;
when x"a" =>
stall_int <= '1';
q_o <= prev_word1;
valid_o <= '1';
when x"b" =>
stall_int <= '0';
q_o <= d_i;
valid_o <= '1';
done_o <= '1';
when others => null;
end case;
end if;
end if;
end if;
end process;
gen_with_vlans : if(g_with_vlans) generate
vut_rd_vid <= to_integer(unsigned(d_i(11 downto 0)));
vut_wr_vid <= to_integer(unsigned(regs_b.vcr1_vid_o));
p_untagged_set_access : process(clk_sys_i)
variable vut_set : std_logic_vector(4095 downto 0);
begin
if rising_edge(clk_sys_i) then
if(regs_b.vcr1_value_wr_o = '1') then
vut_set(vut_wr_vid) := regs_b.vcr1_value_o;
end if;
--vut_untag <= vut_set(vut_rd_vid);
vut_untag <= '1';
end if;
end process;
p_latch_and_delay: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(valid_i ='1') then
prev_word0 <= d_i;
prev_word1 <= prev_word0;
prev_word2 <= prev_word1;
end if;
vut_is_802_1q <= comb_is_802_1q;
end if;
end process;
end generate gen_with_vlans;
stall_o <= stall_int;
end behavioral;
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT section
-- Created : 2009-06-16
-- Last update: 2011-08-15
-- Last update: 2011-08-17
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -75,8 +75,8 @@ entity ep_tx_pcs_tbi is
-- TX Framer inteface
-------------------------------------------------------------------------------
-- TX FIFO input
pcs_data_i : in std_logic_vector(17 downto 0);
-- TX Fabric input
pcs_fab_i : in t_ep_internal_fabric;
-- HI pulse indicates an error during transmission of a frame (buffer underrun)
pcs_error_o : out std_logic;
......@@ -84,10 +84,6 @@ entity ep_tx_pcs_tbi is
-- HI indicates that the PCS is busy (transmitting a frame or during autonegotiation)
pcs_busy_o : out std_logic;
-- HI indicates that pcs_data_i, pcs_bytesel_i, pcs_sof_i, pcs_eof_i,
-- pcs_abort_i contain valid values and should be written to the TX FIFO.
pcs_valid_i : in std_logic;
-- HI indicates that PCS FIFO is almost full.
pcs_dreq_o : out std_logic;
......@@ -108,13 +104,13 @@ entity ep_tx_pcs_tbi is
timestamp_stb_p_o : out std_logic;
-- RMON counters
rmon_o: inout t_rmon_triggers;
rmon_o : inout t_rmon_triggers;
-------------------------------------------------------------------------------
-- PHY Interface
-------------------------------------------------------------------------------
phy_tx_clk_i :in std_logic;
phy_tx_clk_i : in std_logic;
phy_tx_data_o : out std_logic_vector(7 downto 0);
phy_tx_k_o : out std_logic;
phy_tx_disparity_i : in std_logic;
......@@ -136,10 +132,9 @@ architecture behavioral of ep_tx_pcs_tbi is
signal tx_catch_disparity : std_logic;
signal tx_odata_reg : std_logic_vector(7 downto 0);
signal tx_state : t_tbif_tx_state;
signal tx_cntr : unsigned(3 downto 0);
signal tx_cntr : unsigned(3 downto 0);
signal tx_cr_alternate : std_logic;
signal tx_fifo_rdreq : std_logic;
signal tx_newframe : std_logic;
-- TX clock alignment FIFO signals
......@@ -149,6 +144,7 @@ architecture behavioral of ep_tx_pcs_tbi is
signal tx_fifo_start : std_logic;
signal tx_fifo_rdempty : std_logic;
signal tx_fifo_almostempty : std_logic;
signal tx_fifo_write : std_logic;
signal tx_fifo_abort : std_logic;
signal tx_rdreq_toggle : std_logic;
......@@ -160,14 +156,11 @@ architecture behavioral of ep_tx_pcs_tbi is
signal tx_error : std_logic;
signal reset_synced_txclk : std_logic;
signal txdata_encoded : std_logic_vector(9 downto 0);
signal txdata_encoded_d0 : std_logic_vector(9 downto 0);
signal mdio_mcr_pdown_synced : std_logic;
signal tx_fifo_enough_data : std_logic;
signal fifo_almost_full : std_logic;
begin
U_sync_pcs_busy_o : gc_sync_ffs
......@@ -229,6 +222,17 @@ begin
pcs_dreq_o <= not fifo_almost_full;
tx_fifo_data_in <= f_pack_fifo_contents (
pcs_fab_i.data,
pcs_fab_i.sof,
pcs_fab_i.eof,
pcs_fab_i.bytesel,
pcs_fab_i.error,
true
);
tx_fifo_write <= pcs_fab_i.sof or pcs_fab_i.dvalid;
U_TX_FIFO : generic_async_fifo
generic map (
g_data_width => 18,
......@@ -242,8 +246,8 @@ begin
port map (
rst_n_i => tx_fifo_clear_n,
clk_wr_i => clk_sys_i,
d_i => pcs_data_i,
we_i => pcs_valid_i,
d_i => tx_fifo_data_in,
we_i => tx_fifo_write,
wr_empty_o => open,
wr_full_o => open,
wr_almost_empty_o => open,
......@@ -263,10 +267,10 @@ begin
tx_fifo_msb <= tx_fifo_data_out(15 downto 8);
tx_fifo_lsb <= tx_fifo_data_out(7 downto 0);
tx_fifo_singlebyte <= f_is_single_byte(tx_fifo_data_out, '1');
tx_fifo_abort <= f_is_error (tx_fifo_data_out, '1');
tx_fifo_start <= f_is_sof (tx_fifo_data_out, '1');
tx_fifo_end <= f_is_eof (tx_fifo_data_out, '1');
tx_fifo_singlebyte <= f_fifo_is_single_byte(tx_fifo_data_out, '1', true);
tx_fifo_abort <= f_fifo_is_error (tx_fifo_data_out, '1', true);
tx_fifo_start <= f_fifo_is_sof (tx_fifo_data_out, '1', true);
tx_fifo_end <= f_fifo_is_eof (tx_fifo_data_out, '1', true);
-----------------------------------------------------------------------------
-- Main TX PCS state machine
......@@ -285,9 +289,8 @@ begin
tx_odata_reg <= (others => '0');
tx_is_k <= '0';
tx_cr_alternate <= '0';
tx_newframe <= '0';
tx_catch_disparity <= '0';
tx_cntr <= (others => '0');
tx_cntr <= (others => '0');
tx_odd_length <= '0';
tx_rdreq_toggle <= '0';
rmon_o.tx_underrun <= '0';
......@@ -323,11 +326,10 @@ begin
tx_fifo_rdreq <= '0';
-- we've got a new frame in the FIFO
elsif (tx_fifo_start = '1' and fifo_rdy = '1' and tx_cntr = "0000" )then
tx_fifo_rdreq <= '1';
tx_newframe <= '1';
tx_state <= TX_SPD;
tx_cntr <= "0101";
elsif (tx_fifo_start = '1' and fifo_rdy = '1' and tx_cntr = "0000")then
tx_fifo_rdreq <= '1';
tx_state <= TX_SPD;
tx_cntr <= "0101";
-- host requested a calibration pattern
elsif(mdio_wr_spec_tx_cal_i = '1') then
......@@ -342,7 +344,7 @@ begin
else
tx_fifo_rdreq <= (not tx_fifo_rdempty) and tx_fifo_enough_data;
end if;
tx_state <= TX_COMMA;
tx_state <= TX_COMMA;
end if;
tx_is_k <= '0';
......@@ -411,9 +413,9 @@ begin
-------------------------------------------------------------------------------
when TX_SPD =>
tx_fifo_rdreq <= '0';
tx_is_k <= '1';
tx_odata_reg <= c_k27_7;
tx_state <= TX_PREAMBLE;
tx_is_k <= '1';
tx_odata_reg <= c_k27_7;
tx_state <= TX_PREAMBLE;
-------------------------------------------------------------------------------
-- State PREAMBLE: produces an Ethernet preamble
......@@ -436,7 +438,6 @@ begin
-------------------------------------------------------------------------------
when TX_SFD =>
tx_newframe <= '0';
tx_odata_reg <= c_preamble_sfd;
tx_rdreq_toggle <= '1';
tx_state <= TX_DATA;
......@@ -471,7 +472,7 @@ begin
tx_odd_length <= tx_fifo_singlebyte;
if (tx_fifo_end = '1' and (tx_rdreq_toggle = '0' or (tx_rdreq_toggle = '1' and tx_fifo_singlebyte = '1'))) then
tx_state <= TX_EPD;
tx_state <= TX_EPD;
tx_fifo_rdreq <= '0';
end if;
end if;
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.global_defs.all;
use work.endpoint_pkg.all;
entity ep_wb_to_wrf is
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- WRF sink
src_data_o : out std_logic_vector(15 downto 0);
src_ctrl_o : out std_logic_vector(c_wrsw_ctrl_size-1 downto 0);
src_bytesel_o : out std_logic;
src_dreq_i : in std_logic;
src_valid_o : out std_logic;
src_sof_p1_o : out std_logic;
src_eof_p1_o : out std_logic;
src_error_p1_i : in std_logic;
src_abort_p1_o : out std_logic;
-- Pipelined Wishbone slave
wb_dat_i : in std_logic_vector(15 downto 0);
wb_adr_i : in std_logic_vector(1 downto 0);
wb_sel_i : in std_logic_vector(1 downto 0);
wb_cyc_i : in std_logic;
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_stall_o : out std_logic;
wb_ack_o : out std_logic;
wb_err_o : out std_logic;
wb_rty_o : out std_logic
);
end ep_wb_to_wrf;
architecture behavioral of ep_wb_to_wrf is
function f_gen_ctrl(sreg : unsigned; addr : std_logic_vector) return std_logic_vector is
variable tmp : std_logic_vector(3 downto 0);
begin
if(addr = c_WRF_DATA) then
if(sreg(6 downto 0) /= "0000000") then
return c_wrsw_ctrl_none;
else
return c_wrsw_ctrl_payload;
end if;
elsif(addr = c_WRF_OOB) then
return c_wrsw_ctrl_tx_oob;
end if;
end function;
function to_sl(x : boolean) return std_logic is
begin
if(x = true) then
return '1';
else
return '0';
end if;
end function to_sl;
type t_arb_state is (ST_WAIT_CYC, ST_BEGIN_CYC, ST_DATA, ST_TERMINATE_CYC);
signal hdr_sreg : unsigned(9 downto 0);
signal state : t_arb_state;
signal src_ctrl_int : std_logic_vector(3 downto 0);
signal stat : t_wrf_status_reg;
begin -- behavioral
wb_stall_o <= not src_dreq_i or to_sl(state = ST_WAIT_CYC and wb_stb_i = '1' and wb_cyc_i = '1');
stat <= f_unmarshall_wrf_status(wb_dat_i);
arb_fsm : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0'then
hdr_sreg <= (others => '0');
state <= ST_WAIT_CYC;
src_sof_p1_o <= '0';
src_data_o <= (others => '0');
src_ctrl_int <= (others => '0');
src_eof_p1_o <= '0';
src_abort_p1_o <= '0';
src_valid_o <= '0';
wb_ack_o <= '0';
wb_err_o <= '0';
wb_rty_o <= '0';
else
case state is
when ST_WAIT_CYC =>
src_eof_p1_o <= '0';
src_abort_p1_o <= '0';
hdr_sreg <= to_unsigned(1, hdr_sreg'length);
if(wb_cyc_i = '1') then
if(wb_stb_i = '1') then
state <= ST_BEGIN_CYC;
src_data_o <= wb_dat_i;
src_bytesel_o <= '0';
src_ctrl_int <= c_wrsw_ctrl_dst_mac;
wb_ack_o <= '1';
else
state <= ST_DATA;
end if;
src_sof_p1_o <= '1';
end if;
when ST_BEGIN_CYC =>
src_sof_p1_o <= '0';
if(src_dreq_i = '1') then
src_valid_o <= '1';
wb_ack_o <= '1';
if(stat.rx_error = '1' and wb_adr_i = c_WRF_STATUS) then
src_abort_p1_o <= '1';
state <= ST_WAIT_CYC;
wb_ack_o <= '1';
state <= ST_TERMINATE_CYC;
else
src_valid_o <= '1';
state <= ST_DATA;
hdr_sreg <= hdr_sreg sll 1;
end if;
else
src_valid_o <= '0';
wb_ack_o <= '0';
end if;
if(src_error_p1_i = '1') then
wb_err_o <= '1';
state <= ST_TERMINATE_CYC;
end if;
when ST_DATA =>
src_sof_p1_o <= '0';
if(wb_cyc_i = '1') then
if(wb_stb_i = '1') then
case wb_adr_i is
when c_WRF_STATUS =>
if(stat.rx_error = '1') then
src_abort_p1_o <= '1';
src_valid_o <= '0';
state <= ST_TERMINATE_CYC;
wb_ack_o <= '1';
else
src_valid_o <= '0';
end if;
when c_WRF_OOB =>
hdr_sreg <= hdr_sreg sll 1;
src_ctrl_int <= f_gen_ctrl(hdr_sreg, wb_adr_i);
src_data_o <= wb_dat_i;
src_bytesel_o <= not wb_sel_i(0);
src_valid_o <= '1';
wb_ack_o <= '1';
when c_WRF_DATA =>
hdr_sreg <= hdr_sreg sll 1;
src_ctrl_int <= f_gen_ctrl(hdr_sreg, wb_adr_i);
src_data_o <= wb_dat_i;
src_bytesel_o <= not wb_sel_i(0);
src_valid_o <= '1';
wb_ack_o <= '1';
when others =>
end case;
else
wb_ack_o <= '0';
src_valid_o <= '0';
end if;
else
src_eof_p1_o <= '1';
src_valid_o <= '0';
state <= ST_TERMINATE_CYC;
end if;
if(src_error_p1_i = '1') then
wb_err_o <= '1';
state <= ST_TERMINATE_CYC;
end if;
when ST_TERMINATE_CYC =>
wb_err_o <= '0';
if(wb_cyc_i = '0') then
state <= ST_WAIT_CYC;
end if;
end case;
end if;
end if;
end process;
src_ctrl_o <= src_ctrl_int;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.global_defs.all;
use work.endpoint_pkg.all;
entity ep_wrf_to_wb is
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- WRF sink
snk_data_i : in std_logic_vector(15 downto 0);
snk_ctrl_i : in std_logic_vector(c_wrsw_ctrl_size-1 downto 0);
snk_bytesel_i : in std_logic;
snk_dreq_o : out std_logic;
snk_valid_i : in std_logic;
snk_sof_p1_i : in std_logic;
snk_eof_p1_i : in std_logic;
snk_error_p1_i : in std_logic;
-- Pipelined Wishbone master
wb_dat_o : out std_logic_vector(15 downto 0);
wb_adr_o : out std_logic_vector(1 downto 0);
wb_sel_o : out std_logic_vector(1 downto 0);
wb_cyc_o : out std_logic;
wb_stb_o : out std_logic;
wb_we_o : out std_logic;
wb_stall_i : in std_logic;
wb_ack_i : in std_logic);
end ep_wrf_to_wb;
architecture behavioral of ep_wrf_to_wb is
function to_sl(x : boolean) return std_logic is
begin
if(x = true) then
return '1';
else
return '0';
end if;
end function to_sl;
type t_arb_state is (ST_WAIT_FRAME, ST_DATA, ST_RX_ERROR, ST_WAIT_END_CYCLE);
signal is_data : std_logic;
signal is_oob : std_logic;
signal term_cycle : std_logic;
signal ack_counter : unsigned(3 downto 0);
signal wb_stb_int : std_logic;
signal wb_cyc_int : std_logic;
signal wb_stall_d0 : std_logic;
signal stalled_data_in_buffer : std_logic;
signal state : t_arb_state;
begin -- behavioral
is_data <= '1' when snk_ctrl_i = c_wrsw_ctrl_none
or snk_ctrl_i = c_wrsw_ctrl_dst_mac
or snk_ctrl_i = c_wrsw_ctrl_src_mac
or snk_ctrl_i = c_wrsw_ctrl_ethertype
or snk_ctrl_i = c_wrsw_ctrl_vid_prio
or snk_ctrl_i = c_wrsw_ctrl_payload
or snk_ctrl_i = c_wrsw_ctrl_fcs
else '0';
is_oob <= '1' when snk_ctrl_i = c_wrsw_ctrl_tx_oob
or snk_ctrl_i = c_wrsw_ctrl_rx_oob
else '0';
p_count_acks : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
ack_counter <= (others => '0');
else
if(wb_cyc_int = '0') then
ack_counter <= (others => '0');
else
if(wb_stb_int = '1' and wb_ack_i = '0') then
ack_counter <= ack_counter + 1;
elsif(wb_stb_int = '0' and wb_ack_i = '1') then
ack_counter <= ack_counter - 1;
end if;
end if;
end if;
end if;
end process;
arb_fsm : process(clk_sys_i)
variable tmp : t_wrf_status_reg;
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0') then
state <= ST_WAIT_FRAME;
wb_stb_int <= '0';
wb_cyc_int <= '0';
wb_sel_o <= (others => '0');
wb_adr_o <= (others => '0');
wb_dat_o <= (others => '0');
stalled_data_in_buffer <= '0';
else
case state is
when ST_WAIT_FRAME =>
if(snk_sof_p1_i = '1') then
wb_cyc_int <= '1';
state <= ST_DATA;
end if;
when ST_DATA =>
if(snk_eof_p1_i = '1') then
state <= ST_WAIT_END_CYCLE;
end if;
if(snk_error_p1_i = '1') then
tmp.rx_error := '1';
wb_adr_o <= c_WRF_STATUS;
wb_sel_o <= "11";
wb_dat_o <= f_marshall_wrf_status(tmp);
if(wb_stall_i = '0') then
wb_stb_int <= '1';
state <= ST_WAIT_END_CYCLE;
else
wb_stb_int <= '0';
state <= ST_RX_ERROR;
end if;
elsif(snk_valid_i = '1') then
wb_dat_o <= snk_data_i;
if(wb_stall_i = '0') then
wb_stb_int <= '1';
else
wb_stb_int <= '0';
stalled_data_in_buffer <= '1';
end if;
if(is_data = '1') then
wb_adr_o <= c_WRF_DATA;
wb_sel_o(0) <= not snk_bytesel_i;
wb_sel_o(1) <= '1';
elsif(is_oob = '1') then
wb_sel_o <= "11";
wb_adr_o <= c_WRF_OOB;
end if;
elsif(stalled_data_in_buffer = '1') then
if(wb_stall_i = '0') then
wb_stb_int <= '1';
stalled_data_in_buffer <= '0';
else
wb_stb_int <= '0';
stalled_data_in_buffer <= '1';
end if;
else
wb_stb_int <= '0';
end if;
when ST_RX_ERROR =>
if(wb_stall_i = '0') then
wb_stb_int <= '1';
state <= ST_WAIT_END_CYCLE;
end if;
when ST_WAIT_END_CYCLE =>
if(ack_counter = 0 or (ack_counter = 1 and wb_ack_i = '1')) then
wb_cyc_int <= '0';
wb_stb_int <= '0';
state <= ST_WAIT_FRAME;
end if;
when others => null;
end case;
end if;
wb_stall_d0 <= wb_stall_i;
end if;
end process;
wb_cyc_o <= wb_cyc_int;
wb_stb_o <= wb_stb_int;
snk_dreq_o <= not wb_stall_i;
wb_we_o <= '1';
end behavioral;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment