Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit core collection
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
30
Issues
30
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
White Rabbit core collection
Commits
d116d6b1
Commit
d116d6b1
authored
Oct 04, 2018
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wr_streamers: async data path option for Tx streamer [wip]
parent
1254a4f7
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1115 additions
and
357 deletions
+1115
-357
Manifest.py
modules/wr_streamers/Manifest.py
+6
-2
build_wb.sh
modules/wr_streamers/build_wb.sh
+0
-0
fifo_showahead_adapter.vhd
modules/wr_streamers/fifo_showahead_adapter.vhd
+57
-0
fixed_latency_delay.vhd
modules/wr_streamers/fixed_latency_delay.vhd
+238
-0
fixed_latency_ts_match.vhd
modules/wr_streamers/fixed_latency_ts_match.vhd
+102
-0
gc_async_counter_diff.vhd
modules/wr_streamers/gc_async_counter_diff.vhd
+125
-0
streamers_pkg.vhd
modules/wr_streamers/streamers_pkg.vhd
+6
-4
xrx_streamer.vhd
modules/wr_streamers/xrx_streamer.vhd
+259
-234
xtx_streamer.vhd
modules/wr_streamers/xtx_streamer.vhd
+298
-110
xwr_streamers.vhd
modules/wr_streamers/xwr_streamers.vhd
+24
-7
No files found.
modules/wr_streamers/Manifest.py
View file @
d116d6b1
...
...
@@ -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"
,
"gc_async_counter_diff.vhd"
,
"fixed_latency_delay.vhd"
,
"fixed_latency_ts_match.vhd"
,
"fifo_showahead_adapter.vhd"
];
modules/wr_streamers/build_wb.sh
100755 → 100644
View file @
d116d6b1
File mode changed from 100755 to 100644
modules/wr_streamers/fifo_showahead_adapter.vhd
0 → 100644
View file @
d116d6b1
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
;
modules/wr_streamers/fixed_latency_delay.vhd
0 → 100644
View file @
d116d6b1
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
;
modules/wr_streamers/fixed_latency_ts_match.vhd
0 → 100644
View file @
d116d6b1
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
;
modules/wr_streamers/gc_async_counter_diff.vhd
0 → 100644
View file @
d116d6b1
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
use
work
.
gencores_pkg
.
all
;
entity
gc_async_counter_diff
is
generic
(
g_bits
:
integer
:
=
8
;
g_output_clock
:
string
:
=
"inc"
);
port
(
-- reset (g_output_clock clock domain)
rst_n_i
:
in
std_logic
;
-- increment clock
clk_inc_i
:
in
std_logic
;
-- decrement clock
clk_dec_i
:
in
std_logic
;
-- increment enable (clk_inc_i clock domain)
inc_i
:
in
std_logic
;
-- decrement enable (clk_inc_i clock domain)
dec_i
:
in
std_logic
;
-- current counter value, signed (g_output_clock clock domain)
counter_o
:
out
std_logic_vector
(
g_bits
downto
0
)
);
end
gc_async_counter_diff
;
architecture
rtl
of
gc_async_counter_diff
is
signal
cnt1_bin
,
cnt2_bin
:
unsigned
(
g_bits
downto
0
);
signal
cnt1_gray
,
cnt2_gray
:
std_logic_vector
(
g_bits
downto
0
);
signal
cnt1_gray_out
:
std_logic_vector
(
g_bits
downto
0
);
signal
cnt2_gray_out
:
std_logic_vector
(
g_bits
downto
0
);
signal
rst_n_inc
,
rst_n_dec
:
std_logic
;
begin
U_SyncReset_to_IncClk
:
gc_sync_ffs
port
map
(
clk_i
=>
clk_inc_i
,
rst_n_i
=>
'1'
,
data_i
=>
rst_n_i
,
synced_o
=>
rst_n_inc
);
U_SyncReset_to_DecClk
:
gc_sync_ffs
port
map
(
clk_i
=>
clk_dec_i
,
rst_n_i
=>
'1'
,
data_i
=>
rst_n_i
,
synced_o
=>
rst_n_dec
);
p_count_up
:
process
(
clk_inc_i
)
begin
if
rising_edge
(
clk_inc_i
)
then
if
rst_n_inc
=
'0'
then
cnt1_bin
<=
(
others
=>
'0'
);
cnt1_gray
<=
(
others
=>
'0'
);
else
if
inc_i
=
'1'
then
cnt1_bin
<=
cnt1_bin
+
1
;
end
if
;
cnt1_gray
<=
f_gray_encode
(
std_logic_vector
(
cnt1_bin
));
end
if
;
end
if
;
end
process
;
p_count_down
:
process
(
clk_dec_i
)
begin
if
rising_edge
(
clk_dec_i
)
then
if
rst_n_dec
=
'0'
then
cnt2_bin
<=
(
others
=>
'0'
);
cnt2_gray
<=
(
others
=>
'0'
);
else
if
dec_i
=
'1'
then
cnt2_bin
<=
cnt2_bin
+
1
;
end
if
;
cnt2_gray
<=
f_gray_encode
(
std_logic_vector
(
cnt2_bin
));
end
if
;
end
if
;
end
process
;
gen_out_clock_is_inc
:
if
g_output_clock
=
"inc"
generate
cnt1_gray_out
<=
cnt1_gray
;
U_Sync
:
gc_sync_register
generic
map
(
g_width
=>
g_bits
+
1
)
port
map
(
clk_i
=>
clk_inc_i
,
rst_n_a_i
=>
rst_n_i
,
d_i
=>
cnt2_gray
,
q_o
=>
cnt2_gray_out
);
end
generate
gen_out_clock_is_inc
;
gen_out_clock_is_dec
:
if
g_output_clock
=
"dec"
generate
cnt2_gray_out
<=
cnt2_gray
;
U_Sync
:
gc_sync_register
generic
map
(
g_width
=>
g_bits
+
1
)
port
map
(
clk_i
=>
clk_dec_i
,
rst_n_a_i
=>
rst_n_i
,
d_i
=>
cnt1_gray
,
q_o
=>
cnt1_gray_out
);
end
generate
gen_out_clock_is_dec
;
counter_o
<=
std_logic_vector
(
unsigned
(
cnt2_gray_out
)
-
unsigned
(
cnt1_gray_out
));
end
rtl
;
modules/wr_streamers/streamers_pkg.vhd
View file @
d116d6b1
...
...
@@ -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
;
modules/wr_streamers/xrx_streamer.vhd
View file @
d116d6b1
...
...
@@ -46,7 +46,7 @@ use work.streamers_priv_pkg.all;
use
work
.
streamers_pkg
.
all
;
entity
xrx_streamer
is
generic
(
-- Width of the data words, must be multiple of 16 bits. This value set to this generic
-- on the receviving device must be the same as the value of g_tx_data_width set on the
...
...
@@ -54,16 +54,16 @@ entity xrx_streamer is
-- values in the same device (i.e. instantiation of xwr_transmission entity). It is the
-- responsibility of a network designer to make sure these parameters are properly set
-- in the network.
g_data_width
:
integer
:
=
32
;
g_data_width
:
integer
:
=
32
;
-- Size of RX buffer, in data words.
g_buffer_size
:
integer
:
=
256
;
g_buffer_size
:
integer
:
=
256
;
-- DO NOT USE unless you know what you are doing
-- legacy: the streamers that were 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.
g_escape_code_disable
:
boolean
:
=
FALSE
;
g_escape_code_disable
:
boolean
:
=
false
;
-- DO NOT USE unless you know what you are doing
-- legacy: the streamers that were initially used in Btrain accepted only a fixed
...
...
@@ -76,11 +76,15 @@ entity xrx_streamer is
-- 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.
-- in the future, more frequences might be supported..
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
;
-- White Rabbit reference clock
clk_ref_i
:
in
std_logic
:
=
'0'
;
rst_n_i
:
in
std_logic
;
-- Endpoint/WRC interface
...
...
@@ -92,8 +96,6 @@ entity xrx_streamer is
-- Caution: uses clk_ref_i clock domain!
---------------------------------------------------------------------------
-- White Rabbit reference clock
clk_ref_i
:
in
std_logic
:
=
'0'
;
-- Time valid flag
tm_time_valid_i
:
in
std_logic
:
=
'0'
;
...
...
@@ -109,34 +111,34 @@ entity xrx_streamer is
---------------------------------------------------------------------------
-- 1 indicates the 1st word of the data block on rx_data_o.
rx_first_p1_o
:
out
std_logic
;
rx_first_p1_o
:
out
std_logic
;
-- 1 indicates the last word of the data block on rx_data_o.
rx_last_p1_o
:
out
std_logic
;
rx_last_p1_o
:
out
std_logic
;
-- Received data.
rx_data_o
:
out
std_logic_vector
(
g_data_width
-1
downto
0
);
rx_data_o
:
out
std_logic_vector
(
g_data_width
-1
downto
0
);
-- 1 indicted that rx_data_o is outputting a valid data word.
rx_valid_o
:
out
std_logic
;
rx_valid_o
:
out
std_logic
;
-- Synchronous data request input: when 1, the streamer may output another
-- data word in the subsequent clock cycle.
rx_dreq_i
:
in
std_logic
;
rx_dreq_i
:
in
std_logic
;
-- Lost output: 1 indicates that one or more frames or blocks have been lost
-- (left for backward compatibility).
rx_lost_p1_o
:
out
std_logic
:
=
'0'
;
rx_lost_p1_o
:
out
std_logic
:
=
'0'
;
-- indicates that one or more blocks within frame are missing
rx_lost_blocks_p1_o
:
out
std_logic
:
=
'0'
;
rx_lost_blocks_p1_o
:
out
std_logic
:
=
'0'
;
-- indicates that one or more frames are missing, the number of frames is provied
rx_lost_frames_p1_o
:
out
std_logic
:
=
'0'
;
rx_lost_frames_p1_o
:
out
std_logic
:
=
'0'
;
--number of lost frames, the 0xF...F means that counter overflew
rx_lost_frames_cnt_o
:
out
std_logic_vector
(
14
downto
0
);
-- Latency measurement output: indicates the transport latency (between the
-- TX streamer in remote device and this streamer), in clk_ref_i clock cycles.
rx_latency_o
:
out
std_logic_vector
(
27
downto
0
);
rx_latency_o
:
out
std_logic_vector
(
27
downto
0
);
-- 1 when the latency on rx_latency_o is valid.
rx_latency_valid_o
:
out
std_logic
;
-- received
streamer frame (counts all frames, corrupted and not)
rx_frame_p1_o
:
out
std_logic
;
rx_latency_valid_o
:
out
std_logic
;
-- received
streamer frame (counts all frames, corrupted and not)
rx_frame_p1_o
:
out
std_logic
;
-- configuration
rx_streamer_cfg_i
:
in
t_rx_streamer_cfg
:
=
c_rx_streamer_cfg_default
rx_streamer_cfg_i
:
in
t_rx_streamer_cfg
:
=
c_rx_streamer_cfg_default
);
end
xrx_streamer
;
...
...
@@ -149,8 +151,8 @@ architecture rtl of xrx_streamer is
signal
state
:
t_rx_state
;
signal
ser_count
:
unsigned
(
7
downto
0
);
signal
seq_no
,
seq_new
,
count
:
unsigned
(
14
downto
0
);
signal
ser_count
:
unsigned
(
7
downto
0
);
signal
seq_no
,
seq_new
,
count
:
unsigned
(
14
downto
0
);
signal
crc_match
,
crc_en
,
crc_en_masked
,
crc_restart
:
std_logic
;
...
...
@@ -161,34 +163,34 @@ architecture rtl of xrx_streamer is
signal
fifo_drop
,
fifo_accept
,
fifo_accept_d0
,
fifo_dvalid
:
std_logic
;
signal
fifo_sync
,
fifo_last
,
frames_lost
,
blocks_lost
:
std_logic
;
signal
fifo_dout
,
fifo_din
:
std_logic_vector
(
g_data_width
+
1
downto
0
);
signal
fifo_dout
,
fifo_din
:
std_logic_vector
(
g_data_width
+
1
+
28
+
1
downto
0
);
signal
fifo_target_ts_en
:
std_logic
;
signal
fifo_target_ts
:
unsigned
(
27
downto
0
);
signal
pending_write
,
fab_dvalid_pre
:
std_logic
;
signal
tx_tag_cycles
,
rx_tag_cycles
:
std_logic_vector
(
27
downto
0
);
signal
tx_tag_valid
,
rx_tag_valid
:
std_logic
;
signal
rx_tag_valid_stored
:
std_logic
;
signal
got_next_subframe
:
std_logic
;
signal
is_frame_seq_id
:
std_logic
;
signal
word_count
:
unsigned
(
11
downto
0
);
signal
sync_seq_no
:
std_logic
;
-- fixed latency signals
type
t_rx_delay_state
is
(
DISABLED
,
DELAY
,
ALLOW
);
signal
timestamped
:
std_logic
;
signal
delay_cnt
:
unsigned
(
27
downto
0
);
signal
rx_dreq_allow
:
std_logic
;
signal
rx_latency
:
unsigned
(
27
downto
0
);
signal
rx_latency_stored
:
unsigned
(
27
downto
0
);
signal
rx_latency_valid
:
std_logic
;
signal
delay_state
:
t_rx_delay_state
;
signal
rx_dreq
:
std_logic
;
signal
is_vlan
:
std_logic
;
signal
is_frame_seq_id
:
std_logic
;
signal
word_count
:
unsigned
(
11
downto
0
);
signal
sync_seq_no
:
std_logic
;
signal
rx_latency
:
unsigned
(
27
downto
0
);
signal
rx_latency_stored
:
unsigned
(
27
downto
0
);
signal
rx_latency_valid
:
std_logic
;
signal
is_vlan
:
std_logic
;
constant
c_fixed_latency_zero
:
unsigned
(
27
downto
0
)
:
=
(
others
=>
'0'
);
constant
c_timestamper_delay
:
unsigned
(
27
downto
0
)
:
=
to_unsigned
(
12
,
28
);
-- cycles
constant
c_timestamper_delay
:
unsigned
(
27
downto
0
)
:
=
to_unsigned
(
12
,
28
);
-- cycles
signal
fifo_last_int
:
std_logic
;
begin
-- rtl
U_rx_crc_generator
:
gc_crc_gen
...
...
@@ -227,7 +229,7 @@ begin -- rtl
dreq_i
=>
fab
.
dreq
);
fab
.
dvalid
<=
'1'
when
fab_dvalid_pre
=
'1'
and
fab
.
addr
=
c_WRF_DATA
and
fab
.
bytesel
=
'0'
else
'0'
;
gen_escape
:
if
(
g_escape_code_disable
=
FALSE
)
generate
gen_escape
:
if
(
g_escape_code_disable
=
false
)
generate
U_Escape_Detect
:
escape_detector
generic
map
(
g_data_width
=>
16
,
...
...
@@ -244,44 +246,19 @@ begin -- rtl
d_valid_o
=>
fsm_in
.
dvalid
,
d_req_i
=>
fsm_in
.
dreq
);
end
generate
gen_escape
;
gen_no_escape
:
if
(
g_escape_code_disable
=
TRUE
)
generate
gen_no_escape
:
if
(
g_escape_code_disable
=
true
)
generate
fsm_in
.
dvalid
<=
fab
.
dvalid
;
fsm_in
.
data
<=
fab
.
data
;
fab
.
dreq
<=
fsm_in
.
dreq
;
is_escape
<=
'0'
;
end
generate
gen_no_escape
;
fsm_in
.
eof
<=
fab
.
eof
or
fab
.
error
;
fsm_in
.
sof
<=
fab
.
sof
;
U_Output_FIFO
:
dropping_buffer
generic
map
(
g_size
=>
g_buffer_size
,
g_data_width
=>
g_data_width
+
2
)
port
map
(
clk_i
=>
clk_sys_i
,
rst_n_i
=>
rst_n_i
,
d_i
=>
fifo_din
,
d_req_o
=>
fsm_in
.
dreq
,
d_drop_i
=>
fifo_drop
,
d_accept_i
=>
fifo_accept_d0
,
d_valid_i
=>
fifo_dvalid
,
d_o
=>
fifo_dout
,
d_valid_o
=>
rx_valid_o
,
d_req_i
=>
rx_dreq
);
fifo_din
(
g_data_width
+
1
)
<=
fifo_sync
;
fifo_din
(
g_data_width
)
<=
fifo_last
or
((
not
pending_write
)
and
is_escape
);
-- when word is 16 bits
fifo_din
(
g_data_width
-1
downto
0
)
<=
fifo_data
;
rx_data_o
<=
fifo_dout
(
g_data_width
-1
downto
0
);
rx_first_p1_o
<=
fifo_dout
(
g_data_width
+
1
);
rx_last_p1_o
<=
fifo_dout
(
g_data_width
);
U_RX_Timestamper
:
pulse_stamper
generic
map
(
g_ref_clk_rate
=>
g_clk_ref_rate
)
g_ref_clk_rate
=>
g_clk_ref_rate
)
port
map
(
clk_ref_i
=>
clk_ref_i
,
clk_sys_i
=>
clk_sys_i
,
...
...
@@ -290,66 +267,84 @@ begin -- rtl
tm_time_valid_i
=>
tm_time_valid_i
,
tm_tai_i
=>
tm_tai_i
,
tm_cycles_i
=>
tm_cycles_i
,
tag_cycles_o
=>
rx_tag_cycles
);
tag_cycles_o
=>
rx_tag_cycles
,
tag_valid_o
=>
rx_tag_valid
);
-------------------------------------------------------------------------------------------
-- fixed latency implementation
-------------------------------------------------------------------------------------------
fifo_last_int
<=
fifo_last
or
((
not
pending_write
)
and
is_escape
);
-- when word is 16 bit
-- mask rx_dreq to prevent reception
rx_dreq
<=
rx_dreq_i
and
rx_dreq_allow
;
-- produce a pulse when SOF is timestamped, this pulse starts counter in clk_sys clock
-- domain
U_sync_with_clk
:
gc_sync_ffs
U_FixLatencyDelay
:
entity
work
.
fixed_latency_delay
generic
map
(
g_data_width
=>
g_data_width
,
g_buffer_size
=>
32
,
g_use_ref_clock_for_data
=>
g_use_ref_clock_for_data
,
g_clk_ref_rate
=>
g_clk_ref_rate
)
port
map
(
clk_i
=>
clk_sys_i
,
rst_n_i
=>
rst_n_i
,
data_i
=>
fsm_in
.
sof
,
synced_o
=>
timestamped
);
-- introduce fixed latency, if configured to do so
p_fixed_latency_fsm
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
delay_state
<=
DISABLED
;
rx_latency_stored
<=
(
others
=>
'0'
);
rx_dreq_allow
<=
'1'
;
delay_cnt
<=
c_timestamper_delay
;
else
case
delay_state
is
when
DISABLED
=>
if
unsigned
(
rx_streamer_cfg_i
.
fixed_latency
)
/=
c_fixed_latency_zero
then
delay_state
<=
ALLOW
;
end
if
;
rx_latency_stored
<=
(
others
=>
'0'
);
delay_cnt
<=
c_timestamper_delay
;
rx_dreq_allow
<=
'1'
;
when
ALLOW
=>
if
unsigned
(
rx_streamer_cfg_i
.
fixed_latency
)
=
c_fixed_latency_zero
then
delay_state
<=
DISABLED
;
elsif
(
rx_latency_valid
=
'1'
)
then
rx_dreq_allow
<=
'0'
;
rx_latency_stored
<=
rx_latency
;
delay_state
<=
DELAY
;
end
if
;
if
(
timestamped
=
'1'
)
then
delay_cnt
<=
c_timestamper_delay
;
else
delay_cnt
<=
delay_cnt
+
2
;
end
if
;
when
DELAY
=>
if
unsigned
(
rx_streamer_cfg_i
.
fixed_latency
)
<=
delay_cnt
+
rx_latency_stored
then
rx_latency_stored
<=
(
others
=>
'0'
);
rx_dreq_allow
<=
'1'
;
delay_state
<=
ALLOW
;
else
delay_cnt
<=
delay_cnt
+
2
;
end
if
;
end
case
;
end
if
;
end
if
;
end
process
;
rst_n_i
=>
rst_n_i
,
clk_sys_i
=>
clk_sys_i
,
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
,
d_data_i
=>
fifo_data
,
d_last_i
=>
fifo_last_int
,
d_sync_i
=>
fifo_sync
,
d_target_ts_en_i
=>
fifo_target_ts_en
,
d_target_ts_i
=>
std_logic_vector
(
fifo_target_ts
),
d_valid_i
=>
fifo_dvalid
,
d_drop_i
=>
fifo_drop
,
d_accept_i
=>
fifo_accept_d0
,
d_req_o
=>
fsm_in
.
dreq
,
rx_first_p1_o
=>
rx_first_p1_o
,
rx_last_p1_o
=>
rx_last_p1_o
,
rx_data_o
=>
rx_data_o
,
rx_valid_o
=>
rx_valid_o
,
rx_dreq_i
=>
rx_dreq_i
,
rx_streamer_cfg_i
=>
rx_streamer_cfg_i
);
-- introduce fixed latency, if configured to do so
-- p_fixed_latency_fsm : process(clk_sys_i)
-- begin
-- if rising_edge(clk_sys_i) then
-- if rst_n_i = '0' then
-- delay_state <= DISABLED;
-- rx_latency_stored <= (others => '0');
-- rx_dreq_allow <= '1';
-- delay_cnt <= c_timestamper_delay;
-- else
-- case delay_state is
-- when DISABLED =>
-- if unsigned(rx_streamer_cfg_i.fixed_latency) /= c_fixed_latency_zero then
-- delay_state <= ALLOW;
-- end if;
-- rx_latency_stored <= (others => '0');
-- delay_cnt <= c_timestamper_delay;
-- rx_dreq_allow <= '1';
-- when ALLOW =>
-- if unsigned(rx_streamer_cfg_i.fixed_latency) = c_fixed_latency_zero then
-- delay_state <= DISABLED;
-- elsif(rx_latency_valid = '1') then
-- rx_dreq_allow <= '0';
-- rx_latency_stored <= rx_latency;
-- delay_state <= DELAY;
-- end if;
-- if(timestamped = '1') then
-- if(rx_tag_valid= '1') then
-- delay_cnt <= c_timestamper_delay;
-- else
-- delay_cnt <= delay_cnt + 2;
-- end if;
-- when DELAY =>
-- if unsigned(rx_streamer_cfg_i.fixed_latency) <= delay_cnt + rx_latency_stored then
-- rx_latency_stored <= (others => '0');
-- rx_dreq_allow <= '1';
-- delay_state <= ALLOW;
-- else
-- delay_cnt <= delay_cnt + 2;
-- end if;
-- end case;
-- end if;
-- end if;
-- end process;
-------------------------------------------------------------------------------------------
-- end of fixed latency implementation
...
...
@@ -359,56 +354,57 @@ begin -- rtl
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
state
<=
IDLE
;
count
<=
(
others
=>
'0'
);
seq_no
<=
(
others
=>
'1'
);
detect_escapes
<=
'0'
;
crc_en
<=
'0'
;
fifo_accept
<=
'0'
;
fifo_drop
<=
'0'
;
fifo_dvalid
<=
'0'
;
pending_write
<=
'0'
;
got_next_subframe
<=
'0'
;
fifo_sync
<=
'0'
;
fifo_last
<=
'0'
;
tx_tag_valid
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
word_count
<=
(
others
=>
'0'
);
sync_seq_no
<=
'1'
;
rx_frame_p1_o
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
frames_lost
<=
'0'
;
rx_latency
<=
(
others
=>
'0'
);
rx_latency_valid
<=
'0'
;
blocks_lost
<=
'0'
;
pack_data
<=
(
others
=>
'0'
);
is_vlan
<=
'0'
;
state
<=
IDLE
;
count
<=
(
others
=>
'0'
);
seq_no
<=
(
others
=>
'1'
);
detect_escapes
<=
'0'
;
crc_en
<=
'0'
;
fifo_accept
<=
'0'
;
fifo_drop
<=
'0'
;
fifo_dvalid
<=
'0'
;
pending_write
<=
'0'
;
got_next_subframe
<=
'0'
;
fifo_sync
<=
'0'
;
fifo_last
<=
'0'
;
tx_tag_valid
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
word_count
<=
(
others
=>
'0'
);
sync_seq_no
<=
'1'
;
rx_frame_p1_o
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
frames_lost
<=
'0'
;
rx_latency
<=
(
others
=>
'0'
);
rx_latency_valid
<=
'0'
;
blocks_lost
<=
'0'
;
pack_data
<=
(
others
=>
'0'
);
is_vlan
<=
'0'
;
rx_tag_valid_stored
<=
'0'
;
else
case
state
is
when
IDLE
=>
detect_escapes
<=
'0'
;
crc_en
<=
'0'
;
count
<=
(
others
=>
'0'
);
fifo_accept
<=
'0'
;
fifo_drop
<=
'0'
;
fifo_dvalid
<=
'0'
;
pending_write
<=
'0'
;
got_next_subframe
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
fifo_sync
<=
'0'
;
fifo_last
<=
'0'
;
word_count
<=
(
others
=>
'0'
);
tx_tag_valid
<=
'0'
;
rx_frame_p1_o
<=
'0'
;
detect_escapes
<=
'0'
;
crc_en
<=
'0'
;
count
<=
(
others
=>
'0'
);
fifo_accept
<=
'0'
;
fifo_drop
<=
'0'
;
fifo_dvalid
<=
'0'
;
pending_write
<=
'0'
;
got_next_subframe
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
fifo_sync
<=
'0'
;
fifo_last
<=
'0'
;
word_count
<=
(
others
=>
'0'
);
tx_tag_valid
<=
'0'
;
rx_frame_p1_o
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
frames_lost
<=
'0'
;
blocks_lost
<=
'0'
;
rx_latency
<=
(
others
=>
'0'
);
rx_latency
<=
(
others
=>
'0'
);
rx_latency_valid
<=
'0'
;
is_vlan
<=
'0'
;
rx_tag_valid_stored
<=
'0'
;
if
(
fsm_in
.
sof
=
'1'
)
then
state
<=
HEADER
;
state
<=
HEADER
;
end
if
;
when
HEADER
=>
...
...
@@ -432,32 +428,32 @@ begin -- rtl
end
if
;
count
<=
count
+
1
;
when
x"03"
=>
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
47
downto
32
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
47
downto
32
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
state
<=
IDLE
;
end
if
;
count
<=
count
+
1
;
when
x"04"
=>
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
31
downto
16
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
31
downto
16
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
state
<=
IDLE
;
end
if
;
count
<=
count
+
1
;
when
x"05"
=>
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
15
downto
0
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
if
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
mac_remote
(
15
downto
0
)
and
rx_streamer_cfg_i
.
filter_remote
=
'1'
)
then
state
<=
IDLE
;
end
if
;
count
<=
count
+
1
;
when
x"06"
=>
if
(
fsm_in
.
data
=
x"8100"
)
then
is_vlan
<=
'1'
;
is_vlan
<=
'1'
;
elsif
(
fsm_in
.
data
/=
rx_streamer_cfg_i
.
ethertype
)
then
state
<=
IDLE
;
is_vlan
<=
'0'
;
is_vlan
<=
'0'
;
end
if
;
count
<=
count
+
1
;
when
x"07"
=>
if
(
is_vlan
=
'0'
)
then
tx_tag_valid
<=
fsm_in
.
data
(
15
);
tx_tag_cycles
(
27
downto
16
)
<=
fsm_in
.
data
(
11
downto
0
);
tx_tag_valid
<=
fsm_in
.
data
(
15
);
tx_tag_cycles
(
27
downto
16
)
<=
fsm_in
.
data
(
11
downto
0
);
end
if
;
count
<=
count
+
1
;
when
x"08"
=>
...
...
@@ -473,9 +469,9 @@ begin -- rtl
end
if
;
count
<=
count
+
1
;
when
x"09"
=>
tx_tag_valid
<=
fsm_in
.
data
(
15
);
tx_tag_cycles
(
27
downto
16
)
<=
fsm_in
.
data
(
11
downto
0
);
count
<=
count
+
1
;
tx_tag_valid
<=
fsm_in
.
data
(
15
);
tx_tag_cycles
(
27
downto
16
)
<=
fsm_in
.
data
(
11
downto
0
);
count
<=
count
+
1
;
when
x"0A"
=>
tx_tag_cycles
(
15
downto
0
)
<=
fsm_in
.
data
;
count
<=
count
+
1
;
...
...
@@ -483,24 +479,35 @@ begin -- rtl
detect_escapes
<=
'1'
;
state
<=
FRAME_SEQ_ID
;
rx_frame_p1_o
<=
'1'
;
count
<=
count
+
1
;
count
<=
count
+
1
;
when
others
=>
null
;
end
case
;
end
if
;
when
FRAME_SEQ_ID
=>
rx_frame_p1_o
<=
'0'
;
rx_frame_p1_o
<=
'0'
;
if
(
fsm_in
.
eof
=
'1'
)
then
state
<=
IDLE
;
elsif
(
fsm_in
.
dvalid
=
'1'
)
then
count
<=
"000"
&
x"001"
;
-- use as subframe seq_no
state
<=
PAYLOAD
;
fifo_drop
<=
'0'
;
fifo_accept
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
word_count
<=
word_count
+
1
;
-- count words, increment in advance
got_next_subframe
<=
'1'
;
if
(
tx_tag_valid
=
'1'
)
then
count
<=
"000"
&
x"001"
;
-- use as subframe seq_no
state
<=
PAYLOAD
;
fifo_drop
<=
'0'
;
fifo_accept
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
word_count
<=
word_count
+
1
;
-- count words, increment in advance
got_next_subframe
<=
'1'
;
fifo_target_ts_en
<=
'0'
;
fifo_target_ts
<=
unsigned
(
tx_tag_cycles
);
if
(
tx_tag_valid
=
'1'
and
unsigned
(
rx_streamer_cfg_i
.
fixed_latency
)
/=
0
)
then
fifo_target_ts_en
<=
'1'
;
end
if
;
-- latency measurement
if
(
tx_tag_valid
=
'1'
and
rx_tag_valid_stored
=
'1'
)
then
rx_latency_valid
<=
'1'
;
if
(
unsigned
(
tx_tag_cycles
)
>
unsigned
(
rx_tag_cycles
))
then
rx_latency
<=
unsigned
(
rx_tag_cycles
)
-
unsigned
(
tx_tag_cycles
)
+
to_unsigned
(
125000000
,
28
);
...
...
@@ -511,62 +518,72 @@ begin -- rtl
else
rx_latency_valid
<=
'0'
;
end
if
;
rx_tag_valid_stored
<=
'0'
;
if
(
std_logic_vector
(
seq_no
)
/=
fsm_in
.
data
(
14
downto
0
))
then
seq_no
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
))
+
1
;
if
(
sync_seq_no
=
'1'
)
then
-- sync to the first received seq_no
sync_seq_no
<=
'0'
;
frames_lost
<=
'0'
;
seq_no
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
))
+
1
;
if
(
sync_seq_no
=
'1'
)
then
-- sync to the first received seq_no
sync_seq_no
<=
'0'
;
frames_lost
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
else
rx_lost_frames_cnt_o
<=
std_logic_vector
(
unsigned
(
fsm_in
.
data
(
14
downto
0
))
-
seq_no
);
frames_lost
<=
'1'
;
frames_lost
<=
'1'
;
end
if
;
else
seq_no
<=
unsigned
(
seq_no
+
1
);
frames_lost
<=
'0'
;
seq_no
<=
unsigned
(
seq_no
+
1
);
frames_lost
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
end
if
;
end
if
;
when
SUBFRAME_HEADER
=>
if
fifo_dvalid
=
'1'
then
fifo_target_ts_en
<=
'0'
;
end
if
;
fifo_drop
<=
'0'
;
fifo_accept
<=
'0'
;
ser_count
<=
(
others
=>
'0'
);
ser_count
<=
(
others
=>
'0'
);
if
(
fsm_in
.
eof
=
'1'
)
then
state
<=
IDLE
;
state
<=
IDLE
;
got_next_subframe
<=
'0'
;
blocks_lost
<=
'0'
;
blocks_lost
<=
'0'
;
elsif
(
fsm_in
.
dvalid
=
'1'
and
is_escape
=
'1'
)
then
got_next_subframe
<=
'1'
;
if
(
std_logic_vector
(
count
)
/=
fsm_in
.
data
(
14
downto
0
))
then
count
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
))
+
1
;
count
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
))
+
1
;
blocks_lost
<=
'1'
;
else
count
<=
count
+
1
;
count
<=
count
+
1
;
blocks_lost
<=
'0'
;
end
if
;
state
<=
PAYLOAD
;
end
if
;
when
PAYLOAD
=>
frames_lost
<=
'0'
;
if
fifo_dvalid
=
'1'
then
fifo_target_ts_en
<=
'0'
;
end
if
;
frames_lost
<=
'0'
;
rx_lost_frames_cnt_o
<=
(
others
=>
'0'
);
rx_latency_valid
<=
'0'
;
fifo_sync
<=
got_next_subframe
;
rx_latency_valid
<=
'0'
;
fifo_sync
<=
got_next_subframe
;
if
(
fsm_in
.
eof
=
'1'
)
then
state
<=
IDLE
;
fifo_drop
<=
'1'
;
fifo_accept
<=
'0'
;
state
<=
IDLE
;
fifo_drop
<=
'1'
;
fifo_accept
<=
'0'
;
got_next_subframe
<=
'0'
;
elsif
(
fsm_in
.
dvalid
=
'1'
)
then
if
(
is_escape
=
'1'
)
then
ser_count
<=
(
others
=>
'0'
);
fifo_last
<=
'1'
;
...
...
@@ -574,99 +591,107 @@ begin -- rtl
got_next_subframe
<=
'1'
;
if
(
fsm_in
.
data
(
15
)
=
'1'
)
then
if
(
std_logic_vector
(
count
)
/=
fsm_in
.
data
(
14
downto
0
))
then
count
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
));
count
<=
unsigned
(
fsm_in
.
data
(
14
downto
0
));
blocks_lost
<=
'1'
;
else
count
<=
unsigned
(
count
+
1
);
count
<=
unsigned
(
count
+
1
);
blocks_lost
<=
'0'
;
end
if
;
state
<=
PAYLOAD
;
fifo_accept
<=
crc_match
;
--_latched;
fifo_drop
<=
not
crc_match
;
--_latched;
fifo_dvalid
<=
pending_write
and
not
fifo_dvalid
;
pending_write
<=
'0'
;
pending_write
<=
'0'
;
elsif
fsm_in
.
data
=
x"0bad"
then
blocks_lost
<=
'0'
;
blocks_lost
<=
'0'
;
state
<=
EOF
;
fifo_accept
<=
crc_match
;
--_latched;
fifo_drop
<=
not
crc_match
;
--_latched;
fifo_dvalid
<=
pending_write
and
not
fifo_dvalid
;
else
blocks_lost
<=
'0'
;
blocks_lost
<=
'0'
;
state
<=
EOF
;
fifo_drop
<=
'1'
;
fifo_accept
<=
'0'
;
end
if
;
else
--of: if(is_escape = '1' or word_count = g_expected_words_number) then
else
--of: if(is_escape = '1' or word_count = g_expected_words_number) then
fifo_last
<=
'0'
;
fifo_accept
<=
'0'
;
fifo_drop
<=
'0'
;
blocks_lost
<=
'0'
;
blocks_lost
<=
'0'
;
pack_data
(
to_integer
(
ser_count
)
*
16
+
15
downto
to_integer
(
ser_count
)
*
16
)
<=
fsm_in
.
data
;
if
(
ser_count
=
g_data_width
/
16
-
1
)
then
ser_count
<=
(
others
=>
'0'
);
ser_count
<=
(
others
=>
'0'
);
if
(
ser_count
=
x"00"
)
then
-- ML: the case when g_data_width == 16
fifo_sync
<=
got_next_subframe
;
fifo_data
(
g_data_width
-1
downto
0
)
<=
pack_data
(
g_data_width
-1
downto
0
);
fifo_dvalid
<=
not
is_escape
;
pending_write
<=
'0'
;
if
(
ser_count
=
x"00"
)
then
-- ML: the case when g_data_width == 16
fifo_sync
<=
got_next_subframe
;
fifo_data
(
g_data_width
-1
downto
0
)
<=
pack_data
(
g_data_width
-1
downto
0
);
fifo_dvalid
<=
not
is_escape
;
pending_write
<=
'0'
;
else
ser_count
<=
(
others
=>
'0'
);
fifo_data
(
g_data_width
-16-1
downto
0
)
<=
pack_data
(
g_data_width
-16-1
downto
0
);
fifo_data
(
g_data_width
-1
downto
g_data_width
-16
)
<=
fsm_in
.
data
;
fifo_dvalid
<=
'0'
;
pending_write
<=
'1'
;
end
if
;
if
(
word_count
=
g_expected_words_number
)
then
state
<=
EOF
;
fifo_accept
<=
'1'
;
fifo_drop
<=
'0'
;
fifo_accept
<=
'1'
;
fifo_drop
<=
'0'
;
fifo_dvalid
<=
'1'
;
else
word_count
<=
word_count
+
1
;
end
if
;
elsif
(
ser_count
=
g_data_width
/
16-2
and
pending_write
=
'1'
)
then
pending_write
<=
'0'
;
ser_count
<=
ser_count
+
1
;
fifo_dvalid
<=
'1'
;
fifo_sync
<=
got_next_subframe
;
pending_write
<=
'0'
;
ser_count
<=
ser_count
+
1
;
fifo_dvalid
<=
'1'
;
fifo_sync
<=
got_next_subframe
;
got_next_subframe
<=
'0'
;
else
ser_count
<=
ser_count
+
1
;
fifo_dvalid
<=
'0'
;
end
if
;
end
if
;
else
--of: elsif(fsm_in.dvalid = '1') then
else
--of: elsif(fsm_in.dvalid = '1') then
fifo_dvalid
<=
'0'
;
end
if
;
if
(
fifo_dvalid
=
'1'
)
then
fifo_sync
<=
'0'
;
end
if
;
when
EOF
=>
fifo_dvalid
<=
'0'
;
fifo_drop
<=
'0'
;
fifo_accept
<=
'0'
;
state
<=
IDLE
;
end
case
;
end
if
;
end
if
;
end
process
;
p_delay_fifo_accept
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
...
...
@@ -679,6 +704,6 @@ begin -- rtl
rx_lost_frames_p1_o
<=
frames_lost
;
rx_latency_o
<=
std_logic_vector
(
rx_latency
);
rx_latency_valid_o
<=
rx_latency_valid
;
crc_restart
<=
'1'
when
(
state
=
FRAME_SEQ_ID
or
(
is_escape
=
'1'
and
fsm_in
.
data
(
15
)
=
'1'
))
else
not
rst_n_i
;
crc_restart
<=
'1'
when
(
state
=
FRAME_SEQ_ID
or
(
is_escape
=
'1'
and
fsm_in
.
data
(
15
)
=
'1'
))
else
not
rst_n_i
;
end
rtl
;
modules/wr_streamers/xtx_streamer.vhd
View file @
d116d6b1
...
...
@@ -76,19 +76,28 @@ entity xtx_streamer is
-- simulation mode: it is set to override the startaup-timer, the value with which
-- the timer is overriden is set in the second generic
g_simulation
:
integer
:
=
0
;
g_simulation
:
integer
:
=
0
;
-- startup counter, used only in simulatin mode (value in 16ns cycles)
g_sim_startup_cnt
:
integer
:
=
6250
;
-- 100us;
g_sim_startup_cnt
:
integer
:
=
6250
;
-- 100us;
-- 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.
-- in the future, more frequences might be supported..
g_clk_ref_rate
:
integer
:
=
125000000
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
);
port
(
clk_sys_i
:
in
std_logic
;
rst_n_i
:
in
std_logic
;
-- White Rabbit reference clock
clk_ref_i
:
in
std_logic
:
=
'0'
;
rst_n_i
:
in
std_logic
;
-- Endpoint/WRC interface - packet source
src_i
:
in
t_wrf_source_in
;
...
...
@@ -99,8 +108,6 @@ entity xtx_streamer is
-- Caution: uses clk_ref_i clock domain!
---------------------------------------------------------------------------
-- White Rabbit reference clock
clk_ref_i
:
in
std_logic
:
=
'0'
;
-- Time valid flag
tm_time_valid_i
:
in
std_logic
:
=
'0'
;
...
...
@@ -112,9 +119,10 @@ entity xtx_streamer is
tm_cycles_i
:
in
std_logic_vector
(
27
downto
0
)
:
=
x"0000000"
;
-- status of the link, in principle the tx can be done only if link is oK
link_ok_i
:
in
std_logic
:
=
'1'
;
link_ok_i
:
in
std_logic
:
=
'1'
;
---------------------------------------------------------------------------
-- User interface
-- User interface
---------------------------------------------------------------------------
-- Data word to be sent.
...
...
@@ -127,6 +135,10 @@ entity xtx_streamer is
-- the following clock cycle.
tx_dreq_o
:
out
std_logic
;
-- sync signal, allowing to align transmission of the frames to the
-- least supported WR reference clock frequency. Used in fixed latency mode.
tx_sync_o
:
out
std_logic
;
-- Last signal. Can be used to indicate the last data word in a larger
-- block of samples (see documentation for more details).
tx_last_p1_i
:
in
std_logic
:
=
'1'
;
...
...
@@ -137,11 +149,11 @@ entity xtx_streamer is
-- Reset sequence number. When asserted, the internal sequence number
-- generator used to detect loss of frames is reset to 0. Advanced feature.
tx_reset_seq_i
:
in
std_logic
:
=
'0'
;
tx_reset_seq_i
:
in
std_logic
:
=
'0'
;
-- successfully sent streamer frame
tx_frame_p1_o
:
out
std_logic
;
tx_frame_p1_o
:
out
std_logic
;
-- Configuration
tx_streamer_cfg_i
:
in
t_tx_streamer_cfg
:
=
c_tx_streamer_cfg_default
tx_streamer_cfg_i
:
in
t_tx_streamer_cfg
:
=
c_tx_streamer_cfg_default
);
end
xtx_streamer
;
...
...
@@ -155,13 +167,17 @@ architecture rtl of xtx_streamer is
signal
tx_threshold_hit
:
std_logic
;
signal
tx_timeout_hit
:
std_logic
;
signal
tx_flush_latched
:
std_logic
;
signal
tx_idle
:
std_logic
;
signal
tx_fifo_last
,
tx_fifo_we
,
tx_fifo_full
,
tx_fifo_empty
,
tx_fifo_rd
:
std_logic
;
signal
tx_fifo_empty_int
,
tx_fifo_rd_int
,
tx_fifo_rd_int_d
:
std_logic
;
signal
tx_fifo_q_int
,
tx_fifo_q_reg
:
std_logic_vector
(
g_data_width
downto
0
);
signal
tx_fifo_q_valid
:
std_logic
;
signal
tx_fifo_q
,
tx_fifo_d
:
std_logic_vector
(
g_data_width
downto
0
);
signal
state
:
t_tx_state
;
signal
seq_no
,
count
:
unsigned
(
14
downto
0
);
signal
ser_count
:
unsigned
(
7
downto
0
);
signal
word_count
:
unsigned
(
11
downto
0
);
--2^12 = 4096*2 bytes (can accommodate jambo frame)
signal
word_count
:
unsigned
(
11
downto
0
);
--2^12 = 4096*2 bytes (can accommodate jambo frame)
signal
total_words
:
unsigned
(
10
downto
0
);
signal
timeout_counter
:
unsigned
(
11
downto
0
);
...
...
@@ -176,14 +192,26 @@ architecture rtl of xtx_streamer is
signal
tx_almost_empty
,
tx_almost_full
:
std_logic
;
signal
buf_frame_count
:
unsigned
(
5
downto
0
)
:
=
(
others
=>
'0'
);
signal
buf_frame_count_inc_ref
:
std_logic
;
signal
buf_frame_count_dec_sys
:
std_logic
;
signal
buf_frame_count
:
std_logic_vector
(
5
downto
0
);
signal
tag_cycles
:
std_logic_vector
(
27
downto
0
);
signal
tag_valid
,
tag_valid_latched
:
std_logic
;
signal
link_ok_delay_cnt
:
unsigned
(
25
downto
0
);
constant
c_link_ok_rst_delay
:
unsigned
(
25
downto
0
)
:
=
to_unsigned
(
62500000
,
26
);
-- 1s
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
;
signal
rst_n_ref
:
std_logic
;
signal
stamper_pulse_a
:
std_logic
;
constant
c_link_ok_rst_delay
:
unsigned
(
25
downto
0
)
:
=
to_unsigned
(
62500000
,
26
);
-- 1s
constant
c_link_ok_rst_delay_sim
:
unsigned
(
25
downto
0
)
:
=
to_unsigned
(
g_sim_startup_cnt
,
26
);
begin
-- rtl
...
...
@@ -193,11 +221,11 @@ begin -- rtl
-------------------------------------------------------------------------------------------
assert
g_tx_buffer_size
>=
g_tx_threshold
report
"The size of the tx buffer must be greater or equal the tx threashold"
severity
FAILURE
;
severity
failure
;
assert
g_tx_buffer_size
>=
g_tx_max_words_per_frame
report
"The size of tx buffer must be greater or equal the max number of words in frame"
severity
FAILURE
;
severity
failure
;
-------------------------------------------------------------------------------------------
U_tx_crc_generator
:
gc_crc_gen
...
...
@@ -239,8 +267,8 @@ begin -- rtl
fab_src
.
sof
<=
fsm_out
.
sof
;
fab_src
.
eof
<=
fsm_out
.
eof
;
gen_escape
:
if
(
g_escape_code_disable
=
FALSE
)
generate
gen_escape
:
if
(
g_escape_code_disable
=
false
)
generate
U_Insert_Escape
:
gc_escape_inserter
generic
map
(
g_data_width
=>
16
,
...
...
@@ -258,7 +286,7 @@ begin -- rtl
d_valid_o
=>
fab_src
.
dvalid
,
d_req_i
=>
fab_src
.
dreq
);
end
generate
gen_escape
;
gen_no_escape
:
if
(
g_escape_code_disable
=
TRUE
)
generate
gen_no_escape
:
if
(
g_escape_code_disable
=
true
)
generate
fab_src
.
data
<=
fsm_out
.
data
;
fab_src
.
dvalid
<=
fsm_out
.
dvalid
;
fsm_out
.
dreq
<=
fab_src
.
dreq
;
...
...
@@ -267,41 +295,135 @@ begin -- rtl
tx_fifo_we
<=
tx_valid_i
and
not
tx_fifo_full
;
tx_fifo_d
<=
tx_last_p1_i
&
tx_data_i
;
U_TX_Buffer
:
generic_sync_fifo
generic
map
(
g_data_width
=>
g_data_width
+
1
,
g_size
=>
g_tx_buffer_size
,
g_with_almost_full
=>
true
,
g_with_almost_empty
=>
true
,
g_almost_empty_threshold
=>
g_tx_threshold
,
g_almost_full_threshold
=>
g_tx_buffer_size
-
2
,
g_show_ahead
=>
true
)
port
map
(
rst_n_i
=>
rst_n_i
,
clk_i
=>
clk_sys_i
,
d_i
=>
tx_fifo_d
,
we_i
=>
tx_fifo_we
,
q_o
=>
tx_fifo_q
,
rd_i
=>
tx_fifo_rd
,
empty_o
=>
tx_fifo_empty
,
full_o
=>
tx_fifo_full
,
almost_empty_o
=>
tx_almost_empty
,
almost_full_o
=>
tx_almost_full
);
tx_fifo_rd
<=
'1'
when
(
state
=
PAYLOAD
and
ser_count
=
g_data_width
/
16-1
and
fsm_out
.
dreq
=
'1'
and
tx_fifo_empty
=
'0'
)
else
'0'
;
tx_threshold_hit
<=
'1'
when
tx_almost_empty
=
'0'
and
(
buf_frame_count
/=
0
)
else
'0'
;
gen_use_sys_clock_for_data
:
if
g_use_ref_clock_for_data
=
0
generate
U_TX_Buffer
:
generic_sync_fifo
generic
map
(
g_data_width
=>
g_data_width
+
1
,
g_size
=>
g_tx_buffer_size
,
g_with_almost_full
=>
true
,
g_with_almost_empty
=>
true
,
g_almost_empty_threshold
=>
g_tx_threshold
,
g_almost_full_threshold
=>
g_tx_buffer_size
-
2
,
g_show_ahead
=>
true
)
port
map
(
rst_n_i
=>
rst_n_i
,
clk_i
=>
clk_sys_i
,
d_i
=>
tx_fifo_d
,
we_i
=>
tx_fifo_we
,
q_o
=>
tx_fifo_q
,
rd_i
=>
tx_fifo_rd
,
empty_o
=>
tx_fifo_empty
,
full_o
=>
tx_fifo_full
,
almost_empty_o
=>
tx_almost_empty
,
almost_full_o
=>
tx_almost_full
);
clk_data
<=
clk_sys_i
;
stamper_pulse_a
<=
fsm_out
.
sof
;
end
generate
gen_use_sys_clock_for_data
;
gen_use_ref_clock_for_data
:
if
g_use_ref_clock_for_data
/=
0
generate
U_TX_Buffer
:
generic_async_fifo
generic
map
(
g_data_width
=>
g_data_width
+
1
,
g_size
=>
g_tx_buffer_size
,
g_with_rd_empty
=>
true
,
g_with_wr_full
=>
true
,
g_with_wr_almost_full
=>
true
,
g_with_rd_almost_empty
=>
true
,
g_almost_empty_threshold
=>
g_tx_threshold
,
g_almost_full_threshold
=>
g_tx_buffer_size
-
2
,
g_show_ahead
=>
true
)
port
map
(
rst_n_i
=>
rst_n_i
,
clk_wr_i
=>
clk_ref_i
,
clk_rd_i
=>
clk_sys_i
,
d_i
=>
tx_fifo_d
,
we_i
=>
tx_fifo_we
,
q_o
=>
tx_fifo_q_int
,
rd_i
=>
tx_fifo_rd_int
,
rd_empty_o
=>
tx_fifo_empty_int
,
wr_full_o
=>
tx_fifo_full
,
rd_almost_empty_o
=>
tx_almost_empty
,
wr_almost_full_o
=>
tx_almost_full
);
-- emulate show-ahead mode, not supported by async fifos in the
-- general-cores library.
tx_fifo_rd_int
<=
not
tx_fifo_empty_int
when
tx_fifo_q_valid
=
'0'
else
tx_fifo_rd
;
tx_fifo_q
<=
tx_fifo_q_int
when
tx_fifo_rd_int_d
=
'1'
else
tx_fifo_q_reg
;
p_show_ahead
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
tx_fifo_empty
<=
'0'
;
tx_fifo_q_valid
<=
'0'
;
else
if
tx_fifo_rd_int
=
'1'
then
tx_fifo_q_valid
<=
'1'
;
tx_fifo_empty
<=
'0'
;
elsif
tx_fifo_rd
=
'1'
then
tx_fifo_q_valid
<=
not
tx_fifo_empty_int
;
tx_fifo_empty
<=
not
tx_fifo_q_valid
;
end
if
;
if
tx_fifo_rd_int_d
=
'1'
then
tx_fifo_q_reg
<=
tx_fifo_q
;
end
if
;
tx_fifo_rd_int_d
<=
tx_fifo_rd_int
;
end
if
;
end
if
;
end
process
;
clk_data
<=
clk_ref_i
;
p_detect_sof
:
process
(
clk_ref_i
)
begin
if
rising_edge
(
clk_ref_i
)
then
if
rst_n_ref
=
'0'
then
tx_idle
<=
'1'
;
stamper_pulse_a
<=
'0'
;
else
if
tx_last_p1_i
=
'1'
and
tx_valid_i
=
'1'
then
tx_idle
<=
'1'
;
elsif
tx_valid_i
=
'1'
then
tx_idle
<=
'0'
;
end
if
;
stamper_pulse_a
<=
tx_valid_i
and
tx_idle
;
end
if
;
end
if
;
end
process
;
end
generate
gen_use_ref_clock_for_data
;
-- sys clock domain
tx_fifo_rd
<=
'1'
when
(
state
=
PAYLOAD
and
ser_count
=
g_data_width
/
16-1
and
fsm_out
.
dreq
=
'1'
and
tx_fifo_empty
=
'0'
)
else
'0'
;
-- sys clock domain
tx_threshold_hit
<=
'1'
when
tx_almost_empty
=
'0'
and
(
signed
(
buf_frame_count
)
>
0
)
else
'0'
;
tx_fifo_last
<=
tx_fifo_q
(
g_data_width
);
U_Timestamper
:
pulse_stamper
generic
map
(
g_ref_clk_rate
=>
g_clk_ref_rate
)
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_n_i
,
pulse_a_i
=>
fsm_out
.
sof
,
pulse_a_i
=>
stamper_pulse_a
,
tm_time_valid_i
=>
tm_time_valid_i
,
tm_tai_i
=>
tm_tai_i
,
tm_cycles_i
=>
tm_cycles_i
,
...
...
@@ -309,20 +431,21 @@ begin -- rtl
tag_cycles_o
=>
tag_cycles
,
tag_valid_o
=>
tag_valid
);
p_frame_counter
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
buf_frame_count
<=
(
others
=>
'0'
);
else
if
(
tx_fifo_we
=
'1'
and
tx_last_p1_i
=
'1'
and
(
tx_fifo_rd
=
'0'
or
tx_fifo_last
=
'0'
))
then
buf_frame_count
<=
buf_frame_count
+
1
;
elsif
((
tx_fifo_we
=
'0'
or
tx_last_p1_i
=
'0'
)
and
(
tx_fifo_rd
=
'1'
and
tx_fifo_last
=
'1'
))
then
buf_frame_count
<=
buf_frame_count
-
1
;
end
if
;
end
if
;
end
if
;
end
process
;
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
;
U_FrameCounter
:
entity
work
.
gc_async_counter_diff
generic
map
(
g_bits
=>
5
,
g_output_clock
=>
"dec"
)
port
map
(
rst_n_i
=>
rst_n_i
,
clk_inc_i
=>
clk_data
,
clk_dec_i
=>
clk_sys_i
,
inc_i
=>
buf_frame_count_inc_ref
,
dec_i
=>
buf_frame_count_dec_sys
,
counter_o
=>
buf_frame_count
);
p_tx_timeout
:
process
(
clk_sys_i
)
begin
...
...
@@ -346,20 +469,32 @@ begin -- rtl
end
if
;
end
process
;
p_latch_timestamp
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
or
state
=
IDLE
then
tag_valid_latched
<=
'0'
;
elsif
tag_valid
=
'1'
then
tag_valid_latched
<=
'1'
;
end
if
;
end
if
;
end
process
;
p_fsm
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
state
<=
IDLE
;
fsm_out
.
sof
<=
'0'
;
fsm_out
.
eof
<=
'0'
;
fsm_out
.
dvalid
<=
'0'
;
fsm_out
.
data
<=
(
others
=>
'0'
);
count
<=
(
others
=>
'0'
);
seq_no
<=
(
others
=>
'0'
);
word_count
<=
(
others
=>
'0'
);
crc_en
<=
'0'
;
crc_reset
<=
'1'
;
state
<=
IDLE
;
fsm_out
.
sof
<=
'0'
;
fsm_out
.
eof
<=
'0'
;
fsm_out
.
dvalid
<=
'0'
;
fsm_out
.
data
<=
(
others
=>
'0'
);
count
<=
(
others
=>
'0'
);
seq_no
<=
(
others
=>
'0'
);
word_count
<=
(
others
=>
'0'
);
crc_en
<=
'0'
;
crc_reset
<=
'1'
;
tx_frame_p1_o
<=
'0'
;
tag_valid_latched
<=
'0'
;
tx_flush_latched
<=
'0'
;
...
...
@@ -370,19 +505,19 @@ begin -- rtl
if
(
tx_reset_seq_i
=
'1'
)
then
seq_no
<=
(
others
=>
'0'
);
end
if
;
if
(
tag_valid
=
'1'
)
then
tag_valid_latched
<=
'1'
;
-- overriden in IDLE
if
(
tag_valid
=
'1'
)
then
tag_valid_latched
<=
'1'
;
-- overriden in IDLE
end
if
;
tx_flush_latched
<=
'0'
;
-- overriden in IDLE
tx_flush_latched
<=
'0'
;
-- overriden in IDLE
case
state
is
when
IDLE
=>
tag_valid_latched
<=
'0'
;
tx_flush_latched
<=
tx_flush_p1_i
or
tx_timeout_hit
;
crc_en
<=
'0'
;
crc_reset
<=
'0'
;
fsm_out
.
eof
<=
'0'
;
tx_frame_p1_o
<=
'0'
;
crc_en
<=
'0'
;
crc_reset
<=
'0'
;
fsm_out
.
eof
<=
'0'
;
tx_frame_p1_o
<=
'0'
;
if
(
fsm_out
.
dreq
=
'1'
and
(
tx_flush_latched
=
'1'
or
tx_flush_p1_i
=
'1'
or
tx_threshold_hit
=
'1'
))
then
state
<=
SOF
;
...
...
@@ -401,6 +536,8 @@ begin -- rtl
when
ETH_HEADER
=>
if
(
fsm_out
.
dreq
=
'1'
)
then
fsm_out
.
dvalid
<=
'1'
;
case
count
(
7
downto
0
)
is
when
x"00"
=>
fsm_out
.
data
<=
tx_streamer_cfg_i
.
mac_target
(
47
downto
32
);
...
...
@@ -416,6 +553,7 @@ begin -- rtl
count
<=
count
+
1
;
when
x"04"
=>
fsm_out
.
data
<=
tx_streamer_cfg_i
.
mac_local
(
31
downto
16
);
count
<=
count
+
1
;
when
x"05"
=>
fsm_out
.
data
<=
tx_streamer_cfg_i
.
mac_local
(
15
downto
0
);
...
...
@@ -426,14 +564,21 @@ begin -- rtl
else
fsm_out
.
data
<=
x"8100"
;
end
if
;
count
<=
count
+
1
;
count
<=
count
+
1
;
when
x"07"
=>
if
(
tx_streamer_cfg_i
.
qtag_ena
=
'0'
)
then
fsm_out
.
data
<=
tag_valid_latched
&
"000"
&
tag_cycles
(
27
downto
16
);
fsm_out
.
data
<=
"1000"
&
tag_cycles
(
27
downto
16
);
if
tag_valid_latched
=
'1'
then
count
<=
count
+
1
;
fsm_out
.
dvalid
<=
'1'
;
else
fsm_out
.
dvalid
<=
'0'
;
end
if
;
else
fsm_out
.
data
<=
tx_streamer_cfg_i
.
qtag_prio
&
'0'
&
tx_streamer_cfg_i
.
qtag_vid
;
count
<=
count
+
1
;
end
if
;
count
<=
count
+
1
;
when
x"08"
=>
if
(
tx_streamer_cfg_i
.
qtag_ena
=
'0'
)
then
fsm_out
.
data
<=
tag_cycles
(
15
downto
0
);
...
...
@@ -441,10 +586,15 @@ begin -- rtl
else
fsm_out
.
data
<=
tx_streamer_cfg_i
.
ethertype
;
end
if
;
count
<=
count
+
1
;
count
<=
count
+
1
;
when
x"09"
=>
fsm_out
.
data
<=
tag_valid_latched
&
"000"
&
tag_cycles
(
27
downto
16
);
count
<=
count
+
1
;
if
tag_valid_latched
=
'1'
then
count
<=
count
+
1
;
fsm_out
.
dvalid
<=
'1'
;
else
fsm_out
.
dvalid
<=
'0'
;
end
if
;
fsm_out
.
data
<=
"1000"
&
tag_cycles
(
27
downto
16
);
when
x"0A"
=>
fsm_out
.
data
<=
tag_cycles
(
15
downto
0
);
state
<=
FRAME_SEQ_ID
;
...
...
@@ -453,7 +603,6 @@ begin -- rtl
fsm_out
.
data
<=
(
others
=>
'X'
);
count
<=
(
others
=>
'X'
);
end
case
;
fsm_out
.
dvalid
<=
'1'
;
else
fsm_out
.
dvalid
<=
'0'
;
end
if
;
...
...
@@ -469,9 +618,9 @@ begin -- rtl
crc_reset
<=
'0'
;
state
<=
PAYLOAD
;
else
fsm_out
.
dvalid
<=
'0'
;
fsm_out
.
dvalid
<=
'0'
;
end
if
;
when
SUBFRAME_HEADER
=>
crc_en
<=
'1'
;
crc_reset
<=
'0'
;
...
...
@@ -498,10 +647,10 @@ begin -- rtl
end
if
;
if
(
ser_count
=
g_data_width
/
16-1
)
then
word_count
<=
word_count
+
1
;
ser_count
<=
(
others
=>
'0'
);
word_count
<=
word_count
+
1
;
ser_count
<=
(
others
=>
'0'
);
else
ser_count
<=
ser_count
+
1
;
ser_count
<=
ser_count
+
1
;
end
if
;
fsm_out
.
data
<=
tx_fifo_q
((
to_integer
(
ser_count
)
+
1
)
*
16
-1
downto
to_integer
(
ser_count
)
*
16
);
...
...
@@ -535,7 +684,7 @@ begin -- rtl
if
(
fsm_out
.
dreq
=
'1'
)
then
fsm_escape
<=
'1'
;
fsm_out
.
dvalid
<=
'1'
;
fsm_out
.
data
<=
x"0bad"
;
fsm_out
.
data
<=
x"0bad"
;
if
(
total_words
>=
c_min_packet_size
)
then
state
<=
EOF
;
end
if
;
...
...
@@ -544,13 +693,13 @@ begin -- rtl
fsm_out
.
dvalid
<=
'0'
;
fsm_out
.
data
<=
(
others
=>
'X'
);
end
if
;
when
EOF
=>
fsm_out
.
dvalid
<=
'0'
;
if
(
fsm_out
.
dreq
=
'1'
)
then
fsm_out
.
eof
<=
'1'
;
tx_frame_p1_o
<=
'1'
;
state
<=
IDLE
;
fsm_out
.
eof
<=
'1'
;
tx_frame_p1_o
<=
'1'
;
state
<=
IDLE
;
end
if
;
end
case
;
end
if
;
...
...
@@ -580,25 +729,64 @@ begin -- rtl
-- link_ok, i.e. we do not accept requests when link_ok is false.
-- During operation (i.e. after start-up/reset, the behaviour of link_ok
-- signal is satisfactory
p_delay_reset
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
if
(
g_simulation
=
1
)
then
link_ok_delay_cnt
<=
c_link_ok_rst_delay_sim
;
else
link_ok_delay_cnt
<=
c_link_ok_rst_delay
;
end
if
;
p_delay_reset
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
if
(
g_simulation
=
1
)
then
link_ok_delay_cnt
<=
c_link_ok_rst_delay_sim
;
else
-- first initial moments of link_ok_i high are ignored
if
(
link_ok_i
=
'1'
and
link_ok_delay_cnt
>
0
)
then
link_ok_delay_cnt
<=
link_ok_delay_cnt
-1
;
end
if
;
link_ok_delay_cnt
<=
c_link_ok_rst_delay
;
end
if
;
link_ok_delay_expired
<=
'0'
;
else
-- first initial moments of link_ok_i high are ignored
if
(
link_ok_i
=
'1'
and
link_ok_delay_cnt
>
0
)
then
link_ok_delay_cnt
<=
link_ok_delay_cnt
-1
;
end
if
;
if
link_ok_delay_cnt
>
0
then
link_ok_delay_expired
<=
'0'
;
else
link_ok_delay_expired
<=
'1'
;
end
if
;
end
if
;
end
process
;
end
if
;
end
process
;
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
);
U_SyncLinkOK_to_RefClk
:
gc_sync_ffs
port
map
(
clk_i
=>
clk_ref_i
,
rst_n_i
=>
rst_n_ref
,
data_i
=>
link_ok_i
,
synced_o
=>
link_ok_ref
);
U_SyncLinkDelayExpired_to_RefClk
:
gc_sync_ffs
port
map
(
clk_i
=>
clk_ref_i
,
rst_n_i
=>
rst_n_ref
,
data_i
=>
link_ok_delay_expired
,
synced_o
=>
link_ok_delay_expired_ref
);
p_tx_dreq_gen
:
process
(
link_ok_delay_expired_ref
,
tx_almost_full
,
link_ok_ref
)
begin
if
link_ok_delay_expired_ref
=
'0'
then
tx_dreq_o
<=
'0'
;
else
tx_dreq_o
<=
not
tx_almost_full
and
link_ok_ref
;
end
if
;
end
process
;
tx_dreq_o
<=
'0'
when
(
link_ok_delay_cnt
>
0
)
else
(
not
tx_almost_full
)
and
link_ok_i
;
end
rtl
;
modules/wr_streamers/xwr_streamers.vhd
View file @
d116d6b1
...
...
@@ -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
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment