Commit ddf3f87e authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Maciej Lipinski

wr_streamers: async data path option for Tx streamer [wip]

added gc_async_counter_diff to general-cores, thus
updating the submodules
parent 23991f9b
Subproject commit 4e5f7badf0b72f51bdb01c63fcdc6d69afb4b750
Subproject commit e071a1065e0db20983a6f44f818c1a0111431b6d
......@@ -12,5 +12,8 @@ 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"
];
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;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.genram_pkg.all;
use work.streamers_priv_pkg.all;
use work.streamers_pkg.all;
entity fixed_latency_delay is
generic(
g_data_width : integer;
g_buffer_size : integer;
g_use_ref_clock_for_data : integer;
g_clk_ref_rate : integer
);
port(
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
clk_ref_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);
-- input i/f (dropping buffer)
d_data_i : in std_logic_vector(g_data_width-1 downto 0);
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_valid_i : in std_logic;
d_drop_i : in std_logic;
d_accept_i : in std_logic;
d_req_o : out std_logic;
-- output data path (clk_ref_i/clk_sys_i clock domain for
-- g_use_ref_clock_for_data = 1/0 respectively)
rx_first_p1_o : out std_logic;
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_dreq_i : in std_logic;
rx_streamer_cfg_i : in t_rx_streamer_cfg
);
end entity;
architecture rtl of fixed_latency_delay is
type t_state is (IDLE, WAIT_TS_MATCH, SEND);
signal State: t_state;
signal clk_data : std_logic;
signal rst_n_data : std_logic;
signal rst_n_ref : std_logic;
signal wr_full : std_logic;
constant c_datapath_width : integer := g_data_width + 2 + 28 + 1;
signal fifo_rd : std_logic;
signal dbuf_d : std_logic_vector(c_datapath_width-1 downto 0);
signal dbuf_q : std_logic_vector(c_datapath_width-1 downto 0);
signal fifo_d : std_logic_vector(c_datapath_width-1 downto 0);
signal fifo_q : std_logic_vector(c_datapath_width-1 downto 0);
signal dbuf_q_valid : std_logic;
signal dbuf_req : std_logic;
signal fifo_q_int : std_logic_vector(c_datapath_width-1 downto 0);
signal fifo_rd_int, fifo_empty_int, fifo_q_valid : std_logic;
signal fifo_data : std_logic_vector(g_data_width-1 downto 0);
signal fifo_sync, fifo_last, fifo_target_ts_en : std_logic;
signal fifo_target_ts : std_logic_vector(27 downto 0);
signal fifo_we : std_logic;
signal delay_arm : std_logic;
signal delay_match : std_logic;
signal delay_miss : 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);
clk_data <= clk_sys_i when g_use_ref_clock_for_data = 0 else clk_ref_i;
rst_n_data <= rst_n_i when g_use_ref_clock_for_data = 0 else rst_n_ref;
dbuf_d(g_data_width-1 downto 0) <= d_data_i;
dbuf_d(g_data_width) <= d_last_i;
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;
U_DropBuffer : entity work.dropping_buffer
generic map (
g_size => g_buffer_size,
g_data_width => c_datapath_width)
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
d_i => dbuf_d,
d_req_o => d_req_o,
d_drop_i => d_drop_i,
d_accept_i => d_accept_i,
d_valid_i => d_valid_i,
d_o => dbuf_q,
d_valid_o => dbuf_q_valid,
d_req_i => dbuf_req);
dbuf_req <= not wr_full;
fifo_we <= dbuf_q_valid and not wr_full;
U_ClockSyncFifo : generic_async_fifo
generic map (
g_data_width => c_datapath_width,
g_size => 16,
g_show_ahead => false)
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_sys_i,
d_i => dbuf_q,
we_i => dbuf_q_valid,
wr_full_o => wr_full,
clk_rd_i => clk_data,
q_o => fifo_q_int,
rd_i => fifo_rd_int,
rd_empty_o => fifo_empty_int);
U_ShowaheadForFIFO : entity work.fifo_showahead_adapter
generic map (
g_width => c_datapath_width)
port map (
clk_i => clk_data,
rst_n_i => rst_n_data,
fifo_q_i => fifo_q_int,
fifo_empty_i => fifo_empty_int,
fifo_rd_o => fifo_rd_int,
q_o => fifo_q,
valid_o => fifo_q_valid,
rd_i => fifo_rd);
process(clk_data)
begin
if rising_edge(clk_data) then
if rst_n_data = '0' then
state <= IDLE;
else
case state is
when IDLE =>
if fifo_q_valid = '1' then
if fifo_target_ts_en = '1' then
state <= WAIT_TS_MATCH;
else
state <= SEND;
end if;
end if;
when WAIT_TS_MATCH =>
if delay_miss = '1' then
state <= IDLE;
elsif delay_match = '1' then
state <= SEND;
end if;
when SEND =>
if fifo_last = '1' then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
U_Compare: entity work.fixed_latency_ts_match
generic map (
g_clk_ref_rate => g_clk_ref_rate)
port map (
clk_i => clk_ref_i,
rst_n_i => rst_n_ref,
arm_i => delay_arm,
ts_origin_i => fifo_target_ts,
ts_latency_i => rx_streamer_cfg_i.fixed_latency,
tm_time_valid_i => tm_time_valid_i,
tm_tai_i => tm_tai_i,
tm_cycles_i => tm_cycles_i,
match_o => delay_match,
miss_o => delay_miss);
process(state, rx_dreq_i, delay_match, fifo_target_ts_en, fifo_q_valid)
begin
case state is
when IDLE =>
fifo_rd <= fifo_q_valid and rx_dreq_i and not fifo_target_ts_en;
delay_arm <= fifo_q_valid and fifo_target_ts_en;
rx_valid_o <= fifo_q_valid and not fifo_target_ts_en;
rx_first_p1_o <= fifo_sync and not fifo_target_ts_en;
rx_last_p1_o <= fifo_last and not fifo_target_ts_en;
when WAIT_TS_MATCH =>
fifo_rd <= '0';
delay_arm <= '0';
rx_valid_o <= '0';
rx_first_p1_o <= '0';
rx_last_p1_o <= '0';
when SEND =>
fifo_rd <= rx_dreq_i;
delay_arm <= '0';
rx_first_p1_o <= fifo_sync;
rx_last_p1_o <= fifo_last;
rx_valid_o <= fifo_q_valid;
end case;
end process;
fifo_data <= fifo_q(g_data_width-1 downto 0);
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);
rx_data_o <= fifo_data;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fixed_latency_ts_match is
generic
(g_clk_ref_rate : integer);
port
(
clk_i : in std_logic;
rst_n_i : in std_logic;
arm_i : in std_logic;
ts_origin_i : in std_logic_vector(27 downto 0);
ts_latency_i : in std_logic_vector(27 downto 0);
-- Time valid flag
tm_time_valid_i : in std_logic := '0';
-- TAI seconds
tm_tai_i : in std_logic_vector(39 downto 0) := x"0000000000";
-- Fractional part of the second (in clk_ref_i cycles)
tm_cycles_i : in std_logic_vector(27 downto 0) := x"0000000";
match_o : out std_logic;
miss_o : out std_logic
);
end entity;
architecture rtl of fixed_latency_ts_match is
constant c_unwrap_threshold : integer := 62500000;
signal ts_adjusted : unsigned(28 downto 0);
signal target_cycles : unsigned(28 downto 0);
signal delta : signed(28 downto 0);
signal arm_d : std_logic_vector(2 downto 0);
signal armed : std_logic;
signal tm_cycles_scaled : unsigned(28 downto 0);
begin
process(tm_cycles_i)
begin
if g_clk_ref_rate = 62500000 then
tm_cycles_scaled <= unsigned(tm_cycles_i & '0');
elsif g_clk_ref_rate = 125000000 then
tm_cycles_scaled <= unsigned('0' & tm_cycles_i);
else
report "Unsupported g_clk_ref_rate (62.5 / 125 MHz)" severity failure;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
arm_d <= (others => '0');
miss_o <= '0';
else
arm_d <= arm_d(1 downto 0) & arm_i;
if arm_i = '1' then
match_o <= '0';
miss_o <= '0';
ts_adjusted <= resize(unsigned(ts_origin_i) + unsigned(ts_latency_i), 29);
delta <= signed('0'&ts_origin_i) + signed('0'&ts_latency_i) - signed('0'&tm_cycles_i);
end if;
if delta < -c_unwrap_threshold or delta > c_unwrap_threshold then
ts_adjusted <= ts_adjusted + 125000000;
target_cycles <= tm_cycles_scaled + 125000000;
else
target_cycles <= tm_cycles_scaled;
end if;
if (arm_d(1) = '1') then
if ts_adjusted < target_cycles then
miss_o <= '1';
else
armed <= '1';
end if;
end if;
if armed = '1' and ts_adjusted = target_cycles then
match_o <= '1';
armed <= '0';
else
match_o <= '0';
end if;
end if;
end if;
end process;
end rtl;
......@@ -184,13 +184,14 @@ package streamers_pkg is
g_escape_code_disable : boolean := FALSE;
g_simulation : integer := 0;
g_sim_startup_cnt : integer := 6250;--100us
g_clk_ref_rate : integer := 125000000);
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";
......@@ -294,7 +295,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_use_ref_clock_for_data : integer := 0
);
port (
......@@ -333,4 +335,4 @@ package streamers_pkg is
);
end component;
end streamers_pkg;
\ No newline at end of file
end streamers_pkg;
This diff is collapsed.
This diff is collapsed.
......@@ -75,6 +75,12 @@ entity xwr_streamers is
-- 125MHz for WR Nodes. There are some WR Nodes that work with 62.5MHz.
-- in the future, more frequences might be supported..
g_clk_ref_rate : integer := 125000000;
-- when non-zero, the datapath (tx_/rx_ ports) 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.
g_use_ref_clock_for_data : integer := 0;
-----------------------------------------------------------------------------------------
-- Transmission/reception parameters
-----------------------------------------------------------------------------------------
......@@ -97,11 +103,22 @@ entity xwr_streamers is
);
port (
---------------------------------------------------------------------------
-- Clocks & Resets
---------------------------------------------------------------------------
-- System clock. Used always for the WR fabric interface (src/snk) and
-- for the data path (tx_/rx_ ports) if g_use_ref_clock_for_data = 0.
clk_sys_i : in std_logic;
-- WR Reference clock, 62.5 or 125 MHz. Frequency must match g_ref_clk_rate
-- generic. Used for latency measurement and timestamping (tm_ ports).
-- It also clocks Tx_/rx_ interfaces if g_use_ref_clock_for_data != 0.
clk_ref_i : in std_logic := '0';
rst_n_i : in std_logic;
---------------------------------------------------------------------------
-- WR tx/rx interface
-- WR tx/rx interface (clk_sys clock domain)
---------------------------------------------------------------------------
-- Tx
src_i : in t_wrf_source_in;
......@@ -110,8 +127,9 @@ entity xwr_streamers is
snk_i : in t_wrf_sink_in;
snk_o : out t_wrf_sink_out;
---------------------------------------------------------------------------
-- User tx interface
-- User tx interface (clk_data clock domain)
---------------------------------------------------------------------------
-- Data word to be sent.
tx_data_i : in std_logic_vector(g_tx_streamer_params.data_width-1 downto 0);
......@@ -146,8 +164,6 @@ entity xwr_streamers is
-- WRC Timing interface, used for latency measurement
---------------------------------------------------------------------------
-- White Rabbit reference clock
clk_ref_i : in std_logic := '0';
-- Time valid flag
tm_time_valid_i : in std_logic := '0';
-- TAI seconds
......@@ -220,13 +236,14 @@ begin
g_tx_timeout => g_tx_streamer_params.timeout,
g_escape_code_disable => g_tx_streamer_params.escape_code_disable,
g_simulation => g_simulation,
g_clk_ref_rate => g_clk_ref_rate)
g_clk_ref_rate => g_clk_ref_rate,
g_use_ref_clock_for_data => g_use_ref_clock_for_data)
port map(
clk_sys_i => clk_sys_i,
clk_ref_i => clk_ref_i,
rst_n_i => rst_n_i,
src_i => src_i,
src_o => src_o,
clk_ref_i => clk_ref_i,
tm_time_valid_i => tm_time_valid_i,
tm_tai_i => tm_tai_i,
tm_cycles_i => tm_cycles_i,
......@@ -471,4 +488,4 @@ begin
rx_streamer_cfg_i.filter_remote;
rx_streamer_cfg.fixed_latency <= from_wb.rx_cfg5_fixed_latency_o when (from_wb.cfg_or_rx_fix_lat_o='1') else
rx_streamer_cfg_i.fixed_latency;
end rtl;
\ No newline at end of file
end rtl;
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