test: support 1000 KAT Vectors
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
// tb_sample_ntt_xsim.v - Vivado xsim smoke-test testbench for sample_ntt_sync
|
||||
// tb_sample_ntt_xsim.v - Vivado xsim FIPS SampleNTT testbench
|
||||
//
|
||||
// Drives the DUT with test vectors from a hex file, then verifies that
|
||||
// the DUT produces exactly 256 coefficients, each in range [0, Q-1].
|
||||
// This is a smoke test — it does NOT compare against Python expected values
|
||||
// because the RTL uses a per-permutation Keccak-p approach that differs
|
||||
// from standard SHAKE-128 bit-stream semantics.
|
||||
// Drives the DUT with test vectors from a hex file and checks every coefficient
|
||||
// against the FIPS 203 reference generated by gen_vectors.py.
|
||||
//
|
||||
// Vector format (packed hex, 66 chars for $readmemh):
|
||||
// {j_idx[1:0], i_idx[1:0], k_i[2:0], rho_i[255:0]} (264 bits → 66 hex chars)
|
||||
@@ -16,7 +13,8 @@
|
||||
//
|
||||
// Prerequisites:
|
||||
// - Generate vectors: python3 TB/gen_vectors.py
|
||||
// - Output file: vectors/sample_ntt_input.hex
|
||||
// - Or refresh expected vectors: python3 TB/gen_vectors.py --refresh-expected
|
||||
// - Output files: vectors/sample_ntt_input.hex, vectors/sample_ntt_expected.hex
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
@@ -25,11 +23,13 @@ module tb_sample_ntt_xsim;
|
||||
// ================================================================
|
||||
// Parameters
|
||||
// ================================================================
|
||||
parameter VECTOR_FILE = "sync_rtl/sample_ntt/TB/vectors/sample_ntt_input.hex";
|
||||
parameter MAX_VECTORS = 32; // max lines in input file
|
||||
parameter Q = 3329; // ML-KEM modulus
|
||||
parameter N_COEFFS = 256; // coefficients per polynomial
|
||||
parameter TIMEOUT = 500000; // per-vector timeout (cycles)
|
||||
parameter VECTOR_FILE = "sync_rtl/sample_ntt/TB/vectors/sample_ntt_input.hex";
|
||||
parameter EXPECTED_FILE = "sync_rtl/sample_ntt/TB/vectors/sample_ntt_expected.hex";
|
||||
parameter MAX_VECTORS = 32; // allocation limit for input vectors
|
||||
parameter VECTOR_COUNT = 5; // vectors present in VECTOR_FILE
|
||||
parameter Q = 3329; // ML-KEM modulus
|
||||
parameter N_COEFFS = 256; // coefficients per polynomial
|
||||
parameter TIMEOUT = 500000; // per-vector timeout (cycles)
|
||||
|
||||
// ================================================================
|
||||
// DUT signals
|
||||
@@ -75,6 +75,7 @@ module tb_sample_ntt_xsim;
|
||||
// Vector memory (loaded by $readmemh)
|
||||
// ================================================================
|
||||
reg [263:0] vector_mem [0:MAX_VECTORS-1];
|
||||
reg [11:0] expected_mem [0:MAX_VECTORS*N_COEFFS-1];
|
||||
integer vec_count;
|
||||
integer idx;
|
||||
integer cycle_count;
|
||||
@@ -88,27 +89,14 @@ module tb_sample_ntt_xsim;
|
||||
// Main test sequence
|
||||
// ================================================================
|
||||
initial begin
|
||||
vec_count = 0;
|
||||
|
||||
// Load vectors from hex file
|
||||
$readmemh(VECTOR_FILE, vector_mem);
|
||||
$readmemh(EXPECTED_FILE, expected_mem);
|
||||
|
||||
// Count non-zero/X entries to determine actual vector count
|
||||
begin
|
||||
integer found_end;
|
||||
found_end = 0;
|
||||
for (idx = 0; idx < MAX_VECTORS; idx = idx + 1) begin
|
||||
if (!found_end && (vector_mem[idx] === {264{1'bx}} || vector_mem[idx] === {264{1'bz}}))
|
||||
found_end = 1;
|
||||
else if (!found_end)
|
||||
vec_count = vec_count + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (vec_count == 0) begin
|
||||
$display("ERROR: No vectors loaded from %s", VECTOR_FILE);
|
||||
$display(" Check that the file exists and is in the correct format.");
|
||||
$display(" Each line: <66 hex chars> = {j, i, k, rho}");
|
||||
vec_count = VECTOR_COUNT;
|
||||
if (vec_count < 1 || vec_count > MAX_VECTORS) begin
|
||||
$display("ERROR: VECTOR_COUNT=%0d must be in [1,%0d]",
|
||||
vec_count, MAX_VECTORS);
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -141,6 +129,8 @@ module tb_sample_ntt_xsim;
|
||||
reg [1:0] vec_i;
|
||||
reg [1:0] vec_j;
|
||||
reg range_ok;
|
||||
reg coeff_ok;
|
||||
reg last_ok;
|
||||
|
||||
// Extract fields from packed vector_mem
|
||||
// vector_mem[263:0] = {1'b0, j_idx, i_idx, k_i, rho_i}
|
||||
@@ -170,18 +160,31 @@ module tb_sample_ntt_xsim;
|
||||
coeff_idx = 0;
|
||||
cycle_count = 0;
|
||||
range_ok = 1'b1; // assume OK until proven otherwise
|
||||
coeff_ok = 1'b1;
|
||||
last_ok = 1'b1;
|
||||
|
||||
while (coeff_idx < N_COEFFS && cycle_count < TIMEOUT) begin
|
||||
@(posedge clk);
|
||||
cycle_count = cycle_count + 1;
|
||||
|
||||
if (valid_o) begin
|
||||
if (coeff_o !== expected_mem[idx*N_COEFFS + coeff_idx]) begin
|
||||
$display("ERROR: Vector %0d coeff[%0d] mismatch: got=%03h expected=%03h",
|
||||
idx, coeff_idx, coeff_o,
|
||||
expected_mem[idx*N_COEFFS + coeff_idx]);
|
||||
coeff_ok = 1'b0;
|
||||
end
|
||||
// Check range: coefficient must be in [0, Q-1]
|
||||
if (coeff_o >= Q) begin
|
||||
$display("ERROR: Vector %0d coeff[%0d]=%0d out of range [0,%0d]",
|
||||
idx, coeff_idx, coeff_o, Q-1);
|
||||
range_ok = 1'b0;
|
||||
end
|
||||
if (last_o !== (coeff_idx == N_COEFFS-1)) begin
|
||||
$display("ERROR: Vector %0d coeff[%0d] last_o=%b expected=%b",
|
||||
idx, coeff_idx, last_o, coeff_idx == N_COEFFS-1);
|
||||
last_ok = 1'b0;
|
||||
end
|
||||
coeff_idx = coeff_idx + 1;
|
||||
end
|
||||
end
|
||||
@@ -199,8 +202,16 @@ module tb_sample_ntt_xsim;
|
||||
$display("ERROR: Vector %0d produced out-of-range coefficients",
|
||||
idx);
|
||||
fail_count = fail_count + 1;
|
||||
end else if (!coeff_ok) begin
|
||||
$display("ERROR: Vector %0d did not match FIPS SampleNTT",
|
||||
idx);
|
||||
fail_count = fail_count + 1;
|
||||
end else if (!last_ok) begin
|
||||
$display("ERROR: Vector %0d asserted last_o on the wrong coefficient",
|
||||
idx);
|
||||
fail_count = fail_count + 1;
|
||||
end else begin
|
||||
$display("INFO: Vector %0d PASSED (%0d coefficients in %0d cycles, all in range)",
|
||||
$display("INFO: Vector %0d PASSED (%0d FIPS-matching coefficients in %0d cycles)",
|
||||
idx, coeff_idx, cycle_count);
|
||||
pass_count = pass_count + 1;
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user