Files
retroSoC/tests/rtl/dma_crypto_tb.sv
T
maksyuki db9282aaf6 feat: add crypto accelerator support and related tests
- Modified DMA error testbench to include crypto input and output AXI4 stream interfaces.
- Updated DMA register testbench to integrate crypto AXI4 stream interfaces.
- Enhanced SOC IRQ topology test to account for new crypto IRQs.
- Added WS2812 DMA testbench modifications for crypto interfaces.
- Introduced new Python tests for crypto primitives (AES, SHA, RSA) and APB register paths.
- Implemented register parity tests to ensure synchronization between RTL and SDK constants.
- Expanded DMA tests to validate crypto streaming endpoints.
- Updated memory map tests to include crypto address definitions.
- Adjusted SOC topology tests to reflect changes in IRQ mappings and peripheral counts.
2026-08-21 07:29:00 +08:00

265 lines
9.3 KiB
Systemverilog

`timescale 1ns / 1ps
module dma_crypto_tb;
import dma_pkg::*;
localparam int NumChannels = 6;
localparam logic [31:0] SourceBase = 32'h4000_0000;
localparam logic [31:0] DestinationBase = 32'h4000_1000;
localparam logic [31:0] TransferBytes = 32'd64;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic [NumChannels*32-1:0] ch_cfg_i = '0;
logic [NumChannels*32-1:0] src_addr_i = '0;
logic [NumChannels*32-1:0] dst_addr_i = '0;
logic [NumChannels*32-1:0] byte_count_i = '0;
logic [NumChannels*32-1:0] request_sel_i = '0;
logic [NumChannels*32-1:0] burst_cfg_i = '0;
logic [ NumChannels-1:0] start_i = '0;
logic [ NumChannels-1:0] busy_o;
logic [ NumChannels-1:0] done_o;
logic [ NumChannels-1:0] error_o;
logic [NumChannels*32-1:0] bytes_done_o;
logic [ 31:0] cycle_q = '0;
logic read_active_q = 1'b0;
logic [ 31:0] read_addr_q = '0;
logic [ 4:0] read_beats_q = '0;
logic [ 4:0] read_index_q = '0;
logic write_active_q = 1'b0;
logic [ 31:0] write_addr_q = '0;
logic [ 4:0] write_beats_q = '0;
logic [ 4:0] write_index_q = '0;
logic write_response_q = 1'b0;
logic stream_last_seen_q = 1'b0;
integer write_count = 0;
dma_req_if req ();
axi4_if axi4 (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if i2s_tx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if i2s_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if dvp_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if crypto_in_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if crypto_out_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
assign req.i2s_tx_proc = 1'b1;
assign req.i2s_rx_proc = 1'b1;
assign req.qspi_tx_proc = 1'b1;
assign req.qspi_rx_proc = 1'b1;
assign req.uart_tx_proc = 1'b1;
assign req.uart_rx_proc = 1'b1;
assign req.i2c0_tx_proc = 1'b1;
assign req.i2c0_rx_proc = 1'b1;
assign req.i2c1_tx_proc = 1'b1;
assign req.i2c1_rx_proc = 1'b1;
assign req.crypto_in_proc = 1'b1;
assign req.crypto_out_proc = 1'b1;
assign axi4.arready = !read_active_q && cycle_q[0];
assign axi4.rid = '0;
assign axi4.rdata = 32'hcafe_0000 | ((read_addr_q - SourceBase) >> 2) | read_index_q;
assign axi4.rresp = `AXI4_RESP_OKAY;
assign axi4.rlast = (read_index_q + 1'b1) == read_beats_q;
assign axi4.ruser = '0;
assign axi4.rvalid = read_active_q;
assign axi4.awready = !write_active_q && !write_response_q && cycle_q[0];
assign axi4.wready = write_active_q && cycle_q[1];
assign axi4.bid = '0;
assign axi4.bresp = `AXI4_RESP_OKAY;
assign axi4.buser = '0;
assign axi4.bvalid = write_response_q;
assign i2s_tx_axis.tready = 1'b0;
assign i2s_rx_axis.tdata = '0;
assign i2s_rx_axis.tkeep = '0;
assign i2s_rx_axis.tstrb = '0;
assign i2s_rx_axis.tlast = 1'b0;
assign i2s_rx_axis.tid = '0;
assign i2s_rx_axis.tdest = '0;
assign i2s_rx_axis.tuser = '0;
assign i2s_rx_axis.tvalid = 1'b0;
assign dvp_rx_axis.tdata = '0;
assign dvp_rx_axis.tkeep = '0;
assign dvp_rx_axis.tstrb = '0;
assign dvp_rx_axis.tlast = 1'b0;
assign dvp_rx_axis.tid = '0;
assign dvp_rx_axis.tdest = '0;
assign dvp_rx_axis.tuser = '0;
assign dvp_rx_axis.tvalid = 1'b0;
assign crypto_in_axis.tready = crypto_out_axis.tready && cycle_q[0];
assign crypto_out_axis.tdata = crypto_in_axis.tdata;
assign crypto_out_axis.tkeep = crypto_in_axis.tkeep;
assign crypto_out_axis.tstrb = crypto_in_axis.tstrb;
assign crypto_out_axis.tlast = crypto_in_axis.tlast;
assign crypto_out_axis.tid = crypto_in_axis.tid;
assign crypto_out_axis.tdest = crypto_in_axis.tdest;
assign crypto_out_axis.tuser = crypto_in_axis.tuser;
assign crypto_out_axis.tvalid = crypto_in_axis.tvalid && cycle_q[0];
dma_core #(
.NumChannels (NumChannels),
.MaxBurstBeats(16),
.FifoDepth (16)
) u_dma_core (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.global_reset_i (1'b0),
.global_error_clear_i (1'b0),
.ch_cfg_i (ch_cfg_i),
.src_addr_i (src_addr_i),
.dst_addr_i (dst_addr_i),
.byte_count_i (byte_count_i),
.request_sel_i (request_sel_i),
.burst_cfg_i (burst_cfg_i),
.start_i (start_i),
.suspend_i ('0),
.resume_i ('0),
.abort_i ('0),
.channel_reset_i ('0),
.event_clear_i ('0),
.busy_o (busy_o),
.suspended_o (),
.done_o (done_o),
.aborted_o (),
.error_o (error_o),
.stream_last_o (),
.event_status_o (),
.error_status_o (),
.error_addr_o (),
.current_src_o (),
.current_dst_o (),
.remaining_o (),
.bytes_done_o (bytes_done_o),
.stall_cycles_lo_o (),
.stall_cycles_hi_o (),
.first_error_valid_o (),
.first_error_channel_o(),
.first_error_status_o (),
.first_error_addr_hi_o(),
.request_status_o (),
.xpi_xfer_done_o (),
.req (req),
.axi4 (axi4),
.i2s_tx_axis (i2s_tx_axis),
.i2s_rx_axis (i2s_rx_axis),
.dvp_rx_axis (dvp_rx_axis),
.crypto_in_axis (crypto_in_axis),
.crypto_out_axis (crypto_out_axis)
);
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
cycle_q <= '0;
read_active_q <= 1'b0;
write_active_q <= 1'b0;
write_response_q <= 1'b0;
stream_last_seen_q <= 1'b0;
write_count <= 0;
end else begin
cycle_q <= cycle_q + 1'b1;
if (axi4.arvalid && axi4.arready) begin
read_active_q <= 1'b1;
read_addr_q <= axi4.araddr;
read_beats_q <= axi4.arlen + 1'b1;
read_index_q <= '0;
end
if (axi4.rvalid && axi4.rready) begin
if (axi4.rlast) begin
read_active_q <= 1'b0;
end else begin
read_index_q <= read_index_q + 1'b1;
end
end
if (axi4.awvalid && axi4.awready) begin
write_active_q <= 1'b1;
write_addr_q <= axi4.awaddr;
write_beats_q <= axi4.awlen + 1'b1;
write_index_q <= '0;
end
if (axi4.wvalid && axi4.wready) begin
if ((write_addr_q + (write_index_q << 2)) != (DestinationBase + (write_count * 4))) begin
$fatal(1, "crypto DMA write address mismatch");
end
if (axi4.wdata != (32'hcafe_0000 | write_count)) begin
$fatal(1, "crypto DMA write data mismatch: %h at %0d", axi4.wdata, write_count);
end
write_count <= write_count + 1;
if (axi4.wlast) begin
if ((write_index_q + 1'b1) != write_beats_q) begin
$fatal(1, "crypto DMA WLAST mismatch");
end
write_active_q <= 1'b0;
write_response_q <= 1'b1;
end else begin
write_index_q <= write_index_q + 1'b1;
end
end
if (axi4.bvalid && axi4.bready) begin
write_response_q <= 1'b0;
end
if (crypto_in_axis.tvalid && crypto_in_axis.tready && crypto_in_axis.tlast) begin
stream_last_seen_q <= 1'b1;
end
end
end
initial begin
integer wait_cycles;
ch_cfg_i[(4*32)+:32] = {22'd0, 2'd3, 1'b0, 1'b1, DMA_WIDTH_32, 1'b0, DMA_KIND_MM_TO_STREAM};
src_addr_i[(4*32)+:32] = SourceBase;
byte_count_i[(4*32)+:32] = TransferBytes;
request_sel_i[(4*32)+:32] = {28'd0, DMA_REQUEST_CRYPTO_IN};
burst_cfg_i[(4*32)+:32] = 32'd8;
ch_cfg_i[(5*32)+:32] = {22'd0, 2'd3, 1'b1, 1'b0, DMA_WIDTH_32, 1'b0, DMA_KIND_STREAM_TO_MM};
dst_addr_i[(5*32)+:32] = DestinationBase;
byte_count_i[(5*32)+:32] = TransferBytes;
request_sel_i[(5*32)+:32] = {28'd0, DMA_REQUEST_CRYPTO_OUT};
burst_cfg_i[(5*32)+:32] = 32'd8;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
@(negedge clk_i);
start_i[5:4] = 2'b11;
@(negedge clk_i);
start_i = '0;
wait_cycles = 0;
while (!(done_o[4] && done_o[5]) && (wait_cycles < 5000)) begin
@(posedge clk_i);
wait_cycles = wait_cycles + 1;
end
if (!(done_o[4] && done_o[5])) begin
$fatal(1, "crypto DMA endpoint test timeout");
end
if ((error_o != '0) || (write_count != 16) || !stream_last_seen_q ||
(bytes_done_o[(4*32)+:32] != TransferBytes) ||
(bytes_done_o[(5*32)+:32] != TransferBytes)) begin
$fatal(1, "crypto DMA result mismatch errors=%b writes=%0d last=%b", error_o, write_count,
stream_last_seen_q);
end
$display("DMA crypto channel 4/5 streaming test passed");
$finish;
end
endmodule