chore: 删除无用的 mod_add 模块

mod_add_sync 未被 mlkem_top 实例化(模加在各 leaf 算子内部完成),整个
sync_rtl/mod_add 目录(RTL + TB + 向量)已无用。同时:
- 更新 mlkem_top.v 顶部 leaf 模块清单注释(去掉 mod_add_sync,并修正为
  '共享 keccak_core' 的现状)
- run_tb.sh 用法示例改用 ntt 模块

KeyGen KAT 烟囱测试通过。
This commit is contained in:
2026-06-29 22:55:06 +08:00
parent 971ce97d50
commit 5ac7a59289
7 changed files with 4 additions and 503 deletions

View File

@@ -2,7 +2,7 @@
# run_tb.sh - Run Vivado XSIM testbench for a module # run_tb.sh - Run Vivado XSIM testbench for a module
# #
# Usage: ./run_tb.sh <module> [K] [CASE] # Usage: ./run_tb.sh <module> [K] [CASE]
# ./run_tb.sh mod_add # run the module's full xsim_run.tcl # ./run_tb.sh ntt # run the module's full xsim_run.tcl
# ./run_tb.sh top # ML-KEM KeyGen: all K, all cases # ./run_tb.sh top # ML-KEM KeyGen: all K, all cases
# ./run_tb.sh top 2 # only K=2 (ML-KEM-512), all its cases # ./run_tb.sh top 2 # only K=2 (ML-KEM-512), all its cases
# ./run_tb.sh top 2 3 # only K=2, only CASE=3 # ./run_tb.sh top 2 3 # only K=2, only CASE=3

View File

@@ -1,112 +0,0 @@
#!/usr/bin/env python3
"""Generate test vectors for mod_add_sync module.
Produces mod_add_input.hex: one 24-bit hex word per line.
Each word encodes {a[11:0], b[11:0]} as a single hex value
suitable for $readmemh.
Also prints expected results to stdout for reference.
"""
import os
Q = 3329
def mod_add(a, b):
"""Compute (a + b) mod Q."""
s = a + b
if s >= Q:
s -= Q
return s
# Test cases: (a, b, description)
test_cases = [
# Normal operations
(0, 0, "zero + zero"),
(100, 200, "small + small (no overflow)"),
(500, 1000, "medium + medium (no overflow)"),
(2000, 1000, "medium pair (no overflow)"),
(1500, 1500, "medium pair (no overflow)"),
(3328, 0, "max + zero"),
(0, 3328, "zero + max"),
# Near-Q values (still < Q each)
(3000, 300, "near max + small (no overflow)"),
(300, 3000, "small + near max (no overflow)"),
(2000, 1500, "medium pair (overflow by small)"),
(2000, 2000, "medium pair (overflow)"),
(2500, 2500, "large pair (overflow)"),
(3000, 1000, "large + medium (overflow)"),
# Exact Q boundary
(3328, 1, "max + 1 (exact overflow to zero)"),
(1, 3328, "1 + max (exact overflow to zero)"),
# Max values (both Q-1)
(3328, 3328, "max + max (double overflow)"),
# Various overflow amounts
(2000, 3328, "medium + max (overflow)"),
(3328, 2000, "max + medium (overflow)"),
(2500, 1000, "large + medium (overflow)"),
(1000, 2500, "medium + large (overflow)"),
(1234, 2100, "random pair (overflow)"),
(456, 2900, "small + near max (overflow)"),
# No overflow but close
(1500, 1828, "pair sums exactly to Q-1"),
(1829, 1500, "pair sums exactly to Q (overflow -> 0)"),
# Back-to-back stress (all different values)
(1111, 2222, "stress pair"),
(333, 444, "stress pair"),
(777, 1888, "stress pair"),
(2999, 333, "stress pair near overflow"),
(500, 2800, "stress pair near max"),
]
# Restore previously removed concise test cases
additional = [
(42, 42),
(777, 1337),
(1664, 1664), # exactly Q//2 + Q//2 = Q-1? 1664+1664=3328 = Q-1
(200, 3100), # overflow
(0, 1),
(1, 0),
(3327, 2), # exact overflow: 3329 → 0
(1000, 2329), # overflow: 3329 → 0
(50, 3279), # overflow: 3329 → 0
(1600, 1729), # overflow by 0: 3329 → 0
]
test_cases.extend([(a, b) for a, b in additional])
def format_hex(val, bits):
"""Format integer as zero-padded hex string."""
nibbles = (bits + 3) // 4
return f"{val:0{nibbles}x}"
vectors_dir = os.path.join(os.path.dirname(__file__), "vectors")
os.makedirs(vectors_dir, exist_ok=True)
output_path = os.path.join(vectors_dir, "mod_add_input.hex")
with open(output_path, "w") as f:
for idx, item in enumerate(test_cases):
if len(item) == 3:
a, b, desc = item
else:
a, b = item
desc = ""
# Ensure inputs are in valid range
assert 0 <= a < Q, f"a={a} out of range"
assert 0 <= b < Q, f"b={b} out of range"
# Pack: upper 12 bits = a, lower 12 bits = b
word = (a << 12) | b
expected = mod_add(a, b)
f.write(format_hex(word, 24) + "\n")
if desc:
print(f"[{idx:3d}] a={a:4d} b={b:4d} -> expected={expected:4d} ({desc})")
else:
print(f"[{idx:3d}] a={a:4d} b={b:4d} -> expected={expected:4d}")
print(f"\nWrote {len(test_cases)} vectors to {output_path}")

View File

@@ -1,238 +0,0 @@
// tb_mod_add_xsim.v - Standard Verilog testbench for mod_add_sync targeting Vivado xsim
//
// Reads test vectors from a hex file using $readmemh.
// Each line is a single 24-bit hex number encoding:
// bits [23:12] = a, bits [11:0] = b
//
// Drives mod_add_sync, waits for valid_o, and writes
// "RESULT: IDX A B SUM_HEX" to the output file using $fwrite.
//
// Parameters:
// VECTOR_FILE - path to input hex file (default: "vectors/mod_add_input.hex")
// RESULT_FILE - path to output file (default: "vectors/mod_add_result.hex")
//
// Usage:
// xvlog -sv sync_rtl/common/pipeline_reg.v
// xvlog -sv sync_rtl/mod_add/mod_add_sync.v
// xvlog -sv sync_rtl/mod_add/TB/tb_mod_add_xsim.v
// xelab tb_mod_add_xsim -s tb_mod_add_xsim
// xsim tb_mod_add_xsim -R
`timescale 1ns / 1ps
module tb_mod_add_xsim;
// ================================================================
// Parameters
// ================================================================
parameter VECTOR_FILE = "sync_rtl/mod_add/TB/vectors/mod_add_input.hex";
parameter RESULT_FILE = "sync_rtl/mod_add/TB/vectors/mod_add_result.hex";
parameter MAX_VECTORS = 256;
parameter TIMEOUT_CYCLES = 1000;
// ================================================================
// DUT signals
// ================================================================
reg clk;
reg rst_n;
reg [11:0] a;
reg [11:0] b;
reg valid_i;
wire ready_o;
wire [11:0] sum;
wire valid_o;
reg ready_i;
// ================================================================
// DUT instantiation
// ================================================================
mod_add_sync u_dut (
.clk (clk),
.rst_n (rst_n),
.a (a),
.b (b),
.valid_i (valid_i),
.ready_o (ready_o),
.sum (sum),
.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)
// ================================================================
reg [23:0] vector_mem [0:MAX_VECTORS-1];
integer vec_count;
integer idx;
integer cycle_count;
integer result_fd;
// Test result tracking
integer pass_count;
integer fail_count;
// ================================================================
// 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
// Helper: write 3-hex-digit (12-bit) value to file
task write_hex_12bit;
input integer fd;
input [11:0] val;
reg [3:0] nib;
integer j;
begin
for (j = 2; j >= 0; j = j - 1) begin
nib = val[(j*4)+:4];
$fwrite(fd, "%c", nibble_to_ascii(nib));
end
end
endtask
// ================================================================
// Main test sequence
// ================================================================
initial begin
// Count loaded vectors
vec_count = 0;
// Load vectors from hex file
$readmemh(VECTOR_FILE, vector_mem);
// Count non-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] === 24'hx || vector_mem[idx] === 24'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 is in the correct format.");
$display(" Each line: <6 hex chars> = {a[11:0], b[11:0]}");
$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
a <= 12'd0;
b <= 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
reg [11:0] vec_a;
reg [11:0] vec_b;
reg [11:0] captured_sum;
// Extract a and b from memory word
vec_a = vector_mem[idx][23:12];
vec_b = vector_mem[idx][11:0];
$display("INFO: Vector %0d - a=%0d b=%0d", idx, vec_a, vec_b);
// Drive DUT
a <= vec_a;
b <= vec_b;
valid_i <= 1'b1;
@(posedge clk);
valid_i <= 1'b0;
// 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 on vector %0d", idx);
fail_count = fail_count + 1;
end else begin
// Capture sum output
captured_sum = sum;
pass_count = pass_count + 1;
// Write result to output file
// Format: "RESULT: IDX A_HEX B_HEX SUM_HEX"
$fwrite(result_fd, "RESULT: %0d ", idx);
write_hex_12bit(result_fd, vec_a);
$fwrite(result_fd, " ");
write_hex_12bit(result_fd, vec_b);
$fwrite(result_fd, " ");
write_hex_12bit(result_fd, captured_sum);
$fwrite(result_fd, "\n");
end
// One extra cycle for valid_o handshake
@(posedge clk);
end
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 * 10 * 100); // TIMEOUT_CYCLES * 10ns per cycle * extra margin
$display("FATAL: Global simulation timeout reached");
$finish;
end
endmodule

View File

@@ -1,39 +0,0 @@
000000
0640c8
1f43e8
7d03e8
5dc5dc
d00000
000d00
bb812c
12cbb8
7d05dc
7d07d0
9c49c4
bb83e8
d00001
001d00
d00d00
7d0d00
d007d0
9c43e8
3e89c4
4d2834
1c8b54
5dc724
7255dc
4578ae
14d1bc
309760
bb714d
1f4af0
02a02a
309539
680680
0c8c1c
000001
001000
cff002
3e8919
032ccf
6406c1

View File

@@ -1,63 +0,0 @@
# NOTE: On some systems, you may need:
# export LD_PRELOAD=/usr/lib64/libtinfo.so.5
# before running this script.
# xsim_run.tcl - Vivado xsim compilation and simulation script for mod_add_sync
#
# Compiles mod_add_sync RTL plus the file-based vector testbench and runs simulation.
# Run from the project root: ~/Dev/mlkem/
#
# Prerequisites:
# source /opt/Xilinx/Vivado/2019.2/settings64.sh
#
# Usage:
# vivado -mode batch -source sync_rtl/mod_add/TB/xsim_run.tcl
#
# # Or step-by-step:
# xvlog -sv sync_rtl/common/pipeline_reg.v
# xvlog -sv sync_rtl/mod_add/mod_add_sync.v
# xvlog -sv sync_rtl/mod_add/TB/tb_mod_add_xsim.v
# xelab tb_mod_add_xsim -s tb_mod_add_xsim
# xsim tb_mod_add_xsim -R
# ================================================================
# Configuration
# ================================================================
set SRC_DIR sync_rtl/mod_add
set TB_DIR sync_rtl/mod_add/TB
set COMMON_DIR sync_rtl/common
# ================================================================
# Step 1: Compile all source files (xvlog)
# ================================================================
puts "=== Compiling RTL sources ==="
# Common pipeline register
xvlog -sv -i . ${COMMON_DIR}/pipeline_reg.v
# mod_add_sync (includes defines.vh from common/)
xvlog -sv -i . ${SRC_DIR}/mod_add_sync.v
# ================================================================
# Step 2: Compile testbench
# ================================================================
puts "=== Compiling testbench ==="
# File-based vector testbench
xvlog -sv ${TB_DIR}/tb_mod_add_xsim.v
# ================================================================
# Step 3: Elaborate snapshot (xelab)
# ================================================================
puts "=== Elaborating snapshot ==="
xelab tb_mod_add_xsim -s tb_mod_add_xsim --timescale 1ns/1ps
# ================================================================
# Step 4: Run simulation
# ================================================================
puts "=== Running mod_add_sync file-based vector test ==="
xsim tb_mod_add_xsim -R
puts ""
puts "=== mod_add_sync simulation complete ==="

View File

@@ -1,47 +0,0 @@
// mod_add_sync.v - Synchronous modular adder for ML-KEM
//
// Computes (a + b) mod Q where Q = 3329.
// Uses pipeline_reg internally for the computation stage.
// Result is valid one cycle after valid_i && ready_o.
//
// Interface:
// clk, rst_n - clock, active-low reset
// a, b - operands (0 <= a,b < Q)
// valid_i, ready_o, sum, valid_o, ready_i - valid/ready handshake
`include "sync_rtl/common/defines.vh"
module mod_add_sync (
input clk,
input rst_n,
input [11:0] a,
input [11:0] b,
input valid_i,
output ready_o,
output [11:0] sum,
output valid_o,
input ready_i
);
// Compute (a + b) mod Q
wire [12:0] add_raw; // 13 bits to hold potential overflow
wire [11:0] add_sub_q; // (a + b) - Q
wire [11:0] mod_result; // final (a + b) mod Q
assign add_raw = {1'b0, a} + {1'b0, b};
assign add_sub_q = add_raw[11:0] - `Q;
assign mod_result = (add_raw < `Q) ? add_raw[11:0] : add_sub_q;
// Pipeline the result through pipeline_reg
pipeline_reg #(.DW(12)) u_pipe (
.clk (clk),
.rst_n (rst_n),
.data_i (mod_result),
.valid_i(valid_i),
.ready_o(ready_o),
.data_o (sum),
.valid_o(valid_o),
.ready_i(ready_i)
);
endmodule

View File

@@ -16,9 +16,9 @@
// Built incrementally and verified stage-by-stage against reference golden // Built incrementally and verified stage-by-stage against reference golden
// vectors (test_framework/modules/mlkem_keygen/golden) and NIST KAT. // vectors (test_framework/modules/mlkem_keygen/golden) and NIST KAT.
// //
// Uses independent (verified) leaf modules, each with its own keccak_core: // Uses independent (verified) leaf modules over a shared keccak_core:
// sha3_top, sample_ntt_sync, sample_cbd_sync, ntt_core, poly_mul_sync, // sha3_top_shared, sample_ntt_sync_shared, sample_cbd_sync_shared, ntt_core,
// mod_add_sync. No shared-keccak arbiter. // poly_mul_sync, comp_decomp_sync.
`include "sync_rtl/common/defines.vh" `include "sync_rtl/common/defines.vh"