From c69e870b9082bb97b7c2cef3296efd731083e378 Mon Sep 17 00:00:00 2001 From: Alex Utter Date: Wed, 17 Mar 2021 19:11:12 -0700 Subject: [PATCH] Release 1.4.0. (#8) --- doc/CHANGELOG.md | 8 +- project/vivado_2015.4/generate_sgmii_gtx.tcl | 4 +- project/vivado_2015.4/ipcores/EthPort_rtl.xml | 13 ++ .../vivado_2015.4/ipcores/ipcore_shared.tcl | 1 + .../ipcores/wrap_port_adapter.vhd | 6 +- .../ipcores/wrap_port_axi_mailbox.vhd | 2 + .../ipcores/wrap_port_crosslink.vhd | 4 + .../ipcores/wrap_port_gmii_internal.vhd | 2 + .../ipcores/wrap_port_inline_status.vhd | 4 + .../vivado_2015.4/ipcores/wrap_port_rgmii.vhd | 2 + .../vivado_2015.4/ipcores/wrap_port_rmii.vhd | 2 + .../ipcores/wrap_port_serial_auto.vhd | 2 + .../ipcores/wrap_port_serial_spi_clkin.vhd | 2 + .../ipcores/wrap_port_serial_spi_clkout.vhd | 2 + .../ipcores/wrap_port_serial_uart_2wire.vhd | 2 + .../ipcores/wrap_port_serial_uart_4wire.vhd | 2 + .../ipcores/wrap_port_sgmii_gpio.vhd | 2 + .../ipcores/wrap_port_sgmii_gtx.vhd | 2 + .../ipcores/wrap_router_inline.vhd | 4 + .../ipcores/wrap_switch_core.vhd | 64 ++++++++++ .../ipcores/wrap_switch_dual.vhd | 6 +- sim/vhdl/config_stats_refsrc.vhd | 2 + sim/vhdl/config_stats_tb.vhd | 67 ++++++----- sim/vhdl/eth_all8b10b_tb.vhd | 19 ++- sim/vhdl/eth_pause_ctrl_tb.vhd | 1 + sim/vhdl/eth_traffic_sim.vhd | 1 + sim/vhdl/port_inline_status_tb.vhd | 3 + sim/vhdl/port_sgmii_common_tb.vhd | 4 + sim/vhdl/port_statistics_tb.vhd | 24 ++++ src/vhdl/common/config_stats_axi.vhd | 71 +++++++---- src/vhdl/common/config_stats_uart.vhd | 51 ++++---- src/vhdl/common/eth_dec8b10b.vhd | 62 ++++++---- src/vhdl/common/eth_preambles.vhd | 19 ++- src/vhdl/common/port_adapter.vhd | 1 + src/vhdl/common/port_axi_mailbox.vhd | 1 + src/vhdl/common/port_crosslink.vhd | 2 + src/vhdl/common/port_gmii_internal.vhd | 6 + src/vhdl/common/port_inline_status.vhd | 1 + src/vhdl/common/port_nullsink.vhd | 1 + src/vhdl/common/port_rgmii.vhd | 9 ++ src/vhdl/common/port_rmii.vhd | 10 ++ src/vhdl/common/port_serial_auto.vhd | 10 ++ src/vhdl/common/port_serial_spi_clkin.vhd | 1 + src/vhdl/common/port_serial_spi_clkout.vhd | 1 + src/vhdl/common/port_serial_uart_2wire.vhd | 1 + src/vhdl/common/port_serial_uart_4wire.vhd | 1 + src/vhdl/common/port_sgmii_common.vhd | 21 +++- src/vhdl/common/port_statistics.vhd | 113 ++++++++++-------- src/vhdl/common/slip_decoder.vhd | 17 ++- src/vhdl/common/switch_types.vhd | 6 + src/vhdl/xilinx/clkgen_sgmii.vhd | 8 +- src/vhdl/xilinx/port_sgmii_gpio.vhd | 4 +- src/vhdl/xilinx/port_sgmii_gtx.vhd | 35 ++++-- src/vhdl/xilinx/sgmii_input_fifo.vhd | 26 ++-- 54 files changed, 559 insertions(+), 176 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 0cedb5c..e0ab36c 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -38,9 +38,15 @@ This log will be updated for each new release, but may not reflect the latest de * Hotfix for inoperable router_config_axi block. +## v1.4.0 + +* Added diagnostic status flags to the internal Ethernet port definition. +* Compatibility improvements for SGMII startup handshake. +* Timing improvements for traffic statistic counters. + # Copyright Notice -Copyright 2019, 2020 The Aerospace Corporation +Copyright 2019, 2020, 2021 The Aerospace Corporation This file is part of SatCat5. diff --git a/project/vivado_2015.4/generate_sgmii_gtx.tcl b/project/vivado_2015.4/generate_sgmii_gtx.tcl index 225649c..67b2d62 100644 --- a/project/vivado_2015.4/generate_sgmii_gtx.tcl +++ b/project/vivado_2015.4/generate_sgmii_gtx.tcl @@ -35,8 +35,10 @@ proc generate_sgmii_gtx {gt_loc {core_name sgmii_gtx0} {include_shared_logic 1}} # Create the new IP core and set all parameters. create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name $core_name set ip_obj [get_ips $core_name] + # Must enable Auto_Negotiation setting or the configuration_vector used in port_sgmii_gtx.vhd + # does nothing. set_property -dict [list\ - CONFIG.Auto_Negotiation false\ + CONFIG.Auto_Negotiation true\ CONFIG.RefClkRate 125\ CONFIG.Management_Interface false\ CONFIG.MaxDataRate 1G\ diff --git a/project/vivado_2015.4/ipcores/EthPort_rtl.xml b/project/vivado_2015.4/ipcores/EthPort_rtl.xml index 62ee860..7690179 100644 --- a/project/vivado_2015.4/ipcores/EthPort_rtl.xml +++ b/project/vivado_2015.4/ipcores/EthPort_rtl.xml @@ -117,6 +117,19 @@ along with SatCat5. If not, see . in + + rx_status + Diagnostic status flags + + + 8 + + + required + 8 + in + + rx_reset diff --git a/project/vivado_2015.4/ipcores/ipcore_shared.tcl b/project/vivado_2015.4/ipcores/ipcore_shared.tcl index 168fca3..6525403 100644 --- a/project/vivado_2015.4/ipcores/ipcore_shared.tcl +++ b/project/vivado_2015.4/ipcores/ipcore_shared.tcl @@ -173,6 +173,7 @@ proc ipcore_add_ethport { label pname type } { set_property physical_name ${pname}_rx_write [ipx::add_port_map "rx_write" $intf] set_property physical_name ${pname}_rx_error [ipx::add_port_map "rx_error" $intf] set_property physical_name ${pname}_rx_rate [ipx::add_port_map "rx_rate" $intf] + set_property physical_name ${pname}_rx_status [ipx::add_port_map "rx_status" $intf] set_property physical_name ${pname}_rx_reset [ipx::add_port_map "rx_reset" $intf] set_property physical_name ${pname}_tx_clk [ipx::add_port_map "tx_clk" $intf] set_property physical_name ${pname}_tx_data [ipx::add_port_map "tx_data" $intf] diff --git a/project/vivado_2015.4/ipcores/wrap_port_adapter.vhd b/project/vivado_2015.4/ipcores/wrap_port_adapter.vhd index ea5987a..33a2918 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_adapter.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_adapter.vhd @@ -38,6 +38,7 @@ entity wrap_port_adapter is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status : out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -53,7 +54,8 @@ entity wrap_port_adapter is mac_rx_last : in std_logic; mac_rx_write : in std_logic; mac_rx_error : in std_logic; - max_rx_rate : in std_logic_vector(15 downto 0); + mac_rx_rate : in std_logic_vector(15 downto 0); + mac_rx_status : in std_logic_vector(7 downto 0); mac_rx_reset : in std_logic; mac_tx_clk : in std_logic; mac_tx_data : out std_logic_vector(7 downto 0); @@ -79,6 +81,7 @@ sw_rx_last <= sw_rxd.last; sw_rx_write <= sw_rxd.write; sw_rx_error <= sw_rxd.rxerr; sw_rx_rate <= sw_rxd.rate; +sw_rx_status <= sw_rxd.status; sw_rx_reset <= sw_rxd.reset_p; sw_tx_clk <= sw_txc.clk; sw_tx_ready <= sw_txc.ready; @@ -94,6 +97,7 @@ mac_rxd.last <= mac_rx_last; mac_rxd.write <= mac_rx_write; mac_rxd.rxerr <= mac_rx_error; mac_rxd.rate <= mac_rx_rate; +mac_rxd.status <= mac_rx_status; mac_rxd.reset_p <= mac_rx_reset; mac_txc.clk <= mac_tx_clk; mac_txc.ready <= mac_tx_ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_axi_mailbox.vhd b/project/vivado_2015.4/ipcores/wrap_port_axi_mailbox.vhd index 04cd75d..f9edb75 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_axi_mailbox.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_axi_mailbox.vhd @@ -43,6 +43,7 @@ entity wrap_port_axi_mailbox is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status : out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -92,6 +93,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_crosslink.vhd b/project/vivado_2015.4/ipcores/wrap_port_crosslink.vhd index 30910d8..ff2f96b 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_crosslink.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_crosslink.vhd @@ -42,6 +42,7 @@ entity wrap_port_crosslink is pa_rx_write : out std_logic; pa_rx_error : out std_logic; pa_rx_rate : out std_logic_vector(15 downto 0); + pa_rx_status : out std_logic_vector(7 downto 0); pa_rx_reset : out std_logic; pa_tx_clk : out std_logic; pa_tx_data : in std_logic_vector(7 downto 0); @@ -58,6 +59,7 @@ entity wrap_port_crosslink is pb_rx_write : out std_logic; pb_rx_error : out std_logic; pb_rx_rate : out std_logic_vector(15 downto 0); + pb_rx_status : out std_logic_vector(7 downto 0); pb_rx_reset : out std_logic; pb_tx_clk : out std_logic; pb_tx_data : in std_logic_vector(7 downto 0); @@ -87,6 +89,7 @@ pa_rx_last <= arxd.last; pa_rx_write <= arxd.write; pa_rx_error <= arxd.rxerr; pa_rx_rate <= arxd.rate; +pa_rx_status<= arxd.status; pa_rx_reset <= arxd.reset_p; pa_tx_clk <= atxc.clk; pa_tx_ready <= atxc.ready; @@ -102,6 +105,7 @@ pb_rx_last <= brxd.last; pb_rx_write <= brxd.write; pb_rx_error <= brxd.rxerr; pb_rx_rate <= brxd.rate; +pb_rx_status<= brxd.status; pb_rx_reset <= brxd.reset_p; pb_tx_clk <= btxc.clk; pb_tx_ready <= btxc.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_gmii_internal.vhd b/project/vivado_2015.4/ipcores/wrap_port_gmii_internal.vhd index 8e22168..0b0f980 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_gmii_internal.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_gmii_internal.vhd @@ -50,6 +50,7 @@ entity wrap_port_gmii_internal is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -86,6 +87,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_inline_status.vhd b/project/vivado_2015.4/ipcores/wrap_port_inline_status.vhd index d867925..3f7398c 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_inline_status.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_inline_status.vhd @@ -48,6 +48,7 @@ entity wrap_port_inline_status is lcl_rx_write : out std_logic; lcl_rx_error : out std_logic; lcl_rx_rate : out std_logic_vector(15 downto 0); + lcl_rx_status : out std_logic_vector(7 downto 0); lcl_rx_reset : out std_logic; lcl_tx_clk : out std_logic; lcl_tx_data : in std_logic_vector(7 downto 0); @@ -64,6 +65,7 @@ entity wrap_port_inline_status is net_rx_write : in std_logic; net_rx_error : in std_logic; net_rx_rate : in std_logic_vector(15 downto 0); + net_rx_status : in std_logic_vector(7 downto 0); net_rx_reset : in std_logic; net_tx_clk : in std_logic; net_tx_data : out std_logic_vector(7 downto 0); @@ -93,6 +95,7 @@ lcl_rx_last <= lcl_rxd.last; lcl_rx_write <= lcl_rxd.write; lcl_rx_error <= lcl_rxd.rxerr; lcl_rx_rate <= lcl_rxd.rate; +lcl_rx_status <= lcl_rxd.status; lcl_rx_reset <= lcl_rxd.reset_p; lcl_tx_clk <= lcl_txc.clk; lcl_tx_ready <= lcl_txc.ready; @@ -108,6 +111,7 @@ net_rxd.last <= net_rx_last; net_rxd.write <= net_rx_write; net_rxd.rxerr <= net_rx_error; net_rxd.rate <= net_rx_rate; +net_rxd.status <= net_rx_status; net_rxd.reset_p <= net_rx_reset; net_txc.clk <= net_tx_clk; net_txc.ready <= net_tx_ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_rgmii.vhd b/project/vivado_2015.4/ipcores/wrap_port_rgmii.vhd index 8192974..ae64f74 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_rgmii.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_rgmii.vhd @@ -53,6 +53,7 @@ entity wrap_port_rgmii is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -83,6 +84,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_rmii.vhd b/project/vivado_2015.4/ipcores/wrap_port_rmii.vhd index 3863e39..0119ddd 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_rmii.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_rmii.vhd @@ -53,6 +53,7 @@ entity wrap_port_rmii is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -81,6 +82,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_serial_auto.vhd b/project/vivado_2015.4/ipcores/wrap_port_serial_auto.vhd index 05b37c4..f2a688a 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_serial_auto.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_serial_auto.vhd @@ -47,6 +47,7 @@ entity wrap_port_serial_auto is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -76,6 +77,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkin.vhd b/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkin.vhd index bd33af4..596a9aa 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkin.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkin.vhd @@ -44,6 +44,7 @@ entity wrap_port_serial_spi_clkin is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -74,6 +75,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkout.vhd b/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkout.vhd index d3cc03f..6ec1824 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkout.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_serial_spi_clkout.vhd @@ -45,6 +45,7 @@ entity wrap_port_serial_spi_clkout is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -75,6 +76,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_serial_uart_2wire.vhd b/project/vivado_2015.4/ipcores/wrap_port_serial_uart_2wire.vhd index 46565a4..40373a8 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_serial_uart_2wire.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_serial_uart_2wire.vhd @@ -45,6 +45,7 @@ entity wrap_port_serial_uart_2wire is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -74,6 +75,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_serial_uart_4wire.vhd b/project/vivado_2015.4/ipcores/wrap_port_serial_uart_4wire.vhd index 016a34c..e2b0687 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_serial_uart_4wire.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_serial_uart_4wire.vhd @@ -44,6 +44,7 @@ entity wrap_port_serial_uart_4wire is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -74,6 +75,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_sgmii_gpio.vhd b/project/vivado_2015.4/ipcores/wrap_port_sgmii_gpio.vhd index fd3c041..5fffa25 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_sgmii_gpio.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_sgmii_gpio.vhd @@ -52,6 +52,7 @@ entity wrap_port_sgmii_gpio is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -84,6 +85,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_port_sgmii_gtx.vhd b/project/vivado_2015.4/ipcores/wrap_port_sgmii_gtx.vhd index 4cfccdc..243a09c 100644 --- a/project/vivado_2015.4/ipcores/wrap_port_sgmii_gtx.vhd +++ b/project/vivado_2015.4/ipcores/wrap_port_sgmii_gtx.vhd @@ -44,6 +44,7 @@ entity wrap_port_sgmii_gtx is sw_rx_write : out std_logic; sw_rx_error : out std_logic; sw_rx_rate : out std_logic_vector(15 downto 0); + sw_rx_status: out std_logic_vector(7 downto 0); sw_rx_reset : out std_logic; sw_tx_clk : out std_logic; sw_tx_data : in std_logic_vector(7 downto 0); @@ -75,6 +76,7 @@ sw_rx_last <= rx_data.last; sw_rx_write <= rx_data.write; sw_rx_error <= rx_data.rxerr; sw_rx_rate <= rx_data.rate; +sw_rx_status <= rx_data.status; sw_rx_reset <= rx_data.reset_p; sw_tx_clk <= tx_ctrl.clk; sw_tx_ready <= tx_ctrl.ready; diff --git a/project/vivado_2015.4/ipcores/wrap_router_inline.vhd b/project/vivado_2015.4/ipcores/wrap_router_inline.vhd index 4376f91..08c7666 100644 --- a/project/vivado_2015.4/ipcores/wrap_router_inline.vhd +++ b/project/vivado_2015.4/ipcores/wrap_router_inline.vhd @@ -67,6 +67,7 @@ entity wrap_router_inline is lcl_rx_write : out std_logic; lcl_rx_error : out std_logic; lcl_rx_rate : out std_logic_vector(15 downto 0); + lcl_rx_status : out std_logic_vector(7 downto 0); lcl_rx_reset : out std_logic; lcl_tx_clk : out std_logic; lcl_tx_data : in std_logic_vector(7 downto 0); @@ -83,6 +84,7 @@ entity wrap_router_inline is net_rx_write : in std_logic; net_rx_error : in std_logic; net_rx_rate : in std_logic_vector(15 downto 0); + net_rx_status : in std_logic_vector(7 downto 0); net_rx_reset : in std_logic; net_tx_clk : in std_logic; net_tx_data : out std_logic_vector(7 downto 0); @@ -142,6 +144,7 @@ lcl_rx_last <= lcl_rxd.last; lcl_rx_write <= lcl_rxd.write; lcl_rx_error <= lcl_rxd.rxerr; lcl_rx_rate <= lcl_rxd.rate; +lcl_rx_status <= lcl_rxd.status; lcl_rx_reset <= lcl_rxd.reset_p; lcl_tx_clk <= lcl_txc.clk; lcl_tx_ready <= lcl_txc.ready; @@ -157,6 +160,7 @@ net_rxd.last <= net_rx_last; net_rxd.write <= net_rx_write; net_rxd.rxerr <= net_rx_error; net_rxd.rate <= net_rx_rate; +net_rxd.status <= net_rx_status; net_rxd.reset_p <= net_rx_reset; net_txc.clk <= net_tx_clk; net_txc.ready <= net_tx_ready; diff --git a/project/vivado_2015.4/ipcores/wrap_switch_core.vhd b/project/vivado_2015.4/ipcores/wrap_switch_core.vhd index f89c06d..3c6a447 100644 --- a/project/vivado_2015.4/ipcores/wrap_switch_core.vhd +++ b/project/vivado_2015.4/ipcores/wrap_switch_core.vhd @@ -56,6 +56,7 @@ entity wrap_switch_core is p00_rx_write : in std_logic; p00_rx_error : in std_logic; p00_rx_rate : in std_logic_vector(15 downto 0); + p00_rx_status : in std_logic_vector(7 downto 0); p00_rx_reset : in std_logic; p00_tx_clk : in std_logic; p00_tx_data : out std_logic_vector(7 downto 0); @@ -71,6 +72,7 @@ entity wrap_switch_core is p01_rx_write : in std_logic; p01_rx_error : in std_logic; p01_rx_rate : in std_logic_vector(15 downto 0); + p01_rx_status : in std_logic_vector(7 downto 0); p01_rx_reset : in std_logic; p01_tx_clk : in std_logic; p01_tx_data : out std_logic_vector(7 downto 0); @@ -86,6 +88,7 @@ entity wrap_switch_core is p02_rx_write : in std_logic; p02_rx_error : in std_logic; p02_rx_rate : in std_logic_vector(15 downto 0); + p02_rx_status : in std_logic_vector(7 downto 0); p02_rx_reset : in std_logic; p02_tx_clk : in std_logic; p02_tx_data : out std_logic_vector(7 downto 0); @@ -101,6 +104,7 @@ entity wrap_switch_core is p03_rx_write : in std_logic; p03_rx_error : in std_logic; p03_rx_rate : in std_logic_vector(15 downto 0); + p03_rx_status : in std_logic_vector(7 downto 0); p03_rx_reset : in std_logic; p03_tx_clk : in std_logic; p03_tx_data : out std_logic_vector(7 downto 0); @@ -116,6 +120,7 @@ entity wrap_switch_core is p04_rx_write : in std_logic; p04_rx_error : in std_logic; p04_rx_rate : in std_logic_vector(15 downto 0); + p04_rx_status : in std_logic_vector(7 downto 0); p04_rx_reset : in std_logic; p04_tx_clk : in std_logic; p04_tx_data : out std_logic_vector(7 downto 0); @@ -131,6 +136,7 @@ entity wrap_switch_core is p05_rx_write : in std_logic; p05_rx_error : in std_logic; p05_rx_rate : in std_logic_vector(15 downto 0); + p05_rx_status : in std_logic_vector(7 downto 0); p05_rx_reset : in std_logic; p05_tx_clk : in std_logic; p05_tx_data : out std_logic_vector(7 downto 0); @@ -146,6 +152,7 @@ entity wrap_switch_core is p06_rx_write : in std_logic; p06_rx_error : in std_logic; p06_rx_rate : in std_logic_vector(15 downto 0); + p06_rx_status : in std_logic_vector(7 downto 0); p06_rx_reset : in std_logic; p06_tx_clk : in std_logic; p06_tx_data : out std_logic_vector(7 downto 0); @@ -161,6 +168,7 @@ entity wrap_switch_core is p07_rx_write : in std_logic; p07_rx_error : in std_logic; p07_rx_rate : in std_logic_vector(15 downto 0); + p07_rx_status : in std_logic_vector(7 downto 0); p07_rx_reset : in std_logic; p07_tx_clk : in std_logic; p07_tx_data : out std_logic_vector(7 downto 0); @@ -176,6 +184,7 @@ entity wrap_switch_core is p08_rx_write : in std_logic; p08_rx_error : in std_logic; p08_rx_rate : in std_logic_vector(15 downto 0); + p08_rx_status : in std_logic_vector(7 downto 0); p08_rx_reset : in std_logic; p08_tx_clk : in std_logic; p08_tx_data : out std_logic_vector(7 downto 0); @@ -191,6 +200,7 @@ entity wrap_switch_core is p09_rx_write : in std_logic; p09_rx_error : in std_logic; p09_rx_rate : in std_logic_vector(15 downto 0); + p09_rx_status : in std_logic_vector(7 downto 0); p09_rx_reset : in std_logic; p09_tx_clk : in std_logic; p09_tx_data : out std_logic_vector(7 downto 0); @@ -206,6 +216,7 @@ entity wrap_switch_core is p10_rx_write : in std_logic; p10_rx_error : in std_logic; p10_rx_rate : in std_logic_vector(15 downto 0); + p10_rx_status : in std_logic_vector(7 downto 0); p10_rx_reset : in std_logic; p10_tx_clk : in std_logic; p10_tx_data : out std_logic_vector(7 downto 0); @@ -221,6 +232,7 @@ entity wrap_switch_core is p11_rx_write : in std_logic; p11_rx_error : in std_logic; p11_rx_rate : in std_logic_vector(15 downto 0); + p11_rx_status : in std_logic_vector(7 downto 0); p11_rx_reset : in std_logic; p11_tx_clk : in std_logic; p11_tx_data : out std_logic_vector(7 downto 0); @@ -236,6 +248,7 @@ entity wrap_switch_core is p12_rx_write : in std_logic; p12_rx_error : in std_logic; p12_rx_rate : in std_logic_vector(15 downto 0); + p12_rx_status : in std_logic_vector(7 downto 0); p12_rx_reset : in std_logic; p12_tx_clk : in std_logic; p12_tx_data : out std_logic_vector(7 downto 0); @@ -251,6 +264,7 @@ entity wrap_switch_core is p13_rx_write : in std_logic; p13_rx_error : in std_logic; p13_rx_rate : in std_logic_vector(15 downto 0); + p13_rx_status : in std_logic_vector(7 downto 0); p13_rx_reset : in std_logic; p13_tx_clk : in std_logic; p13_tx_data : out std_logic_vector(7 downto 0); @@ -266,6 +280,7 @@ entity wrap_switch_core is p14_rx_write : in std_logic; p14_rx_error : in std_logic; p14_rx_rate : in std_logic_vector(15 downto 0); + p14_rx_status : in std_logic_vector(7 downto 0); p14_rx_reset : in std_logic; p14_tx_clk : in std_logic; p14_tx_data : out std_logic_vector(7 downto 0); @@ -281,6 +296,7 @@ entity wrap_switch_core is p15_rx_write : in std_logic; p15_rx_error : in std_logic; p15_rx_rate : in std_logic_vector(15 downto 0); + p15_rx_status : in std_logic_vector(7 downto 0); p15_rx_reset : in std_logic; p15_tx_clk : in std_logic; p15_tx_data : out std_logic_vector(7 downto 0); @@ -296,6 +312,7 @@ entity wrap_switch_core is p16_rx_write : in std_logic; p16_rx_error : in std_logic; p16_rx_rate : in std_logic_vector(15 downto 0); + p16_rx_status : in std_logic_vector(7 downto 0); p16_rx_reset : in std_logic; p16_tx_clk : in std_logic; p16_tx_data : out std_logic_vector(7 downto 0); @@ -311,6 +328,7 @@ entity wrap_switch_core is p17_rx_write : in std_logic; p17_rx_error : in std_logic; p17_rx_rate : in std_logic_vector(15 downto 0); + p17_rx_status : in std_logic_vector(7 downto 0); p17_rx_reset : in std_logic; p17_tx_clk : in std_logic; p17_tx_data : out std_logic_vector(7 downto 0); @@ -326,6 +344,7 @@ entity wrap_switch_core is p18_rx_write : in std_logic; p18_rx_error : in std_logic; p18_rx_rate : in std_logic_vector(15 downto 0); + p18_rx_status : in std_logic_vector(7 downto 0); p18_rx_reset : in std_logic; p18_tx_clk : in std_logic; p18_tx_data : out std_logic_vector(7 downto 0); @@ -341,6 +360,7 @@ entity wrap_switch_core is p19_rx_write : in std_logic; p19_rx_error : in std_logic; p19_rx_rate : in std_logic_vector(15 downto 0); + p19_rx_status : in std_logic_vector(7 downto 0); p19_rx_reset : in std_logic; p19_tx_clk : in std_logic; p19_tx_data : out std_logic_vector(7 downto 0); @@ -356,6 +376,7 @@ entity wrap_switch_core is p20_rx_write : in std_logic; p20_rx_error : in std_logic; p20_rx_rate : in std_logic_vector(15 downto 0); + p20_rx_status : in std_logic_vector(7 downto 0); p20_rx_reset : in std_logic; p20_tx_clk : in std_logic; p20_tx_data : out std_logic_vector(7 downto 0); @@ -371,6 +392,7 @@ entity wrap_switch_core is p21_rx_write : in std_logic; p21_rx_error : in std_logic; p21_rx_rate : in std_logic_vector(15 downto 0); + p21_rx_status : in std_logic_vector(7 downto 0); p21_rx_reset : in std_logic; p21_tx_clk : in std_logic; p21_tx_data : out std_logic_vector(7 downto 0); @@ -386,6 +408,7 @@ entity wrap_switch_core is p22_rx_write : in std_logic; p22_rx_error : in std_logic; p22_rx_rate : in std_logic_vector(15 downto 0); + p22_rx_status : in std_logic_vector(7 downto 0); p22_rx_reset : in std_logic; p22_tx_clk : in std_logic; p22_tx_data : out std_logic_vector(7 downto 0); @@ -401,6 +424,7 @@ entity wrap_switch_core is p23_rx_write : in std_logic; p23_rx_error : in std_logic; p23_rx_rate : in std_logic_vector(15 downto 0); + p23_rx_status : in std_logic_vector(7 downto 0); p23_rx_reset : in std_logic; p23_tx_clk : in std_logic; p23_tx_data : out std_logic_vector(7 downto 0); @@ -416,6 +440,7 @@ entity wrap_switch_core is p24_rx_write : in std_logic; p24_rx_error : in std_logic; p24_rx_rate : in std_logic_vector(15 downto 0); + p24_rx_status : in std_logic_vector(7 downto 0); p24_rx_reset : in std_logic; p24_tx_clk : in std_logic; p24_tx_data : out std_logic_vector(7 downto 0); @@ -431,6 +456,7 @@ entity wrap_switch_core is p25_rx_write : in std_logic; p25_rx_error : in std_logic; p25_rx_rate : in std_logic_vector(15 downto 0); + p25_rx_status : in std_logic_vector(7 downto 0); p25_rx_reset : in std_logic; p25_tx_clk : in std_logic; p25_tx_data : out std_logic_vector(7 downto 0); @@ -446,6 +472,7 @@ entity wrap_switch_core is p26_rx_write : in std_logic; p26_rx_error : in std_logic; p26_rx_rate : in std_logic_vector(15 downto 0); + p26_rx_status : in std_logic_vector(7 downto 0); p26_rx_reset : in std_logic; p26_tx_clk : in std_logic; p26_tx_data : out std_logic_vector(7 downto 0); @@ -461,6 +488,7 @@ entity wrap_switch_core is p27_rx_write : in std_logic; p27_rx_error : in std_logic; p27_rx_rate : in std_logic_vector(15 downto 0); + p27_rx_status : in std_logic_vector(7 downto 0); p27_rx_reset : in std_logic; p27_tx_clk : in std_logic; p27_tx_data : out std_logic_vector(7 downto 0); @@ -476,6 +504,7 @@ entity wrap_switch_core is p28_rx_write : in std_logic; p28_rx_error : in std_logic; p28_rx_rate : in std_logic_vector(15 downto 0); + p28_rx_status : in std_logic_vector(7 downto 0); p28_rx_reset : in std_logic; p28_tx_clk : in std_logic; p28_tx_data : out std_logic_vector(7 downto 0); @@ -491,6 +520,7 @@ entity wrap_switch_core is p29_rx_write : in std_logic; p29_rx_error : in std_logic; p29_rx_rate : in std_logic_vector(15 downto 0); + p29_rx_status : in std_logic_vector(7 downto 0); p29_rx_reset : in std_logic; p29_tx_clk : in std_logic; p29_tx_data : out std_logic_vector(7 downto 0); @@ -506,6 +536,7 @@ entity wrap_switch_core is p30_rx_write : in std_logic; p30_rx_error : in std_logic; p30_rx_rate : in std_logic_vector(15 downto 0); + p30_rx_status : in std_logic_vector(7 downto 0); p30_rx_reset : in std_logic; p30_tx_clk : in std_logic; p30_tx_data : out std_logic_vector(7 downto 0); @@ -521,6 +552,7 @@ entity wrap_switch_core is p31_rx_write : in std_logic; p31_rx_error : in std_logic; p31_rx_rate : in std_logic_vector(15 downto 0); + p31_rx_status : in std_logic_vector(7 downto 0); p31_rx_reset : in std_logic; p31_tx_clk : in std_logic; p31_tx_data : out std_logic_vector(7 downto 0); @@ -580,6 +612,7 @@ gen_p00 : if (PORT_COUNT > 0) generate rx_data(0).write <= p00_rx_write; rx_data(0).rxerr <= p00_rx_error; rx_data(0).rate <= p00_rx_rate; + rx_data(0).status <= p00_rx_status; rx_data(0).reset_p <= p00_rx_reset; tx_ctrl(0).clk <= p00_tx_clk; tx_ctrl(0).ready <= p00_tx_ready; @@ -603,6 +636,7 @@ gen_p01 : if (PORT_COUNT > 1) generate rx_data(1).write <= p01_rx_write; rx_data(1).rxerr <= p01_rx_error; rx_data(1).rate <= p01_rx_rate; + rx_data(1).status <= p01_rx_status; rx_data(1).reset_p <= p01_rx_reset; tx_ctrl(1).clk <= p01_tx_clk; tx_ctrl(1).ready <= p01_tx_ready; @@ -626,6 +660,7 @@ gen_p02 : if (PORT_COUNT > 2) generate rx_data(2).write <= p02_rx_write; rx_data(2).rxerr <= p02_rx_error; rx_data(2).rate <= p02_rx_rate; + rx_data(2).status <= p02_rx_status; rx_data(2).reset_p <= p02_rx_reset; tx_ctrl(2).clk <= p02_tx_clk; tx_ctrl(2).ready <= p02_tx_ready; @@ -649,6 +684,7 @@ gen_p03 : if (PORT_COUNT > 3) generate rx_data(3).write <= p03_rx_write; rx_data(3).rxerr <= p03_rx_error; rx_data(3).rate <= p03_rx_rate; + rx_data(3).status <= p03_rx_status; rx_data(3).reset_p <= p03_rx_reset; tx_ctrl(3).clk <= p03_tx_clk; tx_ctrl(3).ready <= p03_tx_ready; @@ -672,6 +708,7 @@ gen_p04 : if (PORT_COUNT > 4) generate rx_data(4).write <= p04_rx_write; rx_data(4).rxerr <= p04_rx_error; rx_data(4).rate <= p04_rx_rate; + rx_data(4).status <= p04_rx_status; rx_data(4).reset_p <= p04_rx_reset; tx_ctrl(4).clk <= p04_tx_clk; tx_ctrl(4).ready <= p04_tx_ready; @@ -695,6 +732,7 @@ gen_p05 : if (PORT_COUNT > 5) generate rx_data(5).write <= p05_rx_write; rx_data(5).rxerr <= p05_rx_error; rx_data(5).rate <= p05_rx_rate; + rx_data(5).status <= p05_rx_status; rx_data(5).reset_p <= p05_rx_reset; tx_ctrl(5).clk <= p05_tx_clk; tx_ctrl(5).ready <= p05_tx_ready; @@ -718,6 +756,7 @@ gen_p06 : if (PORT_COUNT > 6) generate rx_data(6).write <= p06_rx_write; rx_data(6).rxerr <= p06_rx_error; rx_data(6).rate <= p06_rx_rate; + rx_data(6).status <= p06_rx_status; rx_data(6).reset_p <= p06_rx_reset; tx_ctrl(6).clk <= p06_tx_clk; tx_ctrl(6).ready <= p06_tx_ready; @@ -741,6 +780,7 @@ gen_p07 : if (PORT_COUNT > 7) generate rx_data(7).write <= p07_rx_write; rx_data(7).rxerr <= p07_rx_error; rx_data(7).rate <= p07_rx_rate; + rx_data(7).status <= p07_rx_status; rx_data(7).reset_p <= p07_rx_reset; tx_ctrl(7).clk <= p07_tx_clk; tx_ctrl(7).ready <= p07_tx_ready; @@ -764,6 +804,7 @@ gen_p08 : if (PORT_COUNT > 8) generate rx_data(8).write <= p08_rx_write; rx_data(8).rxerr <= p08_rx_error; rx_data(8).rate <= p08_rx_rate; + rx_data(8).status <= p08_rx_status; rx_data(8).reset_p <= p08_rx_reset; tx_ctrl(8).clk <= p08_tx_clk; tx_ctrl(8).ready <= p08_tx_ready; @@ -787,6 +828,7 @@ gen_p09 : if (PORT_COUNT > 9) generate rx_data(9).write <= p09_rx_write; rx_data(9).rxerr <= p09_rx_error; rx_data(9).rate <= p09_rx_rate; + rx_data(9).status <= p09_rx_status; rx_data(9).reset_p <= p09_rx_reset; tx_ctrl(9).clk <= p09_tx_clk; tx_ctrl(9).ready <= p09_tx_ready; @@ -810,6 +852,7 @@ gen_p10 : if (PORT_COUNT > 10) generate rx_data(10).write <= p10_rx_write; rx_data(10).rxerr <= p10_rx_error; rx_data(10).rate <= p10_rx_rate; + rx_data(10).status <= p10_rx_status; rx_data(10).reset_p <= p10_rx_reset; tx_ctrl(10).clk <= p10_tx_clk; tx_ctrl(10).ready <= p10_tx_ready; @@ -833,6 +876,7 @@ gen_p11 : if (PORT_COUNT > 11) generate rx_data(11).write <= p11_rx_write; rx_data(11).rxerr <= p11_rx_error; rx_data(11).rate <= p11_rx_rate; + rx_data(11).status <= p11_rx_status; rx_data(11).reset_p <= p11_rx_reset; tx_ctrl(11).clk <= p11_tx_clk; tx_ctrl(11).ready <= p11_tx_ready; @@ -856,6 +900,7 @@ gen_p12 : if (PORT_COUNT > 12) generate rx_data(12).write <= p12_rx_write; rx_data(12).rxerr <= p12_rx_error; rx_data(12).rate <= p12_rx_rate; + rx_data(12).status <= p12_rx_status; rx_data(12).reset_p <= p12_rx_reset; tx_ctrl(12).clk <= p12_tx_clk; tx_ctrl(12).ready <= p12_tx_ready; @@ -879,6 +924,7 @@ gen_p13 : if (PORT_COUNT > 13) generate rx_data(13).write <= p13_rx_write; rx_data(13).rxerr <= p13_rx_error; rx_data(13).rate <= p13_rx_rate; + rx_data(13).status <= p13_rx_status; rx_data(13).reset_p <= p13_rx_reset; tx_ctrl(13).clk <= p13_tx_clk; tx_ctrl(13).ready <= p13_tx_ready; @@ -902,6 +948,7 @@ gen_p14 : if (PORT_COUNT > 14) generate rx_data(14).write <= p14_rx_write; rx_data(14).rxerr <= p14_rx_error; rx_data(14).rate <= p14_rx_rate; + rx_data(14).status <= p14_rx_status; rx_data(14).reset_p <= p14_rx_reset; tx_ctrl(14).clk <= p14_tx_clk; tx_ctrl(14).ready <= p14_tx_ready; @@ -925,6 +972,7 @@ gen_p15 : if (PORT_COUNT > 15) generate rx_data(15).write <= p15_rx_write; rx_data(15).rxerr <= p15_rx_error; rx_data(15).rate <= p15_rx_rate; + rx_data(15).status <= p15_rx_status; rx_data(15).reset_p <= p15_rx_reset; tx_ctrl(15).clk <= p15_tx_clk; tx_ctrl(15).ready <= p15_tx_ready; @@ -948,6 +996,7 @@ gen_p16 : if (PORT_COUNT > 16) generate rx_data(16).write <= p16_rx_write; rx_data(16).rxerr <= p16_rx_error; rx_data(16).rate <= p16_rx_rate; + rx_data(16).status <= p16_rx_status; rx_data(16).reset_p <= p16_rx_reset; tx_ctrl(16).clk <= p16_tx_clk; tx_ctrl(16).ready <= p16_tx_ready; @@ -971,6 +1020,7 @@ gen_p17 : if (PORT_COUNT > 17) generate rx_data(17).write <= p17_rx_write; rx_data(17).rxerr <= p17_rx_error; rx_data(17).rate <= p17_rx_rate; + rx_data(17).status <= p17_rx_status; rx_data(17).reset_p <= p17_rx_reset; tx_ctrl(17).clk <= p17_tx_clk; tx_ctrl(17).ready <= p17_tx_ready; @@ -994,6 +1044,7 @@ gen_p18 : if (PORT_COUNT > 18) generate rx_data(18).write <= p18_rx_write; rx_data(18).rxerr <= p18_rx_error; rx_data(18).rate <= p18_rx_rate; + rx_data(18).status <= p18_rx_status; rx_data(18).reset_p <= p18_rx_reset; tx_ctrl(18).clk <= p18_tx_clk; tx_ctrl(18).ready <= p18_tx_ready; @@ -1017,6 +1068,7 @@ gen_p19 : if (PORT_COUNT > 19) generate rx_data(19).write <= p19_rx_write; rx_data(19).rxerr <= p19_rx_error; rx_data(19).rate <= p19_rx_rate; + rx_data(19).status <= p19_rx_status; rx_data(19).reset_p <= p19_rx_reset; tx_ctrl(19).clk <= p19_tx_clk; tx_ctrl(19).ready <= p19_tx_ready; @@ -1040,6 +1092,7 @@ gen_p20 : if (PORT_COUNT > 20) generate rx_data(20).write <= p20_rx_write; rx_data(20).rxerr <= p20_rx_error; rx_data(20).rate <= p20_rx_rate; + rx_data(20).status <= p20_rx_status; rx_data(20).reset_p <= p20_rx_reset; tx_ctrl(20).clk <= p20_tx_clk; tx_ctrl(20).ready <= p20_tx_ready; @@ -1063,6 +1116,7 @@ gen_p21 : if (PORT_COUNT > 21) generate rx_data(21).write <= p21_rx_write; rx_data(21).rxerr <= p21_rx_error; rx_data(21).rate <= p21_rx_rate; + rx_data(21).status <= p21_rx_status; rx_data(21).reset_p <= p21_rx_reset; tx_ctrl(21).clk <= p21_tx_clk; tx_ctrl(21).ready <= p21_tx_ready; @@ -1086,6 +1140,7 @@ gen_p22 : if (PORT_COUNT > 22) generate rx_data(22).write <= p22_rx_write; rx_data(22).rxerr <= p22_rx_error; rx_data(22).rate <= p22_rx_rate; + rx_data(22).status <= p22_rx_status; rx_data(22).reset_p <= p22_rx_reset; tx_ctrl(22).clk <= p22_tx_clk; tx_ctrl(22).ready <= p22_tx_ready; @@ -1109,6 +1164,7 @@ gen_p23 : if (PORT_COUNT > 23) generate rx_data(23).write <= p23_rx_write; rx_data(23).rxerr <= p23_rx_error; rx_data(23).rate <= p23_rx_rate; + rx_data(23).status <= p23_rx_status; rx_data(23).reset_p <= p23_rx_reset; tx_ctrl(23).clk <= p23_tx_clk; tx_ctrl(23).ready <= p23_tx_ready; @@ -1132,6 +1188,7 @@ gen_p24 : if (PORT_COUNT > 24) generate rx_data(24).write <= p24_rx_write; rx_data(24).rxerr <= p24_rx_error; rx_data(24).rate <= p24_rx_rate; + rx_data(24).status <= p24_rx_status; rx_data(24).reset_p <= p24_rx_reset; tx_ctrl(24).clk <= p24_tx_clk; tx_ctrl(24).ready <= p24_tx_ready; @@ -1155,6 +1212,7 @@ gen_p25 : if (PORT_COUNT > 25) generate rx_data(25).write <= p25_rx_write; rx_data(25).rxerr <= p25_rx_error; rx_data(25).rate <= p25_rx_rate; + rx_data(25).status <= p25_rx_status; rx_data(25).reset_p <= p25_rx_reset; tx_ctrl(25).clk <= p25_tx_clk; tx_ctrl(25).ready <= p25_tx_ready; @@ -1178,6 +1236,7 @@ gen_p26 : if (PORT_COUNT > 26) generate rx_data(26).write <= p26_rx_write; rx_data(26).rxerr <= p26_rx_error; rx_data(26).rate <= p26_rx_rate; + rx_data(26).status <= p26_rx_status; rx_data(26).reset_p <= p26_rx_reset; tx_ctrl(26).clk <= p26_tx_clk; tx_ctrl(26).ready <= p26_tx_ready; @@ -1201,6 +1260,7 @@ gen_p27 : if (PORT_COUNT > 27) generate rx_data(27).write <= p27_rx_write; rx_data(27).rxerr <= p27_rx_error; rx_data(27).rate <= p27_rx_rate; + rx_data(27).status <= p27_rx_status; rx_data(27).reset_p <= p27_rx_reset; tx_ctrl(27).clk <= p27_tx_clk; tx_ctrl(27).ready <= p27_tx_ready; @@ -1224,6 +1284,7 @@ gen_p28 : if (PORT_COUNT > 28) generate rx_data(28).write <= p28_rx_write; rx_data(28).rxerr <= p28_rx_error; rx_data(28).rate <= p28_rx_rate; + rx_data(28).status <= p28_rx_status; rx_data(28).reset_p <= p28_rx_reset; tx_ctrl(28).clk <= p28_tx_clk; tx_ctrl(28).ready <= p28_tx_ready; @@ -1247,6 +1308,7 @@ gen_p29 : if (PORT_COUNT > 29) generate rx_data(29).write <= p29_rx_write; rx_data(29).rxerr <= p29_rx_error; rx_data(29).rate <= p29_rx_rate; + rx_data(29).status <= p29_rx_status; rx_data(29).reset_p <= p29_rx_reset; tx_ctrl(29).clk <= p29_tx_clk; tx_ctrl(29).ready <= p29_tx_ready; @@ -1270,6 +1332,7 @@ gen_p30 : if (PORT_COUNT > 30) generate rx_data(30).write <= p30_rx_write; rx_data(30).rxerr <= p30_rx_error; rx_data(30).rate <= p30_rx_rate; + rx_data(30).status <= p30_rx_status; rx_data(30).reset_p <= p30_rx_reset; tx_ctrl(30).clk <= p30_tx_clk; tx_ctrl(30).ready <= p30_tx_ready; @@ -1293,6 +1356,7 @@ gen_p31 : if (PORT_COUNT > 31) generate rx_data(31).write <= p31_rx_write; rx_data(31).rxerr <= p31_rx_error; rx_data(31).rate <= p31_rx_rate; + rx_data(31).status <= p31_rx_status; rx_data(31).reset_p <= p31_rx_reset; tx_ctrl(31).clk <= p31_tx_clk; tx_ctrl(31).ready <= p31_tx_ready; diff --git a/project/vivado_2015.4/ipcores/wrap_switch_dual.vhd b/project/vivado_2015.4/ipcores/wrap_switch_dual.vhd index 26ff9c4..3b9a9d1 100644 --- a/project/vivado_2015.4/ipcores/wrap_switch_dual.vhd +++ b/project/vivado_2015.4/ipcores/wrap_switch_dual.vhd @@ -42,6 +42,7 @@ entity wrap_switch_dual is pa_rx_write : in std_logic; pa_rx_error : in std_logic; pa_rx_rate : in std_logic_vector(15 downto 0); + pa_rx_status : in std_logic_vector(7 downto 0); pa_rx_reset : in std_logic; pa_tx_clk : in std_logic; pa_tx_data : out std_logic_vector(7 downto 0); @@ -55,7 +56,8 @@ entity wrap_switch_dual is pb_rx_clk : in std_logic; pb_rx_data : in std_logic_vector(7 downto 0); pb_rx_last : in std_logic; - pa_rx_rate : in std_logic_vector(15 downto 0); + pb_rx_rate : in std_logic_vector(15 downto 0); + pb_rx_status : in std_logic_vector(7 downto 0); pb_rx_write : in std_logic; pb_rx_error : in std_logic; pb_rx_reset : in std_logic; @@ -86,6 +88,7 @@ rx_data(0).last <= pa_rx_last; rx_data(0).write <= pa_rx_write; rx_data(0).rxerr <= pa_rx_error; rx_data(0).rate <= pa_rx_rate; +rx_data(0).status <= pa_rx_status; rx_data(0).reset_p <= pa_rx_reset; tx_ctrl(0).clk <= pa_tx_clk; tx_ctrl(0).ready <= pa_tx_ready; @@ -101,6 +104,7 @@ rx_data(1).last <= pb_rx_last; rx_data(1).write <= pb_rx_write; rx_data(1).rxerr <= pb_rx_error; rx_data(1).rate <= pb_rx_rate; +rx_data(1).status <= pb_rx_status; rx_data(1).reset_p <= pb_rx_reset; tx_ctrl(1).clk <= pb_tx_clk; tx_ctrl(1).ready <= pb_tx_ready; diff --git a/sim/vhdl/config_stats_refsrc.vhd b/sim/vhdl/config_stats_refsrc.vhd index ff4bc47..36719f7 100644 --- a/sim/vhdl/config_stats_refsrc.vhd +++ b/sim/vhdl/config_stats_refsrc.vhd @@ -48,6 +48,7 @@ entity config_stats_refsrc is ref_txfrm : out natural; -- High-level control. + rx_status : in port_status_t; rx_rate : in real; tx_rate : in real; burst_run : in std_logic; @@ -92,6 +93,7 @@ prx_data.data <= rx_data; prx_data.last <= rx_last; prx_data.write <= rx_write; prx_data.rate <= get_rate_word(1000); +prx_data.status <= rx_status; prx_data.rxerr <= '0'; prx_data.reset_p <= reset_p; ptx_data.data <= tx_data; diff --git a/sim/vhdl/config_stats_tb.vhd b/sim/vhdl/config_stats_tb.vhd index 506c425..b652968 100644 --- a/sim/vhdl/config_stats_tb.vhd +++ b/sim/vhdl/config_stats_tb.vhd @@ -43,8 +43,13 @@ end config_stats_tb; architecture tb of config_stats_tb is +-- Use a relatively fast UART to keep test length manageable. constant UART_BAUD : integer := 10_000_000; +-- Number of expected items from each format. +constant TOTAL_AXI_WORDS : positive := PORT_COUNT * 8; +constant TOTAL_UART_BYTES : positive := PORT_COUNT * 25; + -- Clock and reset generation. signal clk_100 : std_logic := '0'; signal reset_p : std_logic := '1'; @@ -64,6 +69,7 @@ signal ref_rxbyte : count_array := (others => 0); signal ref_rxfrm : count_array := (others => 0); signal ref_txbyte : count_array := (others => 0); signal ref_txfrm : count_array := (others => 0); +signal ref_status : port_status_t; -- AXI-Lite interface signal axi_clk : std_logic; @@ -102,6 +108,9 @@ axi_clk <= clk_100 after 1 ns; reset_p <= '0' after 1 us; reset_n <= not reset_p; +-- Status word is just the current test index. +ref_status <= i2s(test_index, 8); + -- Traffic generation and reference counters for each port. gen_ports : for n in 0 to PORT_COUNT-1 generate u_port : entity work.config_stats_refsrc @@ -119,6 +128,7 @@ gen_ports : for n in 0 to PORT_COUNT-1 generate ref_rxfrm => ref_rxfrm(n), ref_txbyte => ref_txbyte(n), ref_txfrm => ref_txfrm(n), + rx_status => ref_status, rx_rate => test_rate, tx_rate => test_rate, burst_run => test_run, @@ -158,7 +168,7 @@ uut_axi : entity work.config_stats_axi -- AXI-query state machine. -- Starting at rising edge of test_read, write once and then read --- 4*PORT_COUNT words. As we do so, cross-check results against +-- the entire result array. As we do so, cross-check results against -- the reference counter values. axi_araddr <= i2s(4 * test_arcount, ADDR_WIDTH); @@ -196,7 +206,7 @@ begin elsif (axi_arvalid = '1' and axi_arready = '1') then -- Read in progress; increment address as each command is accepted. -- Note: Read one word past end of array, to test handling. - if (test_arcount < 6*PORT_COUNT) then + if (test_arcount < TOTAL_AXI_WORDS) then axi_arvalid <= '1'; -- Read next word. test_arcount <= test_arcount + 1; else @@ -210,10 +220,10 @@ begin test_rcount <= 0; elsif (axi_rvalid = '0' or axi_rready = '0') then null; -- No new data this cycle. - elsif (test_rcount < 6*PORT_COUNT) then + elsif (test_rcount < TOTAL_AXI_WORDS) then -- Compare read data to the appropriate reference counter: - prt := test_rcount / 6; - case (test_rcount mod 6) is + prt := test_rcount / 8; + case (test_rcount mod 8) is when 0 => assert(u2i(axi_rdata) = ref_bcbyte(prt)) report "RxBcast-Bytes mismatch" severity error; when 1 => assert(u2i(axi_rdata) = ref_bcfrm(prt)) @@ -226,6 +236,10 @@ begin report "TxTot-Bytes mismatch" severity error; when 5 => assert(u2i(axi_rdata) = ref_txfrm(prt)) report "TxTot-Frames mismatch" severity error; + when 6 => assert(u2i(axi_rdata) = 0) + report "Rsvd mismatch" severity error; + when 7 => assert(u2i(axi_rdata) = test_index) + report "Status mismatch" severity error; when others => null; end case; -- Increment read counter. @@ -234,7 +248,7 @@ begin -- Reading past end of array? assert (u2i(axi_rdata) = 0) report "Read past end of array should return zero." severity error; - assert (test_rcount <= 6*PORT_COUNT) + assert (test_rcount <= TOTAL_AXI_WORDS) report "Unexpected read data." severity error; -- Increment read counter. test_rcount <= test_rcount + 1; @@ -310,25 +324,24 @@ begin -- Byte received, add it to the shift register. uart_sreg := uart_sreg(23 downto 0) & uart_rxbyte; -- Compare each received word against reference. - if ((test_ucount mod 4) = 3) then - word_idx := (test_ucount - 3) / 4; - port_idx := word_idx / 6; - case (word_idx mod 6) is - when 0 => assert(u2i(uart_sreg) = ref_bcbyte(port_idx)) - report "RxBcast-Bytes mismatch" severity error; - when 1 => assert(u2i(uart_sreg) = ref_bcfrm(port_idx)) - report "RxBcast-Frames mismatch" severity error; - when 2 => assert(u2i(uart_sreg) = ref_rxbyte(port_idx)) - report "RxTot-Bytes mismatch" severity error; - when 3 => assert(u2i(uart_sreg) = ref_rxfrm(port_idx)) - report "RxTot-Frames mismatch" severity error; - when 4 => assert(u2i(uart_sreg) = ref_txbyte(port_idx)) - report "TxTot-Bytes mismatch" severity error; - when 5 => assert(u2i(uart_sreg) = ref_txfrm(port_idx)) - report "TxTot-Frames mismatch" severity error; - when others => null; - end case; - end if; + port_idx := test_ucount / 25; + case test_ucount is + when 3 => assert(u2i(uart_sreg) = ref_bcbyte(port_idx)) + report "RxBcast-Bytes mismatch" severity error; + when 7 => assert(u2i(uart_sreg) = ref_bcfrm(port_idx)) + report "RxBcast-Frames mismatch" severity error; + when 11 => assert(u2i(uart_sreg) = ref_rxbyte(port_idx)) + report "RxTot-Bytes mismatch" severity error; + when 15 => assert(u2i(uart_sreg) = ref_rxfrm(port_idx)) + report "RxTot-Frames mismatch" severity error; + when 19 => assert(u2i(uart_sreg) = ref_txbyte(port_idx)) + report "TxTot-Bytes mismatch" severity error; + when 23 => assert(u2i(uart_sreg) = ref_txfrm(port_idx)) + report "TxTot-Frames mismatch" severity error; + when 24 => assert(u2i(uart_rxbyte) = test_index) + report "Status mismatch" severity error; + when others => null; + end case; test_ucount <= test_ucount + 1; end if; @@ -339,8 +352,8 @@ end process; -- High-level test control. test_wdone <= and_reduce(txrx_done); -test_rdone <= bool2bit(test_rcount >= 6*PORT_COUNT + 1) - and bool2bit(test_ucount >= 24*PORT_COUNT); +test_rdone <= bool2bit(test_rcount >= TOTAL_AXI_WORDS + 1) + and bool2bit(test_ucount >= TOTAL_UART_BYTES); p_test : process procedure run_test(rate : real) is diff --git a/sim/vhdl/eth_all8b10b_tb.vhd b/sim/vhdl/eth_all8b10b_tb.vhd index a651b2d..7efe37e 100644 --- a/sim/vhdl/eth_all8b10b_tb.vhd +++ b/sim/vhdl/eth_all8b10b_tb.vhd @@ -228,6 +228,7 @@ u_amble : entity work.eth_preamble_rx raw_data => dec_data, raw_dv => dec_dv, raw_err => dec_err, + status => (others => '0'), rx_data => out_port); -- Reference data checking and raw stream inspection. @@ -243,8 +244,9 @@ p_check : process(clk_125) return count; end function; - variable wd, rd : integer := 0; - variable wtemp : std_logic_vector(5 downto 0) := (others => '0'); + variable wd, rd : integer := 0; + variable rxerr_d : std_logic := '0'; + variable wtemp : std_logic_vector(5 downto 0) := (others => '0'); begin if rising_edge(clk_125) then -- Inspect encoded token stream. @@ -277,8 +279,13 @@ begin assert (out_port.last = ref_last) report "Last mismatch" severity error; end if; - assert (test_txen = '0' or out_port.rxerr = '0') - report "Unexpected error strobe" severity error; + + -- Watch for rising-edge of the error signal. + if (out_port.rxerr = '1' and rxerr_d = '0') then + assert (test_txen = '0') + report "Unexpected error strobe" severity error; + end if; + rxerr_d := out_port.rxerr; end if; end process; @@ -298,7 +305,7 @@ p_test : process wait until rising_edge(clk_125); -- Wait for decoder unlock. - timeout := integer(round(1000.0 / rate)); + timeout := integer(round(10000.0 / rate)); while (dec_lock = '1' and timeout > 0) loop wait until rising_edge(clk_125); timeout := timeout - 1; @@ -309,7 +316,7 @@ p_test : process wait until rising_edge(clk_125); -- Wait for decoder lock. - timeout := integer(round(1000.0 / rate)); + timeout := integer(round(10000.0 / rate)); while (cfg_rcvd = '0' and timeout > 0) loop wait until rising_edge(clk_125); timeout := timeout - 1; diff --git a/sim/vhdl/eth_pause_ctrl_tb.vhd b/sim/vhdl/eth_pause_ctrl_tb.vhd index f1c0e84..892a5fa 100644 --- a/sim/vhdl/eth_pause_ctrl_tb.vhd +++ b/sim/vhdl/eth_pause_ctrl_tb.vhd @@ -180,6 +180,7 @@ port_rx.last <= in_last; port_rx.write <= in_write; port_rx.rxerr <= '0'; port_rx.rate <= get_rate_word(test_prate); +port_rx.status <= (others => '0'); port_rx.reset_p <= reset_p; uut : entity work.eth_pause_ctrl diff --git a/sim/vhdl/eth_traffic_sim.vhd b/sim/vhdl/eth_traffic_sim.vhd index 5d052cd..c72ef7b 100644 --- a/sim/vhdl/eth_traffic_sim.vhd +++ b/sim/vhdl/eth_traffic_sim.vhd @@ -100,6 +100,7 @@ begin out_port.clk <= clk after CLK_DELAY; out_port.reset_p <= reset_p; out_port.rate <= get_rate_word(1000); +out_port.status <= (others => '0'); out_port.rxerr <= '0'; out_port.data <= out_data; out_port.write <= out_valid_i and out_ready; diff --git a/sim/vhdl/port_inline_status_tb.vhd b/sim/vhdl/port_inline_status_tb.vhd index e56c3ed..a48fe1f 100644 --- a/sim/vhdl/port_inline_status_tb.vhd +++ b/sim/vhdl/port_inline_status_tb.vhd @@ -76,6 +76,7 @@ signal net_tx_ctrl : port_tx_s2m; -- Frame-check sequence signal lcl_tx_write : std_logic; +signal lcl_tx_status : port_status_t; signal net_tx_write : std_logic; signal out_eg_data : byte_t; signal out_eg_write : std_logic; @@ -119,6 +120,7 @@ u_gen_eg : entity work.eth_traffic_sim out_port.last => lcl_tx_data.last, out_port.write => lcl_tx_write, out_port.rate => lcl_tx_rate, + out_port.status => lcl_tx_status, out_port.rxerr => net_tx_ctrl.txerr, out_port.reset_p => net_tx_ctrl.reset_p, out_bcount => open, @@ -141,6 +143,7 @@ u_gen_ig : entity work.eth_traffic_sim out_port.last => net_rx_data.last, out_port.write => net_rx_data.write, out_port.rate => net_rx_data.rate, + out_port.status => net_rx_data.status, out_port.rxerr => net_rx_data.rxerr, out_port.reset_p => net_rx_data.reset_p, out_bcount => open, diff --git a/sim/vhdl/port_sgmii_common_tb.vhd b/sim/vhdl/port_sgmii_common_tb.vhd index f3f5d99..195a86a 100644 --- a/sim/vhdl/port_sgmii_common_tb.vhd +++ b/sim/vhdl/port_sgmii_common_tb.vhd @@ -118,6 +118,8 @@ u_src_b2a : entity work.port_test_common -- Two units under test, connected back-to-back. uut_a : entity work.port_sgmii_common + generic map( + SHAKE_WAIT => true) port map( tx_clk => clk_125, tx_data => sgmii_a2b, @@ -131,6 +133,8 @@ uut_a : entity work.port_sgmii_common reset_p => reset_p); uut_b : entity work.port_sgmii_common + generic map( + SHAKE_WAIT => true) port map( tx_clk => clk_125, tx_data => sgmii_b2a, diff --git a/sim/vhdl/port_statistics_tb.vhd b/sim/vhdl/port_statistics_tb.vhd index ed80844..e20eb07 100644 --- a/sim/vhdl/port_statistics_tb.vhd +++ b/sim/vhdl/port_statistics_tb.vhd @@ -66,6 +66,8 @@ signal tot_tx_byte : counter_t := (others => '0'); signal tot_tx_frm : counter_t := (others => '0'); signal ref_rx_byte : counter_t := (others => '0'); signal ref_tx_byte : counter_t := (others => '0'); +signal uut_status : port_status_t; +signal ref_status : port_status_t := (others => '0'); -- Test control. signal test_index : integer := 0; @@ -88,6 +90,17 @@ p_src : process(clk_100) variable seed2 : positive := 7861970; variable rand : real := 0.0; + -- Generate a random status word. + impure function rand_status return port_status_t is + variable tmp : port_status_t; + begin + for n in tmp'range loop + uniform(seed1, seed2, rand); + tmp(n) := bool2bit(rand < 0.5); + end loop; + return tmp; + end function; + -- Generate frame lengths from 8 - 64 bytes. impure function rand_len return integer is begin @@ -100,6 +113,11 @@ p_src : process(clk_100) variable rx_brem, rx_frem : integer := 0; begin if rising_edge(clk_100) then + -- Randomize status at the start of each test. + if (test_start = '1') then + ref_status <= rand_status; + end if; + -- Randomize length at the start of each new frame, -- and keep track of the total statistics. if (test_start = '1') then @@ -159,6 +177,8 @@ end process; rx_data.clk <= clk_100; rx_data.data <= (others => '0'); rx_data.rxerr <= '0'; +rx_data.rate <= get_rate_word(1000); +rx_data.status <= ref_status; rx_data.reset_p <= reset_p; tx_data.data <= (others => '0'); @@ -176,6 +196,8 @@ uut : entity work.port_statistics rcvd_frames => uut_rx_frm, sent_bytes => uut_tx_byte, sent_frames => uut_tx_frm, + status_clk => clk_100, + status_word => uut_status, rx_data => rx_data, tx_data => tx_data, tx_ctrl => tx_ctrl); @@ -252,6 +274,8 @@ p_test : process assert (tot_tx_frm = test_frames) report "Tx frame mismatch: got " & u2str(tot_tx_frm) & ", expected " & integer'image(test_frames) severity error; + assert (uut_status = ref_status) + report "Status-word mismatch." severity error; end procedure; begin -- Wait for reset. diff --git a/src/vhdl/common/config_stats_axi.vhd b/src/vhdl/common/config_stats_axi.vhd index d69b266..4ce919c 100644 --- a/src/vhdl/common/config_stats_axi.vhd +++ b/src/vhdl/common/config_stats_axi.vhd @@ -27,13 +27,17 @@ -- counters. (The write address and write value are ignored.) -- -- Once refreshed, each register reports total observed traffic since --- the previous refresh. There are six registers for each port: +-- the previous refresh. There are eight registers for each port: -- * Broadcast bytes received (from device to switch) -- * Broadcast frames received -- * Total bytes received (from device to switch) -- * Total frames received -- * Total bytes sent (from switch to device) -- * Total frames sent +-- * Reserved +-- * Link-status reporting: +-- Bits 31..08: Reserved +-- Bits 07..00: Port status word -- The register map is a consecutive array of 32-bit words (uint32_t), -- starting from the specified base address (default zero). -- The first six registers are for port 0, the next six for port 1, @@ -51,6 +55,7 @@ entity config_stats_axi is generic ( PORT_COUNT : integer; COUNT_WIDTH : natural := 32; -- Internal counter width (16-32 bits) + SAFE_COUNT : boolean := true; -- Safe counters (no overflow) ADDR_WIDTH : natural := 32; -- AXI-Lite address width BASE_ADDR : natural := 0); -- Base address (see above) port ( @@ -84,7 +89,8 @@ end config_stats_axi; architecture config_stats_axi of config_stats_axi is -- Statistics module for each port. -constant WORD_COUNT : natural := 6 * PORT_COUNT; +constant WORD_MULT : natural := 8; +constant WORD_COUNT : natural := WORD_MULT * PORT_COUNT; subtype stat_word is unsigned(COUNT_WIDTH-1 downto 0); type stats_array_t is array(WORD_COUNT-1 downto 0) of stat_word; signal stats_req_t : std_logic := '0'; @@ -94,6 +100,10 @@ signal stats_array : stats_array_t := (others => (others => '0')); constant SUB_ADDR_WIDTH : natural := log2_ceil(WORD_COUNT); subtype sub_addr_t is unsigned(SUB_ADDR_WIDTH-1 downto 0); +-- Write state machine. +signal wr_awready : std_logic; +signal wr_pending : std_logic := '0'; + -- FIFO for read commands. signal araddr_trim : sub_addr_t; signal fifo_rdraw : std_logic_vector(SUB_ADDR_WIDTH-1 downto 0); @@ -112,32 +122,53 @@ begin -- Statistics module for each port. gen_stats : for n in 0 to PORT_COUNT-1 generate - u_stats : entity work.port_statistics - generic map(COUNT_WIDTH => COUNT_WIDTH) - port map( - stats_req_t => stats_req_t, - bcst_bytes => stats_array(6*n+0), - bcst_frames => stats_array(6*n+1), - rcvd_bytes => stats_array(6*n+2), - rcvd_frames => stats_array(6*n+3), - sent_bytes => stats_array(6*n+4), - sent_frames => stats_array(6*n+5), - rx_data => rx_data(n), - tx_data => tx_data(n), - tx_ctrl => tx_ctrl(n)); + blk_stats : block + signal status : port_status_t; + begin + -- Words 0-5 come directly from the statistics block. + u_stats : entity work.port_statistics + generic map( + COUNT_WIDTH => COUNT_WIDTH, + SAFE_COUNT => SAFE_COUNT) + port map( + stats_req_t => stats_req_t, + bcst_bytes => stats_array(WORD_MULT*n+0), + bcst_frames => stats_array(WORD_MULT*n+1), + rcvd_bytes => stats_array(WORD_MULT*n+2), + rcvd_frames => stats_array(WORD_MULT*n+3), + sent_bytes => stats_array(WORD_MULT*n+4), + sent_frames => stats_array(WORD_MULT*n+5), + status_clk => axi_clk, + status_word => status, + rx_data => rx_data(n), + tx_data => tx_data(n), + tx_ctrl => tx_ctrl(n)); + + -- Word 6 is reserved, 7 is for status flags. + stats_array(WORD_MULT*n+6) <= (others => '0'); + stats_array(WORD_MULT*n+7) <= resize(unsigned(status), COUNT_WIDTH); + end block; end generate; -- AXI-Write to any address toggles the "request" signal. -axi_awready <= '1'; -- Always ready to accept address (request-toggle) +-- (One write command at a time, wait for response to be accepted.) +wr_awready <= axi_bready or not wr_pending; +axi_awready <= wr_awready; axi_wready <= '1'; -- Always ready to accept data (ignored) axi_bresp <= "00"; -- Always respond with "OK" -axi_bvalid <= '1'; +axi_bvalid <= wr_pending; -p_axi_wr : process(axi_clk) +p_axi_wr : process(axi_clk, axi_aresetn) begin - if rising_edge(axi_clk) then - if (axi_awvalid = '1') then + if (axi_aresetn = '0') then + wr_pending <= '0'; + stats_req_t <= '0'; + elsif rising_edge(axi_clk) then + if (axi_awvalid = '1' and wr_awready = '1') then + wr_pending <= '1'; -- Command accepted stats_req_t <= not stats_req_t; + elsif (axi_bready = '1') then + wr_pending <= '0'; -- Response consumed end if; end if; end process; diff --git a/src/vhdl/common/config_stats_uart.vhd b/src/vhdl/common/config_stats_uart.vhd index 71abff2..77b258d 100644 --- a/src/vhdl/common/config_stats_uart.vhd +++ b/src/vhdl/common/config_stats_uart.vhd @@ -34,7 +34,9 @@ -- * Total frames received -- * Total bytes sent (from switch to device) -- * Total frames sent --- Each field is a big-endian 32-bit unsigned integer (i.e., uint32_t). +-- * Port status word (one byte) +-- Each field is a big-endian 32-bit unsigned integer (i.e., uint32_t), +-- except the status word, which is a single byte. -- library ieee; @@ -48,6 +50,7 @@ entity config_stats_uart is generic ( PORT_COUNT : integer; COUNT_WIDTH : natural := 32; -- Internal counter width (16-32 bits) + SAFE_COUNT : boolean := true; -- Safe counters (no overflow) BAUD_HZ : natural := 921_600; -- UART baud rate (Hz) REFCLK_HZ : natural := 100_000_000); -- Reference clock freq. (Hz) port ( @@ -68,9 +71,10 @@ architecture config_stats_uart of config_stats_uart is -- Special index 255 indicates a query to all ports. constant CMD_ALL : byte_t := (others => '1'); --- Each report is a total of 6 words = 24 bytes. -constant BYTE_COUNT : natural := 4 * 6; -constant WORD_TOTAL : natural := 6 * PORT_COUNT; +-- Each report is a total of N words + status = 25 bytes. +constant WORD_COUNT : positive := 6; +constant BYTE_COUNT : positive := 4 * WORD_COUNT + 1; +constant WORD_TOTAL : positive := WORD_COUNT * PORT_COUNT; -- Return Nth byte, counting from MSB. subtype stat_report is unsigned(8*BYTE_COUNT-1 downto 0); @@ -86,6 +90,8 @@ end function; -- Statistics module for each port. subtype stat_word is unsigned(COUNT_WIDTH-1 downto 0); type stats_array_t is array(WORD_TOTAL-1 downto 0) of stat_word; +type status_array_t is array(PORT_COUNT-1 downto 0) of port_status_t; +signal flag_array : status_array_t; signal stats_req_t : std_logic_vector(PORT_COUNT-1 downto 0) := (others => '0'); signal stats_array : stats_array_t := (others => (others => '0')); signal stats_zpad : stat_report; @@ -99,11 +105,11 @@ signal cmd_data : byte_t; signal cmd_valid : std_logic; signal cmd_read : std_logic; signal cmd_last : std_logic; -signal cmd_pindex : integer range 0 to PORT_COUNT-1 := 0; -signal cmd_bindex : integer range 0 to BYTE_COUNT-1 := 0; +signal cmd_pindex : integer range 0 to PORT_COUNT-1 := 0; +signal cmd_bindex : integer range 0 to BYTE_COUNT-1 := 0; -- Transmit UART. -signal uart_txdata : byte_t; +signal uart_txdata : byte_t; signal uart_txlast : std_logic; signal uart_txvalid : std_logic := '0'; signal uart_txready : std_logic; @@ -114,15 +120,19 @@ begin gen_stats : for n in 0 to PORT_COUNT-1 generate -- Instantiate module for this port. u_stats : entity work.port_statistics - generic map(COUNT_WIDTH => COUNT_WIDTH) + generic map( + COUNT_WIDTH => COUNT_WIDTH, + SAFE_COUNT => SAFE_COUNT) port map( stats_req_t => stats_req_t(n), - bcst_bytes => stats_array(6*n+0), - bcst_frames => stats_array(6*n+1), - rcvd_bytes => stats_array(6*n+2), - rcvd_frames => stats_array(6*n+3), - sent_bytes => stats_array(6*n+4), - sent_frames => stats_array(6*n+5), + bcst_bytes => stats_array(WORD_COUNT*n+0), + bcst_frames => stats_array(WORD_COUNT*n+1), + rcvd_bytes => stats_array(WORD_COUNT*n+2), + rcvd_frames => stats_array(WORD_COUNT*n+3), + sent_bytes => stats_array(WORD_COUNT*n+4), + sent_frames => stats_array(WORD_COUNT*n+5), + status_clk => refclk, + status_word => flag_array(n), rx_data => rx_data(n), tx_data => tx_data(n), tx_ctrl => tx_ctrl(n)); @@ -213,12 +223,13 @@ begin end process; -- Zero-pad counters to fixed 32-bit width, then concatentate. -stats_zpad <= resize(stats_array(6*cmd_pindex+0), 32) - & resize(stats_array(6*cmd_pindex+1), 32) - & resize(stats_array(6*cmd_pindex+2), 32) - & resize(stats_array(6*cmd_pindex+3), 32) - & resize(stats_array(6*cmd_pindex+4), 32) - & resize(stats_array(6*cmd_pindex+5), 32); +stats_zpad <= resize(stats_array(WORD_COUNT*cmd_pindex+0), 32) + & resize(stats_array(WORD_COUNT*cmd_pindex+1), 32) + & resize(stats_array(WORD_COUNT*cmd_pindex+2), 32) + & resize(stats_array(WORD_COUNT*cmd_pindex+3), 32) + & resize(stats_array(WORD_COUNT*cmd_pindex+4), 32) + & resize(stats_array(WORD_COUNT*cmd_pindex+5), 32) + & unsigned(flag_array(cmd_pindex)); -- Combinational logic to select each output byte: uart_txdata <= get_stat_byte(stats_zpad, cmd_bindex); diff --git a/src/vhdl/common/eth_dec8b10b.vhd b/src/vhdl/common/eth_dec8b10b.vhd index 22efebb..3ab337a 100644 --- a/src/vhdl/common/eth_dec8b10b.vhd +++ b/src/vhdl/common/eth_dec8b10b.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019 The Aerospace Corporation +-- Copyright 2019, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -38,6 +38,10 @@ -- http://standards.ieee.org/getieee802/802.3.html -- https://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=7428774 -- +-- Error reporting can be operated in strict mode, in which every decode +-- error fires the error strobe; or in filtered mode, in which the error +-- strobe is reserved for loss-of-lock or repeated decode errors. +-- library ieee; use ieee.std_logic_1164.all; @@ -45,6 +49,8 @@ use ieee.numeric_std.all; use work.common_functions.all; entity eth_dec8b10b is + generic ( + ERR_STRICT : boolean := false); -- Report every decode error port ( -- Input stream io_clk : in std_logic; -- Data clock @@ -71,6 +77,7 @@ signal align_sreg_d : std_logic_vector(18 downto 0) := (others => '0'); signal align_sreg_q : std_logic_vector(8 downto 0) := (others => '0'); signal align_data : std_logic_vector(9 downto 0) := (others => '0'); signal align_cken : std_logic := '0'; +signal align_error : std_logic := '0'; signal align_lock : std_logic := '0'; signal align_bit : integer range 0 to 9 := 0; @@ -84,8 +91,8 @@ signal lookup_3b : std_logic_vector(2 downto 0) := (others => '0'); signal lookup_err : std_logic := '0'; signal lookup_sof : std_logic := '0'; --- Filter out isolated lookup errors. -signal filter_err : std_logic := '0'; +-- Error reporting +signal err_strobe : std_logic := '0'; -- Packet encapsulation and configuration metadata. signal pkt_active : std_logic := '0'; @@ -102,8 +109,11 @@ begin align_sreg_d <= align_sreg_q & in_data; -- MSB first p_align : process(io_clk) - constant WINDOW_THRESH : positive := 7; -- Minimum matches to lock - constant WINDOW_PENALTY : positive := 3; -- Weight for misaligned commas + -- Note: Increasing time-to-lock can result in autonegotiation failure of + -- some MAC-to-PHY SGMII links. Selected threshold is compatible + -- with all tested PHYs but still tolerates transient glitches. + constant WINDOW_THRESH : positive := 31; -- Minimum matches to lock + constant WINDOW_PENALTY : positive := 2; -- Weight for misaligned commas variable comma_temp : std_logic_vector(6 downto 0) := (others => '0'); variable comma_detect : std_logic_vector(9 downto 0) := (others => '0'); variable comma_error : std_logic_vector(9 downto 0) := (others => '0'); @@ -118,8 +128,10 @@ begin align_cken <= in_cken; -- Update alignment-check state machine. - if (in_lock = '0' or filter_err = '1') then + align_error <= '0'; + if (in_lock = '0') then -- Reset due to upstream errors or major downstream errors. + align_error <= align_lock; align_lock <= '0'; align_bit <= 0; align_count := 0; @@ -130,6 +142,8 @@ begin align_count := align_count - WINDOW_PENALTY; else -- Unlock, then move to next phase hypothesis. + -- (Error strobe if we were already locked.) + align_error <= align_lock; align_lock <= '0'; align_count := 0; if (align_bit = 9) then @@ -172,7 +186,7 @@ p_decode : process(io_clk) begin if rising_edge(io_clk) then -- Simple delay for clock-enable signal. - lookup_cken <= align_lock and align_cken; + lookup_cken <= align_cken; -- Explicit detection for all twelve control codes. if (align_6b = "001111" or align_6b = "110000" -- K28.x @@ -326,26 +340,30 @@ begin end if; end process; --- Filter out occasional lookup errors using a running danger score: --- * Every good frame decrements danger level by one. --- * Every lookup error increments danger level by N. --- * Raise alarm if the danger level ever exceeds threshold. +-- Error reporting for lost-lock and decode errors. p_filter : process(io_clk) constant PENALTY : positive := 30; variable danger : unsigned(7 downto 0) := (others => '0'); begin if rising_edge(io_clk) then - -- Keep a running tally of the warning level: - -- * Every good frame decrements by 1 - -- * Every error increments by N - -- If the warning level exceeds a threshold, declare error. - filter_err <= bool2bit(danger > 200); - if (align_lock = '0') then - danger := (others => '0'); - elsif (lookup_cken = '1' and lookup_err = '1') then - danger := danger + PENALTY; + -- Detect errors of various types: + if (align_error = '1') then + err_strobe <= '1'; -- Loss-of-lock is always reported + elsif (ERR_STRICT and lookup_err = '1') then + err_strobe <= '1'; -- Strict mode: Report every decode error + elsif (danger > 200) then + err_strobe <= '1'; -- Relaxed mode: Too many decode errors + elsif (lookup_cken = '1') then + err_strobe <= '0'; -- Sustain error strobe until next clock-enable. + end if; + + -- For filtered mode, keep a running tally of the warning level: + if (ERR_STRICT or align_lock = '0') then + danger := (others => '0'); -- Disabled or reset + elsif (lookup_err = '1') then + danger := danger + PENALTY; -- Every decode error increments by N elsif (lookup_cken = '1' and lookup_sof = '1' and danger > 0) then - danger := danger - 1; + danger := danger - 1; -- Every good frame decrements by 1 end if; end if; end process; @@ -354,7 +372,7 @@ end process; out_lock <= align_lock; out_cken <= lookup_cken; out_dv <= pkt_active and not lookup_ctrl; -out_err <= filter_err; +out_err <= err_strobe; out_data <= lookup_3b & lookup_5b; cfg_rcvd <= cfg_rcvd_i; cfg_word <= cfg_word_i; diff --git a/src/vhdl/common/eth_preambles.vhd b/src/vhdl/common/eth_preambles.vhd index 731b74e..024e59b 100644 --- a/src/vhdl/common/eth_preambles.vhd +++ b/src/vhdl/common/eth_preambles.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019, 2020 The Aerospace Corporation +-- Copyright 2019, 2020, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -32,6 +32,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +use work.common_functions.all; use work.switch_types.all; entity eth_preamble_rx is @@ -47,9 +48,12 @@ entity eth_preamble_rx is raw_dv : in std_logic; -- Data valid raw_err : in std_logic; -- Error flag - -- Additional error strobe + -- Additional error strobe (optional) aux_err : in std_logic := '0'; + -- Diagnostic status signals + status : in port_status_t; + -- Generic internal port interface. rx_data : out port_rx_m2s); end eth_preamble_rx; @@ -60,6 +64,7 @@ signal out_en : std_logic := '0'; signal reg_data : std_logic_vector(7 downto 0) := (others => '0'); signal reg_dv : std_logic := '0'; signal reg_err : std_logic := '0'; +signal err_dlyct : unsigned(2 downto 0) := (others => '0'); begin @@ -68,8 +73,9 @@ rx_data.reset_p <= not raw_lock; rx_data.data <= reg_data; rx_data.write <= raw_cken and reg_dv and out_en; rx_data.last <= raw_cken and reg_dv and not raw_dv; -rx_data.rxerr <= (raw_cken and reg_err) or aux_err; +rx_data.rxerr <= bool2bit(err_dlyct > 0); rx_data.rate <= get_rate_word(RATE_MBPS); +rx_data.status <= status; p_rx : process(raw_clk) begin @@ -95,6 +101,13 @@ begin reg_err <= raw_err; end if; end if; + + -- Sustain async error strobe for a few clock-cycles. + if (aux_err = '1' or reg_err = '1') then + err_dlyct <= (others => '1'); + elsif (err_dlyct > 0) then + err_dlyct <= err_dlyct - 1; + end if; end if; end process; diff --git a/src/vhdl/common/port_adapter.vhd b/src/vhdl/common/port_adapter.vhd index aac072d..3bc9776 100644 --- a/src/vhdl/common/port_adapter.vhd +++ b/src/vhdl/common/port_adapter.vhd @@ -56,6 +56,7 @@ begin sw_rx_data.clk <= mac_rx_data.clk; sw_rx_data.rxerr <= mac_rx_data.rxerr; sw_rx_data.rate <= mac_rx_data.rate; +sw_rx_data.status <= mac_rx_data.status; sw_rx_data.reset_p <= mac_rx_data.reset_p; sw_tx_ctrl.clk <= mac_tx_ctrl.clk; sw_tx_ctrl.txerr <= mac_tx_ctrl.txerr; diff --git a/src/vhdl/common/port_axi_mailbox.vhd b/src/vhdl/common/port_axi_mailbox.vhd index 0e74cdc..3aef5da 100644 --- a/src/vhdl/common/port_axi_mailbox.vhd +++ b/src/vhdl/common/port_axi_mailbox.vhd @@ -166,6 +166,7 @@ begin rx_data.clk <= axi_clk; rx_data.rxerr <= '0'; rx_data.rate <= get_rate_word(1); +rx_data.status <= (0 => port_reset_p, others => '0'); rx_data.reset_p <= port_reset_p; tx_ctrl.clk <= axi_clk; diff --git a/src/vhdl/common/port_crosslink.vhd b/src/vhdl/common/port_crosslink.vhd index 9287de0..2745575 100644 --- a/src/vhdl/common/port_crosslink.vhd +++ b/src/vhdl/common/port_crosslink.vhd @@ -76,6 +76,7 @@ begin rxa_data.clk <= ref_clk; rxa_data.rxerr <= '0'; rxa_data.rate <= get_rate_word(1000 / RATE_DIV); +rxa_data.status <= (0 => reset_sync, others => '0'); rxa_data.reset_p <= reset_sync; rxa_data.write <= rxa_data_valid and xfer_ready; @@ -86,6 +87,7 @@ txa_ctrl.reset_p <= reset_sync; rxb_data.clk <= ref_clk; rxb_data.rxerr <= '0'; rxb_data.rate <= get_rate_word(1000 / RATE_DIV); +rxb_data.status <= (others => '0'); rxb_data.reset_p <= reset_sync; rxb_data.write <= rxb_data_valid and xfer_ready; diff --git a/src/vhdl/common/port_gmii_internal.vhd b/src/vhdl/common/port_gmii_internal.vhd index 70e7d8c..d2ededf 100644 --- a/src/vhdl/common/port_gmii_internal.vhd +++ b/src/vhdl/common/port_gmii_internal.vhd @@ -80,6 +80,8 @@ signal rxdv, rxerr : std_logic; signal reset_sync : std_logic; -- Reset sync'd to clk_125 +signal status_word : port_status_t; + begin -- Synchronize the external reset signal. @@ -103,6 +105,9 @@ rxdata <= gmii_rxd; rxdv <= gmii_rxdv; rxerr <= gmii_rxerr; +-- Status-reporting +status_word <= (0 => reset_sync, others => '0'); + -- Receive state machine, including preamble removal. u_amble_rx : entity work.eth_preamble_rx generic map( @@ -114,6 +119,7 @@ u_amble_rx : entity work.eth_preamble_rx raw_data => rxdata, raw_dv => rxdv, raw_err => rxerr, + status => status_word, rx_data => rx_data); -- Transmit state machine, including insertion of preamble, diff --git a/src/vhdl/common/port_inline_status.vhd b/src/vhdl/common/port_inline_status.vhd index fcc507f..a588b3f 100644 --- a/src/vhdl/common/port_inline_status.vhd +++ b/src/vhdl/common/port_inline_status.vhd @@ -97,6 +97,7 @@ lcl_rx_data.last <= ig_main_out.last; lcl_rx_data.write <= ig_main_out.valid; lcl_rx_data.rxerr <= net_rx_data.rxerr or ig_err_fifo or ig_err_inj; lcl_rx_data.rate <= net_rx_data.rate; +lcl_rx_data.status <= net_rx_data.status; lcl_rx_data.reset_p <= ig_reset_p; ig_main_out.ready <= '1'; diff --git a/src/vhdl/common/port_nullsink.vhd b/src/vhdl/common/port_nullsink.vhd index 3c583a5..3767601 100644 --- a/src/vhdl/common/port_nullsink.vhd +++ b/src/vhdl/common/port_nullsink.vhd @@ -51,6 +51,7 @@ rx_data.last <= '0'; rx_data.write <= '0'; rx_data.rxerr <= '0'; rx_data.rate <= get_rate_word(1000); +rx_data.status <= (0 => reset_p, others => '0'); rx_data.reset_p <= reset_p; tx_ctrl.clk <= refclk; diff --git a/src/vhdl/common/port_rgmii.vhd b/src/vhdl/common/port_rgmii.vhd index 22945e2..92e2bb6 100644 --- a/src/vhdl/common/port_rgmii.vhd +++ b/src/vhdl/common/port_rgmii.vhd @@ -101,6 +101,8 @@ signal rxdiv_s : std_logic; -- Strobe in clk_125 domain signal reset_sync : std_logic; -- Reset sync'd to clk_125 +signal status_word : port_status_t; + begin -- Synchronize the external reset signal. @@ -240,6 +242,12 @@ begin end if; end process; +-- Upstream status reporting. +status_word <= ( + 0 => reset_sync, + 1 => rxlock, + others => '0'); + -- Receive state machine, including preamble removal. u_amble_rx : entity work.eth_preamble_rx generic map( @@ -251,6 +259,7 @@ u_amble_rx : entity work.eth_preamble_rx raw_data => rxdata, raw_dv => rxdv, raw_err => rxerr, + status => status_word, rx_data => rx_data); -- Transmit state machine, including insertion of preamble, diff --git a/src/vhdl/common/port_rmii.vhd b/src/vhdl/common/port_rmii.vhd index 897c3d1..2b18438 100644 --- a/src/vhdl/common/port_rmii.vhd +++ b/src/vhdl/common/port_rmii.vhd @@ -84,6 +84,7 @@ signal rxclk_det : std_logic := '0'; -- Strobe in lock_refclk signal rxclk_halt : std_logic := '1'; -- Flat in lock_refclk -- All other control signals +signal status_word : port_status_t; signal rxclk : std_logic; signal txrx_halt : std_logic := '1'; signal txrx_lock, txrx_cken : std_logic := '0'; @@ -253,6 +254,14 @@ begin end if; end process; +-- Upstream status reporting. +status_word <= ( + 0 => reset_p, + 1 => rxclk_halt, + 2 => txrx_lock, + 3 => mode_fast, + others => '0'); + -- Preamble insertion and removal. u_amble_rx : entity work.eth_preamble_rx generic map( @@ -264,6 +273,7 @@ u_amble_rx : entity work.eth_preamble_rx raw_data => rx_byte, raw_dv => rx_bvalid, raw_err => rxerr, + status => status_word, rx_data => rx_data); u_amble_tx : entity work.eth_preamble_tx diff --git a/src/vhdl/common/port_serial_auto.vhd b/src/vhdl/common/port_serial_auto.vhd index b125140..41c8103 100644 --- a/src/vhdl/common/port_serial_auto.vhd +++ b/src/vhdl/common/port_serial_auto.vhd @@ -132,6 +132,7 @@ signal uart2_write : std_logic; -- Mode detection state machine. signal det_mode : mode_t := START_TYPE; signal est_rate : port_rate_t := (others => '0'); +signal status_word : port_status_t; signal lock_any : std_logic := '0'; signal lock_spi : std_logic := '0'; signal lock_uart1 : std_logic := '0'; @@ -152,11 +153,20 @@ begin -- Forward clock and reset signals. rx_data.clk <= refclk; rx_data.rate <= est_rate; +rx_data.status <= status_word; rx_data.reset_p <= codec_reset; tx_ctrl.clk <= refclk; tx_ctrl.reset_p <= codec_reset; tx_ctrl.txerr <= '0'; -- No error states +-- Upstream status reporting. +status_word <= ( + 0 => reset_sync, + 1 => lock_spi, + 2 => lock_uart1, + 3 => lock_uart2, + others => '0'); + -- Synchronize the external reset signal. u_rsync : sync_reset port map( diff --git a/src/vhdl/common/port_serial_spi_clkin.vhd b/src/vhdl/common/port_serial_spi_clkin.vhd index 19813e9..ef9c12d 100644 --- a/src/vhdl/common/port_serial_spi_clkin.vhd +++ b/src/vhdl/common/port_serial_spi_clkin.vhd @@ -87,6 +87,7 @@ begin -- Forward clock and reset signals. rx_data.clk <= refclk; rx_data.rate <= get_rate_word(10); +rx_data.status <= (0 => reset_sync, others => '0'); rx_data.reset_p <= reset_sync; tx_ctrl.clk <= refclk; tx_ctrl.reset_p <= wdog_rst_p; diff --git a/src/vhdl/common/port_serial_spi_clkout.vhd b/src/vhdl/common/port_serial_spi_clkout.vhd index df77fe9..39e00b7 100644 --- a/src/vhdl/common/port_serial_spi_clkout.vhd +++ b/src/vhdl/common/port_serial_spi_clkout.vhd @@ -89,6 +89,7 @@ begin -- Forward clock and reset signals. rx_data.clk <= refclk; rx_data.rate <= get_rate_word(clocks_per_baud(SPI_BAUD, 1_000_000)); +rx_data.status <= (0 => reset_p, others => '0'); rx_data.reset_p <= reset_sync; tx_ctrl.clk <= refclk; tx_ctrl.reset_p <= reset_sync; diff --git a/src/vhdl/common/port_serial_uart_2wire.vhd b/src/vhdl/common/port_serial_uart_2wire.vhd index 987f392..ffcbf9c 100644 --- a/src/vhdl/common/port_serial_uart_2wire.vhd +++ b/src/vhdl/common/port_serial_uart_2wire.vhd @@ -88,6 +88,7 @@ begin -- Forward clock and reset signals. rx_data.clk <= refclk; rx_data.rate <= get_rate_word(clocks_per_baud(BAUD_HZ, 1_000_000)); +rx_data.status <= (0 => reset_sync, others => '0'); rx_data.reset_p <= reset_sync; tx_ctrl.clk <= refclk; tx_ctrl.reset_p <= wdog_rst_p; diff --git a/src/vhdl/common/port_serial_uart_4wire.vhd b/src/vhdl/common/port_serial_uart_4wire.vhd index e6de003..3e71a8d 100644 --- a/src/vhdl/common/port_serial_uart_4wire.vhd +++ b/src/vhdl/common/port_serial_uart_4wire.vhd @@ -96,6 +96,7 @@ begin -- Forward clock and reset signals. rx_data.clk <= refclk; rx_data.rate <= get_rate_word(clocks_per_baud(BAUD_HZ, 1_000_000)); +rx_data.status <= (0 => reset_sync, others => '0'); rx_data.reset_p <= reset_sync; tx_ctrl.clk <= refclk; tx_ctrl.reset_p <= wdog_rst_p; diff --git a/src/vhdl/common/port_sgmii_common.vhd b/src/vhdl/common/port_sgmii_common.vhd index 78e000a..bf0b981 100644 --- a/src/vhdl/common/port_sgmii_common.vhd +++ b/src/vhdl/common/port_sgmii_common.vhd @@ -38,7 +38,7 @@ use work.synchronization.all; entity port_sgmii_common is generic ( - SHAKE_WAIT : boolean := true); -- Wait for MAC/PHY handshake? + SHAKE_WAIT : boolean := false); -- Wait for MAC/PHY handshake? port ( -- Transmitter/Serializer interface. tx_clk : in std_logic; -- 125 MHz typical @@ -81,9 +81,13 @@ signal rx_dec_lock : std_logic; signal rx_dec_cken : std_logic; signal rx_dec_dv : std_logic; signal rx_dec_err : std_logic; +signal rx_cfg_ack : std_logic; signal rx_cfg_rcvd : std_logic; signal rx_cfg_reg : std_logic_vector(15 downto 0); +-- Status reporting +signal status_word : port_status_t; + -- For debugging, apply KEEP constraint to certain signals. attribute KEEP : string; attribute KEEP of rx_dly_cken, rx_dly_lock, rx_dly_data : signal is "true"; @@ -91,6 +95,8 @@ attribute KEEP of rx_dly_cken, rx_dly_lock, rx_dly_data : signal is "true"; begin -- Clock domain transitions for specific config-register bits. +rx_cfg_ack <= rx_cfg_reg(14); + hs_cfg_ack : sync_buffer port map( in_flag => rx_cfg_rcvd, @@ -98,7 +104,7 @@ hs_cfg_ack : sync_buffer out_clk => tx_clk); hs_cfg_rcvd : sync_buffer port map( - in_flag => rx_cfg_reg(14), + in_flag => rx_cfg_ack, out_flag => tx_cfg_ack, out_clk => tx_clk); @@ -177,6 +183,17 @@ u_rxamb : entity work.eth_preamble_rx raw_data => rx_dec_data, raw_dv => rx_dec_dv, raw_err => rx_dec_err, + status => status_word, rx_data => prx_data); +-- Upstream status reporting. +status_word <= ( + 0 => reset_p, + 1 => rx_dly_lock, + 2 => rx_dec_lock, + 3 => rx_cfg_rcvd, + 4 => rx_cfg_ack, + 5 => tx_pkten, + others => '0'); + end port_sgmii_common; diff --git a/src/vhdl/common/port_statistics.vhd b/src/vhdl/common/port_statistics.vhd index 10ae64f..8faeead 100644 --- a/src/vhdl/common/port_statistics.vhd +++ b/src/vhdl/common/port_statistics.vhd @@ -41,6 +41,9 @@ -- to send once per second statistics on switch traffic for each port. -- It is also used inside config_stats_axi and config_stats_uart. -- +-- By default, counters saturate at 2^COUNT_WIDTH-1. This safety feature +-- can be disabled to assist with timing closure if needed. +-- library ieee; use ieee.std_logic_1164.all; @@ -51,7 +54,8 @@ use work.synchronization.all; entity port_statistics is generic ( - COUNT_WIDTH : integer := 32); -- Width of each statistics counter + COUNT_WIDTH : integer := 32; -- Width of each statistics counter + SAFE_COUNT : boolean := true); -- Safe counters (no overflow) port ( -- Statistics interface (bytes received/sent, frames received/sent stats_req_t : in std_logic; -- Toggle to request next block @@ -62,6 +66,10 @@ entity port_statistics is sent_bytes : out unsigned(COUNT_WIDTH-1 downto 0); sent_frames : out unsigned(COUNT_WIDTH-1 downto 0); + -- Port status-reporting. + status_clk : in std_logic; + status_word : out port_status_t; + -- Generic internal port interface (monitor only) rx_data : in port_rx_m2s; tx_data : in port_tx_m2s; @@ -71,8 +79,33 @@ end port_statistics; architecture port_statistics of port_statistics is subtype counter_t is unsigned(COUNT_WIDTH-1 downto 0); +constant COUNT_ZERO : counter_t := to_unsigned(0, COUNT_WIDTH); constant COUNT_ONE : counter_t := to_unsigned(1, COUNT_WIDTH); +-- Increment counter with polling. +function accumulator( + acc: counter_t; -- Accumulator value + inc: counter_t; -- Increment value + rst: std_logic; -- Global reset + rd: std_logic; -- Read/consume counter + en: std_logic) -- Increment enable + return counter_t is +begin + if (rst = '1') then + return COUNT_ZERO; -- Reset + elsif (rd = '1' and en = '0') then + return COUNT_ZERO; -- Consumed + elsif (rd = '1' and en = '1') then + return inc; -- Consumed + add + elsif (en = '1' and SAFE_COUNT) then + return saturate_add(acc, inc, COUNT_WIDTH); -- Safe add + elsif (en = '1') then + return acc + inc; -- Unsafe add + else + return acc; -- No change + end if; +end function; + -- Combinational logic for next-byte and last-byte strobes. signal rx_isff : std_logic; signal rx_clk, tx_clk : std_logic; @@ -109,15 +142,9 @@ rcvd_frames <= lat_rcvd_frames; sent_bytes <= lat_sent_bytes; sent_frames <= lat_sent_frames; --- Combinational logic for next-byte and last-byte strobes. --- (And clock reassignment, as a workaround for simulator bugs.) +-- Clock reassignment, as a workaround for simulator bugs. rx_clk <= rx_data.clk; -rx_isff <= bool2bit(rx_data.data = x"FF"); -rx_byte <= rx_data.write; -rx_last <= rx_data.write and rx_data.last; tx_clk <= tx_ctrl.clk; -tx_byte <= tx_data.valid and tx_ctrl.ready; -tx_last <= tx_data.valid and tx_ctrl.ready and tx_data.last; -- Receive clock domain. p_stats_rx : process(rx_clk) @@ -139,33 +166,14 @@ begin end if; -- Working counters are updated on each byte and each frame. - if (rx_data.reset_p = '1') then - wrk_rcvd_bytes <= (others => '0'); - wrk_rcvd_frames <= (others => '0'); - elsif (stats_req_rx = '1' and rx_last = '1') then - wrk_rcvd_bytes <= frm_bytes; - wrk_rcvd_frames <= COUNT_ONE; - elsif (stats_req_rx = '1') then - wrk_rcvd_bytes <= (others => '0'); - wrk_rcvd_frames <= (others => '0'); - elsif (stats_req_rx = '0' and rx_last = '1') then - wrk_rcvd_bytes <= saturate_add(wrk_rcvd_bytes, frm_bytes, COUNT_WIDTH); - wrk_rcvd_frames <= saturate_add(wrk_rcvd_frames, COUNT_ONE, COUNT_WIDTH); - end if; - - if (rx_data.reset_p = '1') then - wrk_bcst_bytes <= (others => '0'); - wrk_bcst_frames <= (others => '0'); - elsif (stats_req_rx = '1' and rx_last = '1' and is_bcast = '1') then - wrk_bcst_bytes <= frm_bytes; - wrk_bcst_frames <= COUNT_ONE; - elsif (stats_req_rx = '1') then - wrk_bcst_bytes <= (others => '0'); - wrk_bcst_frames <= (others => '0'); - elsif (stats_req_rx = '0' and rx_last = '1' and is_bcast = '1') then - wrk_bcst_bytes <= saturate_add(wrk_bcst_bytes, frm_bytes, COUNT_WIDTH); - wrk_bcst_frames <= saturate_add(wrk_bcst_frames, COUNT_ONE, COUNT_WIDTH); - end if; + wrk_rcvd_bytes <= accumulator( + wrk_rcvd_bytes, frm_bytes, rx_data.reset_p, stats_req_rx, rx_last); + wrk_rcvd_frames <= accumulator( + wrk_rcvd_frames, COUNT_ONE, rx_data.reset_p, stats_req_rx, rx_last); + wrk_bcst_bytes <= accumulator( + wrk_bcst_bytes, frm_bytes, rx_data.reset_p, stats_req_rx, rx_last and is_bcast); + wrk_bcst_frames <= accumulator( + wrk_bcst_frames, COUNT_ONE, rx_data.reset_p, stats_req_rx, rx_last and is_bcast); -- Detect broadcast frames (Destination-MAC = FF-FF-FF-FF-FF-FF). if (rx_data.reset_p = '1' or rx_last = '1') then @@ -180,6 +188,11 @@ begin elsif (rx_byte = '1') then frm_bytes := saturate_add(frm_bytes, COUNT_ONE, COUNT_WIDTH); end if; + + -- Buffer write-strobes for improved routing/timing. + rx_isff <= bool2bit(rx_data.data = x"FF"); + rx_byte <= rx_data.write; + rx_last <= rx_data.write and rx_data.last; end if; end process; @@ -198,19 +211,10 @@ begin end if; -- Working counters are updated on each byte and each frame. - if (tx_ctrl.reset_p = '1') then - wrk_sent_bytes <= (others => '0'); - wrk_sent_frames <= (others => '0'); - elsif (stats_req_tx = '1' and tx_last = '0') then - wrk_sent_bytes <= (others => '0'); - wrk_sent_frames <= (others => '0'); - elsif (stats_req_tx = '1' and tx_last = '1') then - wrk_sent_bytes <= frm_bytes; - wrk_sent_frames <= COUNT_ONE; - elsif (stats_req_tx = '0' and tx_last = '1') then - wrk_sent_bytes <= wrk_sent_bytes + frm_bytes; - wrk_sent_frames <= wrk_sent_frames + 1; - end if; + wrk_sent_bytes <= accumulator( + wrk_sent_bytes, frm_bytes, tx_ctrl.reset_p, stats_req_tx, tx_last); + wrk_sent_frames <= accumulator( + wrk_sent_frames, COUNT_ONE, tx_ctrl.reset_p, stats_req_tx, tx_last); -- Count bytes within each frame, so the increment is atomic. if (tx_ctrl.reset_p = '1' or tx_last = '1') then @@ -218,6 +222,10 @@ begin elsif (tx_byte = '1') then frm_bytes := frm_bytes + 1; end if; + + -- Buffer write-strobes for improved routing/timing. + tx_byte <= tx_data.valid and tx_ctrl.ready; + tx_last <= tx_data.valid and tx_ctrl.ready and tx_data.last; end if; end process; @@ -236,4 +244,13 @@ u_req_tx : sync_toggle2pulse out_clk => tx_clk, reset_p => tx_ctrl.reset_p); +-- Synchronize the status word. +gen_status : for n in status_word'range generate + u_sync : sync_buffer + port map( + in_flag => rx_data.status(n), + out_flag => status_word(n), + out_clk => status_clk); +end generate; + end port_statistics; diff --git a/src/vhdl/common/slip_decoder.vhd b/src/vhdl/common/slip_decoder.vhd index f975d94..2e9a3d4 100644 --- a/src/vhdl/common/slip_decoder.vhd +++ b/src/vhdl/common/slip_decoder.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019 The Aerospace Corporation +-- Copyright 2019, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -37,6 +37,7 @@ library ieee; use ieee.std_logic_1164.all; +use ieee.numeric_std.all; use work.common_functions.all; use work.eth_frame_common.all; @@ -82,13 +83,16 @@ signal dly_data : byte_t := (others => '0'); signal dly_write : std_logic := '0'; signal dly_last : std_logic := '0'; +-- Sustain async error strobe for a few clock cycles. +signal err_dlyct : unsigned(2 downto 0) := (others => '0'); + begin -- Drive block-level outputs. out_data <= dly_data; out_write <= dly_write; out_last <= dly_last; -decode_err <= dec_error; +decode_err <= bool2bit(err_dlyct > 0); p_decode : process(refclk) begin @@ -136,6 +140,15 @@ begin dec_state <= DECODE_DATA; -- Normal or escaped data end if; end if; + + -- Sustain async error strobe for a few clock cycles. + if (reset_p = '1') then + err_dlyct <= (others => '0'); + elsif (dec_error = '1') then + err_dlyct <= (others => '1'); + elsif (err_dlyct > 0) then + err_dlyct <= err_dlyct - 1; + end if; end if; end process; diff --git a/src/vhdl/common/switch_types.vhd b/src/vhdl/common/switch_types.vhd index 85beaae..a230d34 100644 --- a/src/vhdl/common/switch_types.vhd +++ b/src/vhdl/common/switch_types.vhd @@ -32,6 +32,11 @@ package SWITCH_TYPES is -- Convert line rate (Mbps) to the rate word. function get_rate_word(rate_mbps : positive) return port_rate_t; + -- Rx ports should also report diagnostic status flags. + -- Each bit is asynchronous with no specific meaning; blocks can use them + -- to report status to a CPU or other supervisor if desired. + subtype port_status_t is std_logic_vector(7 downto 0); + -- Each input port is unidirectional: type port_rx_m2s is record clk : std_logic; @@ -40,6 +45,7 @@ package SWITCH_TYPES is write : std_logic; rxerr : std_logic; rate : port_rate_t; + status : port_status_t; reset_p : std_logic; end record; diff --git a/src/vhdl/xilinx/clkgen_sgmii.vhd b/src/vhdl/xilinx/clkgen_sgmii.vhd index 863b11a..b7b0027 100644 --- a/src/vhdl/xilinx/clkgen_sgmii.vhd +++ b/src/vhdl/xilinx/clkgen_sgmii.vhd @@ -45,6 +45,7 @@ use work.synchronization.all; entity clkgen_sgmii_xilinx is generic ( REFCLK_MHZ : integer := 200; -- Allowed: 25, 50, 100, 125, 200 MHz + MMCM_BANDWIDTH : string := "LOW"; -- Allowed: "LOW" / "OPTIMIZED" / "HIGH" SPEED_MULT : integer := 1); -- 1x or 2x VCO freq. See notes. port ( shdn_p : in std_logic; -- Long-term shutdown @@ -77,15 +78,16 @@ begin -- Instantiate the MMCM. Notes: -- * VCO = 625 MHz * SPEED_MULT. -- * DIVCLK_DIVIDE = 1 for minimal jitter. (Keep CLKFB high.) --- * Select BANDWIDTH = LOW for optimal filtering of input jitter. +-- * Select BANDWIDTH = LOW for optimal filtering of input jitter, +-- or BANDWIDTH = HIGH for minimal output jitter from a clean input. -- * No phase alignment to input --> No BUFG required for CLKFB. u_mmcm : MMCME2_ADV generic map ( - BANDWIDTH => "LOW", -- string + BANDWIDTH => MMCM_BANDWIDTH, -- string CLKIN1_PERIOD => 1000.0 / real(REFCLK_MHZ), -- real CLKIN2_PERIOD => 1000.0 / real(REFCLK_MHZ), -- real REF_JITTER1 => 0.010, -- real - REF_JITTER2 => 0.0, -- real + REF_JITTER2 => 0.010, -- real DIVCLK_DIVIDE => 1, -- integer CLKFBOUT_MULT_F => 625.0 * real(SPEED_MULT) / real(REFCLK_MHZ), CLKFBOUT_PHASE => 0.0, -- real diff --git a/src/vhdl/xilinx/port_sgmii_gpio.vhd b/src/vhdl/xilinx/port_sgmii_gpio.vhd index 9b316a5..9b5b980 100644 --- a/src/vhdl/xilinx/port_sgmii_gpio.vhd +++ b/src/vhdl/xilinx/port_sgmii_gpio.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019 The Aerospace Corporation +-- Copyright 2019, 2020, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -41,7 +41,7 @@ entity port_sgmii_gpio is RX_IOSTD : string := "LVDS_25"; -- Rx I/O standard RX_BIAS_EN : boolean := false; -- Enable split-termination biasing RX_TERM_EN : boolean := true; -- Enable differential termination - SHAKE_WAIT : boolean := true); -- Wait for MAC/PHY handshake? + SHAKE_WAIT : boolean := false); -- Wait for MAC/PHY handshake? port ( -- External SGMII interfaces (direct to FPGA pins) sgmii_rxp : in std_logic; diff --git a/src/vhdl/xilinx/port_sgmii_gtx.vhd b/src/vhdl/xilinx/port_sgmii_gtx.vhd index 8652cd9..56679ef 100644 --- a/src/vhdl/xilinx/port_sgmii_gtx.vhd +++ b/src/vhdl/xilinx/port_sgmii_gtx.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019 The Aerospace Corporation +-- Copyright 2020, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -106,12 +106,15 @@ signal clk_locked : std_logic; signal config_vec : std_logic_vector(4 downto 0); signal status_vec : std_logic_vector(15 downto 0); signal status_linkok : std_logic; +signal status_sync : std_logic; signal status_disperr : std_logic; signal status_badsymb : std_logic; +signal status_phyok : std_logic; signal aux_err_async : std_logic; signal aux_err_sync : std_logic; -- IP-core provides a quasi-GMII interface. +signal gmii_user_clk2 : std_logic; signal gmii_tx_clk : std_logic; signal gmii_tx_data : byte_t; signal gmii_tx_en : std_logic; @@ -120,6 +123,7 @@ signal gmii_rx_clk : std_logic; signal gmii_rx_data : byte_t; signal gmii_rx_dv : std_logic; signal gmii_rx_er : std_logic; +signal gmii_status : port_status_t; begin @@ -138,8 +142,7 @@ u_amble_tx : entity work.eth_preamble_tx -- Remove preambles from the incoming data: u_amble_rx : entity work.eth_preamble_rx generic map( - RATE_MBPS => 1000 - ) + RATE_MBPS => 1000) port map( raw_clk => gmii_rx_clk, raw_lock => clk_locked, @@ -148,6 +151,7 @@ u_amble_rx : entity work.eth_preamble_rx raw_dv => gmii_rx_dv, raw_err => gmii_rx_er, aux_err => aux_err_sync, + status => gmii_status, rx_data => prx_data); -- Flush received data if we get an 8b/10b decode error. @@ -164,19 +168,32 @@ txrx_pwren <= not port_shdn; tx_pkten <= clk_locked and status_linkok; config_vec <= ( - 4 => '0', -- Disable auto-negotation + 4 => '1', -- Enable auto-negotation 3 => '0', -- Normal GMII operation 2 => port_shdn, -- Power-down strobe 1 => '0', -- Disable loopback 0 => '0'); -- Bidirectional mode -status_linkok <= status_vec(0); -status_disperr <= status_vec(5); -status_badsymb <= status_vec(6); +status_linkok <= status_vec(0); -- SGMII link ready for use +status_sync <= status_vec(1); -- 8b/10b initial sync +status_disperr <= status_vec(5); -- 8b/10b disparity error +status_badsymb <= status_vec(6); -- 8b/10b decode error +status_phyok <= status_vec(7); -- Attached PHY status, if applicable + +gmii_status <= ( + 0 => port_shdn, + 1 => clk_locked, + 2 => status_sync, + 3 => status_linkok, + 4 => status_phyok, + others => '0'); -- Instantiate the IP-core. -- TODO: Support for multiple instances, will need different core-names. -- TODO: Cross-connect shared logic and clocks if there's more than one lane. +gmii_rx_clk <= gmii_user_clk2; -- This is the only 125 MHz clock avail from core +gmii_tx_clk <= gmii_user_clk2; -- This is the only 125 MHz clock avail from core + u_ipcore : sgmii_gtx0 port map( gtrefclk_p => gtref_125p, @@ -189,9 +206,9 @@ u_ipcore : sgmii_gtx0 rxn => sgmii_rxn, resetdone => open, userclk_out => open, -- Tx 62.5 MHz - userclk2_out => gmii_tx_clk, -- Tx 125 MHz + userclk2_out => gmii_user_clk2, -- Tx 125 MHz rxuserclk_out => open, -- Rx 62.5 MHz - rxuserclk2_out => gmii_rx_clk, -- Rx 125 MHz + rxuserclk2_out => open, -- Rx 62.5 MHz pma_reset_out => open, mmcm_locked_out => clk_locked, independent_clock_bufg => clkin_200, -- Clock for control logic diff --git a/src/vhdl/xilinx/sgmii_input_fifo.vhd b/src/vhdl/xilinx/sgmii_input_fifo.vhd index 2ec6355..5240e3c 100644 --- a/src/vhdl/xilinx/sgmii_input_fifo.vhd +++ b/src/vhdl/xilinx/sgmii_input_fifo.vhd @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- --- Copyright 2019 The Aerospace Corporation +-- Copyright 2019, 2021 The Aerospace Corporation -- -- This file is part of SatCat5. -- @@ -140,13 +140,14 @@ end prim_in_fifo; architecture prim_ram32 of sgmii_input_fifo is -- Each clock-crossing strobe represents N data words. (4/8/16) -constant BLK_SIZE : integer := 8; +constant BLK_SIZE : integer := 4; -signal wr_addr : unsigned(4 downto 0) := (others => '0'); -signal rd_addr : unsigned(4 downto 0) := (others => '0'); -signal rd_en : std_logic := '0'; -signal blk_tog : std_logic := '0'; -- Toggle in in_clk -signal blk_out : std_logic; -- Strobe in out_clk +signal wr_addr : unsigned(4 downto 0) := (others => '0'); +signal rd_addr : unsigned(4 downto 0) := (others => '0'); +signal rd_en : std_logic := '0'; +signal blk_tog : std_logic := '0'; -- Toggle in in_clk +signal blk_out : std_logic; -- Strobe in out_clk +signal out_reset_p : std_logic; begin @@ -193,6 +194,15 @@ begin end if; end process; +-- Clock-crossing for the synchronous reset signal. +u_rst : sync_reset + generic map( + HOLD_MIN => 3) + port map( + in_reset_p => in_reset_p, + out_reset_p => out_reset_p, + out_clk => out_clk); + -- Clock-domain crossing: One strobe every N clocks. -- When we get a strobe, read up to the next block boundary. u_blk : sync_toggle2pulse @@ -207,7 +217,7 @@ rd_en <= blk_out or bool2bit((rd_addr mod BLK_SIZE) /= 0); p_read : process(out_clk) begin if rising_edge(out_clk) then - if (in_reset_p = '1') then + if (out_reset_p = '1') then rd_addr <= (others => '0'); elsif (rd_en = '1') then rd_addr <= rd_addr + 1;