diff --git a/modules/wr_endpoint/Manifest.py b/modules/wr_endpoint/Manifest.py index f9990e6e47d2e29ac6807d09f15b0bb9bb8886ec..fe50777878b0b792484591396730d2ba01250d97 100644 --- a/modules/wr_endpoint/Manifest.py +++ b/modules/wr_endpoint/Manifest.py @@ -4,7 +4,7 @@ files = [ "endpoint_private_pkg.vhd", "ep_tx_pcs_16bit.vhd", "ep_rx_pcs_16bit.vhd", "ep_autonegotiation.vhd", - "ep_pcs_tbi_mdio_wb.vhd", + "ep_mdio_regs.vhd", "ep_1000basex_pcs.vhd", "ep_rx_crc_size_check.vhd", "ep_rx_bypass_queue.vhd", diff --git a/modules/wr_endpoint/endpoint_pkg.vhd b/modules/wr_endpoint/endpoint_pkg.vhd index 5747963e7804f3f5648b6445b6bb4c2135cdb872..dfdb5fb8e20dffdf28d787928f9e27e45205cf41 100644 --- a/modules/wr_endpoint/endpoint_pkg.vhd +++ b/modules/wr_endpoint/endpoint_pkg.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2010-04-26 --- Last update: 2017-02-20 +-- Last update: 2023-03-13 -- Platform : FPGA-generic -- Standard : VHDL '93 ------------------------------------------------------------------------------- @@ -122,9 +122,8 @@ package endpoint_pkg is rdy : std_logic; sfp_tx_fault : std_logic; sfp_los : std_logic; - lpc_stat : std_logic_vector(15 downto 0); - end record; + type t_phy_16bits_from_wrc is record rst : std_logic; loopen : std_logic; @@ -133,16 +132,14 @@ package endpoint_pkg is loopen_vec : std_logic_vector(2 downto 0); tx_prbs_sel : std_logic_vector(2 downto 0); sfp_tx_disable : std_logic; - lpc_ctrl : std_logic_vector(15 downto 0); - end record; constant c_dummy_phy16_to_wrc : t_phy_16bits_to_wrc := ('0', '0', '0', (others=>'0'), '0', '0', (others=>'0'), '0', - (others=>'0'), '0', '0', '0', (others => '0')); + (others=>'0'), '0', '0', '0'); constant c_dummy_phy16_from_wrc : t_phy_16bits_from_wrc := ('0', '0', (others=>'0'), (others=>'0'), (others=>'0'), - (others=>'0'), '0', (others => '0')); + (others=>'0'), '0'); -- debug CS types @@ -223,8 +220,9 @@ package endpoint_pkg is phy_sfp_los_i : in std_logic := '0'; phy_sfp_tx_disable_o : out std_logic; phy_rdy_i : in std_logic; - phy_lpc_stat_i : in std_logic_vector(15 downto 0) := (others=>'0'); - phy_lpc_ctrl_o : out std_logic_vector(15 downto 0); + + phy_mdio_master_o : out t_wishbone_master_out; + phy_mdio_master_i : in t_wishbone_master_in := cc_dummy_slave_out; phy_ref_clk_i : in std_logic := '0'; phy_tx_data_o : out std_logic_vector(f_pcs_data_width(g_pcs_16bit)-1 downto 0); @@ -339,8 +337,6 @@ package endpoint_pkg is phy_sfp_los_i : in std_logic := '0'; phy_sfp_tx_disable_o : out std_logic; phy_rdy_i : in std_logic; - phy_lpc_stat_i : in std_logic_vector(15 downto 0) := (others=>'0'); - phy_lpc_ctrl_o : out std_logic_vector(15 downto 0); phy_ref_clk_i : in std_logic; phy_tx_data_o : out std_logic_vector(f_pcs_data_width(g_pcs_16bit)-1 downto 0); @@ -352,6 +348,18 @@ package endpoint_pkg is phy_rx_k_i : in std_logic_vector(f_pcs_k_width(g_pcs_16bit)-1 downto 0) := (others=>'0'); phy_rx_enc_err_i : in std_logic; phy_rx_bitslide_i : in std_logic_vector(f_pcs_bts_width(g_pcs_16bit)-1 downto 0) := (others=>'0'); + + -- clk_sys_i domain! + phy_mdio_master_cyc_o : out std_logic; + phy_mdio_master_stb_o : out std_logic; + phy_mdio_master_we_o : out std_logic; + phy_mdio_master_dat_o : out std_logic_vector(31 downto 0); + phy_mdio_master_sel_o : out std_logic_vector(3 downto 0) := "0000"; + phy_mdio_master_adr_o : out std_logic_vector(31 downto 0); + phy_mdio_master_ack_i : in std_logic := '0'; + phy_mdio_master_stall_i : in std_logic := '0'; + phy_mdio_master_dat_i : in std_logic_vector(31 downto 0) := x"00000000"; + gmii_tx_clk_i : in std_logic := '0'; gmii_txd_o : out std_logic_vector(7 downto 0) := x"00"; gmii_tx_en_o : out std_logic := '0'; diff --git a/modules/wr_endpoint/ep_1000basex_pcs.vhd b/modules/wr_endpoint/ep_1000basex_pcs.vhd index 34de5e83699ad429158b2044b2c523cba23bb7ea..d707ae68aea688480383c0835950012b3f9df142 100644 --- a/modules/wr_endpoint/ep_1000basex_pcs.vhd +++ b/modules/wr_endpoint/ep_1000basex_pcs.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz WÅ‚ostowski -- Company : CERN BE-CO-HT -- Created : 2010-11-18 --- Last update: 2021-04-09 +-- Last update: 2023-03-29 -- Platform : FPGA-generic -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -54,6 +54,8 @@ library work; use work.endpoint_private_pkg.all; use work.endpoint_pkg.all; use work.gencores_pkg.all; +use work.wishbone_pkg.all; +use work.ep_mdio_regs_pkg.all; entity ep_1000basex_pcs is @@ -146,10 +148,11 @@ entity ep_1000basex_pcs is -- 1: serdes is locked and aligned serdes_rdy_i : in std_logic; - -- low phase drift feature signals to the PHY - serdes_stat_i : in std_logic_vector(15 downto 0); - serdes_ctrl_o : out std_logic_vector(15 downto 0); - + -- auxillary MDIO registers. PHY-specific. One of applications + -- is low phase drift feature signals to the PHY + serdes_mdio_master_o : out t_wishbone_master_out; + serdes_mdio_master_i : in t_wishbone_master_in; + --------------------------------------------------------------------------- -- Serdes TX path (all synchronous to serdes_tx_clk_i) @@ -180,7 +183,7 @@ entity ep_1000basex_pcs is ------------------------------------------------------------------------------- -- RX recovered clock. MUST be synchronous to incoming serial data stream - -- for proper PTP/SyncE operation. 62.5 MHz in 16-bit mode, 125 MHz in 8-bit mode. + -- for proper PTP/SyncE operation. 62.5 MHz in 16-bit mode, 125 MHz in 8-bit mode serdes_rx_clk_i : in std_logic; serdes_rx_data_i : in std_logic_vector(f_pcs_data_width(g_16bit)-1 downto 0); serdes_rx_k_i : in std_logic_vector(f_pcs_k_width(g_16bit)-1 downto 0); @@ -210,28 +213,13 @@ architecture rtl of ep_1000basex_pcs is alias rst_n_i : std_logic is rst_sys_n_i; - signal mdio_mcr_anrestart : std_logic; + signal mdio_regs_out : t_mdio_regs_master_out; + signal mdio_regs_in : t_mdio_regs_master_in; + + signal mdio_wb_out : t_wishbone_master_in; + signal mdio_wb_in : t_wishbone_master_out; + signal mdio_mcr_pdown : std_logic; - signal mdio_mcr_pdown_cpu : std_logic; - signal mdio_mcr_anenable : std_logic; - signal mdio_mcr_reset : std_logic; - signal mdio_msr_lstatus : std_logic; - signal mdio_msr_rfault : std_logic; - signal mdio_msr_anegcomplete : std_logic; - signal mdio_advertise_pause : std_logic_vector(1 downto 0); - signal mdio_advertise_rfault : std_logic_vector(1 downto 0); - signal mdio_lpa_full : std_logic; - signal mdio_lpa_half : std_logic; - signal mdio_lpa_pause : std_logic_vector(1 downto 0); - signal mdio_lpa_rfault : std_logic_vector(1 downto 0); - signal mdio_lpa_lpack : std_logic; - signal mdio_lpa_npage : std_logic; - signal mdio_wr_spec_tx_cal : std_logic; - signal mdio_wr_spec_rx_cal_stat : std_logic; - signal mdio_wr_spec_cal_crst : std_logic; - signal mdio_wr_spec_bslide : std_logic_vector(4 downto 0); - signal mdio_data_in : std_logic_vector(31 downto 0); - signal mdio_data_out : std_logic_vector(31 downto 0); signal lstat_read_notify : std_logic; @@ -268,12 +256,32 @@ architecture rtl of ep_1000basex_pcs is signal dbg_prbs_control : std_logic_vector(15 downto 0); signal dbg_prbs_status : std_logic_vector(15 downto 0); + signal serdes_rx_bitslide_rx_clk : std_logic_vector(4 downto 0); + + attribute mark_debug : string; + attribute mark_debug of serdes_rx_k_i : signal is "true"; + attribute mark_debug of serdes_rx_data_i : signal is "true"; + attribute mark_debug of serdes_rx_enc_err_i : signal is "true"; + attribute mark_debug of serdes_rx_bitslide_i : signal is "true"; + + attribute mark_debug of synced : signal is "true"; + attribute mark_debug of sync_lost : signal is "true"; + attribute mark_debug of link_ok : signal is "true"; + attribute mark_debug of an_rx_en : signal is "true"; + attribute mark_debug of an_rx_val : signal is "true"; + attribute mark_debug of an_rx_valid : signal is "true"; + attribute mark_debug of an_tx_en : signal is "true"; + attribute mark_debug of an_tx_val : signal is "true"; + attribute mark_debug of mdio_regs_out : signal is "true"; + + + begin -- rtl - pcs_reset_n <= '0' when (mdio_mcr_reset = '1' or rst_n_i = '0') else '1'; + pcs_reset_n <= '0' when (mdio_regs_out.mcr_reset = '1' or rst_n_i = '0') else '1'; gen_16bit : if(g_16bit) generate - U_TX_PCS : ep_tx_pcs_16bit + U_TX_PCS : entity work.ep_tx_pcs_16bit port map ( rst_n_i => pcs_reset_n, clk_sys_i => clk_sys_i, @@ -285,10 +293,10 @@ begin -- rtl pcs_busy_o => txpcs_busy_int, pcs_dreq_o => txpcs_dreq_o, - mdio_mcr_reset_i => mdio_mcr_reset, + mdio_mcr_reset_i => mdio_regs_out.mcr_reset, mdio_mcr_pdown_i => mdio_mcr_pdown, - mdio_wr_spec_tx_cal_i => mdio_wr_spec_tx_cal, - mdio_dbg_prbs_en_i => dbg_prbs_control(0), + mdio_wr_spec_tx_cal_i => mdio_regs_out.wr_spec_tx_cal, + mdio_dbg_prbs_en_i => '0', -- fixme bring back prbs dbg_prbs_control(0), an_tx_en_i => an_tx_en, an_tx_val_i => an_tx_val, @@ -304,7 +312,7 @@ begin -- rtl dbg_rd_count_o => dbg_tx_pcs_rd_count_o ); - U_RX_PCS : ep_rx_pcs_16bit + U_RX_PCS : entity work.ep_rx_pcs_16bit generic map ( g_simulation => g_simulation, g_ep_idx => g_ep_idx) @@ -323,14 +331,14 @@ begin -- rtl timestamp_valid_i => rxpcs_timestamp_valid_i, timestamp_stb_i => rxpcs_timestamp_stb_i, - mdio_mcr_reset_i => mdio_mcr_reset, + mdio_mcr_reset_i => mdio_regs_out.mcr_reset, mdio_mcr_pdown_i => mdio_mcr_pdown, - mdio_wr_spec_cal_crst_i => mdio_wr_spec_cal_crst, - mdio_wr_spec_rx_cal_stat_o => mdio_wr_spec_rx_cal_stat, - mdio_dbg_prbs_check_i => dbg_prbs_control(1), - mdio_dbg_prbs_word_sel_i => dbg_prbs_control(2), - mdio_dbg_prbs_latch_count_i => dbg_prbs_control(3), - mdio_dbg_prbs_errors_o => dbg_prbs_status, + mdio_wr_spec_cal_crst_i => mdio_regs_out.wr_spec_cal_crst, + mdio_wr_spec_rx_cal_stat_o => mdio_regs_in.wr_spec_rx_cal_stat, + mdio_dbg_prbs_check_i => '0', --dbg_prbs_control(1), + mdio_dbg_prbs_word_sel_i => '0', --dbg_prbs_control(2), + mdio_dbg_prbs_latch_count_i => '0', --dbg_prbs_control(3), + mdio_dbg_prbs_errors_o => open, --dbg_prbs_status, synced_o => synced, sync_lost_o => sync_lost, @@ -352,12 +360,12 @@ begin -- rtl nice_dbg_o => nice_dbg_o.rx ); - mdio_wr_spec_bslide <= serdes_rx_bitslide_i(4 downto 0); + serdes_rx_bitslide_rx_clk <= serdes_rx_bitslide_i(4 downto 0); end generate gen_16bit; gen_8bit : if(not g_16bit) generate - U_TX_PCS : ep_tx_pcs_8bit + U_TX_PCS : entity work.ep_tx_pcs_8bit port map ( rst_n_i => pcs_reset_n, clk_sys_i => clk_sys_i, @@ -369,9 +377,9 @@ begin -- rtl pcs_busy_o => txpcs_busy_int, pcs_dreq_o => txpcs_dreq_o, - mdio_mcr_reset_i => mdio_mcr_reset, + mdio_mcr_reset_i => mdio_regs_out.mcr_reset, mdio_mcr_pdown_i => mdio_mcr_pdown, - mdio_wr_spec_tx_cal_i => mdio_wr_spec_tx_cal, + mdio_wr_spec_tx_cal_i => mdio_regs_out.wr_spec_tx_cal, an_tx_en_i => an_tx_en, an_tx_val_i => an_tx_val, @@ -386,7 +394,7 @@ begin -- rtl preamble_shrinkage => preamble_shrinkage ); - U_RX_PCS : ep_rx_pcs_8bit + U_RX_PCS : entity work.ep_rx_pcs_8bit generic map ( g_simulation => g_simulation) port map ( @@ -404,10 +412,10 @@ begin -- rtl timestamp_valid_i => rxpcs_timestamp_valid_i, timestamp_stb_i => rxpcs_timestamp_stb_i, - mdio_mcr_reset_i => mdio_mcr_reset, + mdio_mcr_reset_i => mdio_regs_out.mcr_reset, mdio_mcr_pdown_i => mdio_mcr_pdown, - mdio_wr_spec_cal_crst_i => mdio_wr_spec_cal_crst, - mdio_wr_spec_rx_cal_stat_o => mdio_wr_spec_rx_cal_stat, + mdio_wr_spec_cal_crst_i => mdio_regs_out.wr_spec_cal_crst, + mdio_wr_spec_rx_cal_stat_o => mdio_regs_in.wr_spec_rx_cal_stat, synced_o => synced, sync_lost_o => sync_lost, @@ -427,7 +435,7 @@ begin -- rtl phy_rx_enc_err_i => serdes_rx_enc_err_i ); - mdio_wr_spec_bslide <= '0' & serdes_rx_bitslide_i(3 downto 0); + serdes_rx_bitslide_rx_clk <= '0' & serdes_rx_bitslide_i(3 downto 0); dbg_tx_pcs_rd_count_o <= (others => '0'); dbg_tx_pcs_wr_count_o <= (others => '0'); @@ -438,69 +446,67 @@ begin -- rtl txpcs_busy_o <= txpcs_busy_int; -- to enable killing of link (by ML) - mdio_mcr_pdown <= mdio_mcr_pdown_cpu or (not link_ctr_i); + mdio_mcr_pdown <= mdio_regs_out.mcr_pdown or (not link_ctr_i); -- keep PHY reset also when SFP reports LOS (DL) - serdes_rst_o <= (not pcs_reset_n) or mdio_mcr_pdown - ; - - U_MDIO_WB : ep_pcs_tbi_mdio_wb - port map ( - rst_n_i => rst_n_i, - clk_sys_i => clk_sys_i, - wb_adr_i => mdio_addr_i(4 downto 0), - wb_dat_i => mdio_data_in, - wb_dat_o => mdio_data_out, - - wb_cyc_i => wb_stb, - wb_sel_i => "1111", - wb_stb_i => wb_stb, - wb_we_i => mdio_rw_i, - wb_ack_o => wb_ack, - wb_stall_o => open, - tx_clk_i => serdes_tx_clk_i, - rx_clk_i => serdes_rx_clk_i, - - mdio_mcr_uni_en_o => open, - mdio_mcr_anrestart_o => mdio_mcr_anrestart, - mdio_mcr_pdown_o => mdio_mcr_pdown_cpu, - mdio_mcr_anenable_o => mdio_mcr_anenable, - mdio_mcr_reset_o => mdio_mcr_reset, - mdio_mcr_loopback_o => serdes_loopen_o, - mdio_msr_lstatus_i => mdio_msr_lstatus, - mdio_msr_rfault_i => mdio_msr_rfault, - mdio_msr_anegcomplete_i => mdio_msr_anegcomplete, - mdio_advertise_pause_o => mdio_advertise_pause, - mdio_advertise_rfault_o => mdio_advertise_rfault, - mdio_lpa_full_i => mdio_lpa_full, - mdio_lpa_half_i => mdio_lpa_half, - mdio_lpa_pause_i => mdio_lpa_pause, - mdio_lpa_rfault_i => mdio_lpa_rfault, - mdio_lpa_lpack_i => mdio_lpa_lpack, - mdio_lpa_npage_i => mdio_lpa_npage, - mdio_wr_spec_tx_cal_o => mdio_wr_spec_tx_cal, - mdio_wr_spec_rx_cal_stat_i => mdio_wr_spec_rx_cal_stat, - mdio_wr_spec_cal_crst_o => mdio_wr_spec_cal_crst, - mdio_wr_spec_bslide_i => mdio_wr_spec_bslide, - mdio_ectrl_lpbck_vec_o => serdes_loopen_vec_o, - mdio_ectrl_sfp_tx_fault_i => serdes_sfp_tx_fault_i, - mdio_ectrl_sfp_loss_i => serdes_sfp_los_i, - mdio_ectrl_sfp_tx_disable_o => serdes_sfp_tx_disable_o, - mdio_ectrl_tx_prbs_sel_o => serdes_tx_prbs_sel_o, - mdio_lpc_phy_stat_i => serdes_stat_i, - mdio_lpc_phy_ctrl_o => serdes_ctrl_o, - mdio_dbg_prbs_status_i => dbg_prbs_status, - mdio_dbg_prbs_control_o => dbg_prbs_control, - lstat_read_notify_o => lstat_read_notify - ); + serdes_rst_o <= (not pcs_reset_n) or mdio_mcr_pdown; - mdio_data_in <= X"0000" & mdio_data_i; - mdio_data_o <= mdio_data_out(15 downto 0); - - mdio_msr_rfault <= '0'; + -- process: translates the MDIO reads/writes into Wishbone read/writes + -- inputs: mdio_stb_i, wb_ack + -- ouputs: mdio_ready_o, wb_stb + p_translate_mdio_wb : process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if (rst_n_i = '0') then + mdio_wb_in <= cc_dummy_master_out; + mdio_ready_o <= '1'; + wb_stb <= '0'; + else + if wb_stb = '0' then + if(mdio_stb_i = '1') then + mdio_wb_in.cyc <= '1'; + mdio_wb_in.stb <= '1'; + mdio_wb_in.dat <= X"0000" & mdio_data_i; + mdio_wb_in.sel <= (others => '0'); + mdio_wb_in.adr <= "00" & x"000" & mdio_addr_i & "00"; + mdio_wb_in.we <= mdio_rw_i; + mdio_ready_o <= '0'; + wb_stb <= '1'; + end if; + else + if mdio_wb_out.stall = '0' then + mdio_wb_in.stb <= '0'; + end if; + + if mdio_wb_out.ack = '1' then + mdio_ready_o <= '1'; + mdio_data_o <= mdio_wb_out.dat(15 downto 0); + mdio_wb_in.cyc <= '0'; + mdio_wb_in.stb <= '0'; + wb_stb <= '0'; + end if; + end if; + end if; + end if; + end process; - U_AUTONEGOTIATION : ep_autonegotiation + + U_MDIO_WB: entity work.ep_mdio_regs + port map ( + rst_n_i => rst_n_i, + clk_i => clk_sys_i, + wb_i => mdio_wb_in, + wb_o => mdio_wb_out, + mdio_regs_i => mdio_regs_in, + mdio_regs_o => mdio_regs_out, + phy_specific_regs_i => serdes_mdio_master_i, + phy_specific_regs_o => serdes_mdio_master_o); + + lstat_read_notify <= mdio_regs_out.MSR_rd; + mdio_regs_in.msr_rfault <= '0'; + + U_AUTONEGOTIATION : entity work.ep_autonegotiation generic map ( g_simulation => g_simulation) @@ -518,40 +524,19 @@ begin -- rtl an_rx_valid_i => an_rx_valid, an_tx_en_o => an_tx_en, an_tx_val_o => an_tx_val, - mdio_mcr_anrestart_i => mdio_mcr_anrestart, - mdio_mcr_anenable_i => mdio_mcr_anenable, - mdio_msr_anegcomplete_o => mdio_msr_anegcomplete, - mdio_advertise_pause_i => mdio_advertise_pause, - mdio_advertise_rfault_i => mdio_advertise_rfault, - mdio_lpa_full_o => mdio_lpa_full, - mdio_lpa_half_o => mdio_lpa_half, - mdio_lpa_pause_o => mdio_lpa_pause, - mdio_lpa_rfault_o => mdio_lpa_rfault, - mdio_lpa_lpack_o => mdio_lpa_lpack, - mdio_lpa_npage_o => mdio_lpa_npage + mdio_mcr_anrestart_i => mdio_regs_out.mcr_anrestart, + mdio_mcr_anenable_i => mdio_regs_out.mcr_anenable, + mdio_msr_anegcomplete_o => mdio_regs_in.msr_anegcomplete, + mdio_advertise_pause_i => mdio_regs_out.advertise_pause, + mdio_advertise_rfault_i => mdio_regs_out.advertise_rfault, + mdio_lpa_full_o => mdio_regs_in.lpa_full, + mdio_lpa_half_o => mdio_regs_in.lpa_half, + mdio_lpa_pause_o => mdio_regs_in.lpa_pause, + mdio_lpa_rfault_o => mdio_regs_in.lpa_rfault, + mdio_lpa_lpack_o => mdio_regs_in.lpa_lpack, + mdio_lpa_npage_o => mdio_regs_in.lpa_npage ); - -- process: translates the MDIO reads/writes into Wishbone read/writes - -- inputs: mdio_stb_i, wb_ack - -- ouputs: mdio_ready_o, wb_stb - p_translate_mdio_wb : process(clk_sys_i, rst_n_i) - begin - if rising_edge(clk_sys_i) then - if (rst_n_i = '0') then - wb_stb <= '0'; - mdio_ready_o <= '1'; - else - if(mdio_stb_i = '1' and wb_stb = '0') then - wb_stb <= '1'; - mdio_ready_o <= '0'; - elsif(wb_stb = '1' and wb_ack = '1') then - mdio_ready_o <= '1'; - wb_stb <= '0'; - end if; - end if; - end if; - end process; - -- process: handles the LSTATUS bit in MSR register -- inputs: sync_lost, synced, lstat_read_notify -- outputs: mdio_msr_lstatus @@ -559,12 +544,12 @@ begin -- rtl begin if rising_edge(clk_sys_i) then if(pcs_reset_n = '0') then - mdio_msr_lstatus <= '0'; + mdio_regs_in.msr_lstatus <= '0'; else if(sync_lost = '1') then - mdio_msr_lstatus <= '0'; + mdio_regs_in.msr_lstatus <= '0'; elsif(lstat_read_notify = '1') then - mdio_msr_lstatus <= synced and link_ok; + mdio_regs_in.msr_lstatus <= synced and link_ok; end if; end if; end if; @@ -635,6 +620,15 @@ begin -- rtl npulse_o => open, ppulse_o => rmon_o.rx_sync_lost); + U_sync_bslide: gc_sync_register + generic map ( + g_width => 5) + port map ( + clk_i => clk_sys_i, + rst_n_a_i => rst_n_i, + d_i => serdes_rx_bitslide_rx_clk, + q_o => mdio_regs_in.wr_spec_bslide); + -- drive unused outputs rmon_o.rx_crc_err <= '0'; rmon_o.rx_ok <= '0'; diff --git a/modules/wr_endpoint/ep_mdio_regs.cheby b/modules/wr_endpoint/ep_mdio_regs.cheby new file mode 100644 index 0000000000000000000000000000000000000000..d138c8bc4e1dd64e1c1db8f07f56c7a3e99aa881 --- /dev/null +++ b/modules/wr_endpoint/ep_mdio_regs.cheby @@ -0,0 +1,594 @@ +##############################################################################; +## Title : 802.3 PCS Register Block (slave) +## Project : White Rabbit MAC/Endpoint +##############################################################################; +## File : ep_mdio_registers.cheby +## Author : Tomasz WÅ‚ostowski +## Company : CERN BE-CO-HT +## Created : 2010-11-18 +## Last update: 2013-03-10 +############################################################################## +## Description: Standard PCS register block + WR-specific PCS fields: +## RX bitslide and calibration pattern control. +############################################################################## +## +## Copyright (c) 2011 CERN / BE-CO-HT +## +## This source file is free software; you can redistribute it +## and/or modify it under the terms of the GNU Lesser General +## Public License as published by the Free Software Foundation; +## either version 2.1 of the License, or (at your option) any +## later version. +## +## This source is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied +## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the GNU Lesser General Public License for more +## details. +## +## You should have received a copy of the GNU Lesser General +## Public License along with this source; if not, download it +## from http://www.gnu.org/licenses/lgpl-2.1l.html +## +##############################################################################- + +memory-map: + name: ep_mdio + description: WR Endpoint 1000Base-X MDIO register block + bus: wb-32-be + x-hdl: + busgroup: True + iogroup: mdio_regs + name-suffix: _regs + schema-version: + core: 2.0.0 + x-conversions: 1.0.0 + x-hdl: 1.0.0 + x-map-info: 1.0.0 + x-wbgen: 1.0.0 + children: + - reg: + name: MCR + description: MDIO Control Register + width: 32 + access: rw + address: 0x0 + children: + - field: + name: RESV + description: Reserved + comment: Always return 0s, writes ignored. + range: 4-0 + preset: 0x0 + x-hdl: + type: const + - field: + name: uni_en + description: Unidirectional Enable + comment: 1 = Enable transmit regardless of whether a valid link has been established; 0 = Normal operation + range: 5 + - field: + name: SPEED1000 + description: Speed Selection (MSB) + comment: Always 1, indicating (together with bit 13) a fixed speed of 1000 Mbps + range: 6 + preset: 0x1 + x-hdl: + type: const + - field: + name: ctst + description: Collision Test + comment: Always equal to 0, since collision detection is not supported + range: 7 + preset: 0x0 + x-hdl: + type: const + - field: + name: fulldplx + description: Duplex Mode + comment: Always equal to 1 to indicate Full-Duplex operation + range: 8 + preset: 0x1 + x-hdl: + type: const + - field: + name: anrestart + description: Restart Auto-Negotiation + comment: write 1 = restart Auto-Negotiation process; write 0 = no effect + range: 9 + x-hdl: + type: autoclear + - field: + name: isolate + description: Isolate + comment: GMII Electrical isolation enable. Ignored since the PCS does not use GMII. + range: 10 + preset: 0x0 + x-hdl: + type: const + - field: + name: pdown + description: Power Down + comment: 1 = Power down; 0 = Normal operation. This bit controls directly the PHY Enable pin + range: 11 + - field: + name: anenable + description: Auto-Negotiation Enable + comment: 1 = Enable Auto-Negotiation process; 0 = Disable Auto-Negotiation process + range: 12 + - field: + name: SPEED100 + description: Speed Selection (LSB) + comment: Always 0, indicating (together with bit 6) a fixed speed of 1000 Mbps + range: 13 + preset: 0x0 + x-hdl: + type: const + - field: + name: loopback + description: Loopback + comment: 1 enable loopback mode; 0 = disable loopback mode; With the TBI version, loopback bit is connected to PHY loopback enable pin. When set to 1, indicates to the external PHY to enter loopback mode + range: 14 + - field: + name: reset + description: Reset + comment: Write 1 = triggers reset of the PCS core; write 0 = no effect + range: 15 + x-hdl: + type: autoclear + - reg: + name: MSR + description: MDIO Status Register + width: 32 + access: ro + address: 0x4 + x-hdl: + read-strobe: True + children: + - field: + name: ERCAP + description: Extended Capability + comment: Always 0, since extended register set is not supported + range: 0 + preset: 0x0 + x-hdl: + type: const + - field: + name: JCD + description: Jabber Detect + comment: Always 0, since Jabber Detect is not supported + range: 1 + preset: 0x0 + x-hdl: + type: const + - field: + name: LSTATUS + description: Link Status + comment: 1 = Link is up; 0 = Link is down (or has been down); Latches 0 if Link Status goes down. Clears to current Link Status on read. + range: 2 + - field: + name: ANEGCAPABLE + description: Auto-Negotiation Ability + comment: Always 1, to indicate the support for Auto-Negotiation. + range: 3 + preset: 0x1 + x-hdl: + type: const + - field: + name: RFAULT + description: Remote Fault + comment: 1 = Remote fault condition detected; 0 = No remote fault condition detected. + range: 4 + - field: + name: anegcomplete + description: Auto-Negotiation Complete + comment: 1 = Auto-Negotiation process completed; 0 = Auto-Negotiation process not completed + range: 5 + - field: + name: mfsuppress + description: MF Preamble Suppression + comment: Always 0, feature not supported. + range: 6 + preset: 0x0 + x-hdl: + type: const + - field: + name: unidirable + description: Unidirectional Ability + comment: Always 1, as the Unidirectional mode is supported. + range: 7 + preset: 0x1 + x-hdl: + type: const + - field: + name: estaten + description: Extended Status Capable + comment: Always 1, indicating the presence of the Extended Status Register + range: 8 + preset: 0x1 + x-hdl: + type: const + - field: + name: 100half2 + description: 100BASE-T2 Half Duplex + comment: Always 0 (unsupported medium) + range: 9 + preset: 0x0 + x-hdl: + type: const + - field: + name: 100full2 + description: 100BASE-T2 Full Duplex + comment: Always 0 (unsupported medium) + range: 10 + preset: 0x0 + x-hdl: + type: const + - field: + name: 10half + description: 10 Mbps Half Duplex + comment: Always 0 (unsupported medium) + range: 11 + preset: 0x0 + x-hdl: + type: const + - field: + name: 10full + description: 10 Mbps Full Duplex + comment: Always 0 (unsupported medium) + range: 12 + preset: 0x0 + x-hdl: + type: const + - field: + name: 100half + description: 100BASE-X Half Duplex + comment: Always 0 (unsupported medium) + range: 13 + preset: 0x0 + x-hdl: + type: const + - field: + name: 100full + description: 100BASE-X Full Duplex + comment: Always 0 (unsupported medium) + range: 14 + preset: 0x0 + x-hdl: + type: const + - field: + name: 100base4 + description: 100BASE-T4 + comment: Always 0 (unsupported medium) + range: 15 + preset: 0x0 + x-hdl: + type: const + - reg: + name: PHYSID1 + description: MDIO PHY Identification Register 1 + width: 32 + access: ro + address: 0x8 + children: + - field: + name: OUI + description: Organizationally Unique Identifier (bits 7-21) + comment: Always 0. + range: 15-0 + preset: 0x0 + x-hdl: + type: const + - reg: + name: PHYSID2 + description: MDIO PHY Identification Register 2 + width: 32 + access: ro + address: 0xc + children: + - field: + name: REV_NUM + description: Revision Number + comment: Always 0. + range: 3-0 + preset: 0x0 + x-hdl: + type: const + - field: + name: MMNUM + description: Manufacturer Model Number + comment: Always 0. + range: 9-4 + preset: 0x0 + x-hdl: + type: const + - field: + name: OUI + description: Organizationally Unique Identifier (bits 0-5) + comment: Always 0. + range: 15-10 + preset: 0x0 + x-hdl: + type: const + - reg: + name: ADVERTISE + description: MDIO Auto-Negotiation Advertisement Register + width: 32 + access: rw + address: 0x10 + children: + - field: + name: RSVD3 + description: Reserved + comment: Always 0. + range: 4-0 + preset: 0x0 + x-hdl: + type: const + - field: + name: FULL + description: Full Duplex + comment: Always 1, since Full Duplex Mode is the only supported mode. + range: 5 + preset: 0x1 + x-hdl: + type: const + - field: + name: HALF + description: Half Duplex + comment: Always 0, since Half Duplex Mode is not supported. + range: 6 + preset: 0x0 + x-hdl: + type: const + - field: + name: PAUSE + description: Pause + comment: 00 = No PAUSE; 01 = Symmetric PAUSE; 10 = Asymmetric PAUSE towards link partner; 11 = Both Symmetric PAUSE and Asymmetric PAUSE towards link partner + range: 8-7 + preset: 00 + - field: + name: RSVD2 + description: Reserved + comment: Always 0. + range: 11-9 + preset: 0x0 + x-hdl: + type: const + - field: + name: RFAULT + description: Remote Fault + comment: 00 = No Error; 01 = Offline; 10 = Link Failure; 11 = Auto-Negotiation Error + range: 13-12 + - field: + name: RSVD1 + description: Reserved + comment: Always 0. + range: 14 + preset: 0x0 + x-hdl: + type: const + - field: + name: NPAGE + description: Next Page + comment: Always 0, since Next Page feature is not supported + range: 15 + preset: 0x0 + x-hdl: + type: const + - reg: + name: LPA + description: MDIO Auto-Negotiation Link Partner Ability Register + width: 32 + access: ro + address: 0x14 + children: + - field: + name: RSVD3 + description: Reserved + comment: Always 0. + range: 4-0 + preset: 0x0 + x-hdl: + type: const + - field: + name: FULL + description: Full Duplex + comment: 1 = Remote partner supports Full Duplex operation; 0 = It does not + range: 5 + - field: + name: HALF + description: Half Duplex + comment: 1 = Remote partner supports Half Duplex operation; 0 = It does not + range: 6 + - field: + name: PAUSE + description: Pause + comment: 00 = No PAUSE; 01 = Symmetric PAUSE ; 10 = Asymmetric PAUSE towards link partner; 11 = Both Symmetric PAUSE and Asymmetric PAUSE towards link partner + range: 8-7 + - field: + name: RSVD2 + description: Reserved + comment: Always 0. + range: 11-9 + preset: 0x0 + x-hdl: + type: const + - field: + name: RFAULT + description: Remote Fault + comment: 00 = No Error; 01 = Offline; 10 = Link Failure; 11 = Auto-Negotiation Error + range: 13-12 + - field: + name: LPACK + description: Acknowledge + comment: Used by Auto-Negotiation function to indicate reception of a link partners base or next page. + range: 14 + - field: + name: NPAGE + description: Next Page + comment: 1 = Next Page functionality is supported; 0 = It is not + range: 15 + - reg: + name: EXPANSION + description: MDIO Auto-Negotiation Expansion Register + width: 32 + access: ro + address: 0x18 + children: + - field: + name: RSVD1 + description: Reserved + comment: Always 0. + range: 0 + preset: 0x0 + x-hdl: + type: const + - field: + name: LWCP + description: Page Received + comment: Always 0, since we do not support the Next Page function + range: 1 + preset: 0x0 + x-hdl: + type: const + - field: + name: ENABLENPAGE + description: Next Page Able + comment: Always 0, since we do not support the Next Page function + range: 2 + preset: 0x0 + x-hdl: + type: const + - field: + name: RSVD2 + description: Reserved + comment: Always 0. + range: 15-3 + preset: 0x0 + x-hdl: + type: const + - reg: + name: ESTATUS + description: MDIO Extended Status Register + width: 32 + access: ro + address: 0x3c + children: + - field: + name: RSVD1 + description: Reserved + comment: Always 0. + range: 11-0 + preset: 0x0 + x-hdl: + type: const + - field: + name: 1000_THALF + description: 1000Base-T Half Duplex + comment: Always 0, since this mode is not supported. + range: 12 + preset: 0x0 + x-hdl: + type: const + - field: + name: 1000_TFULL + description: 1000Base-T Full Duplex + comment: Always 0, since this mode is not supported. + range: 13 + preset: 0x0 + x-hdl: + type: const + - field: + name: 1000_XHALF + description: 1000Base-X Half Duplex + comment: Always 0, since this mode is not supported. + range: 14 + preset: 0x0 + x-hdl: + type: const + - field: + name: 1000_XFULL + description: 1000Base-X Full Duplex + comment: Always 1, indicating the support for 1000Base-X Full Duplex mode. + range: 15 + preset: 0x1 + x-hdl: + type: const + - reg: + name: WR_SPEC + description: White Rabbit-specific Configuration Register + width: 32 + access: rw + address: 0x40 + children: + - field: + name: TX_CAL + description: TX Calibration Pattern + comment: Controls the transmission of WR PHY calibration pattern. 1 = PCS is sending calibration pattern; 0 = Normal PCS operation + range: 0 + - field: + name: RX_CAL_STAT + description: Calibration Pattern RX Status + comment: 1 = Valid calibration pattern is being received; 0 = no calibration pattern detected by the receiver + range: 1 + x-hdl: + type: wire + - field: + name: CAL_CRST + description: Reset calibration counter + comment: 1 = resets the calibration pattern valid counter; 0 = no effect + range: 2 + x-hdl: + type: autoclear + - field: + name: BSLIDE + description: PHY RX Bitslide + comment: Current receive path bit slide (valid only for transceivers which support manual bitslip) + range: 8-4 + x-hdl: + type: wire + - reg: + name: ECTRL + description: MDIO Extended Control Register + width: 32 + access: rw + address: 0x44 + children: + - field: + name: lpbck_vec + description: Loopback - detailed + comment: Loopback vector for Xilinx PHYs. 100 = far end loopback mode; 000 = normal mode; \ + See also Transceiver documentation (for example Xilinx UG476 Table 2-37 and Figure 2-23. \ + LOOPBACK bit set to 1 in MCR register may override LPBCK_VEC depending on the PHY wrapper implementation. + range: 2-0 + preset: 0x0 + - field: + name: sfp_tx_fault + description: SFP TX Fault Status + comment: 1 = Some kind of laser failure; 0 = SFP Laser okay + range: 3 + - field: + name: sfp_loss + description: SFP LOS + comment: 1 = Loss of signal; 0 = SFP Receiver signal strength okay + range: 4 + - field: + name: sfp_tx_disable + description: SFP TX Disable + comment: Disables the SFP Transmitter. 1 = SFP TX Disabled; 0 = SFP TX Enabled + range: 5 + preset: 0x0 + - field: + name: tx_prbs_sel + description: tx_prbs_sel + comment: PRBS selection. 000 = Normal mode; 0010 = PRBS-7 + range: 10-8 + preset: 0x0 + - submap: + name: phy_specific_regs + size: 0x2000 + description: Custom PHY-specific registers. + interface: wb-32-be + x-hdl: + busgroup: True diff --git a/modules/wr_endpoint/ep_mdio_regs.vhd b/modules/wr_endpoint/ep_mdio_regs.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a22b9d3f459990d28fe754da3261eab817fd8514 --- /dev/null +++ b/modules/wr_endpoint/ep_mdio_regs.vhd @@ -0,0 +1,504 @@ +-- Do not edit. Generated by cheby 1.5.dev0 using these options: +-- -i ep_mdio_regs.cheby --gen-hdl ep_mdio_regs.vhd +-- Generated on Tue Mar 21 18:03:11 2023 by twl + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; + +package ep_mdio_regs_pkg is + type t_mdio_regs_master_out is record + MCR_uni_en : std_logic; + MCR_anrestart : std_logic; + MCR_pdown : std_logic; + MCR_anenable : std_logic; + MCR_loopback : std_logic; + MCR_reset : std_logic; + MSR_rd : std_logic; + ADVERTISE_PAUSE : std_logic_vector(1 downto 0); + ADVERTISE_RFAULT : std_logic_vector(1 downto 0); + WR_SPEC_TX_CAL : std_logic; + WR_SPEC_RX_CAL_STAT : std_logic; + WR_SPEC_CAL_CRST : std_logic; + WR_SPEC_BSLIDE : std_logic_vector(4 downto 0); + ECTRL_lpbck_vec : std_logic_vector(2 downto 0); + ECTRL_sfp_tx_fault : std_logic; + ECTRL_sfp_loss : std_logic; + ECTRL_sfp_tx_disable : std_logic; + ECTRL_tx_prbs_sel : std_logic_vector(2 downto 0); + end record t_mdio_regs_master_out; + subtype t_mdio_regs_slave_in is t_mdio_regs_master_out; + + type t_mdio_regs_slave_out is record + MSR_LSTATUS : std_logic; + MSR_RFAULT : std_logic; + MSR_anegcomplete : std_logic; + LPA_FULL : std_logic; + LPA_HALF : std_logic; + LPA_PAUSE : std_logic_vector(1 downto 0); + LPA_RFAULT : std_logic_vector(1 downto 0); + LPA_LPACK : std_logic; + LPA_NPAGE : std_logic; + WR_SPEC_RX_CAL_STAT : std_logic; + WR_SPEC_BSLIDE : std_logic_vector(4 downto 0); + end record t_mdio_regs_slave_out; + subtype t_mdio_regs_master_in is t_mdio_regs_slave_out; + +end ep_mdio_regs_pkg; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; +use work.ep_mdio_regs_pkg.all; + +entity ep_mdio_regs is + port ( + rst_n_i : in std_logic; + clk_i : in std_logic; + wb_i : in t_wishbone_slave_in; + wb_o : out t_wishbone_slave_out; + -- Wires and registers + mdio_regs_i : in t_mdio_regs_master_in; + mdio_regs_o : out t_mdio_regs_master_out; + + -- Custom PHY-specific registers. + phy_specific_regs_i : in t_wishbone_master_in; + phy_specific_regs_o : out t_wishbone_master_out + ); +end ep_mdio_regs; + +architecture syn of ep_mdio_regs is + signal adr_int : std_logic_vector(13 downto 2); + signal rd_req_int : std_logic; + signal wr_req_int : std_logic; + signal rd_ack_int : std_logic; + signal wr_ack_int : std_logic; + signal wb_en : std_logic; + signal ack_int : std_logic; + signal wb_rip : std_logic; + signal wb_wip : std_logic; + signal MCR_uni_en_reg : std_logic; + signal MCR_anrestart_reg : std_logic; + signal MCR_pdown_reg : std_logic; + signal MCR_anenable_reg : std_logic; + signal MCR_loopback_reg : std_logic; + signal MCR_reset_reg : std_logic; + signal MCR_wreq : std_logic; + signal MCR_wack : std_logic; + signal ADVERTISE_PAUSE_reg : std_logic_vector(1 downto 0); + signal ADVERTISE_RFAULT_reg : std_logic_vector(1 downto 0); + signal ADVERTISE_wreq : std_logic; + signal ADVERTISE_wack : std_logic; + signal WR_SPEC_TX_CAL_reg : std_logic; + signal WR_SPEC_CAL_CRST_reg : std_logic; + signal WR_SPEC_wreq : std_logic; + signal WR_SPEC_wack : std_logic; + signal ECTRL_lpbck_vec_reg : std_logic_vector(2 downto 0); + signal ECTRL_sfp_tx_fault_reg : std_logic; + signal ECTRL_sfp_loss_reg : std_logic; + signal ECTRL_sfp_tx_disable_reg : std_logic; + signal ECTRL_tx_prbs_sel_reg : std_logic_vector(2 downto 0); + signal ECTRL_wreq : std_logic; + signal ECTRL_wack : std_logic; + signal phy_specific_regs_re : std_logic; + signal phy_specific_regs_we : std_logic; + signal phy_specific_regs_wt : std_logic; + signal phy_specific_regs_rt : std_logic; + signal phy_specific_regs_tr : std_logic; + signal phy_specific_regs_wack : std_logic; + signal phy_specific_regs_rack : std_logic; + signal rd_ack_d0 : std_logic; + signal rd_dat_d0 : std_logic_vector(31 downto 0); + signal wr_req_d0 : std_logic; + signal wr_adr_d0 : std_logic_vector(13 downto 2); + signal wr_dat_d0 : std_logic_vector(31 downto 0); + signal wr_sel_d0 : std_logic_vector(3 downto 0); +begin + + -- WB decode signals + adr_int <= wb_i.adr(13 downto 2); + wb_en <= wb_i.cyc and wb_i.stb; + + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + wb_rip <= '0'; + else + wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int; + end if; + end if; + end process; + rd_req_int <= (wb_en and not wb_i.we) and not wb_rip; + + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + wb_wip <= '0'; + else + wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int; + end if; + end if; + end process; + wr_req_int <= (wb_en and wb_i.we) and not wb_wip; + + ack_int <= rd_ack_int or wr_ack_int; + wb_o.ack <= ack_int; + wb_o.stall <= not ack_int and wb_en; + wb_o.rty <= '0'; + wb_o.err <= '0'; + + -- pipelining for wr-in+rd-out + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + rd_ack_int <= '0'; + wr_req_d0 <= '0'; + else + rd_ack_int <= rd_ack_d0; + wb_o.dat <= rd_dat_d0; + wr_req_d0 <= wr_req_int; + wr_adr_d0 <= adr_int; + wr_dat_d0 <= wb_i.dat; + wr_sel_d0 <= wb_i.sel; + end if; + end if; + end process; + + -- Register MCR + mdio_regs_o.MCR_uni_en <= MCR_uni_en_reg; + mdio_regs_o.MCR_anrestart <= MCR_anrestart_reg; + mdio_regs_o.MCR_pdown <= MCR_pdown_reg; + mdio_regs_o.MCR_anenable <= MCR_anenable_reg; + mdio_regs_o.MCR_loopback <= MCR_loopback_reg; + mdio_regs_o.MCR_reset <= MCR_reset_reg; + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + MCR_uni_en_reg <= '0'; + MCR_anrestart_reg <= '0'; + MCR_pdown_reg <= '0'; + MCR_anenable_reg <= '0'; + MCR_loopback_reg <= '0'; + MCR_reset_reg <= '0'; + MCR_wack <= '0'; + else + if MCR_wreq = '1' then + MCR_uni_en_reg <= wr_dat_d0(5); + MCR_anrestart_reg <= wr_dat_d0(9); + MCR_pdown_reg <= wr_dat_d0(11); + MCR_anenable_reg <= wr_dat_d0(12); + MCR_loopback_reg <= wr_dat_d0(14); + MCR_reset_reg <= wr_dat_d0(15); + else + MCR_anrestart_reg <= '0'; + MCR_reset_reg <= '0'; + end if; + MCR_wack <= MCR_wreq; + end if; + end if; + end process; + + -- Register MSR + + -- Register PHYSID1 + + -- Register PHYSID2 + + -- Register ADVERTISE + mdio_regs_o.ADVERTISE_PAUSE <= ADVERTISE_PAUSE_reg; + mdio_regs_o.ADVERTISE_RFAULT <= ADVERTISE_RFAULT_reg; + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + ADVERTISE_PAUSE_reg <= "00"; + ADVERTISE_RFAULT_reg <= "00"; + ADVERTISE_wack <= '0'; + else + if ADVERTISE_wreq = '1' then + ADVERTISE_PAUSE_reg <= wr_dat_d0(8 downto 7); + ADVERTISE_RFAULT_reg <= wr_dat_d0(13 downto 12); + end if; + ADVERTISE_wack <= ADVERTISE_wreq; + end if; + end if; + end process; + + -- Register LPA + + -- Register EXPANSION + + -- Register ESTATUS + + -- Register WR_SPEC + mdio_regs_o.WR_SPEC_TX_CAL <= WR_SPEC_TX_CAL_reg; + mdio_regs_o.WR_SPEC_RX_CAL_STAT <= wr_dat_d0(1); + mdio_regs_o.WR_SPEC_CAL_CRST <= WR_SPEC_CAL_CRST_reg; + mdio_regs_o.WR_SPEC_BSLIDE <= wr_dat_d0(8 downto 4); + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + WR_SPEC_TX_CAL_reg <= '0'; + WR_SPEC_CAL_CRST_reg <= '0'; + WR_SPEC_wack <= '0'; + else + if WR_SPEC_wreq = '1' then + WR_SPEC_TX_CAL_reg <= wr_dat_d0(0); + WR_SPEC_CAL_CRST_reg <= wr_dat_d0(2); + else + WR_SPEC_CAL_CRST_reg <= '0'; + end if; + WR_SPEC_wack <= WR_SPEC_wreq; + end if; + end if; + end process; + + -- Register ECTRL + mdio_regs_o.ECTRL_lpbck_vec <= ECTRL_lpbck_vec_reg; + mdio_regs_o.ECTRL_sfp_tx_fault <= ECTRL_sfp_tx_fault_reg; + mdio_regs_o.ECTRL_sfp_loss <= ECTRL_sfp_loss_reg; + mdio_regs_o.ECTRL_sfp_tx_disable <= ECTRL_sfp_tx_disable_reg; + mdio_regs_o.ECTRL_tx_prbs_sel <= ECTRL_tx_prbs_sel_reg; + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + ECTRL_lpbck_vec_reg <= "000"; + ECTRL_sfp_tx_fault_reg <= '0'; + ECTRL_sfp_loss_reg <= '0'; + ECTRL_sfp_tx_disable_reg <= '0'; + ECTRL_tx_prbs_sel_reg <= "000"; + ECTRL_wack <= '0'; + else + if ECTRL_wreq = '1' then + ECTRL_lpbck_vec_reg <= wr_dat_d0(2 downto 0); + ECTRL_sfp_tx_fault_reg <= wr_dat_d0(3); + ECTRL_sfp_loss_reg <= wr_dat_d0(4); + ECTRL_sfp_tx_disable_reg <= wr_dat_d0(5); + ECTRL_tx_prbs_sel_reg <= wr_dat_d0(10 downto 8); + end if; + ECTRL_wack <= ECTRL_wreq; + end if; + end if; + end process; + + -- Interface phy_specific_regs + phy_specific_regs_tr <= phy_specific_regs_wt or phy_specific_regs_rt; + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + phy_specific_regs_rt <= '0'; + phy_specific_regs_wt <= '0'; + else + phy_specific_regs_rt <= (phy_specific_regs_rt or phy_specific_regs_re) and not phy_specific_regs_rack; + phy_specific_regs_wt <= (phy_specific_regs_wt or phy_specific_regs_we) and not phy_specific_regs_wack; + end if; + end if; + end process; + phy_specific_regs_o.cyc <= phy_specific_regs_tr; + phy_specific_regs_o.stb <= phy_specific_regs_tr; + phy_specific_regs_wack <= phy_specific_regs_i.ack and phy_specific_regs_wt; + phy_specific_regs_rack <= phy_specific_regs_i.ack and phy_specific_regs_rt; + phy_specific_regs_o.adr <= ((18 downto 0 => '0') & adr_int(12 downto 2)) & (1 downto 0 => '0'); + phy_specific_regs_o.sel <= wr_sel_d0; + phy_specific_regs_o.we <= phy_specific_regs_wt; + phy_specific_regs_o.dat <= wr_dat_d0; + + -- Process for write requests. + process (wr_adr_d0, wr_req_d0, MCR_wack, ADVERTISE_wack, WR_SPEC_wack, ECTRL_wack, + phy_specific_regs_wack) begin + MCR_wreq <= '0'; + ADVERTISE_wreq <= '0'; + WR_SPEC_wreq <= '0'; + ECTRL_wreq <= '0'; + phy_specific_regs_we <= '0'; + case wr_adr_d0(13 downto 13) is + when "0" => + case wr_adr_d0(12 downto 2) is + when "00000000000" => + -- Reg MCR + MCR_wreq <= wr_req_d0; + wr_ack_int <= MCR_wack; + when "00000000001" => + -- Reg MSR + wr_ack_int <= wr_req_d0; + when "00000000010" => + -- Reg PHYSID1 + wr_ack_int <= wr_req_d0; + when "00000000011" => + -- Reg PHYSID2 + wr_ack_int <= wr_req_d0; + when "00000000100" => + -- Reg ADVERTISE + ADVERTISE_wreq <= wr_req_d0; + wr_ack_int <= ADVERTISE_wack; + when "00000000101" => + -- Reg LPA + wr_ack_int <= wr_req_d0; + when "00000000110" => + -- Reg EXPANSION + wr_ack_int <= wr_req_d0; + when "00000001111" => + -- Reg ESTATUS + wr_ack_int <= wr_req_d0; + when "00000010000" => + -- Reg WR_SPEC + WR_SPEC_wreq <= wr_req_d0; + wr_ack_int <= WR_SPEC_wack; + when "00000010001" => + -- Reg ECTRL + ECTRL_wreq <= wr_req_d0; + wr_ack_int <= ECTRL_wack; + when others => + wr_ack_int <= wr_req_d0; + end case; + when "1" => + -- Submap phy_specific_regs + phy_specific_regs_we <= wr_req_d0; + wr_ack_int <= phy_specific_regs_wack; + when others => + wr_ack_int <= wr_req_d0; + end case; + end process; + + -- Process for read requests. + process (adr_int, rd_req_int, MCR_uni_en_reg, MCR_pdown_reg, MCR_anenable_reg, + MCR_loopback_reg, mdio_regs_i.MSR_LSTATUS, mdio_regs_i.MSR_RFAULT, + mdio_regs_i.MSR_anegcomplete, ADVERTISE_PAUSE_reg, + ADVERTISE_RFAULT_reg, mdio_regs_i.LPA_FULL, mdio_regs_i.LPA_HALF, + mdio_regs_i.LPA_PAUSE, mdio_regs_i.LPA_RFAULT, + mdio_regs_i.LPA_LPACK, mdio_regs_i.LPA_NPAGE, WR_SPEC_TX_CAL_reg, + mdio_regs_i.WR_SPEC_RX_CAL_STAT, mdio_regs_i.WR_SPEC_BSLIDE, + ECTRL_lpbck_vec_reg, ECTRL_sfp_tx_fault_reg, ECTRL_sfp_loss_reg, + ECTRL_sfp_tx_disable_reg, ECTRL_tx_prbs_sel_reg, + phy_specific_regs_i.dat, phy_specific_regs_rack) begin + -- By default ack read requests + rd_dat_d0 <= (others => 'X'); + mdio_regs_o.MSR_rd <= '0'; + phy_specific_regs_re <= '0'; + case adr_int(13 downto 13) is + when "0" => + case adr_int(12 downto 2) is + when "00000000000" => + -- Reg MCR + rd_ack_d0 <= rd_req_int; + rd_dat_d0(4 downto 0) <= "00000"; + rd_dat_d0(5) <= MCR_uni_en_reg; + rd_dat_d0(6) <= '1'; + rd_dat_d0(7) <= '0'; + rd_dat_d0(8) <= '1'; + rd_dat_d0(9) <= '0'; + rd_dat_d0(10) <= '0'; + rd_dat_d0(11) <= MCR_pdown_reg; + rd_dat_d0(12) <= MCR_anenable_reg; + rd_dat_d0(13) <= '0'; + rd_dat_d0(14) <= MCR_loopback_reg; + rd_dat_d0(15) <= '0'; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000001" => + -- Reg MSR + mdio_regs_o.MSR_rd <= rd_req_int; + rd_ack_d0 <= rd_req_int; + rd_dat_d0(0) <= '0'; + rd_dat_d0(1) <= '0'; + rd_dat_d0(2) <= mdio_regs_i.MSR_LSTATUS; + rd_dat_d0(3) <= '1'; + rd_dat_d0(4) <= mdio_regs_i.MSR_RFAULT; + rd_dat_d0(5) <= mdio_regs_i.MSR_anegcomplete; + rd_dat_d0(6) <= '0'; + rd_dat_d0(7) <= '1'; + rd_dat_d0(8) <= '1'; + rd_dat_d0(9) <= '0'; + rd_dat_d0(10) <= '0'; + rd_dat_d0(11) <= '0'; + rd_dat_d0(12) <= '0'; + rd_dat_d0(13) <= '0'; + rd_dat_d0(14) <= '0'; + rd_dat_d0(15) <= '0'; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000010" => + -- Reg PHYSID1 + rd_ack_d0 <= rd_req_int; + rd_dat_d0(15 downto 0) <= "0000000000000000"; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000011" => + -- Reg PHYSID2 + rd_ack_d0 <= rd_req_int; + rd_dat_d0(3 downto 0) <= "0000"; + rd_dat_d0(9 downto 4) <= "000000"; + rd_dat_d0(15 downto 10) <= "000000"; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000100" => + -- Reg ADVERTISE + rd_ack_d0 <= rd_req_int; + rd_dat_d0(4 downto 0) <= "00000"; + rd_dat_d0(5) <= '1'; + rd_dat_d0(6) <= '0'; + rd_dat_d0(8 downto 7) <= ADVERTISE_PAUSE_reg; + rd_dat_d0(11 downto 9) <= "000"; + rd_dat_d0(13 downto 12) <= ADVERTISE_RFAULT_reg; + rd_dat_d0(14) <= '0'; + rd_dat_d0(15) <= '0'; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000101" => + -- Reg LPA + rd_ack_d0 <= rd_req_int; + rd_dat_d0(4 downto 0) <= "00000"; + rd_dat_d0(5) <= mdio_regs_i.LPA_FULL; + rd_dat_d0(6) <= mdio_regs_i.LPA_HALF; + rd_dat_d0(8 downto 7) <= mdio_regs_i.LPA_PAUSE; + rd_dat_d0(11 downto 9) <= "000"; + rd_dat_d0(13 downto 12) <= mdio_regs_i.LPA_RFAULT; + rd_dat_d0(14) <= mdio_regs_i.LPA_LPACK; + rd_dat_d0(15) <= mdio_regs_i.LPA_NPAGE; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000000110" => + -- Reg EXPANSION + rd_ack_d0 <= rd_req_int; + rd_dat_d0(0) <= '0'; + rd_dat_d0(1) <= '0'; + rd_dat_d0(2) <= '0'; + rd_dat_d0(15 downto 3) <= "0000000000000"; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000001111" => + -- Reg ESTATUS + rd_ack_d0 <= rd_req_int; + rd_dat_d0(11 downto 0) <= "000000000000"; + rd_dat_d0(12) <= '0'; + rd_dat_d0(13) <= '0'; + rd_dat_d0(14) <= '0'; + rd_dat_d0(15) <= '1'; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "00000010000" => + -- Reg WR_SPEC + rd_ack_d0 <= rd_req_int; + rd_dat_d0(0) <= WR_SPEC_TX_CAL_reg; + rd_dat_d0(1) <= mdio_regs_i.WR_SPEC_RX_CAL_STAT; + rd_dat_d0(2) <= '0'; + rd_dat_d0(3) <= '0'; + rd_dat_d0(8 downto 4) <= mdio_regs_i.WR_SPEC_BSLIDE; + rd_dat_d0(31 downto 9) <= (others => '0'); + when "00000010001" => + -- Reg ECTRL + rd_ack_d0 <= rd_req_int; + rd_dat_d0(2 downto 0) <= ECTRL_lpbck_vec_reg; + rd_dat_d0(3) <= ECTRL_sfp_tx_fault_reg; + rd_dat_d0(4) <= ECTRL_sfp_loss_reg; + rd_dat_d0(5) <= ECTRL_sfp_tx_disable_reg; + rd_dat_d0(7 downto 6) <= (others => '0'); + rd_dat_d0(10 downto 8) <= ECTRL_tx_prbs_sel_reg; + rd_dat_d0(31 downto 11) <= (others => '0'); + when others => + rd_ack_d0 <= rd_req_int; + end case; + when "1" => + -- Submap phy_specific_regs + phy_specific_regs_re <= rd_req_int; + rd_dat_d0 <= phy_specific_regs_i.dat; + rd_ack_d0 <= phy_specific_regs_rack; + when others => + rd_ack_d0 <= rd_req_int; + end case; + end process; +end syn; diff --git a/modules/wr_endpoint/ep_rx_pcs_16bit.vhd b/modules/wr_endpoint/ep_rx_pcs_16bit.vhd index 42e2d145fa38670821365bba71f3c2c55e8d74a8..a9d67f968b0b18366a35dd1441b10de4259143ab 100644 --- a/modules/wr_endpoint/ep_rx_pcs_16bit.vhd +++ b/modules/wr_endpoint/ep_rx_pcs_16bit.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2009-06-16 --- Last update: 2021-04-09 +-- Last update: 2023-03-13 -- Platform : FPGA-generic -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -197,9 +197,6 @@ architecture behavioral of ep_rx_pcs_16bit is signal rx_sync_status : std_logic; signal rx_sync_enable : std_logic; --- Autonegotiation control signals - signal an_rx_en_synced : std_logic; - signal lcr_ready : std_logic; signal lcr_prev_val : std_logic_vector(15 downto 0); signal lcr_cur_val : std_logic_vector(15 downto 0); @@ -216,18 +213,11 @@ architecture behavioral of ep_rx_pcs_16bit is -- Misc. signals signal cal_pattern_cntr : unsigned(c_cal_pattern_counter_bits-1 downto 0); - signal mdio_mcr_reset_synced : std_logic; - signal mdio_mcr_pdown_synced : std_logic; signal pcs_fab_out : t_ep_internal_fabric; signal pcs_valid_int : std_logic; signal timestamp_pending : std_logic_vector(2 downto 0) := "000"; - - signal mdio_dbg_prbs_check_synced: std_logic; - signal mdio_dbg_prbs_word_sel_synced: std_logic; - signal mdio_dbg_prbs_latch_count_synced_p: std_logic; - signal lfsr_rst : std_logic; component lfsr_prbs_check is @@ -249,7 +239,17 @@ architecture behavioral of ep_rx_pcs_16bit is signal prbs_data_in : std_logic_vector(15 downto 0); signal prbs_data_in_valid : std_logic; signal prbs_data_out : std_logic_vector(15 downto 0); - + + signal mdio_wr_spec_rx_cal_stat_rx_clk : std_logic; + signal mdio_wr_spec_cal_crst_rx_clk : std_logic; + +-- Autonegotiation control signals + signal an_rx_en_rx_clk : std_logic; + signal mdio_mcr_reset_rx_clk : std_logic; + signal mdio_mcr_pdown_rx_clk : std_logic; + signal mdio_dbg_prbs_check_rx_clk: std_logic; + signal mdio_dbg_prbs_word_sel_rx_clk: std_logic; + signal mdio_dbg_prbs_latch_count_rx_clk_p: std_logic; begin ------------------------------------------------------------------------------- @@ -274,7 +274,7 @@ begin clk_i => phy_rx_clk_i, rst_n_i => rst_n_rx, data_i => an_rx_en_i, - synced_o => an_rx_en_synced, + synced_o => an_rx_en_rx_clk, npulse_o => open, ppulse_o => open); @@ -285,7 +285,7 @@ begin clk_i => phy_rx_clk_i, rst_n_i => '1', data_i => mdio_mcr_reset_i, - synced_o => mdio_mcr_reset_synced, + synced_o => mdio_mcr_reset_rx_clk, npulse_o => open, ppulse_o => open); @@ -297,7 +297,7 @@ begin clk_i => phy_rx_clk_i, rst_n_i => '1', data_i => mdio_dbg_prbs_check_i, - synced_o => mdio_dbg_prbs_check_synced, + synced_o => mdio_dbg_prbs_check_rx_clk, npulse_o => open, ppulse_o => open); @@ -309,7 +309,7 @@ begin clk_i => phy_rx_clk_i, rst_n_i => '1', data_i => mdio_dbg_prbs_word_sel_i, - synced_o => mdio_dbg_prbs_word_sel_synced, + synced_o => mdio_dbg_prbs_word_sel_rx_clk, npulse_o => open, ppulse_o => open); @@ -321,7 +321,7 @@ begin rst_n_i => '1', data_i => mdio_dbg_prbs_latch_count_i, npulse_o => open, - ppulse_o => mdio_dbg_prbs_latch_count_synced_p); + ppulse_o => mdio_dbg_prbs_latch_count_rx_clk_p); U_sync_power_down : gc_sync_ffs generic map ( @@ -330,12 +330,23 @@ begin clk_i => phy_rx_clk_i, rst_n_i => '1', data_i => mdio_mcr_pdown_i, - synced_o => mdio_mcr_pdown_synced, + synced_o => mdio_mcr_pdown_rx_clk, + npulse_o => open, + ppulse_o => open); + + U_sync_rx_cal_crst : gc_sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + clk_i => phy_rx_clk_i, + rst_n_i => '1', + data_i => mdio_wr_spec_cal_crst_i, + synced_o => mdio_wr_spec_cal_crst_rx_clk, npulse_o => open, ppulse_o => open); - rx_sync_enable <= not mdio_mcr_pdown_synced; - rst_n_rx <= rst_rxclk_n_i and not mdio_mcr_reset_synced and phy_rdy_i; + rx_sync_enable <= not mdio_mcr_pdown_rx_clk; + rst_n_rx <= rst_rxclk_n_i and not mdio_mcr_reset_rx_clk and phy_rdy_i; ------------------------------------------------------------------------------- -- 802.3z Link Synchronization State Machine @@ -364,6 +375,15 @@ begin npulse_o => rx_sync_lost_p, ppulse_o => open); + U_sync_rx_cal_stat : gc_sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + clk_i => clk_sys_i, + rst_n_i => '1', + data_i => mdio_wr_spec_rx_cal_stat_rx_clk, + synced_o => mdio_wr_spec_rx_cal_stat_o ); + synced_o <= rx_sync_status; -- drive the PCS outputs sync_lost_o <= rx_sync_lost_p; @@ -374,7 +394,7 @@ begin -- process checks the presence of valid calibtaion pattern and controls the -- state of CAL_STA bit in Receive Control Register. -- - -- reads: phy_rx_data_i, mdio_wr_spec_cal_crst_i + -- reads: phy_rx_data_i, mdio_wr_spec_cal_crst_rx_clk -- writes: mdio_wr_spec_rx_cal_stat_o -- p_detect_cal : process(phy_rx_clk_i) @@ -387,19 +407,19 @@ begin d_is_cal <= f_to_sl(phy_rx_data_i = (c_k28_7 & c_k28_7) and phy_rx_k_i = "11"); - if(d_is_cal = '1' and mdio_wr_spec_cal_crst_i = '0') then + if(d_is_cal = '1' and mdio_wr_spec_cal_crst_rx_clk = '0') then -- we've got c_cal_pattern_threshold valid calibration characters - indicate -- that we're receiving a valid calibration pattern if(cal_pattern_cntr(cal_pattern_cntr'high) = '1') then - mdio_wr_spec_rx_cal_stat_o <= '1'; + mdio_wr_spec_rx_cal_stat_rx_clk <= '1'; else - mdio_wr_spec_rx_cal_stat_o <= '0'; + mdio_wr_spec_rx_cal_stat_rx_clk <= '0'; cal_pattern_cntr <= cal_pattern_cntr + 1; end if; -- we've got a non-calibration character or the pattern detection has been reset else - mdio_wr_spec_rx_cal_stat_o <= '0'; + mdio_wr_spec_rx_cal_stat_rx_clk <= '0'; cal_pattern_cntr <= (others => '0'); end if; end if; @@ -418,7 +438,7 @@ begin data_out => prbs_data_out); - lfsr_rst <= '1' when rst_n_rx = '0' or mdio_dbg_prbs_check_synced = '0' else '0'; + lfsr_rst <= '1' when rst_n_rx = '0' or mdio_dbg_prbs_check_rx_clk = '0' else '0'; p_prbs_check: process(phy_rx_clk_i) begin if rising_edge(phy_rx_clk_i) then @@ -426,7 +446,7 @@ begin prbs_error_count <= (others => '0'); prbs_data_in_valid <= '0'; else - if mdio_dbg_prbs_check_synced = '1' then + if mdio_dbg_prbs_check_rx_clk = '1' then if phy_rx_data_i = (c_K28_5 & c_d16_2) and phy_rx_k_i = "10" then prbs_data_in_valid <= '0'; @@ -446,7 +466,7 @@ begin - if mdio_dbg_prbs_latch_count_synced_p = '1' then + if mdio_dbg_prbs_latch_count_rx_clk_p = '1' then prbs_error_count_latched <= prbs_error_count; end if; @@ -575,7 +595,7 @@ begin begin if rising_edge(phy_rx_clk_i) then -- reset or PCS disabled - if(rst_n_rx = '0' or mdio_mcr_pdown_synced = '1') then + if(rst_n_rx = '0' or mdio_mcr_pdown_rx_clk = '1') then rx_state <= RX_NOFRAME; rx_busy <= '0'; @@ -603,7 +623,7 @@ begin else -- normal PCS operation -- clear the autogotiation variables if the autonegotiation is disabled - if(an_rx_en_synced = '0') then + if(an_rx_en_rx_clk = '0') then lcr_ready <= '0'; lcr_validity_cntr <= (others => '0'); lcr_prev_val <= (others => '0'); @@ -708,7 +728,7 @@ begin lcr_validity_cntr <= (others => '0'); -- check if the autonegotiation unit has enabled the reception of LCR - elsif (an_rx_en_synced = '1') then + elsif (an_rx_en_rx_clk = '1') then lcr_prev_val <= lcr_cur_val; -- check for 3 subsequent Configuration sequences with identical Config_Reg value diff --git a/modules/wr_endpoint/ep_tx_pcs_16bit.vhd b/modules/wr_endpoint/ep_tx_pcs_16bit.vhd index 08073240d8a8a1d496fba856461f05a3592aa2f2..346ba783bf5d33982cb0ff72d8df7db967d7cc50 100644 --- a/modules/wr_endpoint/ep_tx_pcs_16bit.vhd +++ b/modules/wr_endpoint/ep_tx_pcs_16bit.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz WÅ‚ostowski -- Company : CERN BE-CO-HT section -- Created : 2009-06-16 --- Last update: 2021-04-09 +-- Last update: 2023-03-29 -- Platform : FPGA-generic -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -85,7 +85,7 @@ entity ep_tx_pcs_16bit is pcs_dreq_o : out std_logic; ------------------------------------------------------------------------------- --- WB controller control signals +-- WB controller control signals. clk_sys_i domain. ------------------------------------------------------------------------------- mdio_mcr_reset_i : in std_logic; @@ -158,10 +158,6 @@ architecture behavioral of ep_tx_pcs_16bit is signal prbs_tx_reg : std_logic_vector(15 downto 0); signal prbs_tx_is_k : std_logic_vector(1 downto 0); - signal mdio_mcr_reset_synced : std_logic; - signal mdio_mcr_pdown_synced : std_logic; - - signal an_tx_en_synced : std_logic; signal wr_count : std_logic_vector(6 downto 0); signal rd_count : std_logic_vector(6 downto 0); @@ -196,7 +192,24 @@ architecture behavioral of ep_tx_pcs_16bit is signal rst_tx : std_logic; signal lfsr_enable : std_logic; signal lfsr_out : std_logic_vector(15 downto 0); - signal mdio_dbg_prbs_en_synced : std_logic; + + -- various signals synchronized to the phy_tx_clk_i domain + signal mdio_mcr_reset_tx_clk : std_logic; + signal mdio_mcr_pdown_tx_clk : std_logic; + signal an_tx_en_tx_clk : std_logic; + signal mdio_dbg_prbs_en_tx_clk : std_logic; + signal mdio_wr_spec_tx_cal_tx_clk : std_logic; + + + attribute mark_debug : string; + attribute mark_debug of tx_state : signal is "true"; + attribute mark_debug of mdio_wr_spec_tx_cal_tx_clk : signal is "true"; + attribute mark_debug of mdio_wr_spec_tx_cal_i : signal is "true"; + attribute mark_debug of tx_odata_reg : signal is "true"; + attribute mark_debug of tx_is_k : signal is "true"; + + + begin U_sync_pcs_busy_o : gc_sync_ffs @@ -224,7 +237,7 @@ begin clk_i => phy_tx_clk_i, rst_n_i => rst_n_i, data_i => an_tx_en_i, - synced_o => an_tx_en_synced); + synced_o => an_tx_en_tx_clk); U_sync_mcr_reset : gc_sync_ffs generic map ( @@ -233,7 +246,7 @@ begin clk_i => phy_tx_clk_i, rst_n_i => '1', data_i => mdio_mcr_reset_i, - synced_o => mdio_mcr_reset_synced, + synced_o => mdio_mcr_reset_tx_clk, npulse_o => open, ppulse_o => open); @@ -244,7 +257,7 @@ begin clk_i => phy_tx_clk_i, rst_n_i => '1', data_i => mdio_dbg_prbs_en_i, - synced_o => mdio_dbg_prbs_en_synced, + synced_o => mdio_dbg_prbs_en_tx_clk, npulse_o => open, ppulse_o => open); @@ -255,12 +268,21 @@ begin clk_i => phy_tx_clk_i, rst_n_i => '1', data_i => mdio_mcr_pdown_i, - synced_o => mdio_mcr_pdown_synced); + synced_o => mdio_mcr_pdown_tx_clk); + + U_sync_en_tx_cal : gc_sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + clk_i => phy_tx_clk_i, + rst_n_i => '1', + data_i => mdio_wr_spec_tx_cal_i, + synced_o => mdio_wr_spec_tx_cal_tx_clk); - phy_tx_data_o <= tx_odata_reg when mdio_dbg_prbs_en_synced = '0' else prbs_tx_reg; - phy_tx_k_o <= tx_is_k when mdio_dbg_prbs_en_synced = '0' else prbs_tx_is_k; + phy_tx_data_o <= tx_odata_reg when mdio_dbg_prbs_en_tx_clk = '0' else prbs_tx_reg; + phy_tx_k_o <= tx_is_k when mdio_dbg_prbs_en_tx_clk = '0' else prbs_tx_is_k; - rst_n_tx <= rst_txclk_n_i and not mdio_mcr_reset_synced; + rst_n_tx <= rst_txclk_n_i and not mdio_mcr_reset_tx_clk; rst_tx <= not rst_n_tx; @@ -276,10 +298,10 @@ begin p_prbs_generator : process(phy_tx_clk_i) begin if rising_edge(phy_tx_clk_i) then - if(rst_n_tx = '0' or mdio_mcr_pdown_synced = '1') then + if(rst_n_tx = '0' or mdio_mcr_pdown_tx_clk = '1') then prbs_count <= (others => '0'); else - if mdio_dbg_prbs_en_synced = '1' then + if mdio_dbg_prbs_en_tx_clk = '1' then prbs_count <= prbs_count + 1; @@ -315,7 +337,7 @@ begin -- some hacks to make pdown (in particular killing the link) work with Xilix native FIFOs -- (the rst signal can be set (LOW) only after 4 cycles after rd_i is "unset" (LOW) ------------------------------------------------------------------------------------------- - fifo_clear_n_d0 <= '0' when (rst_n_i = '0') or (mdio_mcr_pdown_synced = '1') else '1'; + fifo_clear_n_d0 <= '0' when (rst_n_i = '0') or (mdio_mcr_pdown_tx_clk = '1') else '1'; p_fifo_clean : process(phy_tx_clk_i) begin if rising_edge(phy_tx_clk_i) then @@ -405,7 +427,7 @@ begin if rising_edge(phy_tx_clk_i) then -- The PCS is reset or disabled - if(rst_n_tx = '0' or mdio_mcr_pdown_synced = '1') then + if(rst_n_tx = '0' or mdio_mcr_pdown_tx_clk = '1') then tx_state <= TX_COMMA_IDLE; timestamp_trigger_p_a_o <= '0'; fifo_rd <= '0'; @@ -439,7 +461,7 @@ begin -- endpoint wants to send Config_Reg - if(an_tx_en_synced = '1') then + if(an_tx_en_tx_clk = '1') then tx_state <= TX_CR12; tx_cr_alternate <= '0'; fifo_rd <= '0'; @@ -451,7 +473,7 @@ begin tx_cntr <= "0001"; -- host requested a calibration pattern - elsif(mdio_wr_spec_tx_cal_i = '1') then + elsif(mdio_wr_spec_tx_cal_tx_clk = '1') then tx_state <= TX_CAL; fifo_rd <= '0'; tx_cr_alternate <= '0'; @@ -479,7 +501,7 @@ begin tx_is_k <= "11"; tx_odata_reg <= c_k28_7 & c_k28_7; tx_cr_alternate <= '1'; - if(mdio_wr_spec_tx_cal_i = '0' and tx_cr_alternate = '1') then + if(mdio_wr_spec_tx_cal_tx_clk = '0' and tx_cr_alternate = '1') then tx_state <= TX_COMMA_IDLE; end if; @@ -509,7 +531,7 @@ begin tx_odata_reg(15 downto 8) <= an_tx_val_i(7 downto 0); tx_odata_reg(7 downto 0) <= an_tx_val_i(15 downto 8); - if(an_tx_en_synced = '1') then + if(an_tx_en_tx_clk = '1') then tx_state <= TX_CR12; else tx_state <= TX_COMMA_IDLE; diff --git a/modules/wr_endpoint/generate-cheby-files.sh b/modules/wr_endpoint/generate-cheby-files.sh new file mode 100755 index 0000000000000000000000000000000000000000..cef04b2601d04afbc7f820a295548a9307edc7ca --- /dev/null +++ b/modules/wr_endpoint/generate-cheby-files.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cheby -i ep_mdio_regs.cheby --gen-hdl ep_mdio_regs.vhd +cheby -i ep_mdio_regs.cheby --gen-c ep_mdio_regs.h +cheby -i ep_mdio_regs.cheby --gen-consts ../../sim/regs/ep_mdio_regs.sv diff --git a/modules/wr_endpoint/wr_endpoint.vhd b/modules/wr_endpoint/wr_endpoint.vhd index 9913a6169ba7b8989f1939507d1f47bd372a4957..4f1433b10a246da546518ac2e8b5c36900eb0de2 100644 --- a/modules/wr_endpoint/wr_endpoint.vhd +++ b/modules/wr_endpoint/wr_endpoint.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2010-04-26 --- Last update: 2018-10-25 +-- Last update: 2023-03-21 -- Platform : FPGA-generics -- Standard : VHDL ------------------------------------------------------------------------------- @@ -119,9 +119,18 @@ entity wr_endpoint is phy_sfp_los_i : in std_logic; phy_sfp_tx_disable_o : out std_logic; phy_rdy_i : in std_logic; - phy_lpc_stat_i : in std_logic_vector(15 downto 0) := (others=>'0'); - phy_lpc_ctrl_o : out std_logic_vector(15 downto 0); + -- clk_sys_i domain! + phy_mdio_master_cyc_o : out std_logic; + phy_mdio_master_stb_o : out std_logic; + phy_mdio_master_we_o : out std_logic; + phy_mdio_master_dat_o : out std_logic_vector(31 downto 0); + phy_mdio_master_sel_o : out std_logic_vector(3 downto 0) := "0000"; + phy_mdio_master_adr_o : out std_logic_vector(31 downto 0); + phy_mdio_master_ack_i : in std_logic := '0'; + phy_mdio_master_stall_i : in std_logic := '0'; + phy_mdio_master_dat_i : in std_logic_vector(31 downto 0) := x"00000000"; + phy_ref_clk_i : in std_logic; phy_tx_data_o : out std_logic_vector(f_pcs_data_width(g_pcs_16bit)-1 downto 0); phy_tx_k_o : out std_logic_vector(f_pcs_k_width(g_pcs_16bit)-1 downto 0); @@ -447,6 +456,9 @@ architecture syn of wr_endpoint is signal phy_rdy_resync_sys : std_logic; signal rst_n_rx_resync_sys : std_logic; + signal phy_mdio_master_out : t_wishbone_master_out; + signal phy_mdio_master_in : t_wishbone_master_in; + ------------------------------------------------------------------------------- -- chipscope (for desperates) ------------------------------------------------------------------------------- @@ -489,7 +501,7 @@ begin mdio_addr <= regs_fromwb.mdio_asr_phyad_o & regs_fromwb.mdio_cr_addr_o; - U_PCS_1000BASEX : ep_1000basex_pcs + U_PCS_1000BASEX : entity work.ep_1000basex_pcs generic map ( g_simulation => g_simulation, g_16bit => g_pcs_16bit, @@ -527,8 +539,8 @@ begin serdes_sfp_los_i => phy_sfp_los_i, serdes_sfp_tx_disable_o => phy_sfp_tx_disable_o, serdes_rdy_i => phy_rdy_i, - serdes_stat_i => phy_lpc_stat_i, - serdes_ctrl_o => phy_lpc_ctrl_o, + serdes_mdio_master_o => phy_mdio_master_out, + serdes_mdio_master_i => phy_mdio_master_in, serdes_tx_clk_i => phy_ref_clk_i, serdes_tx_data_o => phy_tx_data_o, @@ -554,6 +566,18 @@ begin nice_dbg_o => nice_dbg_o.pcs, preamble_shrinkage => regs_fromwb.ecr_txshrin_en_o); + phy_mdio_master_cyc_o <= phy_mdio_master_out.cyc; + phy_mdio_master_stb_o <= phy_mdio_master_out.stb; + phy_mdio_master_we_o <= phy_mdio_master_out.we; + phy_mdio_master_adr_o <= phy_mdio_master_out.adr; + phy_mdio_master_sel_o <= phy_mdio_master_out.sel; + phy_mdio_master_dat_o <= phy_mdio_master_out.dat; + phy_mdio_master_in.dat <= phy_mdio_master_dat_i; + phy_mdio_master_in.ack <= phy_mdio_master_ack_i; + phy_mdio_master_in.stall <= phy_mdio_master_stall_i; + phy_mdio_master_in.rty <= '0'; + phy_mdio_master_in.err <= '0'; + ------------------------------------------------------------------------------- -- TX FRAMER @@ -563,7 +587,7 @@ begin -- txfra_pause_req <= '0'; - U_Tx_Path : ep_tx_path + U_Tx_Path : entity work.ep_tx_path generic map ( g_with_packet_injection => g_with_packet_injection, g_with_vlans => g_with_vlans, @@ -622,7 +646,7 @@ begin -- RX deframer ------------------------------------------------------------------------------- - U_Rx_Path : ep_rx_path + U_Rx_Path : entity work.ep_rx_path generic map ( g_with_vlans => g_with_vlans, g_with_dpi_classifier => g_with_dpi_classifier, @@ -715,7 +739,7 @@ begin -- Timestamping unit ------------------------------------------------------------------------------- - U_EP_TSU : ep_timestamping_unit + U_EP_TSU : entity work.ep_timestamping_unit generic map ( g_timestamp_bits_r => 28, g_timestamp_bits_f => 4, @@ -753,7 +777,7 @@ begin extended_ADDR <= std_logic_vector(resize(unsigned(wb_adr_i), c_wishbone_address_width)); - U_Slave_adapter : wb_slave_adapter + U_Slave_adapter : entity work.wb_slave_adapter generic map ( g_master_use_struct => true, g_master_mode => CLASSIC, @@ -776,7 +800,7 @@ begin master_i => wb_out, master_o => wb_in); - U_WB_SLAVE : ep_wishbone_controller + U_WB_SLAVE : entity work.ep_wishbone_controller port map ( rst_n_i => rst_sys_n_i, clk_sys_i => clk_sys_i, @@ -910,7 +934,7 @@ begin dvalid_rx <= src_out.cyc and src_out.stb and link_ok; gen_leds : if g_with_leds generate - U_Led_Ctrl : ep_leds_controller + U_Led_Ctrl : entity work.ep_leds_controller generic map ( g_blink_period_log2 => 22) port map ( diff --git a/modules/wr_endpoint/xwr_endpoint.vhd b/modules/wr_endpoint/xwr_endpoint.vhd index 0ba1c0b09749bacdc55acb8a8b484dbcf77d7e3f..46b5f4ef2c84e4df112e55eccdef9622ee453df1 100644 --- a/modules/wr_endpoint/xwr_endpoint.vhd +++ b/modules/wr_endpoint/xwr_endpoint.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2010-04-26 --- Last update: 2018-03-08 +-- Last update: 2023-03-13 -- Platform : FPGA-generic -- Standard : VHDL '93 ------------------------------------------------------------------------------- @@ -110,9 +110,7 @@ entity xwr_endpoint is phy_sfp_los_i : in std_logic; phy_sfp_tx_disable_o : out std_logic; phy_rdy_i : in std_logic; - phy_lpc_stat_i : in std_logic_vector(15 downto 0) := (others=>'0'); - phy_lpc_ctrl_o : out std_logic_vector(15 downto 0); - + phy_ref_clk_i : in std_logic := '0'; phy_tx_data_o : out std_logic_vector(f_pcs_data_width(g_pcs_16bit)-1 downto 0); phy_tx_k_o : out std_logic_vector(f_pcs_k_width(g_pcs_16bit)-1 downto 0); @@ -125,6 +123,9 @@ entity xwr_endpoint is phy_rx_enc_err_i : in std_logic := '0'; phy_rx_bitslide_i : in std_logic_vector(f_pcs_bts_width(g_pcs_16bit)-1 downto 0) := (others=>'0'); + phy_mdio_master_o : out t_wishbone_master_out; + phy_mdio_master_i : in t_wishbone_master_in := cc_dummy_slave_out; + -- 2nd option is to use record-based I/Os phy8_o : out t_phy_8bits_from_wrc; phy8_i : in t_phy_8bits_to_wrc; @@ -301,8 +302,6 @@ architecture syn of xwr_endpoint is signal sfp_tx_fault : std_logic; signal sfp_los : std_logic; - signal phy_lpc_stat_in : std_logic_vector(15 downto 0); - signal phy_lpc_ctrl_out : std_logic_vector(15 downto 0); begin U_Wrapped_Endpoint : wr_endpoint @@ -345,8 +344,16 @@ begin phy_loopen_vec_o => phy_loopen_vec, phy_tx_prbs_sel_o => phy_tx_prbs_sel, phy_rdy_i => phy_rdy, - phy_lpc_stat_i => phy_lpc_stat_in, - phy_lpc_ctrl_o => phy_lpc_ctrl_out, + + phy_mdio_master_cyc_o => phy_mdio_master_o.cyc, + phy_mdio_master_stb_o => phy_mdio_master_o.stb, + phy_mdio_master_we_o => phy_mdio_master_o.we, + phy_mdio_master_sel_o => phy_mdio_master_o.sel, + phy_mdio_master_adr_o => phy_mdio_master_o.adr, + phy_mdio_master_dat_o => phy_mdio_master_o.dat, + phy_mdio_master_dat_i => phy_mdio_master_i.dat, + phy_mdio_master_stall_i => phy_mdio_master_i.stall, + phy_mdio_master_ack_i => phy_mdio_master_i.ack, phy_sfp_tx_fault_i => sfp_tx_fault, phy_sfp_los_i => sfp_los, @@ -454,7 +461,6 @@ begin phy16_o.tx_k <= phy_tx_k; phy16_o.tx_prbs_sel <= phy_tx_prbs_sel; phy16_o.sfp_tx_disable <= sfp_tx_disable; - phy16_o.lpc_ctrl <= phy_lpc_ctrl_out; phy_tx_clk <= phy16_i.ref_clk; phy_tx_disparity <= phy16_i.tx_disparity; @@ -465,7 +471,6 @@ begin phy_rx_enc_err <= phy16_i.rx_enc_err; phy_rx_bts <= phy16_i.rx_bitslide; phy_rdy <= phy16_i.rdy; - phy_lpc_stat_in <= phy16_i.lpc_stat; sfp_tx_fault <= phy16_i.sfp_tx_fault; sfp_los <= phy16_i.sfp_los; @@ -521,7 +526,6 @@ begin phy_tx_k_o <= phy_tx_k; phy_tx_prbs_sel_o <= phy_tx_prbs_sel; phy_sfp_tx_disable_o <= sfp_tx_disable; - phy_lpc_ctrl_o <= phy_lpc_ctrl_out; phy_tx_clk <= phy_ref_clk_i; phy_tx_disparity <= phy_tx_disparity_i; @@ -532,7 +536,6 @@ begin phy_rx_enc_err <= phy_rx_enc_err_i; phy_rx_bts <= phy_rx_bitslide_i; phy_rdy <= phy_rdy_i; - phy_lpc_stat_in <= phy_lpc_stat_i; sfp_tx_fault <= phy_sfp_tx_fault_i; sfp_los <= phy_sfp_los_i;