Files
retroSoC/tests/rtl/spisd_command_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

169 lines
5.6 KiB
Systemverilog

`timescale 1ns / 1ps
module spisd_command_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic clock_enable_i = 1'b0;
logic [15:0] half_period_i = 16'd1;
logic rise_tick;
logic fall_tick;
logic sck;
logic running;
logic start_i = 1'b0;
logic abort_i = 1'b0;
logic [ 5:0] cmd_index_i = 6'd0;
logic [31:0] cmd_arg_i = 32'd0;
spisd_pkg::spisd_resp_type_e resp_type_i = spisd_pkg::SpisdRespNone;
logic stuff_byte_i = 1'b0;
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 busy_o;
logic done_o;
logic error_o;
logic timeout_o;
logic busy_timeout_o;
logic [ 7:0] error_code_o;
logic [39:0] response_o;
logic [ 5:0] last_cmd_index_o;
logic [47:0] s_captured_cmd;
logic [ 7:0] s_model_resp;
integer s_captured_bits;
integer s_resp_bit;
logic s_capture_cmd;
logic s_send_resp;
always #1 clk_i = ~clk_i;
spisd_clock u_spisd_clock (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.enable_i (clock_enable_i),
.pause_i (1'b0),
.half_period_i(half_period_i),
.sck_o (sck),
.rise_tick_o (rise_tick),
.fall_tick_o (fall_tick),
.running_o (running)
);
spisd_command u_spisd_command (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rise_tick_i (rise_tick),
.fall_tick_i (fall_tick),
.start_i (start_i),
.abort_i (abort_i),
.cmd_index_i (cmd_index_i),
.cmd_arg_i (cmd_arg_i),
.resp_type_i (resp_type_i),
.stuff_byte_i (stuff_byte_i),
.timeout_cycles_i (timeout_cycles_i),
.busy_timeout_cycles_i(busy_timeout_cycles_i),
.miso_i (miso_i),
.mosi_o (mosi_o),
.busy_o (busy_o),
.done_o (done_o),
.error_o (error_o),
.timeout_o (timeout_o),
.busy_timeout_o (busy_timeout_o),
.error_code_o (error_code_o),
.response_o (response_o),
.last_cmd_index_o (last_cmd_index_o)
);
always @(posedge sck) begin
if (s_capture_cmd && (s_captured_bits < 48)) begin
s_captured_cmd = {s_captured_cmd[46:0], mosi_o};
s_captured_bits = s_captured_bits + 1;
end
end
always @(negedge sck) begin
if (s_send_resp && (s_captured_bits == 48) && (s_resp_bit < 8)) begin
miso_i <= s_model_resp[7-s_resp_bit];
s_resp_bit = s_resp_bit + 1;
end else begin
miso_i <= 1'b1;
end
end
task automatic start_command;
begin
@(negedge clk_i);
start_i = 1'b1;
@(negedge clk_i);
start_i = 1'b0;
end
endtask
task automatic wait_complete;
begin
wait (done_o);
clock_enable_i = 1'b0;
@(posedge clk_i);
wait (!done_o);
wait (!running);
end
endtask
initial begin
s_captured_cmd = '0;
s_captured_bits = 0;
s_resp_bit = 0;
s_capture_cmd = 1'b1;
s_send_resp = 1'b0;
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
clock_enable_i = 1'b1;
cmd_index_i = 6'd0;
cmd_arg_i = 32'd0;
resp_type_i = spisd_pkg::SpisdRespNone;
start_command();
wait (done_o);
if (error_o || (s_captured_bits != 48) ||
(s_captured_cmd != {2'b01, 6'd0, 32'd0, 7'h4A, 1'b1}) ||
(last_cmd_index_o != 6'd0)) begin
$fatal(1, "command frame failed: frame=%h bits=%0d err=%b", s_captured_cmd, s_captured_bits,
error_o);
end
wait_complete();
s_captured_cmd = '0;
s_captured_bits = 0;
s_resp_bit = 0;
s_model_resp = 8'h01;
s_send_resp = 1'b1;
cmd_index_i = 6'd8;
cmd_arg_i = 32'h0000_01AA;
resp_type_i = spisd_pkg::SpisdRespR1;
start_command();
clock_enable_i = 1'b1;
wait (done_o);
if (error_o || (response_o[7:0] != 8'h01) ||
(s_captured_cmd != {2'b01, 6'd8, 32'h0000_01AA, 7'h43, 1'b1})) begin
$fatal(1, "R1 command/response failed: frame=%h response=%h", s_captured_cmd, response_o);
end
wait_complete();
s_captured_bits = 0;
s_capture_cmd = 1'b0;
s_send_resp = 1'b0;
miso_i = 1'b1;
timeout_cycles_i = 32'd12;
cmd_index_i = 6'd13;
cmd_arg_i = 32'd0;
resp_type_i = spisd_pkg::SpisdRespR1;
start_command();
clock_enable_i = 1'b1;
wait (done_o);
if (!error_o || !timeout_o || busy_timeout_o ||
(error_code_o != spisd_pkg::SpisdErrCmdTimeout)) begin
$fatal(1, "response timeout classification failed");
end
$display("SPISD command frame, R1 response, and timeout test passed");
$finish;
end
endmodule