mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
- Introduced a new USB2 transaction engine testbench to validate the functionality of the USB2 transaction engine. - Updated clock and reset domain tests to include USB2 ULPI crossings. - Enhanced memory map tests to verify USB2 base addresses and performance offsets. - Modified pin map tests to ensure USB2 ULPI pins are correctly generated. - Updated SOC topology tests to account for USB2 peripherals and IRQ mappings. - Added static timing analysis constraints for USB2 clock domains. - Created dedicated USB2 tests for various components including packet RAM, descriptor validation, and transaction engine. - Implemented a register parity test to ensure ABI consistency between RTL and C header definitions.
214 lines
6.8 KiB
Systemverilog
214 lines
6.8 KiB
Systemverilog
`timescale 1ns / 1ps
|
|
|
|
module usb2_packet_store_tb;
|
|
logic clk_i = 1'b0;
|
|
logic rst_n_i = 1'b0;
|
|
logic fill_start_valid_i = 1'b0;
|
|
logic fill_start_ready_o;
|
|
logic [11:0] fill_base_i = '0;
|
|
logic [14:0] fill_bytes_i = '0;
|
|
logic fill_valid_i = 1'b0;
|
|
logic fill_ready_o;
|
|
logic [31:0] fill_data_i = '0;
|
|
logic [ 3:0] fill_strb_i = '0;
|
|
logic fill_last_i = 1'b0;
|
|
logic fill_done_o;
|
|
logic fill_error_o;
|
|
logic drain_start_valid_i = 1'b0;
|
|
logic drain_start_ready_o;
|
|
logic [11:0] drain_base_i = '0;
|
|
logic [14:0] drain_bytes_i = '0;
|
|
logic drain_valid_o;
|
|
logic drain_ready_i = 1'b1;
|
|
logic [31:0] drain_data_o;
|
|
logic [ 3:0] drain_strb_o;
|
|
logic drain_last_o;
|
|
logic drain_done_o;
|
|
logic rx_start_valid_i = 1'b0;
|
|
logic rx_start_ready_o;
|
|
logic [11:0] rx_base_i = '0;
|
|
logic [14:0] rx_limit_i = '0;
|
|
logic rx_valid_i = 1'b0;
|
|
logic rx_ready_o;
|
|
logic [ 7:0] rx_data_i = '0;
|
|
logic rx_commit_i = 1'b0;
|
|
logic rx_cancel_i = 1'b0;
|
|
logic rx_done_o;
|
|
logic [14:0] rx_bytes_o;
|
|
logic rx_overflow_o;
|
|
logic tx_start_valid_i = 1'b0;
|
|
logic tx_start_ready_o;
|
|
logic [11:0] tx_base_i = '0;
|
|
logic [14:0] tx_bytes_i = '0;
|
|
logic tx_valid_o;
|
|
logic tx_ready_i = 1'b1;
|
|
logic [ 7:0] tx_data_o;
|
|
logic tx_done_o;
|
|
logic busy_o;
|
|
logic ecc_corrected_o;
|
|
logic ecc_uncorrectable_o;
|
|
integer tx_count;
|
|
integer drain_count;
|
|
logic [ 7:0] tx_bytes [0:4];
|
|
logic [31:0] drain_words [0:1];
|
|
logic [ 3:0] drain_strb [0:1];
|
|
|
|
always #5 clk_i = ~clk_i;
|
|
|
|
always_ff @(posedge clk_i) begin
|
|
if (!rst_n_i) begin
|
|
tx_count <= 0;
|
|
drain_count <= 0;
|
|
end else begin
|
|
if (tx_valid_o && tx_ready_i) begin
|
|
tx_bytes[tx_count] <= tx_data_o;
|
|
tx_count <= tx_count + 1;
|
|
end
|
|
if (drain_valid_o && drain_ready_i) begin
|
|
drain_words[drain_count] <= drain_data_o;
|
|
drain_strb[drain_count] <= drain_strb_o;
|
|
drain_count <= drain_count + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
usb2_packet_store u_dut (
|
|
.clk_i (clk_i),
|
|
.rst_n_i (rst_n_i),
|
|
.fill_start_valid_i (fill_start_valid_i),
|
|
.fill_start_ready_o (fill_start_ready_o),
|
|
.fill_base_i (fill_base_i),
|
|
.fill_bytes_i (fill_bytes_i),
|
|
.fill_valid_i (fill_valid_i),
|
|
.fill_ready_o (fill_ready_o),
|
|
.fill_data_i (fill_data_i),
|
|
.fill_strb_i (fill_strb_i),
|
|
.fill_last_i (fill_last_i),
|
|
.fill_done_o (fill_done_o),
|
|
.fill_error_o (fill_error_o),
|
|
.drain_start_valid_i(drain_start_valid_i),
|
|
.drain_start_ready_o(drain_start_ready_o),
|
|
.drain_base_i (drain_base_i),
|
|
.drain_bytes_i (drain_bytes_i),
|
|
.drain_valid_o (drain_valid_o),
|
|
.drain_ready_i (drain_ready_i),
|
|
.drain_data_o (drain_data_o),
|
|
.drain_strb_o (drain_strb_o),
|
|
.drain_last_o (drain_last_o),
|
|
.drain_done_o (drain_done_o),
|
|
.rx_start_valid_i (rx_start_valid_i),
|
|
.rx_start_ready_o (rx_start_ready_o),
|
|
.rx_base_i (rx_base_i),
|
|
.rx_limit_i (rx_limit_i),
|
|
.rx_valid_i (rx_valid_i),
|
|
.rx_ready_o (rx_ready_o),
|
|
.rx_data_i (rx_data_i),
|
|
.rx_commit_i (rx_commit_i),
|
|
.rx_cancel_i (rx_cancel_i),
|
|
.rx_done_o (rx_done_o),
|
|
.rx_bytes_o (rx_bytes_o),
|
|
.rx_overflow_o (rx_overflow_o),
|
|
.tx_start_valid_i (tx_start_valid_i),
|
|
.tx_start_ready_o (tx_start_ready_o),
|
|
.tx_base_i (tx_base_i),
|
|
.tx_bytes_i (tx_bytes_i),
|
|
.tx_valid_o (tx_valid_o),
|
|
.tx_ready_i (tx_ready_i),
|
|
.tx_data_o (tx_data_o),
|
|
.tx_done_o (tx_done_o),
|
|
.busy_o (busy_o),
|
|
.ecc_corrected_o (ecc_corrected_o),
|
|
.ecc_uncorrectable_o(ecc_uncorrectable_o)
|
|
);
|
|
|
|
task automatic pulse_fill(input logic [31:0] data_i, input logic [3:0] strb_i,
|
|
input logic last_i);
|
|
begin
|
|
@(negedge clk_i);
|
|
fill_data_i = data_i;
|
|
fill_strb_i = strb_i;
|
|
fill_last_i = last_i;
|
|
fill_valid_i = 1'b1;
|
|
while (!fill_ready_o) @(negedge clk_i);
|
|
@(negedge clk_i);
|
|
fill_valid_i = 1'b0;
|
|
end
|
|
endtask
|
|
|
|
task automatic pulse_rx(input logic [7:0] data_i);
|
|
begin
|
|
@(negedge clk_i);
|
|
rx_data_i = data_i;
|
|
rx_valid_i = 1'b1;
|
|
while (!rx_ready_o) @(negedge clk_i);
|
|
@(negedge clk_i);
|
|
rx_valid_i = 1'b0;
|
|
end
|
|
endtask
|
|
|
|
initial begin
|
|
repeat (4) @(posedge clk_i);
|
|
rst_n_i = 1'b1;
|
|
|
|
@(negedge clk_i);
|
|
fill_base_i = 12'd8;
|
|
fill_bytes_i = 15'd5;
|
|
fill_start_valid_i = 1'b1;
|
|
@(negedge clk_i);
|
|
fill_start_valid_i = 1'b0;
|
|
pulse_fill(32'h4433_2211, 4'hF, 1'b0);
|
|
pulse_fill(32'h0000_0055, 4'h1, 1'b1);
|
|
wait (fill_done_o);
|
|
if (fill_error_o) $fatal(1, "packet store fill failed");
|
|
|
|
@(negedge clk_i);
|
|
tx_base_i = 12'd8;
|
|
tx_bytes_i = 15'd5;
|
|
tx_start_valid_i = 1'b1;
|
|
@(negedge clk_i);
|
|
tx_start_valid_i = 1'b0;
|
|
wait (tx_done_o);
|
|
@(posedge clk_i);
|
|
if ((tx_count != 5) || (tx_bytes[0] != 8'h11) || (tx_bytes[1] != 8'h22) ||
|
|
(tx_bytes[2] != 8'h33) || (tx_bytes[3] != 8'h44) || (tx_bytes[4] != 8'h55)) begin
|
|
$fatal(1, "packet store transmit mismatch count=%0d", tx_count);
|
|
end
|
|
|
|
@(negedge clk_i);
|
|
rx_base_i = 12'd16;
|
|
rx_limit_i = 15'd5;
|
|
rx_start_valid_i = 1'b1;
|
|
@(negedge clk_i);
|
|
rx_start_valid_i = 1'b0;
|
|
pulse_rx(8'hA1);
|
|
pulse_rx(8'hB2);
|
|
pulse_rx(8'hC3);
|
|
pulse_rx(8'hD4);
|
|
pulse_rx(8'hE5);
|
|
@(negedge clk_i);
|
|
rx_commit_i = 1'b1;
|
|
@(negedge clk_i);
|
|
rx_commit_i = 1'b0;
|
|
wait (rx_done_o);
|
|
if ((rx_bytes_o != 15'd5) || rx_overflow_o) $fatal(1, "packet store receive failed");
|
|
|
|
@(negedge clk_i);
|
|
drain_base_i = 12'd16;
|
|
drain_bytes_i = 15'd5;
|
|
drain_start_valid_i = 1'b1;
|
|
@(negedge clk_i);
|
|
drain_start_valid_i = 1'b0;
|
|
wait (drain_done_o);
|
|
@(posedge clk_i);
|
|
if ((drain_count != 2) || (drain_words[0] != 32'hD4C3_B2A1) ||
|
|
(drain_words[1][7:0] != 8'hE5) || (drain_strb[0] != 4'hF) ||
|
|
(drain_strb[1] != 4'h1)) begin
|
|
$fatal(1, "packet store drain mismatch count=%0d", drain_count);
|
|
end
|
|
if (ecc_corrected_o || ecc_uncorrectable_o) $fatal(1, "unexpected ECC event");
|
|
|
|
$display("USB2 packet store paths passed");
|
|
$finish;
|
|
end
|
|
endmodule
|