Commit 1c53def3 authored by Maciej Lipinski's avatar Maciej Lipinski

Merge branch 'Fixed-latency-streamers' into proposed_master

parents 94c94685 8c3ee07c
......@@ -75,6 +75,10 @@ package wr_board_pkg is
application_size : integer
) return integer;
function f_pick_clk_ref_rate (
pcs_16bit_in : boolean
) return integer;
function f_vectorize_diag (
diag_in : t_generic_word_array;
diag_vector_size : integer)
......@@ -288,6 +292,18 @@ package body wr_board_pkg is
end if;
end f_pick_diag_size;
-- guess clk_ref (WR reference Clock) rate based on PCS word width
function f_pick_clk_ref_rate (
pcs_16bit_in : boolean
) return integer is
begin
if(pcs_16bit_in = TRUE) then
return 62500000;
else
return 125000000;
end if;
end f_pick_clk_ref_rate;
function f_vectorize_diag (
diag_in : t_generic_word_array;
diag_vector_size : integer)
......
......@@ -491,7 +491,8 @@ begin -- architecture struct
g_streamers_op_mode => g_streamers_op_mode,
g_tx_streamer_params => g_tx_streamer_params,
g_rx_streamer_params => g_rx_streamer_params,
g_simulation => g_simulation)
g_simulation => g_simulation,
g_clk_ref_rate => f_pick_clk_ref_rate(g_pcs_16bit))
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
......
Subproject commit 4e5f7badf0b72f51bdb01c63fcdc6d69afb4b750
Subproject commit f73bc3d2959bdaab52adf910d99ed90cabab11ab
......@@ -4,5 +4,6 @@ files = ["dmtd_phase_meas.vhd",
"hpll_period_detect.vhd",
"pulse_gen.vhd",
"oserdes_4_to_1.vhd",
"pulse_stamper.vhd" ]
"pulse_stamper.vhd",
"pulse_stamper_sync.vhd"]
......@@ -84,6 +84,31 @@ architecture rtl of pulse_stamper is
signal pulse_sys_p1 : std_logic;
signal pulse_back : std_logic_vector(2 downto 0);
-- One of two clocks is used in WR for timestamping: 125MHz or 62.5MHz
-- This functions translates the cycle count into 125MHz-clock cycles
-- in the case when 62.5MHz clock is used. As a result, timestamps are
-- always in the same "clock domain". This is important, e.g. for streamers,
-- in applicatinos where one WR Node works with 62.5MHz WR clock and
-- another in 125MHz.
function f_8ns_cycle_cnt (in_cyc: std_logic_vector; ref_clk: integer)
return std_logic_vector is
variable out_cyc : std_logic_vector(27 downto 0);
begin
if (ref_clk = 125000000) then
out_cyc := in_cyc;
elsif(ref_clk = 62500000) then
out_cyc := in_cyc(26 downto 0) & '0';
else
assert FALSE report
"The only ref_clk_rate supported: 62.5MHz and 125MHz"
severity FAILURE;
end if;
return out_cyc;
end f_8ns_cycle_cnt;
begin -- architecture rtl
-- Synchronization of external pulse into the clk_ref_i clock domain
......@@ -150,7 +175,7 @@ begin -- architecture rtl
tag_valid_o <= '0';
elsif pulse_sys_p1='1' then
tag_tai_o <= tag_utc_ref;
tag_cycles_o <= tag_cycles_ref;
tag_cycles_o <= f_8ns_cycle_cnt(tag_cycles_ref,g_ref_clk_rate);
tag_valid_o <= '1';
else
tag_valid_o <='0';
......
--------------------------------------------------------------------------------
-- CERN
-- wr-cores/timing
-- https://www.ohwr.org/project/wr-cores
--------------------------------------------------------------------------------
--
-- unit name : pulse_stamper_sync.vhd
-- author : Tomasz Wlostowski, based on pulse_stamper by Javier Serrano
-- description:
--
-- this module allows to time stamp pulses that are synchronous to clk_ref
-- domain, so in the domain of the WR time (i.e. tm_tai_i and tm_cycles_i).
-- The generated timestamp is then made available in the clk_sys domain.
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN BE/CO/HT
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity pulse_stamper_sync is
generic (
-- reference clock frequency
g_ref_clk_rate : integer := 125000000);
port(
clk_ref_i : in std_logic; -- timing reference clock
clk_sys_i : in std_logic; -- data output reference clock
rst_n_i : in std_logic; -- system reset
pulse_i : in std_logic; -- pulse to be stamped (ref clock domain)
-------------------------------------------------------------------------------
-- Timing input (from WRPC), clk_ref_i domain
------------------------------------------------------------------------------
-- 1: time given on tm_utc_i and tm_cycles_i is valid (otherwise, don't timestamp)
tm_time_valid_i : in std_logic;
-- number of seconds
tm_tai_i : in std_logic_vector(39 downto 0);
-- number of clk_ref_i cycles
tm_cycles_i : in std_logic_vector(27 downto 0);
---------------------------------------------------------------------------
-- Time tag output (clk_sys_i domain)
---------------------------------------------------------------------------
tag_tai_o : out std_logic_vector(39 downto 0);
tag_cycles_o : out std_logic_vector(27 downto 0);
-- single-cycle pulse: strobe tag on tag_utc_o and tag_cycles_o
tag_valid_o : out std_logic;
tag_error_o : out std_logic -- 1 when pulse came with tm_time_valid_i = 0
);
end pulse_stamper_sync;
architecture rtl of pulse_stamper_sync is
signal rst_n_ref : std_logic;
signal pulse_d : std_logic;
signal tag_ready_ref, tag_ready_ref_d, tag_ready_ref_p1 : std_logic;
signal tag_time_valid_ref : std_logic;
signal tag_ready_sys_p1 : std_logic;
-- Time tagger signals
signal tag_utc_ref : std_logic_vector(39 downto 0);
signal tag_cycles_ref : std_logic_vector(27 downto 0);
-- One of two clocks is used in WR for timestamping: 125MHz or 62.5MHz
-- This functions translates the cycle count into 125MHz-clock cycles
-- in the case when 62.5MHz clock is used. As a result, timestamps are
-- always in the same "clock domain". This is important, e.g. for streamers,
-- in applicatinos where one WR Node works with 62.5MHz WR clock and
-- another in 125MHz.
function f_8ns_cycle_cnt (in_cyc : std_logic_vector; ref_clk : integer)
return std_logic_vector is
variable out_cyc : std_logic_vector(27 downto 0);
begin
if (ref_clk = 125000000) then
out_cyc := in_cyc;
elsif(ref_clk = 62500000) then
out_cyc := in_cyc(26 downto 0) & '0';
else
assert false report
"The only ref_clk_rate supported: 62.5MHz and 125MHz"
severity failure;
end if;
return out_cyc;
end f_8ns_cycle_cnt;
begin -- architecture rtl
U_sync_reset_ref : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_i,
rst_n_i => '1',
data_i => rst_n_i,
synced_o => rst_n_ref);
-- Time tagging of the pulse, still in the clk_ref_i domain
p_tagger : process (clk_ref_i)
begin
if rising_edge(clk_ref_i) then
if rst_n_ref = '0' then
pulse_d <= '0';
tag_ready_ref <= '0';
tag_ready_ref_d <= '0';
tag_ready_ref_p1 <= '0';
else
pulse_d <= pulse_i;
tag_ready_ref_d <= tag_ready_ref;
tag_ready_ref_p1 <= not tag_ready_ref_d and tag_ready_ref;
if pulse_i = '1' and pulse_d = '0' then
tag_utc_ref <= tm_tai_i;
tag_cycles_ref <= tm_cycles_i;
tag_time_valid_ref <= tm_time_valid_i;
tag_ready_ref <= '1';
else
tag_ready_ref <= '0';
end if;
end if;
end if;
end process;
U_SyncTagReady : gc_pulse_synchronizer2
port map (
clk_in_i => clk_ref_i,
rst_in_n_i => rst_n_ref,
clk_out_i => clk_sys_i,
rst_out_n_i => rst_n_i,
d_ready_o => open,
d_p_i => tag_ready_ref_p1,
q_p_o => tag_ready_sys_p1);
-- Now we can take the time tags into the clk_sys_i domain
p_sys_tags : process (clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
tag_tai_o <= (others => '0');
tag_cycles_o <= (others => '0');
tag_valid_o <= '0';
tag_error_o <= '0';
elsif tag_ready_sys_p1 = '1' then
tag_tai_o <= tag_utc_ref;
tag_cycles_o <= f_8ns_cycle_cnt(tag_cycles_ref, g_ref_clk_rate);
tag_valid_o <= '1';
tag_error_o <= not tag_time_valid_ref;
else
tag_valid_o <= '0';
end if;
end if;
end process;
end architecture rtl;
......@@ -93,7 +93,7 @@ architecture behavioral of ep_rx_crc_size_check is
signal crc_gen_enable : std_logic;
signal crc_gen_reset : std_logic;
signal crc_match, crc_match2 : std_logic;
signal crc_match : std_logic;
signal crc_cur : std_logic_vector(31 downto 0);
signal crc_in_data : std_logic_vector(15 downto 0);
......@@ -106,7 +106,6 @@ architecture behavioral of ep_rx_crc_size_check is
signal state : t_state;
signal q_flush, q_empty : std_logic;
signal q_purge : std_logic;
signal q_in, q_out : std_logic_vector(17 downto 0);
signal q_bytesel : std_logic;
......@@ -306,6 +305,7 @@ begin -- behavioral
src_fab_o.error <= '1';
q_purge <= '1';
elsif(snk_fab_i.eof = '1') then
q_purge <= '1';
state <= ST_WAIT_FRAME;
else
state <= ST_OOB;
......@@ -324,6 +324,7 @@ begin -- behavioral
if(src_dreq_i = '1' and snk_fab_i.eof='1') then
state <= ST_WAIT_FRAME;
q_purge <= '1';
end if;
end case;
......
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2009-06-22
-- Last update: 2017-02-02
-- Last update: 2018-10-03
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -117,34 +117,6 @@ end ep_rx_path;
architecture behavioral of ep_rx_path is
type t_rx_deframer_state is (RXF_IDLE, RXF_DATA, RXF_FLUSH_STALL, RXF_FINISH_CYCLE, RXF_THROW_ERROR);
signal state : t_rx_deframer_state;
signal gap_cntr : unsigned(3 downto 0);
-- new sigs
signal counter : unsigned(7 downto 0);
signal rxdata_saved : std_logic_vector(15 downto 0);
signal next_hdr : std_logic;
signal is_pause : std_logic;
signal data_firstword : std_logic;
signal flush_stall : std_logic;
signal stb_int : std_logic;
signal fab_int : t_ep_internal_fabric;
signal dreq_int : std_logic;
signal ack_count : unsigned(7 downto 0);
signal src_out_int : t_wrf_source_out;
signal tmp_sel : std_logic;
signal tmp_dat : std_logic_vector(15 downto 0);
signal fab_pipe : t_fab_pipe(0 to 9);
signal dreq_pipe : std_logic_vector(9 downto 0);
......
......@@ -12,5 +12,9 @@ files = ["streamers_pkg.vhd",
"wr_streamers_wb.vhd",
"streamers_priv_pkg.vhd",
"xtx_streamers_stats.vhd",
"xrx_streamers_stats.vhd"
]
"xrx_streamers_stats.vhd",
"fixed_latency_delay.vhd",
"fixed_latency_ts_match.vhd",
"fifo_showahead_adapter.vhd",
"ts_restore_tai.vhd",
];
......@@ -58,7 +58,8 @@ entity dropping_buffer is
d_o : out std_logic_vector(g_data_width-1 downto 0);
d_valid_o : out std_logic;
d_req_i : in std_logic);
d_req_i : in std_logic;
d_full_o : out std_logic);
end dropping_buffer;
......@@ -104,6 +105,7 @@ begin -- behavioral
full <= '1' when (wr_ptr + 1 = rd_ptr) else '0';
d_req_o <= not full;
d_full_o <= full;
p_empty_reg : process(clk_i)
begin
......
--------------------------------------------------------------------------------
-- CERN
-- wr-cores/wr-streamers
-- https://www.ohwr.org/project/wr-cores
--------------------------------------------------------------------------------
--
-- unit name : fifo_showahead_adapter.vhd
-- author : Tomasz Wlostowski
-- description:
--
-- Emulation of show-ahead FIFO, used if the show-ahead feature in a FIFO
-- is not supported.
--
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN BE/CO/HT
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity fifo_showahead_adapter is
generic (
g_width : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
fifo_q_i : in std_logic_vector(g_width-1 downto 0);
fifo_empty_i : in std_logic;
fifo_rd_o : out std_logic;
q_o : out std_logic_vector(g_width-1 downto 0);
valid_o : out std_logic;
rd_i : in std_logic
);
end fifo_showahead_adapter;
architecture rtl of fifo_showahead_adapter is
signal rd, rd_d : std_logic;
signal valid_int : std_logic;
begin
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_d <= '0';
valid_int <= '0';
else
rd_d <= rd;
if rd = '1' then
valid_int <= '1';
elsif rd_i = '1' then
valid_int <= not fifo_empty_i;
end if;
end if;
end if;
end process;
rd <= not fifo_empty_i when valid_int = '0' else rd_i and not fifo_empty_i;
q_o <= fifo_q_i;
fifo_rd_o <= rd;
valid_o <= valid_int;
end rtl;
This diff is collapsed.
This diff is collapsed.
......@@ -75,6 +75,11 @@ package streamers_pkg is
-- legacy: the streamers initially used in Btrain did not check/insert the escape
-- code. This is justified if only one block of a known number of words is sent/expected
escape_code_disable : boolean;
-- when non-zero, the datapath (tx port) are in the clk_ref_i clock
-- domain instead of clk_sys_i. This is a must for fixed latency mode if
-- clk_sys_i is asynchronous (i.e. not locked) to the WR timing.
use_ref_clk_for_data : integer;
end record;
-----------------------------------------------------------------------------------------
......@@ -105,6 +110,11 @@ package streamers_pkg is
-- In combination with the g_escape_code_disable generic set to TRUE, the behaviour of
-- the "Btrain streamers" can be recreated.
expected_words_number : integer;
-- when non-zero, the datapath (rx port) are in the clk_ref_i clock
-- domain instead of clk_sys_i. This is a must for fixed latency mode if
-- clk_sys_i is asynchronous (i.e. not locked) to the WR timing.
use_ref_clk_for_data : integer;
end record;
constant c_tx_streamer_params_defaut: t_tx_streamer_params :=(
......@@ -113,12 +123,14 @@ package streamers_pkg is
threshold => 128,
max_words_per_frame => 256,
timeout => 1024,
use_ref_clk_for_data => 0,
escape_code_disable => FALSE);
constant c_rx_streamer_params_defaut: t_rx_streamer_params :=(
data_width => 32,
buffer_size => 256,
escape_code_disable => FALSE,
use_ref_clk_for_data => 0,
expected_words_number => 0);
type t_rx_streamer_cfg is record
......@@ -139,6 +151,13 @@ package streamers_pkg is
filter_remote : std_logic;
-- value in cycles of fixed-latency enforced on data
fixed_latency : std_logic_vector(27 downto 0);
-- value in cycles of fixed-latency timeout (if it takes longer than this value
-- to output the packet, it's dropped)
fixed_latency_timeout : std_logic_vector(27 downto 0);
-- software controlled reset
sw_reset : std_logic;
end record;
type t_tx_streamer_cfg is record
......@@ -156,6 +175,8 @@ package streamers_pkg is
qtag_vid : std_logic_vector(11 downto 0);
-- priority used to tag
qtag_prio : std_logic_vector(2 downto 0);
-- software controlled reset
sw_reset : std_logic;
end record;
constant c_rx_streamer_cfg_default: t_rx_streamer_cfg :=(
......@@ -164,7 +185,9 @@ package streamers_pkg is
ethertype => x"dbff",
accept_broadcasts => '1',
filter_remote => '0',
fixed_latency => x"0000000");
fixed_latency => x"0000000",
fixed_latency_timeout => x"1000000",
sw_reset => '0');
constant c_tx_streamer_cfg_default: t_tx_streamer_cfg :=(
mac_local => x"000000000000",
......@@ -172,7 +195,8 @@ package streamers_pkg is
ethertype => x"dbff",
qtag_ena => '0',
qtag_vid => x"000",
qtag_prio => "000");
qtag_prio => "000",
sw_reset => '0');
component xtx_streamer
generic (
......@@ -183,13 +207,15 @@ package streamers_pkg is
g_tx_timeout : integer := 1024;
g_escape_code_disable : boolean := FALSE;
g_simulation : integer := 0;
g_sim_startup_cnt : integer := 6250);--100us
g_sim_startup_cnt : integer := 6250;--100us
g_clk_ref_rate : integer := 125000000;
g_use_ref_clock_for_data : integer := 0);
port (
clk_sys_i : in std_logic;
clk_ref_i : in std_logic := '0';
rst_n_i : in std_logic;
src_i : in t_wrf_source_in;
src_o : out t_wrf_source_out;
clk_ref_i : in std_logic := '0';
tm_time_valid_i : in std_logic := '0';
tm_tai_i : in std_logic_vector(39 downto 0) := x"0000000000";
tm_cycles_i : in std_logic_vector(27 downto 0) := x"0000000";
......@@ -209,7 +235,11 @@ package streamers_pkg is
g_data_width : integer := 32;
g_buffer_size : integer := 256;
g_escape_code_disable : boolean := FALSE;
g_expected_words_number : integer := 0);
g_expected_words_number : integer := 0;
g_clk_ref_rate : integer := 125000000;
g_simulation : integer := 0;
g_sim_cycle_counter_range : integer := 125000000;
g_use_ref_clock_for_data : integer := 0);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
......@@ -223,6 +253,8 @@ package streamers_pkg is
rx_last_p1_o : out std_logic;
rx_data_o : out std_logic_vector(g_data_width-1 downto 0);
rx_valid_o : out std_logic;
rx_late_o : out std_logic;
rx_timeout_o : out std_logic;
rx_dreq_i : in std_logic;
rx_lost_p1_o : out std_logic := '0';
rx_lost_blocks_p1_o : out std_logic := '0';
......@@ -230,16 +262,21 @@ package streamers_pkg is
rx_lost_frames_cnt_o : out std_logic_vector(14 downto 0);
rx_latency_o : out std_logic_vector(27 downto 0);
rx_latency_valid_o : out std_logic;
rx_stat_overflow_p1_o : out std_logic;
rx_stat_match_p1_o : out std_logic;
rx_stat_late_p1_o : out std_logic;
rx_stat_timeout_p1_o : out std_logic;
rx_frame_p1_o : out std_logic;
rx_streamer_cfg_i : in t_rx_streamer_cfg := c_rx_streamer_cfg_default);
end component;
constant c_WRS_STATS_ARR_SIZE_OUT : integer := 18;
constant c_WRS_STATS_ARR_SIZE_OUT : integer := 24;
constant c_WRS_STATS_ARR_SIZE_IN : integer := 1;
component xrtx_streamers_stats is
generic (
g_streamers_op_mode : t_streamers_op_mode := TX_AND_RX;
g_clk_ref_rate : integer := 125000000;
g_cnt_width : integer := 50;
g_acc_width : integer := 64
);
......@@ -253,6 +290,9 @@ package streamers_pkg is
lost_frames_cnt_i : in std_logic_vector(14 downto 0);
rcvd_latency_i : in std_logic_vector(27 downto 0);
rcvd_latency_valid_i : in std_logic;
rx_stat_match_p1_i : in std_logic;
rx_stat_late_p1_i : in std_logic;
rx_stat_timeout_p1_i : in std_logic;
clk_ref_i : in std_logic;
tm_time_valid_i : in std_logic := '0';
tm_tai_i : in std_logic_vector(39 downto 0) := x"0000000000";
......@@ -266,6 +306,9 @@ package streamers_pkg is
lost_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_block_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_match_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_late_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_timeout_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_acc_overflow_o : out std_logic;
latency_acc_o : out std_logic_vector(g_acc_width-1 downto 0);
latency_max_o : out std_logic_vector(27 downto 0);
......@@ -281,6 +324,7 @@ package streamers_pkg is
component xwr_streamers is
generic (
g_streamers_op_mode : t_streamers_op_mode := TX_AND_RX;
g_clk_ref_rate : integer := 125000000;
--tx/rx
g_tx_streamer_params : t_tx_streamer_params := c_tx_streamer_params_defaut;
g_rx_streamer_params : t_rx_streamer_params := c_rx_streamer_params_defaut;
......@@ -290,7 +334,8 @@ package streamers_pkg is
-- WB i/f
g_slave_mode : t_wishbone_interface_mode := CLASSIC;
g_slave_granularity : t_wishbone_address_granularity := BYTE;
g_simulation : integer := 0
g_simulation : integer := 0;
g_sim_cycle_counter_range : integer := 125000
);
port (
......
......@@ -72,9 +72,15 @@ package streamers_priv_pkg is
tm_time_valid_i : in std_logic;
snapshot_ena_i : in std_logic := '0';
reset_stats_i : in std_logic;
rx_stat_match_p1_i : in std_logic;
rx_stat_late_p1_i : in std_logic;
rx_stat_timeout_p1_i : in std_logic;
rcvd_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_block_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_match_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_late_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_timeout_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_acc_overflow_o : out std_logic;
latency_acc_o : out std_logic_vector(g_acc_width-1 downto 0);
......@@ -82,26 +88,10 @@ package streamers_priv_pkg is
latency_min_o : out std_logic_vector(27 downto 0));
end component;
component wr_streamers_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(5 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_wr_streamers_in_registers;
regs_o : out t_wr_streamers_out_registers
);
end component;
-- component from wr-core/modules/timing
component pulse_stamper
generic (
g_ref_clk_rate : integer := 125000000);
port (
clk_ref_i : in std_logic;
clk_sys_i : in std_logic;
......
--------------------------------------------------------------------------------
-- CERN
-- wr-cores/wr-streamers
-- https://www.ohwr.org/project/wr-cores
--------------------------------------------------------------------------------
--
-- unit name : ts_restore_tai.vhd
-- author : Tomasz Wlostowski
-- description:
--
-- This module restores full TAI timestamp from the timestamp
-- received in WR_streamer frame
--
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN BE/CO/HT
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity ts_restore_tai is
generic
(
g_tm_sample_period : integer := 20;
g_clk_ref_rate : integer;
g_simulation : integer := 0;
g_sim_cycle_counter_range : integer := 125000000
);
port (
clk_sys_i : in std_logic;
clk_ref_i : in std_logic;
rst_n_i : in std_logic;
-- Timing I/F, clk_ref_i clock domain
tm_time_valid_i : in std_logic;
tm_tai_i : in std_logic_vector(39 downto 0);
tm_cycles_i : in std_logic_vector(27 downto 0);
-- Timestamp I/F, clk_sys_i clock domain
ts_valid_i : in std_logic;
ts_cycles_i : in std_logic_vector(27 downto 0);
ts_valid_o : out std_logic;
ts_cycles_o : out std_logic_vector(27 downto 0);
ts_error_o : out std_logic;
ts_tai_o : out std_logic_vector(39 downto 0)
);
end entity;
architecture rtl of ts_restore_tai is
signal tm_cycles_sys, tm_cycles_ref, tm_cycles_ref_d : std_logic_vector(27 downto 0);
signal tm_tai_sys, tm_tai_ref, tm_tai_ref_d : std_logic_vector(39 downto 0);
signal tm_valid_sys, tm_valid_ref, tm_valid_ref_d : std_logic;
signal tm_sample_cnt : unsigned(5 downto 0);
signal tm_sample_p_ref : std_logic;
signal tm_sample_p_sys : std_logic;
impure function f_cycles_counter_range return integer is
begin
if g_simulation = 1 then
if g_clk_ref_rate = 62500000 then
return 2*g_sim_cycle_counter_range;
else
return g_sim_cycle_counter_range;
end if;
else
return 125000000;
end if;
end function;
constant c_rollover_threshold_lo : integer := f_cycles_counter_range / 4;
constant c_rollover_threshold_hi : integer := f_cycles_counter_range * 3 / 4;
signal rst_n_ref : std_logic;
begin
U_SyncReset_to_RefClk : gc_sync_ffs
port map (
clk_i => clk_ref_i,
rst_n_i => '1',
data_i => rst_n_i,
synced_o => rst_n_ref);
p_sample_tm_ref : process(clk_ref_i)
begin
if rising_edge(clk_ref_i) then
if rst_n_ref = '0' then
tm_sample_p_ref <= '0';
tm_sample_cnt <= (others => '0');
else
tm_cycles_ref <= tm_cycles_ref_d;
tm_tai_ref <= tm_tai_ref_d;
tm_valid_ref <= tm_valid_ref_d;
if tm_sample_cnt = g_tm_sample_period-1 then
tm_sample_p_ref <= '1';
tm_cycles_ref_d <= tm_cycles_i;
tm_tai_ref_d <= tm_tai_i;
tm_valid_ref_d <= tm_time_valid_i;
tm_sample_cnt <= (others => '0');
else
tm_sample_p_ref <= '0';
tm_sample_cnt <= tm_sample_cnt + 1;
end if;
end if;
end if;
end process;
U_Sync_Sample_Pulse : gc_pulse_synchronizer2
port map (
clk_in_i => clk_ref_i,
rst_in_n_i => rst_n_ref,
clk_out_i => clk_sys_i,
rst_out_n_i => rst_n_i,
d_ready_o => open,
d_p_i => tm_sample_p_ref,
q_p_o => tm_sample_p_sys);
p_sample_tm_sys : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
tm_valid_sys <= '0';
elsif tm_sample_p_sys = '1' then
tm_tai_sys <= tm_tai_ref;
tm_cycles_sys <= tm_cycles_ref;
tm_valid_sys <= tm_valid_ref;
end if;
end if;
end process;
p_process : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
ts_valid_o <= '0';
else
if ts_valid_i = '1' then
if unsigned(ts_cycles_i) > c_rollover_threshold_hi and unsigned(tm_cycles_sys) < c_rollover_threshold_lo then
ts_tai_o <= std_logic_vector(unsigned(tm_tai_sys) - 1);
else
ts_tai_o <= tm_tai_sys;
end if;
ts_cycles_o <= ts_cycles_i;
ts_error_o <= not tm_valid_sys;
ts_valid_o <= '1';
else
ts_valid_o <= '0';
end if;
end if;
end if;
end process;
end rtl;
......@@ -3,8 +3,8 @@
---------------------------------------------------------------------------------------
-- File : wr_streamers_wb.vhd
-- Author : auto-generated by wbgen2 from wr_streamers_wb.wb
-- Created : Wed Aug 16 22:45:12 2017
-- Version : 0x00000001
-- Created : Thu May 23 16:11:14 2019
-- Version : 0x00000002
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_streamers_wb.wb
......@@ -30,6 +30,8 @@ entity wr_streamers_wb is
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_err_o : out std_logic;
wb_rty_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_wr_streamers_in_registers;
regs_o : out t_wr_streamers_out_registers
......@@ -72,11 +74,19 @@ signal wr_streamers_cfg_or_rx_ftr_remote_int : std_logic ;
signal wr_streamers_cfg_or_rx_fix_lat_int : std_logic ;
signal wr_streamers_dbg_ctrl_mux_int : std_logic ;
signal wr_streamers_dbg_ctrl_start_byte_int : std_logic_vector(7 downto 0);
signal wr_streamers_rstr_rst_sw_dly0 : std_logic ;
signal wr_streamers_rstr_rst_sw_int : std_logic ;
signal wr_streamers_rx_cfg6_rx_fixed_latency_timeout_int : std_logic_vector(27 downto 0);
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(5 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments
......@@ -89,7 +99,7 @@ begin
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
wr_streamers_ver_id_int <= "00000000000000000000000000000001";
wr_streamers_ver_id_int <= "00000000000000000000000000000010";
wr_streamers_sscr1_rst_stats_int <= '0';
wr_streamers_sscr1_rst_seq_id_int <= '0';
wr_streamers_sscr1_snapshot_stats_int <= '0';
......@@ -121,6 +131,8 @@ begin
wr_streamers_cfg_or_rx_fix_lat_int <= '0';
wr_streamers_dbg_ctrl_mux_int <= '0';
wr_streamers_dbg_ctrl_start_byte_int <= "00000000";
wr_streamers_rstr_rst_sw_int <= '0';
wr_streamers_rx_cfg6_rx_fixed_latency_timeout_int <= "0001000000000000000000000000";
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
......@@ -129,6 +141,7 @@ begin
if (ack_sreg(0) = '1') then
wr_streamers_sscr1_rst_stats_int <= '0';
wr_streamers_sscr1_rst_seq_id_int <= '0';
wr_streamers_rstr_rst_sw_int <= '0';
ack_in_progress <= '0';
else
end if;
......@@ -580,6 +593,92 @@ begin
rddata_reg(31 downto 0) <= regs_i.dummy_dummy_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100010" =>
if (wb_we_i = '1') then
wr_streamers_rstr_rst_sw_int <= wrdata_reg(0);
end if;
rddata_reg(0) <= '0';
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when "100011" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat15_rx_late_frames_cnt_lsb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100100" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat16_rx_late_frames_cnt_msb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100101" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat17_rx_timeout_frames_cnt_lsb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100110" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat18_rx_timeout_frames_cnt_msb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100111" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat19_rx_match_frames_cnt_lsb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "101000" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.rx_stat20_rx_match_frames_cnt_msb_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "101001" =>
if (wb_we_i = '1') then
wr_streamers_rx_cfg6_rx_fixed_latency_timeout_int <= wrdata_reg(27 downto 0);
end if;
rddata_reg(27 downto 0) <= wr_streamers_rx_cfg6_rx_fixed_latency_timeout_int;
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
......@@ -699,8 +798,31 @@ begin
regs_o.dbg_ctrl_start_byte_o <= wr_streamers_dbg_ctrl_start_byte_int;
-- Debug content
-- DUMMY value to read
-- Software reset streamers
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
wr_streamers_rstr_rst_sw_dly0 <= '0';
regs_o.rstr_rst_sw_o <= '0';
elsif rising_edge(clk_sys_i) then
wr_streamers_rstr_rst_sw_dly0 <= wr_streamers_rstr_rst_sw_int;
regs_o.rstr_rst_sw_o <= wr_streamers_rstr_rst_sw_int and (not wr_streamers_rstr_rst_sw_dly0);
end if;
end process;
-- WR Streamer RX Late Frames Count (LSB)
-- WR Streamer RX Late Frames Count (MSB)
-- WR Streamer RX Timed-out Frames Count (LSB)
-- WR Streamer RX Timed-out Frames Count (MSB)
-- WR Streamer RX OK Frames Count (LSB)
-- WR Streamer RX OK Frames Count (MSB)
-- RX Fixed Latency Timeout (Default: 0x1000000=~134ms)
regs_o.rx_cfg6_rx_fixed_latency_timeout_o <= wr_streamers_rx_cfg6_rx_fixed_latency_timeout_int;
rwaddr_reg <= wb_adr_i;
wb_stall_o <= (not ack_sreg(0)) and (wb_stb_i and wb_cyc_i);
wb_err_o <= '0';
wb_rty_o <= '0';
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
......@@ -28,7 +28,7 @@ peripheral {
-----------------------------------------------------------------";
prefix = "wr_streamers";
hdl_entity = "wr_streamers_wb";
version= 1;
version= 2;
reg {
name = "Statistics status and ctrl register";
......@@ -77,6 +77,7 @@ peripheral {
access_dev = WRITE_ONLY;
};
};
reg {
name = "Statistics status and ctrl register";
prefix = "SSCR2";
......@@ -289,6 +290,9 @@ peripheral {
};
};
reg {
name = "Tx Config Reg 0";
prefix = "TX_CFG0";
......@@ -615,6 +619,7 @@ peripheral {
access_dev = WRITE_ONLY;
};
};
reg {
name = "Test value";
prefix = "DUMMY";
......@@ -627,4 +632,114 @@ peripheral {
access_dev = WRITE_ONLY;
};
};
reg {
name = "Reset Register";
prefix = "RSTR";
field {
name = "Software reset streamers";
prefix = "RST_SW";
description = "Writing 1 triggers a full software reset of the streamers.";
type = MONOSTABLE;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT15";
field {
name = "WR Streamer RX Late Frames Count (LSB)";
description = "Number of RX frames that missed their fixed-latency deadline";
prefix = "RX_LATE_FRAMES_CNT_LSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT16";
field {
name = "WR Streamer RX Late Frames Count (MSB)";
description = "Number of RX frames that missed their fixed-latency deadline";
prefix = "RX_LATE_FRAMES_CNT_MSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT17";
field {
name = "WR Streamer RX Timed-out Frames Count (LSB)";
description = "Number of RX frames that had their execution timestamp too far in the future (exceeding the RX_CFG6 value)";
prefix = "RX_TIMEOUT_FRAMES_CNT_LSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT18";
field {
name = "WR Streamer RX Timed-out Frames Count (MSB)";
description = "Number of RX frames that had their execution timestamp too far in the future (exceeding the RX_CFG6 value)";
prefix = "RX_TIMEOUT_FRAMES_CNT_MSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT19";
field {
name = "WR Streamer RX OK Frames Count (LSB)";
description = "Number of RX executed on time in the fixed latency mode";
prefix = "RX_MATCH_FRAMES_CNT_LSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx statistics";
prefix = "RX_STAT20";
field {
name = "WR Streamer RX OK Frames Count (MSB)";
description = "Number of RX executed on time in the fixed latency mode";
prefix = "RX_MATCH_FRAMES_CNT_MSB";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Rx Config Reg 6";
prefix = "RX_CFG6";
field {
name = "RX Fixed Latency Timeout (Default: 0x1000000=~134ms)";
prefix = "RX_FIXED_LATENCY_TIMEOUT";
type = SLV;
size = 28;
reset_value = 0x1000000;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
};
......@@ -3,8 +3,8 @@
---------------------------------------------------------------------------------------
-- File : wr_streamers_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from wr_streamers_wb.wb
-- Created : Wed Aug 16 22:45:12 2017
-- Version : 0x00000001
-- Created : Thu May 23 16:11:14 2019
-- Version : 0x00000002
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_streamers_wb.wb
......@@ -41,6 +41,12 @@ package wr_streamers_wbgen2_pkg is
rx_stat13_rx_latency_acc_cnt_msb_i : std_logic_vector(31 downto 0);
dbg_data_i : std_logic_vector(31 downto 0);
dummy_dummy_i : std_logic_vector(31 downto 0);
rx_stat15_rx_late_frames_cnt_lsb_i : std_logic_vector(31 downto 0);
rx_stat16_rx_late_frames_cnt_msb_i : std_logic_vector(31 downto 0);
rx_stat17_rx_timeout_frames_cnt_lsb_i : std_logic_vector(31 downto 0);
rx_stat18_rx_timeout_frames_cnt_msb_i : std_logic_vector(31 downto 0);
rx_stat19_rx_match_frames_cnt_lsb_i : std_logic_vector(31 downto 0);
rx_stat20_rx_match_frames_cnt_msb_i : std_logic_vector(31 downto 0);
end record;
constant c_wr_streamers_in_registers_init_value: t_wr_streamers_in_registers := (
......@@ -63,7 +69,13 @@ package wr_streamers_wbgen2_pkg is
rx_stat12_rx_latency_acc_cnt_lsb_i => (others => '0'),
rx_stat13_rx_latency_acc_cnt_msb_i => (others => '0'),
dbg_data_i => (others => '0'),
dummy_dummy_i => (others => '0')
dummy_dummy_i => (others => '0'),
rx_stat15_rx_late_frames_cnt_lsb_i => (others => '0'),
rx_stat16_rx_late_frames_cnt_msb_i => (others => '0'),
rx_stat17_rx_timeout_frames_cnt_lsb_i => (others => '0'),
rx_stat18_rx_timeout_frames_cnt_msb_i => (others => '0'),
rx_stat19_rx_match_frames_cnt_lsb_i => (others => '0'),
rx_stat20_rx_match_frames_cnt_msb_i => (others => '0')
);
-- Output registers (WB slave -> user design)
......@@ -101,6 +113,8 @@ package wr_streamers_wbgen2_pkg is
cfg_or_rx_fix_lat_o : std_logic;
dbg_ctrl_mux_o : std_logic;
dbg_ctrl_start_byte_o : std_logic_vector(7 downto 0);
rstr_rst_sw_o : std_logic;
rx_cfg6_rx_fixed_latency_timeout_o : std_logic_vector(27 downto 0);
end record;
constant c_wr_streamers_out_registers_init_value: t_wr_streamers_out_registers := (
......@@ -135,11 +149,33 @@ package wr_streamers_wbgen2_pkg is
cfg_or_rx_ftr_remote_o => '0',
cfg_or_rx_fix_lat_o => '0',
dbg_ctrl_mux_o => '0',
dbg_ctrl_start_byte_o => (others => '0')
dbg_ctrl_start_byte_o => (others => '0'),
rstr_rst_sw_o => '0',
rx_cfg6_rx_fixed_latency_timeout_o => (others => '0')
);
function "or" (left, right: t_wr_streamers_in_registers) return t_wr_streamers_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
component wr_streamers_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(5 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_err_o : out std_logic;
wb_rty_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_wr_streamers_in_registers;
regs_o : out t_wr_streamers_out_registers
);
end component;
end package;
package body wr_streamers_wbgen2_pkg is
......@@ -155,7 +191,7 @@ function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if x(i) = '1' then
if(x(i) = '1') then
tmp(i):= '1';
else
tmp(i):= '0';
......@@ -186,6 +222,12 @@ tmp.rx_stat12_rx_latency_acc_cnt_lsb_i := f_x_to_zero(left.rx_stat12_rx_latency_
tmp.rx_stat13_rx_latency_acc_cnt_msb_i := f_x_to_zero(left.rx_stat13_rx_latency_acc_cnt_msb_i) or f_x_to_zero(right.rx_stat13_rx_latency_acc_cnt_msb_i);
tmp.dbg_data_i := f_x_to_zero(left.dbg_data_i) or f_x_to_zero(right.dbg_data_i);
tmp.dummy_dummy_i := f_x_to_zero(left.dummy_dummy_i) or f_x_to_zero(right.dummy_dummy_i);
tmp.rx_stat15_rx_late_frames_cnt_lsb_i := f_x_to_zero(left.rx_stat15_rx_late_frames_cnt_lsb_i) or f_x_to_zero(right.rx_stat15_rx_late_frames_cnt_lsb_i);
tmp.rx_stat16_rx_late_frames_cnt_msb_i := f_x_to_zero(left.rx_stat16_rx_late_frames_cnt_msb_i) or f_x_to_zero(right.rx_stat16_rx_late_frames_cnt_msb_i);
tmp.rx_stat17_rx_timeout_frames_cnt_lsb_i := f_x_to_zero(left.rx_stat17_rx_timeout_frames_cnt_lsb_i) or f_x_to_zero(right.rx_stat17_rx_timeout_frames_cnt_lsb_i);
tmp.rx_stat18_rx_timeout_frames_cnt_msb_i := f_x_to_zero(left.rx_stat18_rx_timeout_frames_cnt_msb_i) or f_x_to_zero(right.rx_stat18_rx_timeout_frames_cnt_msb_i);
tmp.rx_stat19_rx_match_frames_cnt_lsb_i := f_x_to_zero(left.rx_stat19_rx_match_frames_cnt_lsb_i) or f_x_to_zero(right.rx_stat19_rx_match_frames_cnt_lsb_i);
tmp.rx_stat20_rx_match_frames_cnt_msb_i := f_x_to_zero(left.rx_stat20_rx_match_frames_cnt_msb_i) or f_x_to_zero(right.rx_stat20_rx_match_frames_cnt_msb_i);
return tmp;
end function;
end package body;
......@@ -68,13 +68,17 @@ entity xrtx_streamers_stats is
g_streamers_op_mode : t_streamers_op_mode := TX_AND_RX;
-- Width of frame counters
g_cnt_width : integer := 50; -- min:15, max:64, 50 bits should be ok for 50 years
g_acc_width : integer := 64 -- max value 64
g_acc_width : integer := 64; -- max value 64
-- rate fo the White Rabbit referene clock. By default, this clock is
-- 125MHz for WR Nodes. There are some WR Nodes that work with 62.5MHz.
g_clk_ref_rate : integer := 125000000
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- input signals from streamers
sent_frame_i : in std_logic;
rcvd_frame_i : in std_logic;
lost_block_i : in std_logic;
......@@ -83,6 +87,10 @@ entity xrtx_streamers_stats is
rcvd_latency_i : in std_logic_vector(27 downto 0);
rcvd_latency_valid_i : in std_logic;
rx_stat_match_p1_i : in std_logic;
rx_stat_late_p1_i : in std_logic;
rx_stat_timeout_p1_i : in std_logic;
clk_ref_i : in std_logic;
tm_time_valid_i : in std_logic := '0';
tm_tai_i : in std_logic_vector(39 downto 0) := x"0000000000";
......@@ -100,6 +108,10 @@ entity xrtx_streamers_stats is
rcvd_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_block_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_match_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_late_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_timeout_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
-- output statistics: latency
latency_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_acc_overflow_o : out std_logic;
......@@ -118,21 +130,24 @@ architecture rtl of xrtx_streamers_stats is
signal reset_time_tai : std_logic_vector(39 downto 0);
signal reset_time_cycles : std_logic_vector(27 downto 0);
signal sent_frame_cnt : unsigned(g_cnt_width-1 downto 0);
signal rcvd_frame_cnt : unsigned(g_cnt_width-1 downto 0);
signal lost_frame_cnt : unsigned(g_cnt_width-1 downto 0);
signal lost_block_cnt : unsigned(g_cnt_width-1 downto 0);
signal latency_cnt : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_match_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rx_stat_timeout_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rx_stat_late_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal latency_max : std_logic_vector(27 downto 0);
signal latency_min : std_logic_vector(27 downto 0);
signal latency_acc : unsigned(g_acc_width-1+1 downto 0);
signal latency_acc_overflow: std_logic;
signal latency_acc_overflow : std_logic;
signal sent_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rcvd_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal lost_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal lost_block_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rx_match_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rx_late_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal rx_timeout_frame_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal latency_cnt_out : std_logic_vector(g_cnt_width-1 downto 0);
signal latency_acc_overflow_out : std_logic;
signal latency_acc_out : std_logic_vector(g_acc_width-1 downto 0);
......@@ -184,6 +199,8 @@ begin
-------------------------------------------------------------------------------------------
-- process that timestamps the reset so that we can make statistics over time
U_Reset_Timestamper : pulse_stamper
generic map(
g_ref_clk_rate => g_clk_ref_rate)
port map (
clk_ref_i => clk_ref_i,
clk_sys_i => clk_i,
......@@ -240,12 +257,20 @@ begin
lost_frames_cnt_i => lost_frames_cnt_i,
rcvd_latency_i => rcvd_latency_i,
rcvd_latency_valid_i => rcvd_latency_valid_i,
rx_stat_timeout_p1_i => rx_stat_timeout_p1_i,
rx_stat_match_p1_i => rx_stat_match_p1_i,
rx_stat_late_p1_i => rx_stat_late_p1_i,
tm_time_valid_i => tm_time_valid_i,
snapshot_ena_i => snapshot_ena,
reset_stats_i => reset_stats,
rcvd_frame_cnt_o => rcvd_frame_cnt_out,
lost_frame_cnt_o => lost_frame_cnt_out,
lost_block_cnt_o => lost_block_cnt_out,
rx_stat_match_cnt_o => rx_stat_match_cnt_out,
rx_stat_late_cnt_o => rx_stat_late_cnt_out,
rx_stat_timeout_cnt_o => rx_stat_timeout_cnt_out,
latency_cnt_o => latency_cnt_out,
latency_acc_overflow_o => latency_acc_overflow_out,
latency_acc_o => latency_acc_out,
......@@ -256,6 +281,9 @@ begin
rcvd_frame_cnt_out <= (others => '0');
lost_frame_cnt_out <= (others => '0');
lost_block_cnt_out <= (others => '0');
rx_stat_match_cnt_out <= (others => '0');
rx_stat_late_cnt_out <= (others => '0');
rx_stat_timeout_cnt_out <= (others => '0');
latency_cnt_out <= (others => '0');
latency_acc_overflow_out <= '0';
latency_acc_out <= (others => '0');
......@@ -274,6 +302,9 @@ begin
latency_acc_o <= latency_acc_out;
latency_cnt_o <= latency_cnt_out;
latency_acc_overflow_o <= latency_acc_overflow_out;
rx_stat_timeout_cnt_o <= rx_stat_timeout_cnt_out;
rx_stat_late_cnt_o <= rx_stat_late_cnt_out;
rx_stat_match_cnt_o <= rx_stat_match_cnt_out;
-------------------------------------------------------------------------------------------
-- SNMP remote output
......@@ -323,6 +354,18 @@ begin
snmp_array_o(14)(c_cw-1 downto 0) <= latency_cnt_out;
snmp_array_o(14)(31 downto c_cw) <= (others => '0');
snmp_array_o(15)(31 downto 0) <= (others => '0');
snmp_array_o(18)(c_cw-1 downto 0) <= rx_stat_match_cnt_out;
snmp_array_o(19)(31 downto c_cw) <= (others => '0');
snmp_array_o(19)(31 downto 0) <= (others => '0');
snmp_array_o(20)(c_cw-1 downto 0) <= rx_stat_late_cnt_out;
snmp_array_o(21)(31 downto c_cw) <= (others => '0');
snmp_array_o(21)(31 downto 0) <= (others => '0');
snmp_array_o(22)(c_cw-1 downto 0) <= rx_stat_timeout_cnt_out;
snmp_array_o(23)(31 downto c_cw) <= (others => '0');
snmp_array_o(23)(31 downto 0) <= (others => '0');
end generate;
ACC_SINGLE_WORD_gen: if(c_aw < 33) generate
snmp_array_o(16)(c_aw-1 downto 0) <= latency_acc_out;
......@@ -351,6 +394,18 @@ begin
snmp_array_o(14)(31 downto 0) <= latency_cnt_out(31 downto 0);
snmp_array_o(15)(c_cw-32-1 downto 0) <= latency_cnt_out(c_cw-1 downto 32);
snmp_array_o(15 )(31 downto c_cw-32) <= (others => '0');
snmp_array_o(18)(31 downto 0) <= rx_stat_match_cnt_out(31 downto 0);
snmp_array_o(19)(c_cw-32-1 downto 0) <= rx_stat_match_cnt_out(c_cw-1 downto 32);
snmp_array_o(19)(31 downto c_cw-32) <= (others => '0');
snmp_array_o(20)(31 downto 0) <= rx_stat_late_cnt_out(31 downto 0);
snmp_array_o(21)(c_cw-32-1 downto 0) <= rx_stat_late_cnt_out(c_cw-1 downto 32);
snmp_array_o(21)(31 downto c_cw-32) <= (others => '0');
snmp_array_o(22)(31 downto 0) <= rx_stat_timeout_cnt_out(31 downto 0);
snmp_array_o(23)(c_cw-32-1 downto 0) <= rx_stat_timeout_cnt_out(c_cw-1 downto 32);
snmp_array_o(23)(31 downto c_cw-32) <= (others => '0');
end generate;
ACC_TWO_WORDs_gen: if(c_aw > 32) generate
snmp_array_o(16)(31 downto 0) <= latency_acc_out(31 downto 0);
......
This diff is collapsed.
......@@ -67,12 +67,21 @@ entity xrx_streamers_stats is
snapshot_ena_i : in std_logic := '0';
reset_stats_i : in std_logic;
rx_stat_match_p1_i : in std_logic;
rx_stat_late_p1_i : in std_logic;
rx_stat_timeout_p1_i : in std_logic;
----------------------- statistics ----------------------------------------
-- output statistics: tx/rx counters
rcvd_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_frame_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
lost_block_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
-- output statistics: latency
rx_stat_match_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_late_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
rx_stat_timeout_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
-- output statistics: latency
latency_cnt_o : out std_logic_vector(g_cnt_width-1 downto 0);
latency_acc_overflow_o : out std_logic;
latency_acc_o : out std_logic_vector(g_acc_width-1 downto 0);
......@@ -88,6 +97,9 @@ architecture rtl of xrx_streamers_stats is
signal rcvd_frame_cnt : unsigned(g_cnt_width-1 downto 0);
signal lost_frame_cnt : unsigned(g_cnt_width-1 downto 0);
signal lost_block_cnt : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_late_cnt : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_match_cnt : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_timeout_cnt : unsigned(g_cnt_width-1 downto 0);
signal latency_cnt : unsigned(g_cnt_width-1 downto 0);
signal latency_max : std_logic_vector(27 downto 0);
......@@ -100,6 +112,9 @@ architecture rtl of xrx_streamers_stats is
signal lost_frame_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal lost_block_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal latency_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_late_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_match_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal rx_stat_timeout_cnt_d1 : unsigned(g_cnt_width-1 downto 0);
signal latency_max_d1 : std_logic_vector(27 downto 0);
signal latency_min_d1 : std_logic_vector(27 downto 0);
......@@ -121,6 +136,10 @@ begin
rcvd_frame_cnt <= (others => '0');
lost_frame_cnt <= (others => '0');
lost_block_cnt <= (others => '0');
rx_stat_timeout_cnt <= (others => '0');
rx_stat_late_cnt <= (others => '0');
rx_stat_match_cnt <= (others => '0');
else
-- count received frames
if(rcvd_frame_i = '1') then
......@@ -134,6 +153,19 @@ begin
if(lost_block_i = '1') then
lost_block_cnt <= lost_block_cnt + 1;
end if;
-- count fixed latency on-time frames
if(rx_stat_match_p1_i = '1') then
rx_stat_match_cnt <= rx_stat_match_cnt + 1;
end if;
-- count fixed latency late frames
if(rx_stat_late_p1_i = '1') then
rx_stat_late_cnt <= rx_stat_late_cnt + 1;
end if;
-- count fixed latency timed-out frames
if(rx_stat_timeout_p1_i = '1') then
rx_stat_timeout_cnt <= rx_stat_timeout_cnt + 1;
end if;
end if;
end if;
end process;
......@@ -198,6 +230,10 @@ begin
lost_block_cnt_d1 <= lost_block_cnt;
latency_cnt_d1 <= latency_cnt;
rx_stat_timeout_cnt_d1 <= rx_stat_timeout_cnt;
rx_stat_match_cnt_d1 <= rx_stat_match_cnt;
rx_stat_late_cnt_d1 <= rx_stat_late_cnt;
latency_max_d1 <= latency_max;
latency_min_d1 <= latency_min;
latency_acc_d1 <= latency_acc;
......@@ -211,6 +247,13 @@ begin
-------------------------------------------------------------------------------------------
-- snapshot or current value
-------------------------------------------------------------------------------------------
rx_stat_match_cnt_o <= std_logic_vector(rx_stat_match_cnt_d1) when (snapshot_ena_d1 = '1') else
std_logic_vector(rx_stat_match_cnt);
rx_stat_late_cnt_o <= std_logic_vector(rx_stat_late_cnt_d1) when (snapshot_ena_d1 = '1') else
std_logic_vector(rx_stat_late_cnt);
rx_stat_timeout_cnt_o <= std_logic_vector(rx_stat_timeout_cnt_d1) when (snapshot_ena_d1 = '1') else
std_logic_vector(rx_stat_timeout_cnt);
rcvd_frame_cnt_o <= std_logic_vector(rcvd_frame_cnt_d1) when (snapshot_ena_d1 = '1') else
std_logic_vector(rcvd_frame_cnt);
lost_frame_cnt_o <= std_logic_vector(lost_frame_cnt_d1) when (snapshot_ena_d1 = '1') else
......
This diff is collapsed.
This diff is collapsed.
`define WBGEN2_WR_STREAMERS_VERSION 32'h00000001
`define WBGEN2_WR_STREAMERS_VERSION 32'h00000002
`define ADDR_WR_STREAMERS_VER 8'h0
`define WR_STREAMERS_VER_ID_OFFSET 0
`define WR_STREAMERS_VER_ID 32'hffffffff
......@@ -135,3 +135,27 @@
`define ADDR_WR_STREAMERS_DUMMY 8'h84
`define WR_STREAMERS_DUMMY_DUMMY_OFFSET 0
`define WR_STREAMERS_DUMMY_DUMMY 32'hffffffff
`define ADDR_WR_STREAMERS_RSTR 8'h88
`define WR_STREAMERS_RSTR_RST_SW_OFFSET 0
`define WR_STREAMERS_RSTR_RST_SW 32'h00000001
`define ADDR_WR_STREAMERS_RX_STAT15 8'h8c
`define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB_OFFSET 0
`define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_STAT16 8'h90
`define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB_OFFSET 0
`define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_STAT17 8'h94
`define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB_OFFSET 0
`define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_STAT18 8'h98
`define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB_OFFSET 0
`define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_STAT19 8'h9c
`define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB_OFFSET 0
`define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_STAT20 8'ha0
`define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB_OFFSET 0
`define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB 32'hffffffff
`define ADDR_WR_STREAMERS_RX_CFG6 8'ha4
`define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_OFFSET 0
`define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT 32'h0fffffff
......@@ -12,6 +12,6 @@ modules = { "local" : ["../../..",
"../../../top/spec_1_1/wr_streamers_demo",
"../../../ip_cores/general-cores"]}
files = ["main.sv"]
files = ["main.sv","synthesis_descriptor.vhd"]
......@@ -46,8 +46,8 @@ module main;
.clk_125m_pllref_p_i (clk_ref),
.clk_125m_pllref_n_i (~clk_ref),
.fpga_pll_ref_clk_101_p_i (clk_ref),
.fpga_pll_ref_clk_101_n_i (~clk_ref),
.clk_125m_gtp_p_i (clk_ref),
.clk_125m_gtp_n_i (~clk_ref),
.clk_20m_vcxo_i(clk_20m),
......@@ -71,8 +71,8 @@ module main;
.clk_125m_pllref_p_i (clk_ref),
.clk_125m_pllref_n_i (~clk_ref),
.fpga_pll_ref_clk_101_p_i (clk_ref),
.fpga_pll_ref_clk_101_n_i (~clk_ref),
.clk_125m_gtp_p_i (clk_ref),
.clk_125m_gtp_n_i (~clk_ref),
.clk_20m_vcxo_i(clk_20m),
......@@ -91,8 +91,8 @@ module main;
// observe the link LEDs on both sides, and tell us when the link is ready.
wire link_up_a = SPEC_A.U_The_WR_Core.led_link_o;
wire link_up_b = SPEC_B.U_The_WR_Core.led_link_o;
wire link_up_a = SPEC_A.cmp_xwrc_board_spec.led_link_o;
wire link_up_b = SPEC_B.cmp_xwrc_board_spec.led_link_o;
initial begin
// wait until both SPECs see the Ethernet link. Otherwise the packet we're going
......
--------------------------------------------------------------------------------
-- SDB meta information for spec_wr_ref.xise.
--
-- This file was automatically generated by ../../ip_cores/general-cores/tools/sdb_desc_gen.tcl on:
-- Monday, May 13 2019
--
-- ../../ip_cores/general-cores/tools/sdb_desc_gen.tcl is part of OHWR general-cores:
-- https://www.ohwr.org/projects/general-cores/wiki
--
-- For more information on SDB meta information, see also:
-- https://www.ohwr.org/projects/sdb/wiki
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
package synthesis_descriptor is
constant c_sdb_synthesis_info : t_sdb_synthesis := (
syn_module_name => "spec_wr_ref ",
syn_commit_id => "94c94685dfc78fe1c2e81ba0467dc7b*",
syn_tool_name => "ISE ",
syn_tool_version => x"00000147",
syn_date => x"20190513",
syn_username => "Maciej Lipinski");
constant c_sdb_repo_url : t_sdb_repo_url := (
repo_url => "https://ohwr.org/project/wr-cores.git ");
end package synthesis_descriptor;
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /main/link_up_a
add wave -noupdate /main/link_up_b
add wave -noupdate -divider {SPEC A-common}
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/clk_ref_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/clk_sys_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/rst_n_i
add wave -noupdate -divider {SPEC A - WR timing}
add wave -noupdate /main/SPEC_A/dio_p_i(1)
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tm_time_valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tm_tai_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tm_cycles_i
add wave -noupdate -radix hexadecimal /main/link_up_a
add wave -noupdate -radix hexadecimal /main/link_up_b
add wave -noupdate -divider {SPEC A - common}
add wave -noupdate -radix hexadecimal /main/SPEC_A/clk_sys_62m5
add wave -noupdate -radix hexadecimal /main/SPEC_A/rst_sys_62m5_n
add wave -noupdate -radix hexadecimal /main/SPEC_A/rst_ref_125m_n
add wave -noupdate -radix hexadecimal /main/SPEC_A/clk_ref_125m
add wave -noupdate -divider {SPEC A - WR Timing}
add wave -noupdate -radix hexadecimal /main/SPEC_A/dio_p_i(1)
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/tm_time_valid_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/tm_tai_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/tm_cycles_o
add wave -noupdate -divider {SPEC A - pulse stamper}
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tag_tai_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tag_cycles_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_Pulse_Stamper/tag_valid_o
add wave -noupdate -divider {SPEC A - TX Streamer}
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_TX_Streamer/tx_data_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_TX_Streamer/tx_valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_TX_Streamer/tx_dreq_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_TX_Streamer/src_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/U_TX_Streamer/src_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/wrs_tx_data_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/wrs_tx_valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/wrs_tx_dreq_o
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/gen_wr_streamers/cmp_xwr_streamers/src_i
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/gen_wr_streamers/cmp_xwr_streamers/src_o
add wave -noupdate -divider {SPEC A - PHY}
add wave -noupdate -radix hexadecimal /main/SPEC_A/phy_tx_data
add wave -noupdate -radix hexadecimal /main/SPEC_A/phy_tx_k
add wave -noupdate -radix hexadecimal /main/SPEC_A/phy_tx_disparity
add wave -noupdate -radix hexadecimal /main/SPEC_A/phy_tx_enc_err
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/phy8_o.tx_data
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/phy8_o.tx_k
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/phy8_i.tx_disparity
add wave -noupdate -radix hexadecimal /main/SPEC_A/cmp_xwrc_board_spec/cmp_board_common/phy8_i.tx_enc_err
add wave -noupdate -divider {SPEC B - PHY}
add wave -noupdate -radix hexadecimal /main/SPEC_B/phy_rx_data
add wave -noupdate -radix hexadecimal /main/SPEC_B/phy_rx_rbclk
add wave -noupdate -radix hexadecimal /main/SPEC_B/phy_rx_k
add wave -noupdate -radix hexadecimal /main/SPEC_B/phy_rx_enc_err
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/phy8_i.rx_data
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/phy8_i.ref_clk
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/phy8_o.tx_k
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/phy8_i.tx_enc_err
add wave -noupdate -divider {SPEC B - WR timing}
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Stamper/tm_time_valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Stamper/tm_tai_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Stamper/tm_cycles_i
add wave -noupdate -divider {SPEC B - RX streamer}
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_RX_Streamer/snk_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_RX_Streamer/snk_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_RX_Streamer/rx_data_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_RX_Streamer/rx_valid_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_RX_Streamer/rx_dreq_i
add wave -noupdate /main/SPEC_B/U_Pulse_Stamper/tm_time_valid_i
add wave -noupdate /main/SPEC_B/U_Pulse_Stamper/tm_tai_i
add wave -noupdate /main/SPEC_B/U_Pulse_Stamper/tm_cycles_i
add wave -noupdate -divider {SPEC B - RX Streamer}
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/gen_wr_streamers/cmp_xwr_streamers/snk_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/gen_wr_streamers/cmp_xwr_streamers/snk_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/rx_data
add wave -noupdate -radix hexadecimal /main/SPEC_B/rx_valid
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/wrs_rx_data_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/wrs_rx_valid_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/cmp_xwrc_board_spec/cmp_board_common/wrs_rx_dreq_i
add wave -noupdate -divider {SPEC B - Timestamp adder}
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/a_tai_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/a_cycles_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/b_tai_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/b_cycles_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/valid_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/q_tai_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/q_cycles_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Add_Delay1/valid_o
add wave -noupdate -divider {SPEC B - pulse generator}
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/trig_ready_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/trig_tai_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/trig_cycles_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/trig_valid_i
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/trig_ready_o
add wave -noupdate -radix hexadecimal /main/SPEC_B/U_Pulse_Generator/pulse_o
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {593239379560 fs} 1} {{Cursor 2} {538394383110 fs} 0}
configure wave -namecolwidth 150
WaveRestoreCursors {{Cursor 1} {560018003180 fs} 0} {{Cursor 2} {530003823340 fs} 0}
configure wave -namecolwidth 221
configure wave -valuecolwidth 152
configure wave -justifyvalue left
configure wave -signalnamewidth 1
......@@ -72,4 +75,4 @@ configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {0 fs} {839137496540 fs}
WaveRestoreZoom {0 fs} {55629 ns}
action= "simulation"
target= "xilinx"
syn_device="xc6slx45t"
sim_tool="modelsim"
top_module="main"
sim_top="main"
vcom_opt="-mixedsvvh l"
fetchto="../../../ip_cores"
include_dirs=["../../../sim"]
modules = { "local" : ["../../..",
"../../../modules/wr_streamers",
"../../../ip_cores/general-cores"]}
files = ["main.sv"]
//
// White Rabbit Core Hands-On Course
//
// Lesson 04: Simulating the streamers
//
// Objectives:
// - demonstrate packet transfers in WR Core MAC interface
// - demonstrate the user interface of tx_streamer/rx_streamer modules.
// - demonstrate latency measurement feature of the streamers
//
// Brief description:
// A continuous sequence of 64-bit numbers (counting up from 0) is streamed
// via the TX streamer, sent as Ethernet packets over WR MAC interface and decoded
// in the RX streamer module.
//
`include "simdrv_defs.svh"
`include "if_wb_master.svh"
`include "if_wb_link.svh"
`timescale 1ns/1ps
import wishbone_pkg::*;
import streamers_pkg::*;
import wr_fabric_pkg::*;
class WBModule;
protected CBusAccessor m_bus;
protected uint64_t m_base;
function new(CBusAccessor bus, uint64_t base);
m_bus = bus;
m_base = base;
endfunction // new
task automatic writel(uint32_t addr, uint32_t data);
m_bus.write(m_base + addr, data);
endtask // writel
task automatic readl(uint32_t addr, ref uint32_t data);
uint64_t rv;
m_bus.read(m_base + addr, rv);
data = rv;
endtask // writel
endclass // unmatched endclass
class StreamersDriver extends WBModule;
function new(CBusAccessor bus, uint64_t base);
super.new(bus, base);
endfunction // new
task automatic configure();
// set fixed latency
// writel(`ADDR_WR_STREAMERS_RX_CFG5, 10); // in periods of 8ns.
// enable fixed latency (overide register)
// writel(`ADDR_WR_STREAMERS_CFG, 1<<21);
endtask // configure
endclass // WRStreamers
module main;
// Parameters
// Size of data record to be used by the streamers - in our case, a 64-bit
// word.
parameter g_record_size = 64;
parameter g_wr_cycles_per_second = 625000;
// 16-bit data, 2-bit address Wishbone bus that connects the WR MAC interfaces
// of both streamers
IWishboneLink #(16, 2) mac();
// Clock & reset
reg clk_ref = 0;
reg clk_sys = 0;
reg rst = 0;
// TX Streamer signals
reg tx_streamer_dvalid = 0;
reg [g_record_size-1:0] tx_streamer_data = 0;
reg tx_streamer_flush = 0;
reg tx_streamer_last = 0;
wire tx_streamer_dreq;
wire tx_streamer_sync;
// RX Streamer signals
reg rx_streamer_dreq = 0;
wire [g_record_size-1:0] rx_streamer_data;
wire rx_streamer_dvalid;
wire rx_streamer_lost;
wire [27:0] rx_latency;
wire rx_latency_valid;
// Fake White Rabbit reference clock (125 MHz) and cycle counte (we don't use
// TAI counter as the latency never exceeds 1 second...)
reg [27:0] tm_cycles = 0;
reg [39:0] tm_tai = 0;
// Currently transmitted counter value
int tx_counter = 0;
t_rx_streamer_cfg rx_streamer_cfg;
t_tx_streamer_cfg tx_streamer_cfg;
t_wrf_source_out src_out;
t_wrf_source_in src_in;
typedef struct {
bit [g_record_size-1:0] data;
time ts;
} t_queue_entry;
int tx_delay_count = 1;
initial #100 rst = 1;
always #8ns clk_ref <= ~clk_ref;
always #7.9ns clk_sys <= ~clk_sys;
// transfer queue. Used to pass sent data to the verification process.
t_queue_entry queue[$];
// WR clock cycle counter
always@(posedge clk_ref)
if( tm_cycles == g_wr_cycles_per_second - 1 )
begin
tm_cycles <= 0;
tm_tai <= tm_tai + 1;
end else
tm_cycles <= tm_cycles + 1;
// TX data stream generation.
always@(posedge clk_ref)
if(!rst)
begin
tx_streamer_dvalid <= 0;
tx_counter <= 0;
end else begin
// TX streamer is fed with a subsequent data word at random intervals (you can
// change the probability in the condition below). New value is sent only when
// the streamer can accept it (i.e. its tx_dreq_o output is active)
if(tx_delay_count > 0 )
tx_delay_count --;
// $display("txdc %d", tx_delay_count);
if(tx_streamer_dreq && (tx_delay_count == 0) ) begin
automatic t_queue_entry qe;
qe.data = tx_counter;
qe.ts = $time;
tx_delay_count = 300 + {$random} % 100;
queue.push_back(qe);
tx_streamer_data <= tx_counter;
tx_streamer_dvalid <= 1;
tx_streamer_last <= 1;
tx_streamer_flush <= 1;
tx_counter++;
end else
tx_streamer_dvalid <= 0;
end // if (rst)
// Instantiation of the streamers. The TX streamer will assemble packets
// containing max. 8 records, or flush the buffer after 512 clk cycles if
// it contains less than 8 records to prevent latency buildup.
xtx_streamer
#(
.g_data_width (g_record_size),
.g_tx_threshold (8),
.g_tx_buffer_size(16),
.g_tx_max_words_per_frame(16),
.g_tx_timeout (512),
.g_simulation(1),
.g_clk_ref_rate(62500000),
.g_use_ref_clock_for_data(1),
.g_sim_startup_cnt(100)
)
U_TX_Streamer
(
.clk_sys_i(clk_sys),
.rst_n_i (rst),
.src_o (src_out),
.src_i (src_in),
.clk_ref_i(clk_ref), // fake WR time
.tm_time_valid_i(1'b1),
.tm_cycles_i(tm_cycles),
.tm_tai_i(tm_tai),
.tx_data_i (tx_streamer_data),
.tx_valid_i (tx_streamer_dvalid),
.tx_dreq_o (tx_streamer_dreq),
.tx_last_p1_i( tx_streamer_last),
.tx_flush_p1_i( tx_streamer_flush),
.tx_sync_o(tx_streamer_sync),
.tx_streamer_cfg_i(tx_streamer_cfg)
);
// tx config
assign tx_streamer_cfg.ethertype = 16'hdbff;
assign tx_streamer_cfg.mac_local = 48'hdeadbeefcafe;
assign tx_streamer_cfg.mac_target = 48'hffffffffffff;
assign tx_streamer_cfg.qtag_ena = 1'b0;
assign rx_streamer_cfg.ethertype = 16'hdbff;
assign rx_streamer_cfg.mac_local = 48'h000000000000;
assign rx_streamer_cfg.mac_remote = 48'h000000000000;
assign rx_streamer_cfg.accept_broadcasts = 1'b1;
assign rx_streamer_cfg.filter_remote = 1'b0;
assign rx_streamer_cfg.fixed_latency = 200;
xrx_streamer
#(
.g_data_width (g_record_size),
.g_simulation(1),
.g_clk_ref_rate(62500000),
.g_use_ref_clock_for_data(1),
.g_sim_cycle_counter_range(g_wr_cycles_per_second)
)
U_RX_Streamer
(
.clk_sys_i (clk_sys),
.rst_n_i (rst),
.snk_i (src_out),
.snk_o (src_in),
.clk_ref_i(clk_ref), // fake WR time
.tm_time_valid_i(1'b1),
.tm_cycles_i(tm_cycles),
.tm_tai_i(tm_tai),
.rx_data_o (rx_streamer_data),
.rx_valid_o (rx_streamer_dvalid),
.rx_dreq_i (rx_streamer_dreq),
.rx_latency_o (rx_latency),
.rx_latency_valid_o(rx_latency_valid),
.rx_streamer_cfg_i(rx_streamer_cfg)
);
initial rx_streamer_dreq = 1'b1;
// Client-side reception logic. Compares the received records with their copies
// stored in the queue.
always@(posedge clk_ref)
if(!rst)
begin
rx_streamer_dreq <= 1;
end else begin
if(rx_streamer_dvalid)
begin
// Got a record? Compare it against the copy stored in queue.
automatic t_queue_entry qe = queue.pop_front();
automatic time ts_rx = $time, delta;
const time c_pipeline_delay = 64ns;
if( rx_streamer_data != qe.data )
begin
$error("Failure: got rec %x, should be %x", rx_streamer_data, qe.data);
end
// $display("Tx ts %t rx ts %t", qe.ts, ts_rx);
delta = ts_rx - qe.ts - rx_streamer_cfg.fixed_latency * 16ns - c_pipeline_delay;
$display("delta: %.3f us %t", real'(delta) / real'(1us), delta );
end // if (rx_streamer_dvalid)
end // else: !if(!rst)
// Show the latency value when a new frame arrives
// always@(posedge clk)
// if(rst && rx_latency_valid)
// $display("This frame's latency: %.3f microseconds\n", real'(rx_latency) * 0.008);
endmodule // main
# make -f Makefile > /dev/null 2>&1
vsim -L unisim work.main -novopt -suppress 8684,8683
set NumericStdNoWarnings 1
set StdArithNoWarnings 1
do wave.do
run 10us
wave zoomfull
radix -hex
This diff is collapsed.
files = ["spec_top.vhd", "spec_top.ucf", "spec_reset_gen.vhd","timestamp_adder.vhd" ]
files = ["spec_top.vhd", "spec_top.ucf", "timestamp_adder.vhd" ]
modules = { "local" : ["../../../", "../../../platform/xilinx/chipscope"] }
\ No newline at end of file
modules = { "local" : ["../../../", "../../../platform/xilinx/chipscope",
"../../../board/spec/"] }
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
use work.gencores_pkg.all;
entity spec_reset_gen is
port (
clk_sys_i : in std_logic;
rst_pcie_n_a_i : in std_logic;
rst_button_n_a_i : in std_logic;
rst_n_o : out std_logic
);
end spec_reset_gen;
architecture behavioral of spec_reset_gen is
signal powerup_cnt : unsigned(7 downto 0) := x"00";
signal button_synced_n : std_logic;
signal pcie_synced_n : std_logic;
signal powerup_n : std_logic := '0';
begin -- behavioral
U_EdgeDet_PCIe : gc_sync_ffs port map (
clk_i => clk_sys_i,
rst_n_i => '1',
data_i => rst_pcie_n_a_i,
ppulse_o => pcie_synced_n);
U_Sync_Button : gc_sync_ffs port map (
clk_i => clk_sys_i,
rst_n_i => '1',
data_i => rst_button_n_a_i,
synced_o => button_synced_n);
p_powerup_reset : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(powerup_cnt /= x"ff") then
powerup_cnt <= powerup_cnt + 1;
powerup_n <= '0';
else
powerup_n <= '1';
end if;
end if;
end process;
rst_n_o <= powerup_n and button_synced_n and (not pcie_synced_n);
end behavioral;
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment