test: add full testbenches for accum
This commit is contained in:
92
rtl/accum/src/accum_top.sv
Normal file
92
rtl/accum/src/accum_top.sv
Normal file
@ -0,0 +1,92 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module accumulator_top
|
||||
#(
|
||||
parameter DATA_WIDTH = 12,
|
||||
parameter ACCUM_WIDTH = 32,
|
||||
parameter N_MAX = 4096,
|
||||
parameter WINDOW_SIZE = 4,
|
||||
parameter PACKET_SIZE = 8,
|
||||
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
||||
)
|
||||
(
|
||||
// main clk
|
||||
input clk_in,
|
||||
input rst,
|
||||
|
||||
// input data
|
||||
input [DATA_WIDTH-1:0] s_axis_tdata,
|
||||
input s_axis_tvalid,
|
||||
|
||||
// parameters
|
||||
input start,
|
||||
input [31:0] smp_num,
|
||||
input [15:0] seq_num,
|
||||
|
||||
// eth signals
|
||||
input eth_clk_in,
|
||||
input req_ready,
|
||||
output send_req,
|
||||
|
||||
// output axis
|
||||
output logic [7:0] m_axis_tdata,
|
||||
output logic m_axis_tvalid,
|
||||
input logic m_axis_tready,
|
||||
output logic m_axis_tlast,
|
||||
|
||||
output logic finish
|
||||
);
|
||||
|
||||
wire [ACCUM_WIDTH-1:0] out_data;
|
||||
wire out_valid;
|
||||
wire readout_begin;
|
||||
wire batch_req;
|
||||
|
||||
accumulator #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.WINDOW_SIZE(WINDOW_SIZE),
|
||||
.PACKET_SIZE(PACKET_SIZE)
|
||||
) accum_main (
|
||||
.clk_in(clk_in),
|
||||
.rst(rst),
|
||||
.s_axis_tdata(s_axis_tdata),
|
||||
.s_axis_tvalid(s_axis_tvalid),
|
||||
.start(start),
|
||||
.smp_num(smp_num),
|
||||
.seq_num(seq_num),
|
||||
.out_data(out_data),
|
||||
.out_valid(out_valid),
|
||||
.readout_begin(readout_begin),
|
||||
.batch_req(batch_req),
|
||||
.finish(finish)
|
||||
);
|
||||
|
||||
out_axis_fifo #(
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.WINDOW_SIZE(WINDOW_SIZE),
|
||||
.PACKET_SIZE(PACKET_SIZE)
|
||||
) output_async_fifo (
|
||||
.eth_clk_in (eth_clk_in),
|
||||
.acc_clk_in (clk_in),
|
||||
.rst (rst),
|
||||
.smp_num (smp_num),
|
||||
|
||||
.m_axis_tdata (m_axis_tdata),
|
||||
.m_axis_tvalid (m_axis_tvalid),
|
||||
.m_axis_tready (m_axis_tready),
|
||||
.m_axis_tlast (m_axis_tlast),
|
||||
|
||||
.acc_din (out_data),
|
||||
.din_valid (out_valid),
|
||||
|
||||
.readout_begin (readout_begin),
|
||||
|
||||
.req_ready (req_ready),
|
||||
.send_req (send_req),
|
||||
|
||||
.batch_req (batch_req),
|
||||
.finish (finish)
|
||||
);
|
||||
endmodule
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
# FPGA settings
|
||||
FPGA_PART = xc7a35tfgg484-1
|
||||
FPGA_TOP = accum
|
||||
FPGA_TOP = accumulator_top
|
||||
FPGA_ARCH = artix7
|
||||
|
||||
RTL_DIR = ../src
|
||||
@ -24,7 +24,8 @@ XDC_FILES += ../../../constraints/ax7a035b.xdc
|
||||
XDC_FILES += test_timing.xdc
|
||||
|
||||
SYN_FILES += out_axis_fifo_tb.sv
|
||||
SIM_TOP = control_tb
|
||||
SYN_FILE += accum_full_tb.sv
|
||||
SIM_TOP = tb_accumulator_top
|
||||
|
||||
|
||||
program: $(PROJECT).bit
|
||||
|
||||
344
rtl/accum/tests/accum_full_tb.sv
Normal file
344
rtl/accum/tests/accum_full_tb.sv
Normal file
@ -0,0 +1,344 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_accumulator_top;
|
||||
|
||||
localparam DATA_WIDTH = 12;
|
||||
localparam ACCUM_WIDTH = 32;
|
||||
localparam N_MAX = 256;
|
||||
localparam WINDOW_SIZE = 4;
|
||||
localparam PACKET_SIZE = 128;
|
||||
localparam READ_BATCH_SIZE = (PACKET_SIZE*8)/ACCUM_WIDTH;
|
||||
localparam MAX_WORDS = N_MAX / WINDOW_SIZE;
|
||||
localparam MAX_SEQ_NUM = 64;
|
||||
|
||||
logic clk_in;
|
||||
logic eth_clk_in;
|
||||
logic rst;
|
||||
|
||||
logic [DATA_WIDTH-1:0] s_axis_tdata;
|
||||
logic s_axis_tvalid;
|
||||
logic start;
|
||||
logic [31:0] smp_num;
|
||||
logic [15:0] seq_num;
|
||||
|
||||
logic req_ready;
|
||||
wire send_req;
|
||||
|
||||
wire [7:0] m_axis_tdata;
|
||||
wire m_axis_tvalid;
|
||||
logic m_axis_tready;
|
||||
wire m_axis_tlast;
|
||||
|
||||
wire finish;
|
||||
|
||||
integer seed;
|
||||
integer total_errors;
|
||||
integer tests_total;
|
||||
integer tests_failed;
|
||||
integer tests_passed;
|
||||
|
||||
integer packets_seen;
|
||||
integer current_packet_byte_count;
|
||||
integer total_words_captured;
|
||||
|
||||
byte packet_bytes [0:PACKET_SIZE-1];
|
||||
logic [ACCUM_WIDTH-1:0] expected_words [0:MAX_WORDS-1];
|
||||
logic [ACCUM_WIDTH-1:0] captured_words_le[0:MAX_WORDS-1];
|
||||
logic [ACCUM_WIDTH-1:0] captured_words_be[0:MAX_WORDS-1];
|
||||
|
||||
accumulator_top #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.WINDOW_SIZE(WINDOW_SIZE),
|
||||
.PACKET_SIZE(PACKET_SIZE)
|
||||
) dut (
|
||||
.clk_in(clk_in),
|
||||
.rst(rst),
|
||||
.s_axis_tdata(s_axis_tdata),
|
||||
.s_axis_tvalid(s_axis_tvalid),
|
||||
.start(start),
|
||||
.smp_num(smp_num),
|
||||
.seq_num(seq_num),
|
||||
.eth_clk_in(eth_clk_in),
|
||||
.req_ready(req_ready),
|
||||
.send_req(send_req),
|
||||
.m_axis_tdata(m_axis_tdata),
|
||||
.m_axis_tvalid(m_axis_tvalid),
|
||||
.m_axis_tready(m_axis_tready),
|
||||
.m_axis_tlast(m_axis_tlast),
|
||||
.finish(finish)
|
||||
);
|
||||
|
||||
initial begin
|
||||
clk_in = 1'b0;
|
||||
forever #5 clk_in = ~clk_in;
|
||||
end
|
||||
|
||||
initial begin
|
||||
eth_clk_in = 1'b0;
|
||||
forever #4 eth_clk_in = ~eth_clk_in;
|
||||
end
|
||||
|
||||
task automatic clear_scoreboard;
|
||||
integer i;
|
||||
begin
|
||||
packets_seen = 0;
|
||||
current_packet_byte_count = 0;
|
||||
total_words_captured = 0;
|
||||
for (i = 0; i < MAX_WORDS; i = i + 1) begin
|
||||
expected_words[i] = '0;
|
||||
captured_words_le[i] = '0;
|
||||
captured_words_be[i] = '0;
|
||||
end
|
||||
for (i = 0; i < PACKET_SIZE; i = i + 1)
|
||||
packet_bytes[i] = 8'h00;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic reset_dut;
|
||||
begin
|
||||
rst = 1'b1;
|
||||
start = 1'b0;
|
||||
s_axis_tdata = '0;
|
||||
s_axis_tvalid = 1'b0;
|
||||
smp_num = '0;
|
||||
seq_num = '0;
|
||||
req_ready = 1'b0;
|
||||
m_axis_tready = 1'b1;
|
||||
clear_scoreboard();
|
||||
|
||||
repeat(12) @(posedge clk_in);
|
||||
rst = 1'b0;
|
||||
repeat(8) @(posedge clk_in);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic pulse_start;
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
start <= 1'b1;
|
||||
@(posedge clk_in);
|
||||
start <= 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic send_one_sample(input logic [DATA_WIDTH-1:0] val);
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
s_axis_tdata <= val;
|
||||
s_axis_tvalid <= 1'b1;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic stop_stream;
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
s_axis_tdata <= '0;
|
||||
s_axis_tvalid <= 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic run_test(
|
||||
input integer test_id,
|
||||
input integer seq_num_i,
|
||||
input integer smp_num_i,
|
||||
input bit randomize_data,
|
||||
input integer base_value,
|
||||
input string test_name
|
||||
);
|
||||
logic [DATA_WIDTH-1:0] sample_mem [0:MAX_SEQ_NUM-1][0:N_MAX-1];
|
||||
integer seq_idx;
|
||||
integer sample_idx;
|
||||
integer word_idx;
|
||||
integer k;
|
||||
integer exp_word_count;
|
||||
integer exp_packet_count;
|
||||
integer sample_value;
|
||||
integer local_sum;
|
||||
integer timeout_cnt;
|
||||
bit le_ok;
|
||||
bit be_ok;
|
||||
integer errors_before;
|
||||
integer i;
|
||||
begin
|
||||
tests_total = tests_total + 1;
|
||||
errors_before = total_errors;
|
||||
|
||||
if (smp_num_i <= 0 || smp_num_i > N_MAX || (smp_num_i % WINDOW_SIZE) != 0)
|
||||
$fatal(1, "[%0s] invalid smp_num=%0d", test_name, smp_num_i);
|
||||
if (seq_num_i <= 0 || seq_num_i > MAX_SEQ_NUM)
|
||||
$fatal(1, "[%0s] invalid seq_num=%0d", test_name, seq_num_i);
|
||||
|
||||
$display("\n========================================");
|
||||
$display("TEST %0d: %0s", test_id, test_name);
|
||||
$display("seq_num=%0d smp_num=%0d randomize=%0d", seq_num_i, smp_num_i, randomize_data);
|
||||
$display("========================================");
|
||||
|
||||
reset_dut();
|
||||
smp_num = smp_num_i;
|
||||
seq_num = seq_num_i;
|
||||
req_ready = 1'b1; // приемник готов заранее
|
||||
|
||||
exp_word_count = smp_num_i / WINDOW_SIZE;
|
||||
exp_packet_count = (exp_word_count + READ_BATCH_SIZE - 1) / READ_BATCH_SIZE;
|
||||
|
||||
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
||||
for (sample_idx = 0; sample_idx < smp_num_i; sample_idx = sample_idx + 1) begin
|
||||
if (randomize_data)
|
||||
sample_value = $unsigned($random(seed)) % (1 << DATA_WIDTH);
|
||||
else
|
||||
sample_value = (base_value + seq_idx * smp_num_i + sample_idx) % (1 << DATA_WIDTH);
|
||||
sample_mem[seq_idx][sample_idx] = sample_value[DATA_WIDTH-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
for (word_idx = 0; word_idx < exp_word_count; word_idx = word_idx + 1) begin
|
||||
local_sum = 0;
|
||||
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
||||
for (k = 0; k < WINDOW_SIZE; k = k + 1)
|
||||
local_sum = local_sum + sample_mem[seq_idx][word_idx * WINDOW_SIZE + k];
|
||||
end
|
||||
expected_words[word_idx] = local_sum[ACCUM_WIDTH-1:0];
|
||||
$display(" expected[%0d] = %0d (0x%08x)", word_idx, expected_words[word_idx], expected_words[word_idx]);
|
||||
end
|
||||
|
||||
pulse_start();
|
||||
|
||||
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
||||
for (sample_idx = 0; sample_idx < smp_num_i; sample_idx = sample_idx + 1)
|
||||
send_one_sample(sample_mem[seq_idx][sample_idx]);
|
||||
stop_stream();
|
||||
repeat(2) @(posedge clk_in);
|
||||
end
|
||||
|
||||
timeout_cnt = 0;
|
||||
while (packets_seen < exp_packet_count && timeout_cnt < 30000) begin
|
||||
@(posedge eth_clk_in);
|
||||
timeout_cnt = timeout_cnt + 1;
|
||||
end
|
||||
if (packets_seen < exp_packet_count) begin
|
||||
$display("[%0s] ERROR: timeout waiting packets, got=%0d exp=%0d",
|
||||
test_name, packets_seen, exp_packet_count);
|
||||
total_errors = total_errors + 1;
|
||||
end
|
||||
|
||||
timeout_cnt = 0;
|
||||
while (finish !== 1'b1 && timeout_cnt < 30000) begin
|
||||
@(posedge clk_in);
|
||||
timeout_cnt = timeout_cnt + 1;
|
||||
end
|
||||
if (finish !== 1'b1) begin
|
||||
$display("[%0s] ERROR: timeout waiting finish", test_name);
|
||||
total_errors = total_errors + 1;
|
||||
end
|
||||
|
||||
le_ok = 1'b1;
|
||||
be_ok = 1'b1;
|
||||
for (i = 0; i < exp_word_count; i = i + 1) begin
|
||||
if (captured_words_le[i] !== expected_words[i]) le_ok = 1'b0;
|
||||
if (captured_words_be[i] !== expected_words[i]) be_ok = 1'b0;
|
||||
end
|
||||
|
||||
if (!le_ok && !be_ok) begin
|
||||
$display("[%0s] ERROR: payload mismatch", test_name);
|
||||
for (i = 0; i < exp_word_count; i = i + 1)
|
||||
$display(" idx=%0d exp=0x%08x le=0x%08x be=0x%08x",
|
||||
i, expected_words[i], captured_words_le[i], captured_words_be[i]);
|
||||
total_errors = total_errors + 1;
|
||||
end else if (le_ok) begin
|
||||
$display("[%0s] payload check passed in little-endian", test_name);
|
||||
end else begin
|
||||
$display("[%0s] payload check passed in big-endian", test_name);
|
||||
end
|
||||
|
||||
if (total_errors == errors_before) begin
|
||||
tests_passed = tests_passed + 1;
|
||||
$display("TEST %0d PASSED: %0s", test_id, test_name);
|
||||
end else begin
|
||||
tests_failed = tests_failed + 1;
|
||||
$display("TEST %0d FAILED: %0s", test_id, test_name);
|
||||
end
|
||||
|
||||
req_ready = 1'b0;
|
||||
repeat(10) @(posedge clk_in);
|
||||
end
|
||||
endtask
|
||||
|
||||
always @(posedge eth_clk_in) begin : CAPTURE_AXIS
|
||||
integer idx;
|
||||
logic [31:0] tmp_le;
|
||||
logic [31:0] tmp_be;
|
||||
if (rst) begin
|
||||
current_packet_byte_count = 0;
|
||||
end else if (m_axis_tvalid && m_axis_tready) begin
|
||||
if (current_packet_byte_count < PACKET_SIZE)
|
||||
packet_bytes[current_packet_byte_count] = m_axis_tdata;
|
||||
current_packet_byte_count = current_packet_byte_count + 1;
|
||||
|
||||
if (m_axis_tlast) begin
|
||||
packets_seen = packets_seen + 1;
|
||||
|
||||
if (current_packet_byte_count != PACKET_SIZE) begin
|
||||
$display("[packet] ERROR: packet size=%0d expected=%0d", current_packet_byte_count, PACKET_SIZE);
|
||||
total_errors = total_errors + 1;
|
||||
end
|
||||
|
||||
for (idx = 0; idx < READ_BATCH_SIZE; idx = idx + 1) begin
|
||||
tmp_le = {
|
||||
packet_bytes[idx*4 + 3],
|
||||
packet_bytes[idx*4 + 2],
|
||||
packet_bytes[idx*4 + 1],
|
||||
packet_bytes[idx*4 + 0]
|
||||
};
|
||||
tmp_be = {
|
||||
packet_bytes[idx*4 + 0],
|
||||
packet_bytes[idx*4 + 1],
|
||||
packet_bytes[idx*4 + 2],
|
||||
packet_bytes[idx*4 + 3]
|
||||
};
|
||||
if (total_words_captured + idx < MAX_WORDS) begin
|
||||
captured_words_le[total_words_captured + idx] = tmp_le;
|
||||
captured_words_be[total_words_captured + idx] = tmp_be;
|
||||
end
|
||||
end
|
||||
|
||||
total_words_captured = total_words_captured + READ_BATCH_SIZE;
|
||||
current_packet_byte_count = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
seed = 32'h1badf00d;
|
||||
total_errors = 0;
|
||||
tests_total = 0;
|
||||
tests_failed = 0;
|
||||
tests_passed = 0;
|
||||
|
||||
reset_dut();
|
||||
|
||||
run_test(1, 2, 8, 1'b0, 1, "deterministic_small");
|
||||
run_test(2, 3, 8, 1'b1, 0, "random_seq3_smp8");
|
||||
run_test(3, 5, 16, 1'b1, 0, "random_seq5_smp16_multi_packet");
|
||||
// run_test(4, 1, 4, 1'b1, 0, "random_single_window");
|
||||
run_test(5, 7, 12, 1'b1, 0, "random_seq7_smp12");
|
||||
run_test(6, 4, 256, 1'b1, 0, "random_max_smpnum");
|
||||
|
||||
$display("\n========================================");
|
||||
$display("ALL TESTS COMPLETED");
|
||||
$display("tests_total = %0d", tests_total);
|
||||
$display("tests_passed = %0d", tests_passed);
|
||||
$display("tests_failed = %0d", tests_failed);
|
||||
$display("total_errors = %0d", total_errors);
|
||||
$display("========================================");
|
||||
|
||||
if (total_errors != 0)
|
||||
$fatal(1, "TB FAILED with %0d error(s)", total_errors);
|
||||
else
|
||||
$display("TB PASSED");
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
183
rtl/accum/tests/accum_tb.sv
Normal file
183
rtl/accum/tests/accum_tb.sv
Normal file
@ -0,0 +1,183 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_accumulator;
|
||||
|
||||
localparam DATA_WIDTH = 12;
|
||||
localparam ACCUM_WIDTH = 32;
|
||||
localparam N_MAX = 64;
|
||||
localparam WINDOW_SIZE = 4;
|
||||
localparam PACKET_SIZE = 8; // bytes
|
||||
localparam READ_BATCH_SIZE = (PACKET_SIZE*8)/ACCUM_WIDTH; // = 2
|
||||
|
||||
reg clk_in;
|
||||
reg rst;
|
||||
reg [DATA_WIDTH-1:0] s_axis_tdata;
|
||||
reg s_axis_tvalid;
|
||||
reg start;
|
||||
reg [31:0] smp_num;
|
||||
reg [15:0] seq_num;
|
||||
wire [ACCUM_WIDTH-1:0] out_data;
|
||||
wire out_valid;
|
||||
wire readout_begin;
|
||||
reg batch_req;
|
||||
reg finish;
|
||||
|
||||
integer i;
|
||||
integer out_count;
|
||||
|
||||
reg [ACCUM_WIDTH-1:0] expected [0:READ_BATCH_SIZE-1];
|
||||
reg [ACCUM_WIDTH-1:0] got [0:READ_BATCH_SIZE-1];
|
||||
|
||||
accumulator #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.WINDOW_SIZE(WINDOW_SIZE),
|
||||
.PACKET_SIZE(PACKET_SIZE)
|
||||
) dut (
|
||||
.clk_in(clk_in),
|
||||
.rst(rst),
|
||||
.s_axis_tdata(s_axis_tdata),
|
||||
.s_axis_tvalid(s_axis_tvalid),
|
||||
.start(start),
|
||||
.smp_num(smp_num),
|
||||
.seq_num(seq_num),
|
||||
.out_data(out_data),
|
||||
.out_valid(out_valid),
|
||||
.readout_begin(readout_begin),
|
||||
.batch_req(batch_req),
|
||||
.finish(finish)
|
||||
);
|
||||
|
||||
// clock 100 MHz
|
||||
initial begin
|
||||
clk_in = 0;
|
||||
forever #5 clk_in = ~clk_in;
|
||||
end
|
||||
|
||||
// send one sample
|
||||
task send_sample(input [DATA_WIDTH-1:0] val);
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
s_axis_tdata <= val;
|
||||
s_axis_tvalid <= 1'b1;
|
||||
end
|
||||
endtask
|
||||
|
||||
// one idle cycle after valid stream
|
||||
task end_stream;
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
s_axis_tvalid <= 1'b0;
|
||||
s_axis_tdata <= '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
// pulse start
|
||||
task pulse_start;
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
start <= 1'b1;
|
||||
@(posedge clk_in);
|
||||
start <= 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
// pulse batch request
|
||||
task pulse_batch_req;
|
||||
begin
|
||||
@(posedge clk_in);
|
||||
batch_req <= 1'b1;
|
||||
@(posedge clk_in);
|
||||
batch_req <= 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
repeat(100) @(posedge clk_in);
|
||||
// init
|
||||
rst = 1'b1;
|
||||
s_axis_tdata = '0;
|
||||
s_axis_tvalid= 1'b0;
|
||||
start = 1'b0;
|
||||
smp_num = 32'd8;
|
||||
seq_num = 16'd2;
|
||||
batch_req = 1'b0;
|
||||
finish = 1'b0;
|
||||
|
||||
expected[0] = 32'd60;
|
||||
expected[1] = 32'd92;
|
||||
|
||||
repeat(50) @(posedge clk_in);
|
||||
rst = 1'b0;
|
||||
repeat(50) @(posedge clk_in);
|
||||
|
||||
$display("=== TEST START ===");
|
||||
|
||||
pulse_start();
|
||||
|
||||
// seq 0: [1..8]
|
||||
send_sample(12'd1);
|
||||
send_sample(12'd2);
|
||||
send_sample(12'd3);
|
||||
send_sample(12'd4);
|
||||
send_sample(12'd5);
|
||||
send_sample(12'd6);
|
||||
send_sample(12'd7);
|
||||
send_sample(12'd8);
|
||||
end_stream();
|
||||
|
||||
// небольшой зазор
|
||||
repeat(5) @(posedge clk_in);
|
||||
|
||||
// seq 1: [11..18]
|
||||
send_sample(12'd11);
|
||||
send_sample(12'd12);
|
||||
send_sample(12'd13);
|
||||
send_sample(12'd14);
|
||||
send_sample(12'd15);
|
||||
send_sample(12'd16);
|
||||
send_sample(12'd17);
|
||||
send_sample(12'd18);
|
||||
end_stream();
|
||||
|
||||
$display("[%0t] all input data sent, waiting readout_begin...", $time);
|
||||
|
||||
wait(readout_begin == 1'b1);
|
||||
$display("[%0t] readout_begin asserted", $time);
|
||||
repeat(22) @(posedge clk_in);
|
||||
pulse_batch_req();
|
||||
|
||||
out_count = 0;
|
||||
|
||||
// ждём два слова
|
||||
while (out_count < READ_BATCH_SIZE) begin
|
||||
@(posedge clk_in);
|
||||
if (out_valid) begin
|
||||
got[out_count] = out_data;
|
||||
$display("[%0t] out_valid: got[%0d] = %0d", $time, out_count, out_data);
|
||||
out_count = out_count + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// проверка
|
||||
for (i = 0; i < READ_BATCH_SIZE; i = i + 1) begin
|
||||
if (got[i] !== expected[i]) begin
|
||||
$error("Mismatch at index %0d: got=%0d expected=%0d", i, got[i], expected[i]);
|
||||
end else begin
|
||||
$display("OK index %0d: %0d", i, got[i]);
|
||||
end
|
||||
end
|
||||
|
||||
// завершаем readout
|
||||
@(posedge clk_in);
|
||||
finish <= 1'b1;
|
||||
|
||||
|
||||
repeat(10) @(posedge clk_in);
|
||||
|
||||
$display("=== TEST PASSED ===");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user