feat(tb): add Vivado XSIM Verilog testbenches for all 10 sync modules
Add file-based vector testbenches ( + ) for: - mod_add_sync, rng_sync, poly_arith_sync, comp_decomp_sync - s_bram/sd_bram, sha3_chain_top - ntt_core, poly_mul_sync - sample_cbd_sync, sample_ntt_sync Each module includes: - tb_<module>_xsim.v: Vivado XSIM testbench - gen_vectors.py: Python vector generator (stdlib only) - vectors/<module>_input.hex: test input vectors - xsim_run.tcl: compile + elaborate + simulate script
This commit is contained in:
195
sync_rtl/poly_mul/TB/gen_vectors.py
Normal file
195
sync_rtl/poly_mul/TB/gen_vectors.py
Normal file
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python3
|
||||
"""gen_vectors.py - Generate poly_mul test vectors for Vivado XSIM testbench.
|
||||
|
||||
Generates input vectors for poly_mul_sync module in hex format.
|
||||
Each line encodes {256x12-bit poly A, 256x12-bit poly B} = 6144 bits
|
||||
packed as a single hex number (1536 hex chars).
|
||||
|
||||
The poly_mul_sync module uses basecase_mul (degree-1 Karatsuba
|
||||
multiplication) with zeta from poly_mul_zeta_rom.
|
||||
|
||||
For each pair of degree-1 polynomials (A[2k], A[2k+1]) and (B[2k], B[2k+1]):
|
||||
c0 = (a0*b0 + a1*b1*zeta) mod Q
|
||||
c1 = (a0*b1 + a1*b0) mod Q
|
||||
|
||||
Usage:
|
||||
python3 gen_vectors.py
|
||||
Output:
|
||||
vectors/poly_mul_input.hex
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import random
|
||||
|
||||
# ============================================================
|
||||
# Constants
|
||||
# ============================================================
|
||||
Q = 3329 # ML-KEM modulus
|
||||
N = 256 # Number of coefficients per polynomial
|
||||
|
||||
# poly_mul_zeta_rom values (zeta = zeta_bitRev[k]^2 * 17 mod Q)
|
||||
# These match sync_rtl/poly_mul/poly_mul_zeta_rom.v exactly
|
||||
POLY_MUL_ZETA = [
|
||||
17, 3312, 2761, 568, 583, 2746, 2649, 680,
|
||||
1637, 1692, 723, 2606, 2288, 1041, 1100, 2229,
|
||||
1409, 1920, 2662, 667, 3281, 48, 233, 3096,
|
||||
756, 2573, 2156, 1173, 3015, 314, 3050, 279,
|
||||
1703, 1626, 1651, 1678, 2789, 540, 1789, 1540,
|
||||
1847, 1482, 952, 2377, 1461, 1868, 2687, 642,
|
||||
939, 2390, 2308, 1021, 2437, 892, 2388, 941,
|
||||
733, 2596, 2337, 992, 268, 3061, 641, 2688,
|
||||
1584, 1745, 2298, 1031, 2037, 1292, 3220, 109,
|
||||
375, 2954, 2549, 780, 2090, 1239, 1645, 1684,
|
||||
1063, 2266, 319, 3010, 2773, 556, 757, 2572,
|
||||
2099, 1230, 561, 2768, 2466, 863, 2594, 735,
|
||||
2804, 525, 1092, 2237, 403, 2926, 1026, 2303,
|
||||
1143, 2186, 2150, 1179, 2775, 554, 886, 2443,
|
||||
1722, 1607, 1212, 2117, 1874, 1455, 1029, 2300,
|
||||
2110, 1219, 2935, 394, 885, 2444, 2154, 1175,
|
||||
]
|
||||
|
||||
|
||||
def barrett_mul(a: int, b: int) -> int:
|
||||
"""Barrett modular multiplication: (a * b) mod Q."""
|
||||
return (a * b) % Q
|
||||
|
||||
|
||||
def compute_expected(a_coeffs: list, b_coeffs: list) -> list:
|
||||
"""Compute expected output of poly_mul_sync.
|
||||
|
||||
The poly_mul_sync module processes coefficient pairs using basecase_mul:
|
||||
For each k in 0..127:
|
||||
a0=A[2k], a1=A[2k+1], b0=B[2k], b1=B[2k+1], zeta=zeta_rom[k]
|
||||
c0 = (a0*b0 + a1*b1*zeta) mod Q
|
||||
c1 = (a0*b1 + a1*b0) mod Q
|
||||
"""
|
||||
result = [0] * N
|
||||
for k in range(N // 2):
|
||||
a0 = a_coeffs[2 * k]
|
||||
a1 = a_coeffs[2 * k + 1]
|
||||
b0 = b_coeffs[2 * k]
|
||||
b1 = b_coeffs[2 * k + 1]
|
||||
zeta = POLY_MUL_ZETA[k]
|
||||
|
||||
# c0 = (a0*b0 + a1*b1*zeta) mod Q
|
||||
t1 = barrett_mul(a0, b0)
|
||||
t2 = barrett_mul(a1, b1)
|
||||
t2_zeta = barrett_mul(t2, zeta)
|
||||
c0 = (t1 + t2_zeta) % Q
|
||||
|
||||
# c1 = (a0*b1 + a1*b0) mod Q
|
||||
t3 = barrett_mul(a0, b1)
|
||||
t4 = barrett_mul(a1, b0)
|
||||
c1 = (t3 + t4) % Q
|
||||
|
||||
result[2 * k] = c0
|
||||
result[2 * k + 1] = c1
|
||||
return result
|
||||
|
||||
|
||||
def coeffs_pair_to_hex(a_coeffs: list, b_coeffs: list) -> str:
|
||||
"""Convert 256+256 12-bit coefficients to a 1536-char hex string.
|
||||
|
||||
A coeffs in the MSB half, B coeffs in the LSB half.
|
||||
A[0] at the very top, B[255] at the very bottom.
|
||||
"""
|
||||
result = 0
|
||||
for c in a_coeffs:
|
||||
result = (result << 12) | (c & 0xFFF)
|
||||
for c in b_coeffs:
|
||||
result = (result << 12) | (c & 0xFFF)
|
||||
return f"{result:01536X}"
|
||||
|
||||
|
||||
def write_vector(f, a_coeffs: list, b_coeffs: list, label: str):
|
||||
"""Write a single test vector to the hex file."""
|
||||
hex_str = coeffs_pair_to_hex(a_coeffs, b_coeffs)
|
||||
f.write(f"// {label}\n")
|
||||
f.write(hex_str + "\n")
|
||||
|
||||
|
||||
def generate_vectors():
|
||||
"""Generate test vectors for poly_mul_sync."""
|
||||
os.makedirs("vectors", exist_ok=True)
|
||||
hex_path = os.path.join("vectors", "poly_mul_input.hex")
|
||||
|
||||
tests = []
|
||||
|
||||
# --- Test 0: All zeros ---
|
||||
zeros = [0] * N
|
||||
expected = [0] * N
|
||||
tests.append((zeros, zeros, expected, "A=0, B=0"))
|
||||
|
||||
# --- Test 1: A = 1 at all positions, B = all zeros ---
|
||||
a_ones = [1] * N
|
||||
tests.append((a_ones, zeros, [0] * N, "A=1, B=0"))
|
||||
|
||||
# --- Test 2: A = [1,0,1,0,...], B = [0,1,0,1,...] ---
|
||||
a_10 = [1 if i % 2 == 0 else 0 for i in range(N)]
|
||||
b_01 = [0 if i % 2 == 0 else 1 for i in range(N)]
|
||||
expected = compute_expected(a_10, b_01)
|
||||
tests.append((a_10, b_01, expected, "A=1010..., B=0101..."))
|
||||
|
||||
# --- Test 3: impulse at index 0 for both A and B ---
|
||||
a_imp0 = [0] * N
|
||||
a_imp0[0] = 1
|
||||
b_imp0 = [0] * N
|
||||
b_imp0[0] = 1
|
||||
expected = compute_expected(a_imp0, b_imp0)
|
||||
tests.append((a_imp0, b_imp0, expected, "A=imp[0], B=imp[0]"))
|
||||
|
||||
# --- Test 4: impulse at index 1 for both A and B ---
|
||||
a_imp1 = [0] * N
|
||||
a_imp1[1] = 1
|
||||
b_imp1 = [0] * N
|
||||
b_imp1[1] = 1
|
||||
expected = compute_expected(a_imp1, b_imp1)
|
||||
tests.append((a_imp1, b_imp1, expected, "A=imp[1], B=imp[1]"))
|
||||
|
||||
# --- Test 5: impulse pair (0,1) ---
|
||||
a_imp01 = [0] * N
|
||||
a_imp01[0] = 1
|
||||
a_imp01[1] = 1
|
||||
b_imp01 = [0] * N
|
||||
b_imp01[0] = 1
|
||||
b_imp01[1] = 1
|
||||
expected = compute_expected(a_imp01, b_imp01)
|
||||
tests.append((a_imp01, b_imp01, expected, "A=imp[0,1], B=imp[0,1]"))
|
||||
|
||||
# --- Test 6: all pairs identity ---
|
||||
a_id = [1, 0] * (N // 2)
|
||||
b_id = [0, 0] * (N // 2)
|
||||
b_id[0] = 1 # B = [1,0,0,0,...]
|
||||
expected = compute_expected(a_id, b_id)
|
||||
tests.append((a_id, b_id, expected, "A=all pairs (1,0), B=imp[0]"))
|
||||
|
||||
# --- Tests 7-10: random vectors ---
|
||||
random.seed(0xBEEF)
|
||||
for i in range(4):
|
||||
a_rand = [random.randrange(0, Q) for _ in range(N)]
|
||||
b_rand = [random.randrange(0, Q) for _ in range(N)]
|
||||
expected = compute_expected(a_rand, b_rand)
|
||||
tests.append((a_rand, b_rand, expected, f"random {i}"))
|
||||
|
||||
# Write input hex file
|
||||
with open(hex_path, "w") as f:
|
||||
f.write("// poly_mul_sync test vectors\n")
|
||||
f.write("// Format: {768 hex chars A coeffs}{768 hex chars B coeffs}\n")
|
||||
f.write("// A coeffs: 256 x 12-bit values, A[0] at MSB\n")
|
||||
f.write("// B coeffs: 256 x 12-bit values, B[0] after A[255]\n")
|
||||
f.write("\n")
|
||||
for a_coeffs, b_coeffs, expected, label in tests:
|
||||
write_vector(f, a_coeffs, b_coeffs, label)
|
||||
|
||||
print(f"Generated {len(tests)} test vectors → {hex_path}")
|
||||
|
||||
# Print expected results for reference
|
||||
print("\nExpected output summary (first 4 coeffs of each test):")
|
||||
for a_coeffs, b_coeffs, expected, label in tests:
|
||||
first4 = expected[:4]
|
||||
print(f" {label:35s} → [{first4[0]:4d}, {first4[1]:4d}, {first4[2]:4d}, {first4[3]:4d}, ...]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_vectors()
|
||||
312
sync_rtl/poly_mul/TB/tb_poly_mul_xsim.v
Normal file
312
sync_rtl/poly_mul/TB/tb_poly_mul_xsim.v
Normal file
@@ -0,0 +1,312 @@
|
||||
// tb_poly_mul_xsim.v - Standard Verilog testbench for poly_mul_sync targeting Vivado xsim
|
||||
//
|
||||
// Reads test vectors from a hex file using $readmemh.
|
||||
// Each line is a single hex number encoding 512 coefficient values:
|
||||
// - bits [6143:3072]: 256 x 12-bit polynomial A coefficients
|
||||
// - bits [3071:0]: 256 x 12-bit polynomial B coefficients
|
||||
// - Total: 1536 hex chars per line, NO spaces
|
||||
//
|
||||
// Drives poly_mul_sync, streams in 256 A+B coefficient pairs via valid/ready,
|
||||
// waits for valid_o output, streams out 256 result coefficients,
|
||||
// and writes "RESULT: INDEX COEFF_HEX" to the output file.
|
||||
//
|
||||
// poly_mul_sync FSM: IDLE → LOAD → COMP_CALC → COMP_C0 → COMP_C1 → ... → DONE → IDLE
|
||||
// valid_o is asserted during COMP_C0 and COMP_C1 states.
|
||||
//
|
||||
// Parameters:
|
||||
// VECTOR_FILE - path to input hex file (default: "vectors/poly_mul_input.hex")
|
||||
// RESULT_FILE - path to output file (default: "vectors/poly_mul_result.hex")
|
||||
//
|
||||
// Usage:
|
||||
// xvlog -sv barrett_mul.v basecase_mul.v poly_mul_zeta_rom.v poly_mul_sync.v tb_poly_mul_xsim.v
|
||||
// xelab tb_poly_mul_xsim -s tb_poly_mul_xsim
|
||||
// xsim tb_poly_mul_xsim -R
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_poly_mul_xsim;
|
||||
|
||||
// ================================================================
|
||||
// Parameters
|
||||
// ================================================================
|
||||
parameter VECTOR_FILE = "sync_rtl/poly_mul/TB/vectors/poly_mul_input.hex";
|
||||
parameter RESULT_FILE = "sync_rtl/poly_mul/TB/vectors/poly_mul_result.hex";
|
||||
parameter MAX_VECTORS = 64;
|
||||
parameter N_COEFFS = 256;
|
||||
parameter TIMEOUT_CYCLES= 100000;
|
||||
|
||||
// ================================================================
|
||||
// DUT signals
|
||||
// ================================================================
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
reg [11:0] coeff_a_in;
|
||||
reg [11:0] coeff_b_in;
|
||||
reg valid_i;
|
||||
wire ready_o;
|
||||
wire [11:0] coeff_out;
|
||||
wire valid_o;
|
||||
reg ready_i;
|
||||
|
||||
// ================================================================
|
||||
// DUT instantiation
|
||||
// ================================================================
|
||||
poly_mul_sync u_dut (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.coeff_a_in (coeff_a_in),
|
||||
.coeff_b_in (coeff_b_in),
|
||||
.valid_i (valid_i),
|
||||
.ready_o (ready_o),
|
||||
.coeff_out (coeff_out),
|
||||
.valid_o (valid_o),
|
||||
.ready_i (ready_i)
|
||||
);
|
||||
|
||||
// ================================================================
|
||||
// Clock generation: 100 MHz (10 ns period)
|
||||
// ================================================================
|
||||
initial clk = 1'b0;
|
||||
always #5 clk = ~clk;
|
||||
|
||||
// ================================================================
|
||||
// Vector memory (loaded by $readmemh)
|
||||
// 6144 bits per word:
|
||||
// bits [6143:3072]: 256 x 12-bit A coefficients (A[0] at MSB)
|
||||
// bits [3071:0]: 256 x 12-bit B coefficients (B[0] at MSB of lower half)
|
||||
// ================================================================
|
||||
reg [6143:0] vector_mem [0:MAX_VECTORS-1];
|
||||
integer vec_count;
|
||||
integer idx;
|
||||
integer ci;
|
||||
integer cycle_count;
|
||||
integer result_fd;
|
||||
|
||||
// Test result tracking
|
||||
integer pass_count;
|
||||
integer fail_count;
|
||||
|
||||
// Temporary storage for coefficients
|
||||
reg [11:0] a_coeffs [0:N_COEFFS-1];
|
||||
reg [11:0] b_coeffs [0:N_COEFFS-1];
|
||||
reg [11:0] output_coeffs [0:N_COEFFS-1];
|
||||
|
||||
// ================================================================
|
||||
// Hex-to-ASCII conversion helper
|
||||
// ================================================================
|
||||
function [7:0] nibble_to_ascii;
|
||||
input [3:0] nibble;
|
||||
begin
|
||||
if (nibble < 4'd10)
|
||||
nibble_to_ascii = 8'h30 + {4'd0, nibble}; // '0'-'9'
|
||||
else
|
||||
nibble_to_ascii = 8'h41 + ({4'd0, nibble} - 4'd10); // 'A'-'F'
|
||||
end
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Main test sequence
|
||||
// ================================================================
|
||||
initial begin
|
||||
// Count loaded vectors
|
||||
vec_count = 0;
|
||||
|
||||
// Load vectors from hex file
|
||||
$readmemh(VECTOR_FILE, vector_mem);
|
||||
|
||||
// Count entries (XSim leaves unloaded entries as 6144'hX)
|
||||
begin
|
||||
integer found_end;
|
||||
found_end = 0;
|
||||
for (idx = 0; idx < MAX_VECTORS; idx = idx + 1) begin
|
||||
if (!found_end && (vector_mem[idx] === 6144'hx ||
|
||||
vector_mem[idx] === 6144'hz))
|
||||
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 format is correct.");
|
||||
$display(" Each line: 1536 hex chars (768 hex A + 768 hex B)");
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("INFO: Loaded %0d test vectors from %s", vec_count, VECTOR_FILE);
|
||||
|
||||
// Open result file
|
||||
result_fd = $fopen(RESULT_FILE, "w");
|
||||
if (result_fd == 0) begin
|
||||
$display("ERROR: Cannot open result file: %s", RESULT_FILE);
|
||||
$finish;
|
||||
end
|
||||
|
||||
// Initialize DUT inputs
|
||||
coeff_a_in <= 12'd0;
|
||||
coeff_b_in <= 12'd0;
|
||||
valid_i <= 1'b0;
|
||||
ready_i <= 1'b1; // always ready to accept output
|
||||
|
||||
// Reset sequence: rst_n low for 3 cycles, then high
|
||||
rst_n <= 1'b0;
|
||||
repeat (3) @(posedge clk);
|
||||
rst_n <= 1'b1;
|
||||
@(posedge clk);
|
||||
|
||||
pass_count = 0;
|
||||
fail_count = 0;
|
||||
|
||||
// ============================================================
|
||||
// Process each vector
|
||||
// ============================================================
|
||||
for (idx = 0; idx < vec_count; idx = idx + 1) begin
|
||||
begin
|
||||
integer out_idx;
|
||||
integer input_ok;
|
||||
|
||||
// Extract A and B coefficients from vector memory
|
||||
//
|
||||
// Memory layout (A in MSB half, B in LSB half):
|
||||
// A[0] → bits [6143:6132]
|
||||
// A[1] → bits [6131:6120]
|
||||
// ...
|
||||
// A[255] → bits [3083:3072]
|
||||
// B[0] → bits [3071:3060]
|
||||
// B[1] → bits [3059:3048]
|
||||
// ...
|
||||
// B[255] → bits [11:0]
|
||||
//
|
||||
// Formula: coeff[i] = vector_mem[(N-1-i)*12+11+offset : (N-1-i)*12+offset]
|
||||
// A: offset = N*12 = 3072
|
||||
// B: offset = 0
|
||||
for (ci = 0; ci < N_COEFFS; ci = ci + 1) begin
|
||||
a_coeffs[ci] = vector_mem[idx][(N_COEFFS-1-ci)*12 + 11 + N_COEFFS*12
|
||||
: (N_COEFFS-1-ci)*12 + N_COEFFS*12];
|
||||
b_coeffs[ci] = vector_mem[idx][(N_COEFFS-1-ci)*12 + 11
|
||||
: (N_COEFFS-1-ci)*12];
|
||||
end
|
||||
|
||||
$display("INFO: Vector %0d", idx);
|
||||
|
||||
input_ok = 1;
|
||||
|
||||
// ----------------------------------------------------
|
||||
// LOAD phase: stream in 256 A+B coefficient pairs
|
||||
// ----------------------------------------------------
|
||||
for (ci = 0; ci < N_COEFFS && input_ok; ci = ci + 1) begin
|
||||
// Wait for ready_o before driving next input
|
||||
cycle_count = 0;
|
||||
while (!ready_o && cycle_count < TIMEOUT_CYCLES) begin
|
||||
@(posedge clk);
|
||||
cycle_count = cycle_count + 1;
|
||||
end
|
||||
if (cycle_count >= TIMEOUT_CYCLES) begin
|
||||
$display("ERROR: Timeout waiting for ready_o (input ci=%0d) on vector %0d",
|
||||
ci, idx);
|
||||
fail_count = fail_count + 1;
|
||||
input_ok = 0;
|
||||
end else begin
|
||||
coeff_a_in <= a_coeffs[ci];
|
||||
coeff_b_in <= b_coeffs[ci];
|
||||
valid_i <= 1'b1;
|
||||
@(posedge clk);
|
||||
valid_i <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
if (!input_ok) begin
|
||||
// Skip output reading for this failed vector
|
||||
@(posedge clk);
|
||||
end else begin
|
||||
// ----------------------------------------------------
|
||||
// OUTPUT phase: wait for valid_o and stream out results
|
||||
// poly_mul_sync enters COMP_CALC→COMP_C0 state after LOAD.
|
||||
// valid_o is asserted during COMP_C0 and COMP_C1.
|
||||
// There may be cycles with valid_o=0 between outputs
|
||||
// (during COMP_CALC transitions).
|
||||
// ----------------------------------------------------
|
||||
out_idx = 0;
|
||||
while (out_idx < N_COEFFS) begin
|
||||
// Wait for valid_o
|
||||
cycle_count = 0;
|
||||
while (!valid_o && cycle_count < TIMEOUT_CYCLES) begin
|
||||
@(posedge clk);
|
||||
cycle_count = cycle_count + 1;
|
||||
end
|
||||
|
||||
if (cycle_count >= TIMEOUT_CYCLES) begin
|
||||
$display("ERROR: Timeout waiting for valid_o (output %0d) on vector %0d",
|
||||
out_idx, idx);
|
||||
fail_count = fail_count + 1;
|
||||
out_idx = N_COEFFS; // break out
|
||||
end else begin
|
||||
// Capture output coefficient
|
||||
output_coeffs[out_idx] = coeff_out;
|
||||
out_idx = out_idx + 1;
|
||||
@(posedge clk); // ready_i=1, consume output
|
||||
end
|
||||
end
|
||||
|
||||
pass_count = pass_count + 1;
|
||||
|
||||
// Write result to output file
|
||||
// Format: "RESULT: INDEX COEFF_HEX"
|
||||
$fwrite(result_fd, "RESULT: %0d ", idx);
|
||||
// Write all 256 output coeffs as hex (3 chars each = 768 total)
|
||||
begin
|
||||
integer oi;
|
||||
reg [3:0] nib;
|
||||
for (oi = 0; oi < N_COEFFS; oi = oi + 1) begin
|
||||
nib = output_coeffs[oi][11:8];
|
||||
$fwrite(result_fd, "%c", nibble_to_ascii(nib));
|
||||
nib = output_coeffs[oi][7:4];
|
||||
$fwrite(result_fd, "%c", nibble_to_ascii(nib));
|
||||
nib = output_coeffs[oi][3:0];
|
||||
$fwrite(result_fd, "%c", nibble_to_ascii(nib));
|
||||
end
|
||||
end
|
||||
$fwrite(result_fd, "\n");
|
||||
|
||||
// Wait for DUT to return to IDLE before next vector
|
||||
// The DUT goes to S_DONE then S_IDLE after all outputs
|
||||
cycle_count = 0;
|
||||
while (!ready_o && cycle_count < 1000) begin
|
||||
@(posedge clk);
|
||||
cycle_count = cycle_count + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Extra cycle before next vector
|
||||
@(posedge clk);
|
||||
end // inner begin block
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// Summary
|
||||
// ============================================================
|
||||
$fclose(result_fd);
|
||||
|
||||
$display("========================================");
|
||||
$display("TEST COMPLETE");
|
||||
$display(" Total vectors: %0d", vec_count);
|
||||
$display(" Passed: %0d", pass_count);
|
||||
$display(" Failed: %0d", fail_count);
|
||||
$display(" Results written to: %s", RESULT_FILE);
|
||||
$display("========================================");
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
// ================================================================
|
||||
// Timeout watchdog
|
||||
// ================================================================
|
||||
initial begin
|
||||
// TIMEOUT_CYCLES * 10ns per cycle * 10x margin
|
||||
#(TIMEOUT_CYCLES * 10 * 10);
|
||||
$display("FATAL: Global simulation timeout reached");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
27
sync_rtl/poly_mul/TB/vectors/poly_mul_input.hex
Normal file
27
sync_rtl/poly_mul/TB/vectors/poly_mul_input.hex
Normal file
@@ -0,0 +1,27 @@
|
||||
// poly_mul_sync test vectors
|
||||
// Format: {768 hex chars A coeffs}{768 hex chars B coeffs}
|
||||
// A coeffs: 256 x 12-bit values, A[0] at MSB
|
||||
// B coeffs: 256 x 12-bit values, B[0] after A[255]
|
||||
|
||||
// A=0, B=0
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// A=1, B=0
|
||||
001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// A=1010..., B=0101...
|
||||
001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001
|
||||
// A=imp[0], B=imp[0]
|
||||
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// A=imp[1], B=imp[1]
|
||||
000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// A=imp[0,1], B=imp[0,1]
|
||||
001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// A=all pairs (1,0), B=imp[0]
|
||||
001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// random 0
|
||||
0B2837A5C17D23B4A88A0ACE5DE1CDC86644B0E74ECAA7DAA6F5144AB67E56B6F928900BA1D2B45A92D8A4287701027666A8F1A7705705EBD304D3AF0796544D97645126AB8D97F96D60F73E148564B52B5226E7602663B8E84ABCF89782018EBEBAF68C7B867758675C906D467B7408C75EA76BFE899391049AE83004577AA98A30914DB6F8D79DE4AD9516D5BF3B52726091447843B6B24C2CF6F8973BC94EE06F7CC3B95558C55051643E03579A72D59BB423C7858F29F1D1C463BA61D99897E36209791E761C8D6F5A089C873ECC46054F88339E708298B18986E7FB8A41FCCEEA2F9375DFBCC633AF7054034BDD2F016B9A781866339E9113164D15F700875C00A489B15036BC40782243AD6804FBC8BCD75DB261A8369A1B1AB7B5D9BC4271DBA6D8CC6744E5CA39104F45DB2923A8A0D6A83B7C782173870C5A8C5966DA437A5256A22086626088887A073BD68D1A8AB93126BC773799E84A43B8A82C9A98AD59E8A0503EACF40D3578D3B44C7F4835A28E7A6A62D1E15F9301579C68746849B5CC46A71BAD53504C8050590D69EE62289205F6C810DC1EA1B2AA8A24A12EAC358378E44EA15E0F73153C32E78A7002BAB1A09B889D21D8302760282F6C279ECCDF2957D1BC174A8C36EDB5F33B7B67577F78670C53972842C010C0A08AE9DABA9B3061125D6DDC5316B8524148095CA4E9BA8BDE5D23589F9A7EA316294262A53648C4B9B9617818AD7B20D0481A7F95A0F69225C1010403B36092CA04BCAE94E91D762CBA53435E602A149AC729A6094A5C0637A72E91E834B8F7FD9494AA911601564C3B33691F48F35001D9968922BE411C6913B48114F644B200E2BA425D041177A65320A21B2E01F09D772713360AAB868C3165637537237D353A30705B2F5B28FE809A169273599AD1C99455DABE299A219051904389BEA258700041BAFB3A3172CF081082AB62B18B7993B794948C142E8C2B751F6176512A5C935B5184F496793C3931E7E15BC0A1006B923F934922A72F7AC0CB2C3ABF79992D3D39F44E21A929DBC62F000B78EC4DA4A0149068AA8EFA201C433B0E00E6
|
||||
// random 1
|
||||
B3834B167A128C439F7ADB928B720338438A95E3FD92A6637090ADB0F8219726B426C182A85A839522C43F62EC3749860797B998224B8A2375922C951E55A3B074EA1203512C30740232F95E691334F3D7BEE0F66DE88944A0BF9C67708AD8947432D17F584604437737A4C05EE797A9C51EA7F908061B6C8FA359150A6B9509422DA7207F778302B0D65CB39B1D69587AD6189D44344A6AB389648D27E31C24D5AA7C7A696EAC477005AB94F6AABF50D53CACA30EC7294E35045856687B9843BC395EC9C802B904F011FA204C627A2B8CB84A0C827D1AA85160C55FA94F5C2A1C7774C042F77799F85198FADE613992428A3137B86445FAFF93580E643589A0B367C77877688B60222C04AFECB24242A23D01D1668201B74AB20CFAF526F3347219B6C555859796939076252F09BD0594B61B021BA276C24338E03DEA212AB29C72361BB3C8B84C852790957C2A50F894E7D7A1A5B23B0B808EC2B4C1510E2822A544CCBB05B0CDB5B031AA449019B842787C99A74C3166ECAE6C104D590BF5C866D7A8D54F43C8AE350174A0FB8F9F742CB8B5956D3B8A78C3C6AF025A5BB8043BEB805F29B19A1641272CD1BB937C6037CC3741B863499D650BC65E75204F99C98B87DD8445133479D18D5828862C224469BF3ED79556417F137B1B835BE323584035461C8564FD7504627AEB7673CCF2A595CD18804D86B01232F9CD84E86CAD8048347686390857AD80E32BE83A0737B81CC43A5CCC0D9B46F8223BF3285B096A46FBACF701A2AC6298A79891637D3AF3A928F7FE1A9BAA9977B5AA5B5AA2A63D32F5AA8595EA070121C9B85E4B522A112C37A5716D830A1D23E1DE7BA8EAC687894EC4617D2CC56959237CD5432EE969C2F8C26DC8193806CB1769C08BB728CB6BD55BD17308324C51E8FA4339670705D7A2F01D94362A84026E16C66937F76F0CE933B3DC602D7698426650CE6279C54CEEB879D069B57879633AA1826344B77AAEA3E509115D696832CEC40E8249BB5A2A7E79DB67C213455F21FF2DF5B32978376D08E039F3B3456CCE66F4A6861BB620C9037299843E9B8B6608ED
|
||||
// random 2
|
||||
C844BF8EE53A6C5C4ACA20BD0C6BDD49F02C56430F8B4C02020915B4143D3411691F72F442F3D90C120C98F609304AE7C240FD5C35906A5026A0A040B2631A1B48819A349960670533968C124B37A5E84A0232B59B955C67DCD7A3E53383F25C787BD77B2C74A6C33A82CA47760B163F19E50CC6D72C2916B60A96197C0E95CB787576A6CFA28767C48CAB2A973202300DE6C6BADBF091798A08A43F6AFB8129F3AE510CF867E2768B863D4F57064AEABF74B29B55578D7EE7093DE7220680B51D659FBD8C817154DF09FA6273A76A49F19B7325FECE42DCB998F354D33B23F5B7CE249F33944E7A962D13358B8CDBC799E942B8B3A57068653FF47274CC9837A79D2EEB5B2028DCAF74189D59EB68980C011C1868D215A8E0B4BAF5A74025EC0E42C0727C814187FCB7A538CF98142FD7227716944C5C821F34F67D65580827599429AC1141183AFC9A2292E8CE8B028FCC1D2484570EA6B80506A2C5A1DD8A95503B4517C892088D10A366FB2209636961FAB3C900114E52AABEEC434666998193F983D1DA9C375C162AED98CC4A7F7245716A5DB9C947C5825F50057C48CA9B28BC696CF3791700B6C5AAC305229586F49540A52868CAE87858F7A0B786A597D09F37AB1AE1E03AFC7351B59E2E130017F8DF183CB7953BB8A7938A4519338AD1AB7A637323A606C21082B0F7252462F0C467058957C3168775127C7AAEE1A3C7A1BA8AC8B95AC95D640A93748C81BD40668DF3A5CB5674A59A311DC9651BE4DE91ABFDB594F500A4C411DA7C20709AB8AC5E4526091E114A015533990A61B2EA0C1483861F33B2C616C19B919CB19A7B4F59B2742C002D54931251E91FD76881C55B7F2BD230418C18493010F2503DACEE3DE8FA55467628A758063140B3383B3364193C56EA39E93F4845EB7009CF4D383DC387D2A0207600D6F2C2FC0570B0E37104B5A179227550BA636160075B440B6006510C0117730D1A1BC02867BE13AA1C4D8B8188774618569C97EBBB4578ADC4C8292E661337EC9401D11CB9556433CBED3C236146ACCE24FCD883CB878D715EAC80914DA642AFE2A6365BD7
|
||||
// random 3
|
||||
AFEC344F665D166A8EB25B55C64780C961871BECEBB0910E3437821593EF5F0BBD8ADC6D9229184282028A128196FCC37B44F4B490777858438F27023D11CDC253E84098856FA4BA403CDC63F00B92225CA5BAAE38074D59DAF35A0B20B4A249B1A2E5C235E4975685A5C58E6263DD99F948122B3E79708D0889541FF33D90D07A6E30531B577258870386E860C4802E34865C5D57F0B906504E33BB19363D1021D13B292C6545818AC8EA2E6A2A8EE101B3D45D360657CD15C253B8B6AEFC694C888EC078CF058A407C76079752253543685B98750B78BD19C55D7C02027DB3BEA74C8246F65BC8BAC7966C12AD732181D0E218984863C9842D9A953CEA5AA8409CB7992F9A10F3153A6286015C587A341886A4C9B5341FA04E8BD4F6AB804121963781D460333BF046E88F4023652C5407C74188A4129653C6D09F73A093F245404CB68BE4CD294163CA58492BC24A83FC74006A7B0E38500188963C259E428C5173D3329ECA347F739998D264B2C75830060E0EE9C4A12C2CB972F6C5EA9C02D95D60AC6F18F7C646255155C073907C3308CAC2B733CC70F537827A6AC2B6F079D4F26E47A735355B83A4BA2B049BC254503397E5818C2B5113DAA5F7C33DE3F5CE9B380D7CEF9DC1E39573A55A67C990B1633D12D0ABE43963E5A73B2B5696D2620077262E2697AD517280A5EE30A9E644ABD69A7CEB00EB326AA9AD2C7B2020E5AE8E271016703C6048FD0AC5740F62B96FB10F5FB7A768101687A7F07B657874902F2873FB05BA3F2FD4BA495997346A7E49615858EA2280AAB89344C2C541065BAA0BAD60E70C222A0A4648727102BA8B1E107A22ACCB91687B120E80E729F0A90219E633C93B0AB8D126983B850773869174C793F297D7B69A5444A488815C8CF0AD94260930C83AEBE232C5F8895BBE4239148AA9E8293119B760E6A086E530002E1D9A25CA5526A9AC97835C912FD079698A993DEB5D9BACDD3EC09B4AA7F57121599EE2481F68CAAA29B7A351DAAD18FDC25932B8D060BF057EADF7DF8726EB77E29412A62D34E1F886357E031753023C5C886153415962C7A790
|
||||
69
sync_rtl/poly_mul/TB/xsim_run.tcl
Normal file
69
sync_rtl/poly_mul/TB/xsim_run.tcl
Normal file
@@ -0,0 +1,69 @@
|
||||
# xsim_run.tcl - Vivado xsim compilation and simulation script for PolyMul
|
||||
#
|
||||
# Compiles all PolyMul RTL sources plus dependencies, then testbench,
|
||||
# and runs simulation.
|
||||
# Run from the project root: ~/Dev/mlkem/
|
||||
#
|
||||
# Prerequisites:
|
||||
# source /opt/Xilinx/Vivado/2019.2/settings64.sh
|
||||
#
|
||||
# Usage examples:
|
||||
# # Run poly_mul_sync testbench
|
||||
# xsim poly_mul_sim -R
|
||||
#
|
||||
# # Step-by-step:
|
||||
# vivado -mode batch -source xsim_run.tcl
|
||||
|
||||
# ================================================================
|
||||
# Configuration
|
||||
# ================================================================
|
||||
set NTT_DIR sync_rtl/ntt
|
||||
set PM_DIR sync_rtl/poly_mul
|
||||
set TB_DIR sync_rtl/poly_mul/TB
|
||||
|
||||
# ================================================================
|
||||
# Step 1: Compile dependency sources (ntt/barrett_mul)
|
||||
# ================================================================
|
||||
puts "=== Compiling RTL dependencies ==="
|
||||
|
||||
# Barrett modular multiplier (shared dependency from ntt/)
|
||||
xvlog -sv ${NTT_DIR}/barrett_mul.v
|
||||
|
||||
# ================================================================
|
||||
# Step 2: Compile PolyMul sources
|
||||
# ================================================================
|
||||
puts "=== Compiling PolyMul RTL sources ==="
|
||||
|
||||
# Basecase multiplier (instantiates barrett_mul)
|
||||
xvlog -sv ${PM_DIR}/basecase_mul.v
|
||||
|
||||
# PolyMul zeta ROM
|
||||
xvlog -sv ${PM_DIR}/poly_mul_zeta_rom.v
|
||||
|
||||
# PolyMul sync top (instantiates basecase_mul + poly_mul_zeta_rom)
|
||||
xvlog -sv ${PM_DIR}/poly_mul_sync.v
|
||||
|
||||
# ================================================================
|
||||
# Step 3: Compile testbench
|
||||
# ================================================================
|
||||
puts "=== Compiling testbench ==="
|
||||
|
||||
# File-based vector testbench for poly_mul_sync
|
||||
xvlog -sv ${TB_DIR}/tb_poly_mul_xsim.v
|
||||
|
||||
# ================================================================
|
||||
# Step 4: Elaborate (xelab)
|
||||
# ================================================================
|
||||
puts "=== Elaborating snapshot ==="
|
||||
|
||||
xelab tb_poly_mul_xsim -s poly_mul_sim
|
||||
|
||||
# ================================================================
|
||||
# Step 5: Run simulation
|
||||
# ================================================================
|
||||
puts ""
|
||||
puts "=== Running poly_mul_sync test ==="
|
||||
xsim poly_mul_sim -R
|
||||
|
||||
puts ""
|
||||
puts "=== Simulation complete ==="
|
||||
Reference in New Issue
Block a user