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

276 lines
8.2 KiB
Systemverilog

`timescale 1ns / 1ps
module crypto_engine_tb;
import crypto_pkg::*;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic zeroize_i = 1'b0;
logic aes_abort;
logic aes_key_commit;
logic [ 1:0] aes_key_size;
logic [255:0] aes_key;
logic aes_key_valid;
logic aes_key_busy;
logic aes_start;
logic [ 1:0] aes_mode;
logic aes_decrypt;
logic [ 31:0] aes_length;
logic [127:0] aes_iv;
logic aes_input_valid;
logic aes_input_ready;
logic [ 31:0] aes_input_data;
logic [ 3:0] aes_input_keep;
logic aes_input_last;
logic aes_output_valid;
logic aes_output_ready;
logic [ 31:0] aes_output_data;
logic [ 3:0] aes_output_keep;
logic aes_output_last;
logic aes_busy;
logic aes_done;
logic aes_error;
logic [ 31:0] aes_bytes_in;
logic [ 31:0] aes_bytes_out;
logic [ 31:0] aes_cycles;
logic [127:0] aes_chain;
logic sha_abort;
logic sha_start;
logic sha256;
logic [ 63:0] sha_length;
logic sha_input_valid;
logic sha_input_ready;
logic [ 31:0] sha_input_data;
logic [ 3:0] sha_input_keep;
logic sha_input_last;
logic sha_busy;
logic sha_done;
logic sha_error;
logic sha_digest_valid;
logic [255:0] sha_digest;
logic [ 63:0] sha_bytes_in;
logic [ 31:0] sha_cycles;
always #5 clk_i = ~clk_i;
crypto_aes_engine u_crypto_aes_engine (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.zeroize_i (zeroize_i),
.abort_i (aes_abort),
.key_commit_i (aes_key_commit),
.key_size_i (aes_key_size),
.key_i (aes_key),
.key_valid_o (aes_key_valid),
.key_busy_o (aes_key_busy),
.start_i (aes_start),
.mode_i (aes_mode),
.decrypt_i (aes_decrypt),
.length_i (aes_length),
.iv_i (aes_iv),
.input_valid_i (aes_input_valid),
.input_ready_o (aes_input_ready),
.input_data_i (aes_input_data),
.input_keep_i (aes_input_keep),
.input_last_i (aes_input_last),
.output_valid_o(aes_output_valid),
.output_ready_i(aes_output_ready),
.output_data_o (aes_output_data),
.output_keep_o (aes_output_keep),
.output_last_o (aes_output_last),
.busy_o (aes_busy),
.done_o (aes_done),
.error_o (aes_error),
.bytes_in_o (aes_bytes_in),
.bytes_out_o (aes_bytes_out),
.cycles_o (aes_cycles),
.chain_o (aes_chain)
);
crypto_sha2_engine u_crypto_sha2_engine (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.zeroize_i (zeroize_i),
.abort_i (sha_abort),
.start_i (sha_start),
.sha256_i (sha256),
.length_i (sha_length),
.input_valid_i (sha_input_valid),
.input_ready_o (sha_input_ready),
.input_data_i (sha_input_data),
.input_keep_i (sha_input_keep),
.input_last_i (sha_input_last),
.busy_o (sha_busy),
.done_o (sha_done),
.error_o (sha_error),
.digest_valid_o(sha_digest_valid),
.digest_o (sha_digest),
.bytes_in_o (sha_bytes_in),
.cycles_o (sha_cycles)
);
task automatic aes_load_key(input logic [255:0] key);
begin
@(negedge clk_i);
aes_key_size = AES_KEY_128;
aes_key = key;
aes_key_commit = 1'b1;
@(negedge clk_i);
aes_key_commit = 1'b0;
wait (aes_key_valid);
end
endtask
task automatic aes_begin(input logic [1:0] mode, input logic [31:0] length,
input logic [127:0] iv);
begin
@(negedge clk_i);
aes_mode = mode;
aes_length = length;
aes_iv = iv;
aes_decrypt = 1'b0;
aes_start = 1'b1;
@(negedge clk_i);
aes_start = 1'b0;
wait (aes_busy);
end
endtask
task automatic aes_send(input logic [31:0] data, input logic [3:0] keep, input logic last);
begin
@(negedge clk_i);
aes_input_data = data;
aes_input_keep = keep;
aes_input_last = last;
aes_input_valid = 1'b1;
while (!aes_input_ready) begin
@(negedge clk_i);
end
@(negedge clk_i);
aes_input_valid = 1'b0;
end
endtask
task automatic aes_expect(input logic [31:0] data, input logic [3:0] keep, input logic last);
begin
aes_output_ready = 1'b1;
while (!aes_output_valid) begin
@(negedge clk_i);
end
if ((aes_output_data != data) || (aes_output_keep != keep) || (aes_output_last != last)) begin
$fatal(1, "AES stream mismatch: got %h/%h/%b expected %h/%h/%b", aes_output_data,
aes_output_keep, aes_output_last, data, keep, last);
end
@(negedge clk_i);
aes_output_ready = 1'b0;
end
endtask
task automatic sha_begin(input logic use_sha256, input logic [63:0] length);
begin
@(negedge clk_i);
sha256 = use_sha256;
sha_length = length;
sha_start = 1'b1;
@(negedge clk_i);
sha_start = 1'b0;
wait (sha_busy);
end
endtask
task automatic sha_send(input logic [31:0] data, input logic [3:0] keep, input logic last);
begin
@(negedge clk_i);
sha_input_data = data;
sha_input_keep = keep;
sha_input_last = last;
sha_input_valid = 1'b1;
while (!sha_input_ready) begin
@(negedge clk_i);
end
@(negedge clk_i);
sha_input_valid = 1'b0;
end
endtask
initial begin
aes_abort = 1'b0;
aes_key_commit = 1'b0;
aes_key_size = AES_KEY_128;
aes_key = '0;
aes_start = 1'b0;
aes_mode = AES_MODE_ECB;
aes_decrypt = 1'b0;
aes_length = '0;
aes_iv = '0;
aes_input_valid = 1'b0;
aes_input_data = '0;
aes_input_keep = '0;
aes_input_last = 1'b0;
aes_output_ready = 1'b0;
sha_abort = 1'b0;
sha_start = 1'b0;
sha256 = 1'b1;
sha_length = '0;
sha_input_valid = 1'b0;
sha_input_data = '0;
sha_input_keep = '0;
sha_input_last = 1'b0;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
aes_load_key(256'h000102030405060708090a0b0c0d0e0f_00000000000000000000000000000000);
aes_begin(AES_MODE_ECB, 32'd16, '0);
aes_send(32'h33221100, 4'hf, 1'b0);
aes_send(32'h77665544, 4'hf, 1'b0);
aes_send(32'hbbaa9988, 4'hf, 1'b0);
aes_send(32'hffeeddcc, 4'hf, 1'b1);
aes_expect(32'hd8e0c469, 4'hf, 1'b0);
aes_expect(32'h30047b6a, 4'hf, 1'b0);
aes_expect(32'h80b7cdd8, 4'hf, 1'b0);
aes_expect(32'h5ac5b470, 4'hf, 1'b1);
wait (aes_done);
if (aes_error || (aes_bytes_in != 32'd16) || (aes_bytes_out != 32'd16)) begin
$fatal(1, "AES ECB status mismatch");
end
aes_load_key(256'h2b7e151628aed2a6abf7158809cf4f3c_00000000000000000000000000000000);
aes_begin(AES_MODE_CTR, 32'd20, 128'hf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff);
aes_send(32'he2bec16b, 4'hf, 1'b0);
aes_send(32'h969f402e, 4'hf, 1'b0);
aes_send(32'h117e3de9, 4'hf, 1'b0);
aes_send(32'h2a179373, 4'hf, 1'b0);
aes_send(32'h578a2dae, 4'hf, 1'b1);
aes_expect(32'h91614d87, 4'hf, 1'b0);
aes_expect(32'h26e320b6, 4'hf, 1'b0);
aes_expect(32'h6468ef1b, 4'hf, 1'b0);
aes_expect(32'hceb60d99, 4'hf, 1'b0);
aes_expect(32'h6bf60698, 4'hf, 1'b1);
wait (aes_done);
if (aes_error || (aes_chain != 128'hf0f1f2f3f4f5f6f7f8f9fafbfcfdff01)) begin
$fatal(1, "AES CTR status mismatch: error=%b chain=%h", aes_error, aes_chain);
end
sha_begin(1'b1, 64'd3);
sha_send(32'h00636261, 4'h7, 1'b1);
wait (sha_done);
if (sha_error || !sha_digest_valid ||
(sha_digest != 256'hba7816bf8f01cfea414140de5dae2223b00361a396177a9c_b410ff61f20015ad)) begin
$fatal(1, "SHA-256 stream result mismatch: %h", sha_digest);
end
sha_begin(1'b0, 64'd0);
wait (sha_done);
if (sha_error || !sha_digest_valid ||
(sha_digest != 256'hd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f_00000000)) begin
$fatal(1, "SHA-224 empty result mismatch: %h", sha_digest);
end
$display("Crypto streaming engine tests passed");
$finish;
end
endmodule