Files
retroSoC/tests/rtl/spisd_data_tb.sv
T
maksyuki 075344df58 feat: add SPI-SD RTL tests and enhance interconnect testbench
- Increased the number of masters in the AXI4 interconnect testbench from 5 to 6.
- Added new testbench for SPI-SD clock functionality (spisd_clock_tb).
- Introduced testbench for SPI-SD command engine (spisd_command_tb).
- Created testbench for SPI-SD CRC calculation (spisd_crc_tb).
- Implemented testbench for SPI-SD data handling (spisd_data_tb).
- Developed wrapper testbench for SPI-SD with APB and training checks (spisd_wrapper_tb).
- Added Python test suite for SPI-SD RTL regressions (test_spisd.py).
- Created a test for verifying register parity between RTL and C header definitions (test_spisd_register_parity.py).
2026-08-20 16:12:15 +08:00

221 lines
7.6 KiB
Systemverilog

`timescale 1ns / 1ps
module spisd_data_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic rise_tick_i = 1'b0;
logic fall_tick_i = 1'b0;
logic start_i = 1'b0;
logic abort_i = 1'b0;
spisd_pkg::spisd_data_direction_e direction_i = spisd_pkg::SpisdDataFromCard;
logic multi_block_i = 1'b0;
logic crc_check_i = 1'b1;
logic [15:0] block_size_i = 16'd4;
logic [15:0] block_count_i = 16'd1;
logic [31:0] timeout_cycles_i = 32'd1000;
logic [31:0] busy_timeout_cycles_i = 32'd1000;
logic miso_i = 1'b1;
logic mosi_o;
logic clock_pause_o;
logic tx_valid_i = 1'b0;
logic tx_ready_o;
logic [31:0] tx_data_i = 32'd0;
logic [ 3:0] tx_strb_i = 4'd0;
logic tx_last_i = 1'b0;
logic rx_valid_o;
logic rx_ready_i = 1'b0;
logic [31:0] rx_data_o;
logic [ 3:0] rx_strb_o;
logic rx_last_o;
logic busy_o;
logic done_o;
logic error_o;
logic timeout_o;
logic crc_error_o;
logic busy_timeout_o;
logic [ 7:0] error_code_o;
logic [15:0] blocks_done_o;
logic [87:0] s_write_serial;
logic [15:0] s_write_crc;
always #1 clk_i = ~clk_i;
spisd_data u_spisd_data (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rise_tick_i (rise_tick_i),
.fall_tick_i (fall_tick_i),
.start_i (start_i),
.abort_i (abort_i),
.direction_i (direction_i),
.multi_block_i (multi_block_i),
.crc_check_i (crc_check_i),
.block_size_i (block_size_i),
.block_count_i (block_count_i),
.timeout_cycles_i (timeout_cycles_i),
.busy_timeout_cycles_i(busy_timeout_cycles_i),
.miso_i (miso_i),
.mosi_o (mosi_o),
.clock_pause_o (clock_pause_o),
.tx_valid_i (tx_valid_i),
.tx_ready_o (tx_ready_o),
.tx_data_i (tx_data_i),
.tx_strb_i (tx_strb_i),
.tx_last_i (tx_last_i),
.rx_valid_o (rx_valid_o),
.rx_ready_i (rx_ready_i),
.rx_data_o (rx_data_o),
.rx_strb_o (rx_strb_o),
.rx_last_o (rx_last_o),
.busy_o (busy_o),
.done_o (done_o),
.error_o (error_o),
.timeout_o (timeout_o),
.crc_error_o (crc_error_o),
.busy_timeout_o (busy_timeout_o),
.error_code_o (error_code_o),
.blocks_done_o (blocks_done_o)
);
task automatic pulse_start;
begin
@(negedge clk_i);
start_i = 1'b1;
@(negedge clk_i);
start_i = 1'b0;
end
endtask
task automatic rise_bit(input logic value);
begin
@(negedge clk_i);
miso_i = value;
rise_tick_i = 1'b1;
@(negedge clk_i);
rise_tick_i = 1'b0;
end
endtask
task automatic rise_byte(input logic [7:0] value);
begin
for (integer bit_index = 7; bit_index >= 0; bit_index--) begin
rise_bit(value[bit_index]);
end
end
endtask
task automatic fall_capture;
begin
@(negedge clk_i);
s_write_serial = {s_write_serial[86:0], mosi_o};
fall_tick_i = 1'b1;
@(negedge clk_i);
fall_tick_i = 1'b0;
end
endtask
task automatic consume_read_word;
begin
wait (rx_valid_o);
if ((rx_data_o != 32'h4433_2211) || (rx_strb_o != 4'hF) || !rx_last_o || !clock_pause_o) begin
$fatal(1, "read stream packing/backpressure failed: data=%h strb=%h last=%b pause=%b",
rx_data_o, rx_strb_o, rx_last_o, clock_pause_o);
end
@(negedge clk_i);
rx_ready_i = 1'b1;
@(negedge clk_i);
rx_ready_i = 1'b0;
end
endtask
initial begin
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
direction_i = spisd_pkg::SpisdDataFromCard;
pulse_start();
rise_byte(8'hFF);
rise_byte(8'hFE);
rise_byte(8'h11);
rise_byte(8'h22);
rise_byte(8'h33);
rise_byte(8'h44);
consume_read_word();
rise_byte(8'hDD);
rise_byte(8'h33);
wait (done_o);
if (error_o || (blocks_done_o != 16'd1)) begin
$fatal(1, "valid read block failed: err=%b code=%h blocks=%0d", error_o, error_code_o,
blocks_done_o);
end
@(posedge clk_i);
wait (!done_o);
direction_i = spisd_pkg::SpisdDataFromCard;
pulse_start();
rise_byte(8'hFE);
rise_byte(8'h11);
rise_byte(8'h22);
rise_byte(8'h33);
rise_byte(8'h44);
consume_read_word();
rise_byte(8'h00);
rise_byte(8'h00);
wait (done_o);
if (!error_o || !crc_error_o || (error_code_o != spisd_pkg::SpisdErrDataCrc)) begin
$fatal(1, "read CRC fault was not classified");
end
@(posedge clk_i);
wait (!done_o);
direction_i = spisd_pkg::SpisdDataToCard;
block_size_i = 16'd8;
tx_data_i = 32'h4433_2211;
tx_strb_i = 4'hF;
tx_last_i = 1'b0;
s_write_crc = 16'h0000;
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h11);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h22);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h33);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h44);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h55);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h66);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h77);
s_write_crc = spisd_pkg::spisd_crc16_byte(s_write_crc, 8'h88);
s_write_serial = '0;
pulse_start();
wait (tx_ready_o);
@(negedge clk_i);
tx_valid_i = 1'b1;
@(negedge clk_i);
tx_valid_i = 1'b0;
repeat (40) fall_capture();
wait (tx_ready_o);
tx_data_i = 32'h8877_6655;
tx_last_i = 1'b1;
@(negedge clk_i);
tx_valid_i = 1'b1;
@(negedge clk_i);
tx_valid_i = 1'b0;
repeat (48) fall_capture();
if (s_write_serial != {8'hFE, 64'h1122_3344_5566_7788, s_write_crc}) begin
$fatal(1, "write token/payload/CRC serialization failed: got=%h crc=%h", s_write_serial,
s_write_crc);
end
rise_bit(1'b0);
rise_bit(1'b0);
rise_bit(1'b1);
rise_bit(1'b0);
rise_bit(1'b1);
rise_bit(1'b0);
rise_bit(1'b1);
wait (done_o);
if (error_o || timeout_o || busy_timeout_o || (blocks_done_o != 16'd1)) begin
$fatal(1, "write response/busy completion failed: err=%b code=%h blocks=%0d", error_o,
error_code_o, blocks_done_o);
end
$display("SPISD read/write data, CRC, and backpressure test passed");
$finish;
end
endmodule