Skip to content

Commit 1a294d7

Browse files
committed
Merge branch 'marushchenko-feat-uvm-network_mod-generate_timestamps' into 'devel'
feat(core): generate timestamps in NETWORK_MOD verification See merge request ndk/ndk-fpga!185
2 parents 83f5776 + 7ea5283 commit 1a294d7

File tree

11 files changed

+210
-6
lines changed

11 files changed

+210
-6
lines changed

core/comp/eth/network_mod/uvm/tbench/base/env/env.sv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ class env #(
204204
m_usr_tx_hdr[it].analysis_port.connect(m_scoreboard.usr_tx_hdr[it]);
205205
end
206206

207+
m_tsu.analysis_port.connect(m_scoreboard.tsu);
208+
207209
m_sequencer.usr_rst = m_usr_rst.m_sequencer;
208210
m_sequencer.mi_rst = m_mi_rst.m_sequencer;
209211
m_sequencer.mi_phy_rst = m_mi_phy_rst.m_sequencer;
@@ -217,6 +219,7 @@ class env #(
217219
m_sequencer.port[it].usr_tx_data = m_usr_tx_data[it].m_sequencer;
218220
m_sequencer.port[it].usr_tx_hdr = m_usr_tx_hdr[it].m_sequencer;
219221
end
222+
m_sequencer.tsu = m_tsu.m_sequencer;
220223
endfunction
221224
endclass
222225

core/comp/eth/network_mod/uvm/tbench/base/env/pkg.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ package uvm_network_mod_env;
1818
`include "sequencer.sv"
1919
`include "model.sv"
2020
`include "scoreboard_cmp.sv"
21+
`include "timestamp_checker.sv"
2122
`include "scoreboard.sv"
2223
`include "env.sv"
2324

2425
`include "reg_sequence.sv"
2526
`include "sequence_eth.sv"
27+
`include "sequence_timestamp.sv"
2628
`include "sequence.sv"
2729
endpackage
2830
`endif

core/comp/eth/network_mod/uvm/tbench/base/env/scoreboard.sv

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@ class scoreboard #(ETH_CORE_ARCH, ETH_PORTS, int unsigned ETH_PORT_SPEED[ETH_POR
1919
uvm_analysis_export #(uvm_logic_vector_array::sequence_item#(ITEM_WIDTH)) usr_tx_data[ETH_PORTS];
2020
uvm_analysis_export #(uvm_logic_vector::sequence_item#(ETH_RX_HDR_WIDTH)) usr_tx_hdr[ETH_PORTS];
2121

22+
uvm_analysis_export #(uvm_logic_vector::sequence_item #(64)) tsu;
23+
2224
//comparators
2325
protected uvm_common::comparer_ordered #(uvm_logic_vector_array::sequence_item#(ITEM_WIDTH)) m_eth_tx_data[ETH_PORTS];
2426
protected uvm_common::comparer_ordered #(uvm_logic_vector::sequence_item#(1)) m_eth_tx_hdr[ETH_PORTS];
2527

2628
protected uvm_common::comparer_ordered #(uvm_logic_vector_array::sequence_item#(ITEM_WIDTH)) m_usr_tx_data[ETH_PORTS];
2729
protected uvm_network_mod_env::comparer_tx_hdr#(ETH_RX_HDR_WIDTH) m_usr_tx_hdr[ETH_PORTS];
2830

31+
// Timestamp checker
32+
timestamp_checker #(ETH_RX_HDR_WIDTH) m_timestamp_checker[ETH_PORTS];
33+
2934
//METERS
3035
protected uvm_logic_vector_array::meter#(ITEM_WIDTH) m_eth_rx_meter[ETH_PORTS];
3136
protected uvm_logic_vector_array::meter#(ITEM_WIDTH) m_eth_tx_meter[ETH_PORTS];
@@ -47,15 +52,18 @@ class scoreboard #(ETH_CORE_ARCH, ETH_PORTS, int unsigned ETH_PORT_SPEED[ETH_POR
4752
usr_tx_data[it] = new($sformatf("usr_tx_data_%0d", it), this);
4853
usr_tx_hdr [it] = new($sformatf("usr_tx_hdr_%0d", it), this);
4954
end
55+
56+
tsu = new("tsu", this);
5057
endfunction
5158

5259
function int unsigned success();
5360
int unsigned ret = 1;
5461
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
55-
ret &= m_eth_tx_data[it].success();
56-
ret &= m_eth_tx_hdr [it].success();
57-
ret &= m_usr_tx_data[it].success();
58-
ret &= m_usr_tx_hdr [it].success();
62+
ret &= m_eth_tx_data [it].success();
63+
ret &= m_eth_tx_hdr [it].success();
64+
ret &= m_usr_tx_data [it].success();
65+
ret &= m_usr_tx_hdr [it].success();
66+
ret &= m_timestamp_checker[it].success();
5967
end
6068
return ret;
6169
endfunction
@@ -87,6 +95,8 @@ class scoreboard #(ETH_CORE_ARCH, ETH_PORTS, int unsigned ETH_PORT_SPEED[ETH_POR
8795
m_eth_tx_meter[it] = uvm_logic_vector_array::meter#(ITEM_WIDTH)::type_id::create($sformatf("m_eth_tx_meter_%0d", it), this);
8896
m_usr_rx_meter[it] = uvm_logic_vector_array::meter#(ITEM_WIDTH)::type_id::create($sformatf("m_usr_rx_meter_%0d", it), this);
8997
m_usr_tx_meter[it] = uvm_logic_vector_array::meter#(ITEM_WIDTH)::type_id::create($sformatf("m_usr_tx_meter_%0d", it), this);
98+
99+
m_timestamp_checker[it] = timestamp_checker #(ETH_RX_HDR_WIDTH)::type_id::create($sformatf("m_timestamp_checker_%0d", it), this);
90100
end
91101

92102
m_model = model#(ETH_CORE_ARCH, ETH_PORTS, ETH_PORT_SPEED, ETH_PORT_CHAN, REGIONS, ITEM_WIDTH, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH)::type_id::create("m_model", this);
@@ -115,6 +125,10 @@ class scoreboard #(ETH_CORE_ARCH, ETH_PORTS, int unsigned ETH_PORT_SPEED[ETH_POR
115125
usr_rx_data[it].connect(m_usr_rx_meter[it].analysis_export);
116126
usr_tx_data[it].connect(m_usr_tx_meter[it].analysis_export);
117127

128+
// TSU -> Timestamp checker
129+
tsu.connect(m_timestamp_checker[it].in_model.analysis_export);
130+
// DUT USR TX HDR -> Timestamp checker
131+
usr_tx_hdr[it].connect(m_timestamp_checker[it].in_dut.analysis_export);
118132
end
119133
endfunction
120134

core/comp/eth/network_mod/uvm/tbench/base/env/scoreboard_cmp.sv

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ class comparer_tx_hdr #(int unsigned ITEM_WIDTH) extends uvm_common::comparer_ba
5959
ret &= dut_multicast === model_multicast ;
6060
ret &= dut_mac_hit_vld === model_mac_hit_vld ;
6161
ret &= (model_mac_hit_vld === 1'b0 || dut_mac_hit === model_mac_hit);
62-
ret &= dut_timestamp_vld === model_timestamp_vld;
63-
ret &= (model_timestamp_vld === 1'b0 || dut_timestamp === model_timestamp);
6462

6563
return ret;
6664
endfunction

core/comp/eth/network_mod/uvm/tbench/base/env/sequence.sv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ class virt_sequence_simple#(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_
118118
protected uvm_logic_vector_array::config_sequence usr_rx_seq_cfg[ETH_PORTS];
119119
//MI SEQUENCE
120120

121+
// TSU
122+
sequence_timestamp tsu;
123+
121124
//SYNC END
122125
uvm_common::sequence_cfg_signal seq_sync_end;
123126
uvm_common::sequence_cfg_signal seq_sync_port_end;
@@ -150,6 +153,8 @@ class virt_sequence_simple#(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_
150153
port[it] = virt_sequence_port#(ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WIDTH, REGIONS, REGION_SIZE, BLOCK_SIZE, ETH_PORT_CHAN[0], MI_DATA_WIDTH, MI_ADDR_WIDTH)::type_id::create($sformatf("port_%0d", it), p_sequencer.port[it]);
151154
port[it].packet_size_set(usr_rx_seq_cfg[it]);
152155
end
156+
157+
tsu = sequence_timestamp::type_id::create("tsu");
153158
endtask
154159

155160
virtual function void packet_size_set(int unsigned min = 64, int unsigned max = 1500);
@@ -208,6 +213,8 @@ class virt_sequence_stop#(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WI
208213
uvm_config_db#(uvm_common::sequence_cfg)::set(p_sequencer.port[it], "", "state", seq_sync_end);
209214
port[it] = virt_sequence_port_stop#(ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WIDTH, REGIONS, REGION_SIZE, BLOCK_SIZE, ETH_PORT_CHAN[0], MI_DATA_WIDTH, MI_ADDR_WIDTH)::type_id::create($sformatf("port_%0d", it), p_sequencer.port[it]);
210215
end
216+
217+
tsu = sequence_timestamp::type_id::create("tsu");
211218
endtask
212219

213220
virtual task body();
@@ -236,6 +243,13 @@ class virt_sequence_stop#(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WI
236243
end
237244
join_none
238245

246+
fork
247+
forever begin
248+
assert(tsu.randomize());
249+
tsu.start(p_sequencer.tsu);
250+
end
251+
join_none
252+
239253
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
240254
fork
241255
automatic int unsigned index = it;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// sequence_timestamp.sv: Generates timestamps
2+
// Copyright (C) 2025 CESNET z. s. p. o.
3+
// Author(s): Yaroslav Marushchenko <xmarus09@stud.fit.vutbr.cz>
4+
// SPDX-License-Identifier: BSD-3-Clause
5+
6+
class sequence_timestamp extends uvm_logic_vector::sequence_simple #(64);
7+
`uvm_object_utils(uvm_network_mod_env::sequence_timestamp)
8+
9+
localparam int unsigned STEP_MAX = 100;
10+
localparam int unsigned STEP_MIN = 1;
11+
12+
// Shared accumulator
13+
static longint unsigned accumulator = $urandom();
14+
15+
// Constructor
16+
function new(string name = "sequence_timestamp");
17+
super.new(name);
18+
endfunction
19+
20+
task body;
21+
repeat (transaction_count) begin
22+
req = uvm_logic_vector::sequence_item #(64)::type_id::create("req");
23+
start_item(req);
24+
req.data = get_timestamp();
25+
finish_item(req);
26+
end
27+
endtask
28+
29+
function longint unsigned get_timestamp();
30+
int unsigned step = $urandom_range(STEP_MAX, STEP_MIN);
31+
accumulator += step;
32+
33+
return accumulator;
34+
endfunction
35+
36+
endclass

core/comp/eth/network_mod/uvm/tbench/base/env/sequencer.sv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class sequencer#(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WIDTH, REGI
3838
sequencer_port#(ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_WIDTH, REGIONS, REGION_SIZE, BLOCK_SIZE, ETH_PORT_CHAN[0], MI_DATA_WIDTH, MI_ADDR_WIDTH) port[ETH_PORTS];
3939
// MI PHY
4040

41+
// TSU
42+
uvm_logic_vector::sequencer #(64) tsu;
43+
4144
function new(string name, uvm_component parent = null);
4245
super.new(name, parent);
4346
endfunction
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// timestamp_checker.sv: Checks the validity of the DUT timestamps
2+
// Copyright (C) 2025 CESNET z. s. p. o.
3+
// Author(s): Yaroslav Marushchenko <xmarus09@stud.fit.vutbr.cz>
4+
// SPDX-License-Identifier: BSD-3-Clause
5+
6+
class timestamp_checker #(int unsigned DUT_ITEM_WIDTH) extends uvm_component;
7+
`uvm_component_param_utils(uvm_network_mod_env::timestamp_checker #(DUT_ITEM_WIDTH));
8+
9+
// ------ //
10+
// Inputs //
11+
// ------ //
12+
13+
uvm_tlm_analysis_fifo #(uvm_logic_vector::sequence_item #(64)) in_model;
14+
uvm_tlm_analysis_fifo #(uvm_logic_vector::sequence_item #(DUT_ITEM_WIDTH)) in_dut;
15+
16+
// ------------------ //
17+
// Internal variables //
18+
// ------------------ //
19+
20+
bit waiting_for_model_item;
21+
int unsigned dut_timestamp_counter;
22+
longint unsigned previous_dut_timestamp;
23+
24+
// Constructor
25+
function new(string name = "timestamp_checker", uvm_component parent = null);
26+
super.new(name, parent);
27+
28+
in_model = new("in_model", this);
29+
in_dut = new("in_dut", this);
30+
31+
waiting_for_model_item = 0;
32+
dut_timestamp_counter = 0;
33+
previous_dut_timestamp = 0;
34+
endfunction
35+
36+
task run_phase(uvm_phase phase);
37+
uvm_logic_vector::sequence_item #(64) model_item;
38+
uvm_logic_vector::sequence_item #(DUT_ITEM_WIDTH) dut_item;
39+
bit dut_timestamp_valid;
40+
longint unsigned dut_timestamp;
41+
42+
forever begin
43+
in_dut.get(dut_item);
44+
dut_timestamp_counter++;
45+
46+
dut_timestamp = dut_item.data[DUT_ITEM_WIDTH -1 -: 64];
47+
dut_timestamp_valid = dut_item.data[DUT_ITEM_WIDTH-64-1 -: 1];
48+
49+
// Skip invalid timestamps
50+
if (dut_timestamp_valid !== 1'b1) begin
51+
continue;
52+
end
53+
54+
// Check that the timestamp value does not decrease over time
55+
if (dut_timestamp < previous_dut_timestamp) begin
56+
`uvm_error(get_full_name(), $sformatf("\n\tThe timestamp value must not decrease over time. Current: 0x%0h, Previous: 0x%0h", dut_timestamp, previous_dut_timestamp))
57+
end
58+
59+
// The timestamp obtained from the DUT may be duplicated
60+
if (dut_timestamp == previous_dut_timestamp) begin
61+
continue;
62+
end
63+
64+
// Try to find the next matching model timestamp
65+
do begin
66+
waiting_for_model_item = 1;
67+
in_model.get(model_item);
68+
waiting_for_model_item = 0;
69+
70+
if (dut_timestamp < model_item.data) begin
71+
`uvm_error(get_full_name(), $sformatf("\n\tThe timestamp (#%0d) obtained from the DUT has an unknown origin", dut_timestamp_counter));
72+
end
73+
end while (dut_timestamp > model_item.data);
74+
75+
previous_dut_timestamp = dut_timestamp;
76+
end
77+
endtask
78+
79+
function bit success();
80+
return (waiting_for_model_item == 0); // Check if the call `in_model.get(model_item)` is not blocked
81+
endfunction
82+
83+
function void check_phase(uvm_phase phase);
84+
super.check_phase(phase);
85+
86+
assert(this.success())
87+
else begin
88+
`uvm_error(get_full_name(), $sformatf("\n\tThe timestamp (#%0d) obtained from the DUT has an unknown origin", dut_timestamp_counter));
89+
end
90+
endfunction
91+
92+
endclass

core/comp/eth/network_mod/uvm/tbench/cmac/env/sequence.sv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,13 @@ class virt_sequence_simple #(
397397
tsu_rst.start(p_sequencer.tsu_rst);
398398
join_none
399399

400+
fork
401+
forever begin
402+
assert(tsu.randomize());
403+
tsu.start(p_sequencer.tsu);
404+
end
405+
join_none
406+
400407
// Run sequences
401408
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
402409
fork
@@ -504,6 +511,13 @@ class virt_sequence_stop #(
504511
end while (!seq_sync_end.stopped());
505512
join_none
506513

514+
fork
515+
forever begin
516+
assert(tsu.randomize());
517+
tsu.start(p_sequencer.tsu);
518+
end
519+
join_none
520+
507521
// Run the sequences
508522
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
509523
fork

core/comp/eth/network_mod/uvm/tbench/e-tile/env/sequence.sv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ class virt_sequence_simple #(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM
361361
tsu_rst.start(p_sequencer.tsu_rst);
362362
join_none
363363

364+
fork
365+
forever begin
366+
assert(tsu.randomize());
367+
tsu.start(p_sequencer.tsu);
368+
end
369+
join_none
370+
364371
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
365372
fork
366373
automatic int unsigned index = it;
@@ -450,6 +457,13 @@ class virt_sequence_stop #(ETH_PORTS, ETH_TX_HDR_WIDTH, ETH_RX_HDR_WIDTH, ITEM_W
450457
end while (!seq_sync_end.stopped());
451458
join_none
452459

460+
fork
461+
forever begin
462+
assert(tsu.randomize());
463+
tsu.start(p_sequencer.tsu);
464+
end
465+
join_none
466+
453467
for (int unsigned it = 0; it < ETH_PORTS; it++) begin
454468
fork
455469
automatic int unsigned index = it;

0 commit comments

Comments
 (0)