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:
2026-06-25 20:48:38 +08:00
parent ae5f0ca048
commit d4c3fc86fc
42 changed files with 7745 additions and 0 deletions

View 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()

View 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_CALCCOMP_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

View 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

View 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 ==="