Commit 39aedf14 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Maciej Lipinski

streamers: bunch of improvements, including addition of ts_restore_tai [WIP]

parent f654ad0b
......@@ -15,5 +15,6 @@ files = ["streamers_pkg.vhd",
"xrx_streamers_stats.vhd",
"fixed_latency_delay.vhd",
"fixed_latency_ts_match.vhd",
"fifo_showahead_adapter.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
......
......@@ -31,7 +31,9 @@ entity fixed_latency_delay is
d_last_i : in std_logic;
d_sync_i : in std_logic;
d_target_ts_en_i : in std_logic;
d_target_ts_i : in std_logic_vector(27 downto 0);
d_target_ts_tai_i : in std_logic_vector(39 downto 0);
d_target_ts_cycles_i : in std_logic_vector(27 downto 0);
d_target_ts_error_i : in std_logic;
d_valid_i : in std_logic;
d_drop_i : in std_logic;
......@@ -81,6 +83,9 @@ architecture rtl of fixed_latency_delay is
signal delay_match : std_logic;
signal delay_miss : std_logic;
signal fifo_target_ts_error : std_logic;
signal fifo_target_ts_tai : std_logic_vector(39 downto 0);
signal fifo_target_ts_cycles : std_logic_vector(27 downto 0);
begin
......@@ -102,8 +107,10 @@ begin
dbuf_d(g_data_width+1) <= d_sync_i;
dbuf_d(g_data_width+2) <= d_target_ts_en_i;
dbuf_d(g_data_width+3+27 downto g_data_width+3) <= d_target_ts_i;
dbuf_d(g_data_width+3+28+39 downto g_data_width+3+28) <= d_target_ts_tai_i;
dbuf_d(g_data_width+3+28+40) <= d_target_ts_error_i;
U_DropBuffer : entity work.dropping_buffer
generic map (
g_size => g_buffer_size,
......@@ -164,7 +171,7 @@ begin
when TS_SETUP_MATCH =>
if fifo_valid = '1' then
if fifo_target_ts_en = '1' then
if fifo_target_ts_en = '1' and fifo_target_ts_error = '0' then
state <= TS_WAIT_MATCH;
else
state <= SEND;
......@@ -208,7 +215,8 @@ begin
clk_i => clk_ref_i,
rst_n_i => rst_n_ref,
arm_i => delay_arm,
ts_origin_i => fifo_target_ts,
ts_tai_i => fifo_target_ts_tai,
ts_cycles_i => fifo_target_ts_cycles,
ts_latency_i => rx_streamer_cfg_i.fixed_latency,
tm_time_valid_i => tm_time_valid_i,
tm_tai_i => tm_tai_i,
......@@ -246,7 +254,9 @@ begin
fifo_last <= fifo_q(g_data_width);
fifo_sync <= fifo_q(g_data_width+1);
fifo_target_ts_en <= fifo_q(g_data_width+2);
fifo_target_ts <= fifo_q(g_data_width + 3 + 27 downto g_data_width + 3);
fifo_target_ts_cycles <= fifo_q(g_data_width+3+27 downto g_data_width+3);
fifo_target_ts_tai <= fifo_q(g_data_width+3+28+39 downto g_data_width+3+28);
fifo_target_ts_error <= fifo_q(g_data_width+3+28+40);
rx_data_o <= fifo_data;
rx_valid_o <= rx_valid;
......
......@@ -15,7 +15,9 @@ entity fixed_latency_ts_match is
rst_n_i : in std_logic;
arm_i : in std_logic;
ts_origin_i : in std_logic_vector(27 downto 0);
ts_tai_i : in std_logic_vector(39 downto 0);
ts_cycles_i : in std_logic_vector(27 downto 0);
ts_latency_i : in std_logic_vector(27 downto 0);
-- Time valid flag
......@@ -53,23 +55,44 @@ architecture rtl of fixed_latency_ts_match is
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 ts_adjusted : unsigned(28 downto 0);
signal armed : std_logic;
signal ts_adjusted_cycles : unsigned(28 downto 0);
signal ts_adjusted_tai : unsigned(39 downto 0);
signal tm_cycles_scaled : unsigned(28 downto 0);
signal ts_latency_scaled : unsigned(28 downto 0);
signal match : std_logic;
signal tm_cycles_scaled_d : unsigned(28 downto 0);
signal ts_latency_scaled_d : unsigned(28 downto 0);
signal ts_adjusted_d : unsigned(28 downto 0);
signal match, late : std_logic;
signal state : t_state;
signal ts_adj_next_cycle, roll_lo, roll_hi : std_logic;
attribute mark_debug : string;
attribute mark_debug of ts_adjusted_d : signal is "TRUE";
attribute mark_debug of tm_cycles_scaled_d : signal is "TRUE";
attribute mark_debug of ts_latency_scaled_d : signal is "TRUE";
attribute mark_debug of state : signal is "TRUE";
attribute mark_debug of match : signal is "TRUE";
attribute mark_debug of late : signal is "TRUE";
begin
process(clk_i)
begin
if rising_edge(clk_i) then
ts_adjusted_d <= ts_adjusted_cycles;
tm_cycles_scaled_d <= tm_cycles_scaled;
ts_latency_scaled_d <= ts_latency_scaled;
end if;
end process;
process(tm_cycles_i, ts_latency_i)
begin
if g_clk_ref_rate = 62500000 then
......@@ -89,8 +112,7 @@ begin
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
armed <= '0';
late_o <= '0';
late <= '0';
match <= '0';
State <= IDLE;
......@@ -99,54 +121,44 @@ begin
case State is
when IDLE =>
match <= '0';
late_o <= '0';
armed <= '0';
late <= '0';
if arm_i = '1' then
ts_adjusted <= resize(unsigned(ts_origin_i) + unsigned(ts_latency_i), 29);
State <= WRAP_ADJ_TS;
armed <= '1';
ts_adjusted_cycles <= resize(unsigned(ts_cycles_i) + unsigned(ts_latency_i), 29);
ts_adjusted_tai <= resize(unsigned(ts_tai_i), 40);
State <= WRAP_ADJ_TS;
end if;
when WRAP_ADJ_TS =>
ts_adj_next_cycle <= '0';
roll_lo <= '0';
roll_hi <= '0';
if ts_adjusted >= f_cycles_counter_range then
ts_adj_next_cycle <= '1';
ts_adjusted <= ts_adjusted - f_cycles_counter_range;
if ts_adjusted_cycles >= f_cycles_counter_range then
ts_adjusted_cycles <= ts_adjusted_cycles - f_cycles_counter_range;
ts_adjusted_tai <= ts_adjusted_tai + 1;
end if;
if ts_adjusted < c_rollover_threshold_lo then
roll_lo <= '1';
end if;
State <= CHECK_LATE;
if tm_cycles_scaled > c_rollover_threshold_hi then
roll_hi <= '1';
when CHECK_LATE =>
if tm_time_valid_i = '0' then
late <= '1';
state <= IDLE;
end if;
State <= CHECK_LATE;
when CHECK_LATE =>
if roll_lo = '1' and roll_hi = '1' then
if ts_adj_next_cycle = '0' then
late_o <= '1';
State <= IDLE;
else
State <= WAIT_TRIG;
end if;
if ts_adjusted_tai < unsigned(tm_tai_i) then
late <= '1';
State <= IDLE;
elsif ts_adjusted_tai = unsigned(tm_tai_i) and ts_adjusted_cycles <= tm_cycles_scaled then
late <= '1';
State <= IDLE;
else
State <= WAIT_TRIG;
end if;
when WAIT_TRIG =>
if ts_adjusted = tm_cycles_scaled then
if ts_adjusted_cycles = tm_cycles_scaled and ts_adjusted_tai = unsigned(tm_tai_i) then
match <= '1';
State <= IDLE;
end if;
......@@ -157,5 +169,6 @@ begin
end process;
match_o <= match;
late_o <= late;
end rtl;
......@@ -218,7 +218,10 @@ package streamers_pkg is
g_buffer_size : integer := 256;
g_escape_code_disable : boolean := FALSE;
g_expected_words_number : integer := 0;
g_clk_ref_rate : integer := 125000000);
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;
......@@ -302,7 +305,8 @@ package streamers_pkg is
g_slave_mode : t_wishbone_interface_mode := CLASSIC;
g_slave_granularity : t_wishbone_address_granularity := BYTE;
g_simulation : integer := 0;
g_use_ref_clock_for_data : integer := 0
g_use_ref_clock_for_data : integer := 0;
g_sim_cycle_counter_range : integer := 125000
);
port (
......
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;
This diff is collapsed.
......@@ -204,8 +204,17 @@ architecture rtl of xtx_streamer is
signal link_ok_delay_expired : std_logic;
signal link_ok_delay_expired_ref : std_logic;
signal link_ok_ref : std_logic;
signal clk_data : std_logic;
attribute mark_debug : string;
attribute mark_debug of link_ok_delay_cnt : signal is "true";
attribute mark_debug of link_ok_delay_expired_ref : signal is "true";
attribute mark_debug of link_ok_delay_expired : signal is "true";
attribute mark_debug of link_ok_ref : signal is "true";
signal clk_data : std_logic;
signal rst_n_ref : std_logic;
signal stamper_pulse_a : std_logic;
......@@ -413,20 +422,21 @@ begin -- rtl
tx_fifo_last <= tx_fifo_q(g_data_width);
U_Timestamper : pulse_stamper
U_Timestamper : entity work.pulse_stamper_sync
generic map(
g_ref_clk_rate => g_clk_ref_rate)
port map (
clk_ref_i => clk_ref_i,
clk_sys_i => clk_sys_i,
rst_n_i => rst_int_n,
pulse_a_i => stamper_pulse_a,
pulse_i => stamper_pulse_a,
tm_time_valid_i => tm_time_valid_i,
tm_tai_i => tm_tai_i,
tm_cycles_i => tm_cycles_i,
tag_tai_o => open,
tag_cycles_o => tag_cycles,
tag_valid_o => tag_valid);
tag_valid_o => tag_valid,
tag_error_o => tag_error);
buf_frame_count_inc_ref <= tx_fifo_we and tx_last_p1_i;
buf_frame_count_dec_sys <= tx_fifo_rd and tx_fifo_last;
......@@ -563,7 +573,12 @@ begin -- rtl
when x"07" =>
if(tx_streamer_cfg_i.qtag_ena = '0') then
fsm_out.data <= "1000" & tag_cycles(27 downto 16);
if tag_error = '1' then
fsm_out.data <= x"ffff";
else
fsm_out.data <= "1000" & tag_cycles(27 downto 16);
end if;
if tag_valid_latched = '1' then
count <= count + 1;
fsm_out.dvalid <= '1';
......@@ -589,7 +604,13 @@ begin -- rtl
else
fsm_out.dvalid <= '0';
end if;
fsm_out.data <= "1000" & tag_cycles(27 downto 16);
if tag_error = '1' then
fsm_out.data <= x"ffff";
else
fsm_out.data <= "1000" & tag_cycles(27 downto 16);
end if;
when x"0A" =>
fsm_out.data <= tag_cycles(15 downto 0);
state <= FRAME_SEQ_ID;
......
......@@ -99,7 +99,8 @@ entity xwr_streamers is
-----------------------------------------------------------------------------------------
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 (
......@@ -274,7 +275,10 @@ begin
g_buffer_size => g_rx_streamer_params.buffer_size,
g_escape_code_disable => g_rx_streamer_params.escape_code_disable,
g_expected_words_number => g_rx_streamer_params.expected_words_number,
g_clk_ref_rate => g_clk_ref_rate
g_clk_ref_rate => g_clk_ref_rate,
g_simulation => g_simulation,
g_sim_cycle_counter_range => g_sim_cycle_counter_range,
g_use_ref_clock_for_data => g_use_ref_clock_for_data
)
port map(
clk_sys_i => clk_sys_i,
......
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