Compare commits
2 Commits
717a9929b6
...
b7eb59fb5b
| Author | SHA1 | Date | |
|---|---|---|---|
| b7eb59fb5b | |||
| faf15ee113 |
326
docs/design_report.md
Normal file
326
docs/design_report.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# ML-KEM 硬件 IP 设计报告
|
||||
|
||||
> 模块:`mlkem_top`(FIPS 203 ML-KEM 全功能加速器)
|
||||
> 器件:Xilinx Artix-7 `xc7a200tfbg676-1`
|
||||
> 工具:Vivado 2019.2(综合)+ XSIM(功能仿真)
|
||||
> 日期:2026-06
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 设计目标
|
||||
|
||||
本 IP 实现 NIST FIPS 203 标准化的后量子密钥封装机制 **ML-KEM**(源自 CRYSTALS-Kyber),
|
||||
在单一硬件模块 `mlkem_top` 中同时支持三种核心操作,并在运行时可选三种安全等级:
|
||||
|
||||
| 操作 | `op_i` | FIPS 203 算法 | 输入 | 输出 |
|
||||
|:---|:---:|:---|:---|:---|
|
||||
| 密钥生成 KeyGen | 0 | 算法 16 | 种子 `d`, `z` | 公钥 `ek`、私钥 `dk` |
|
||||
| 密钥封装 Encaps | 1 | 算法 17 | `ek`, 消息 `m` | 共享密钥 `K`、密文 `c` |
|
||||
| 密钥解封装 Decaps | 2 | 算法 18 | `dk`, 密文 `c` | 共享密钥 `K`(含隐式拒绝) |
|
||||
|
||||
| 等级 (`k_i`) | 方案 | K | η₁ | (d_u,d_v) | ek | dk | 密文 c |
|
||||
|:---:|:---|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| 2 | ML-KEM-512 | 2 | 3 | (10,4) | 800 B | 1632 B | 768 B |
|
||||
| 3 | ML-KEM-768 | 3 | 2 | (10,4) | 1184 B | 2400 B | 1088 B |
|
||||
| 4 | ML-KEM-1024 | 4 | 2 | (11,5) | 1568 B | 3168 B | 1568 B |
|
||||
|
||||
固定参数:模数 **q = 3329**、多项式次数 **n = 256**、共享密钥 32 B。
|
||||
|
||||
### 1.2 关键特性
|
||||
|
||||
- **运行时可重构**:`k_i`/`op_i` 在 `start_i` 时锁存,存储按最坏情况(ML-KEM-1024)静态分配,
|
||||
无需为不同等级重新综合。
|
||||
- **资源高度复用**:同一套叶子算子与存储库被三条数据通路分时复用;Decaps 的重加密
|
||||
(FO 变换核心)直接复用整条 Encaps 流水线。
|
||||
- **共享 Keccak 核**:G/H/J、SampleNTT、CBD 三类哈希消费者分时共用单个 `keccak_core`。
|
||||
- **逐字节流式 I/O**:`ek/dk/c` 经 BRAM 端口逐字节装载与回读,避免超宽顶层总线。
|
||||
- **常量时间隐式拒绝**:Decaps 比较 `c'==c` 全程恒定工作量,无早退分支。
|
||||
- **完整 KAT 验证**:三种等级、三种操作全部对 NIST KAT 标准答案逐字节比对通过。
|
||||
|
||||
### 1.3 代码规模
|
||||
|
||||
| 项 | 行数 |
|
||||
|:---|:---:|
|
||||
| `mlkem_top.v`(顶层集成 + FSM + 数据通路) | 2252 |
|
||||
| RTL 合计(不含测试平台) | 5517 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 顶层接口
|
||||
|
||||
```verilog
|
||||
module mlkem_top #(parameter KMAX = 4) (
|
||||
input clk, rst_n, // 100 MHz 设计时钟, 低电平异步复位
|
||||
input [2:0] k_i, // 运行时等级 2/3/4 (start_i 锁存)
|
||||
input [1:0] op_i, // 0=KeyGen 1=Encaps 2=Decaps
|
||||
input [255:0] d_i, z_i, msg_i, // 种子 d/z, Encaps 消息 m
|
||||
input start_i,
|
||||
output busy_o, done_o,
|
||||
output [255:0] ss_o, // 共享密钥 K
|
||||
|
||||
input ek_in_we; input [10:0] ek_in_addr; input [7:0] ek_in_byte; // Encaps ek 装载
|
||||
input dk_in_we; input [11:0] dk_in_addr; input [7:0] dk_in_byte; // Decaps dk 装载
|
||||
input c_in_we; input [10:0] c_in_addr; input [7:0] c_in_byte; // Decaps c 装载
|
||||
|
||||
// 调试 / 结果回读抽头(只读)
|
||||
input [10:0] dbg_ct_idx_i; output [7:0] dbg_ct_o; // 密文 c
|
||||
input [5:0] dbg_slot_i; input [7:0] dbg_idx_i; output [11:0] dbg_coeff_o; // 系数
|
||||
input dbg_byte_sel_i; input [10:0] dbg_byte_idx_i; output [7:0] dbg_byte_o; // ek/dk_pke
|
||||
input [11:0] dbg_dk_idx_i; output [7:0] dbg_dk_o; // 完整 dk
|
||||
output [255:0] dbg_rho_o, dbg_sigma_o, dbg_r_o, dbg_hek_o,
|
||||
dbg_mprime_o, dbg_kbar_o, dbg_decz_o, dbg_dech_o
|
||||
);
|
||||
```
|
||||
|
||||
**握手时序**:外部先经流式端口预装载所需数据(Encaps→ek,Decaps→dk+c),
|
||||
`start_i` 拉一拍锁存 `k_i/op_i` 并启动;`busy_o` 在 `st≠IDLE` 期间为高;
|
||||
`done_o` 在 `st==DONE` 拉高,此时 `ss_o` 及各 BRAM 产物有效。
|
||||
|
||||
数据约定:所有 256-bit 端口为「byte0 在低位」,即 `value[8m+:8] = byte m`。
|
||||
|
||||
---
|
||||
|
||||
## 3. 微架构
|
||||
|
||||
### 3.1 总体结构
|
||||
|
||||
`mlkem_top` 采用「**单 FSM 调度 + 共享叶子算子 + 统一存储库**」架构。顶层 RTL 结构见
|
||||
`docs/mlkem_top_rtl.svg`。数据流分为四层:
|
||||
|
||||
```
|
||||
输入端口 ──► 控制 FSM / 状态寄存器 ──► 叶子算子(共享 keccak + 算术引擎) ◄──► 存储库 ──► 输出/回读
|
||||
```
|
||||
|
||||
### 3.2 叶子算子
|
||||
|
||||
| 实例 | 模块 | 功能 |
|
||||
|:---|:---|:---|
|
||||
| `u_keccak` | `keccak_core` | Keccak-f[1600] 置换(单核,三方共享) |
|
||||
| `u_sha3` | `sha3_top_shared` | SHA3-512 (G) / SHA3-256 (H) / SHAKE-256 (J),单/多块吸收 |
|
||||
| `u_snt` | `sample_ntt_sync_shared` | SampleNTT(SHAKE-128 拒绝采样)生成 Â |
|
||||
| `u_cbd` | `sample_cbd_sync_shared` | CBD_η 中心二项分布采样(s/e/y/e1/e2) |
|
||||
| `u_ntt` | `ntt_core` | 前向 NTT / 逆向 NTT(mode 选择,×3303 尾乘) |
|
||||
| `u_pmul` | `poly_mul_sync` | NTT 域逐点乘(basecase,含 Barrett 模乘) |
|
||||
| `u_comp` | `comp_decomp_sync` | Compress_d / Decompress_d(Barrett 除法约简) |
|
||||
|
||||
模加、byteEncode₁₂/byteDecode₁₂、bit-packer/解包、`c'==c` 比较等轻量逻辑在顶层内联实现。
|
||||
|
||||
### 3.3 共享 Keccak 核
|
||||
|
||||
G/H/J、SampleNTT、CBD 都需要 Keccak 置换,但分处互斥的 FSM 阶段,故共用单个 `u_keccak`:
|
||||
|
||||
- **输入复用**:`kc_state_i_mux` / `kc_valid_i_mux` 按相位三选一
|
||||
(`sel_snt` / `sel_cbd` / 默认 SHA3)。
|
||||
- **输出门控**:核输出 `kc_state_o` / `kc_valid_o` 广播给所有消费者,但只有当前激活方看到有效信号
|
||||
(`kc_valid_o_sha3` / `_snt` / `_cbd`)。
|
||||
- 相位选择由 FSM 状态推导:`sel_sha3 = (st∈{G,H,J,…})`、`sel_snt = (st∈{A,ENC_A})`、
|
||||
`sel_cbd = (st∈{C,ENC_C})`。
|
||||
|
||||
此设计省去 Keccak 核的多份例化(Keccak-f 是面积大户),是 LUT 占用仅 25% 的主要原因之一。
|
||||
|
||||
### 3.4 存储库
|
||||
|
||||
| 实例 | 宽×深 | 用途 | 读写信号 |
|
||||
|:---|:---|:---|:---|
|
||||
| `u_bank_a` | 12×4096 | Â[i][j] 矩阵;Decaps 中转 ŝ/e2/v' | `ba_rd_*` / `ba_we/wa/wd` |
|
||||
| `u_bank_se` | 12×2048 | ŝ/ê (KeyGen)·ŷ (Encaps)·û (Decaps) | `bse_rd_*` / `bse_we/wa/wd` |
|
||||
| `u_bank_t` | 12×1024 | t̂·累加和·Encaps v·Decaps w | `bt_rd_*` / `bt_we/wa/wd` |
|
||||
| `u_ek_bram` | 8×2048 | ek = byteEncode₁₂(t̂)‖ρ | — |
|
||||
| `u_dkp_bram` | 8×2048 | dk_pke = byteEncode₁₂(ŝ) | — |
|
||||
| `u_ct_bram` | 8×2048 | 计算出的密文 c / Decaps c' | — |
|
||||
| `u_c_in_bram` | 8×2048 | Decaps 输入密文 c(与 ct 分开以便比较) | — |
|
||||
|
||||
全部基于 `sd_bram`(1R/1W、寄存读、1 拍读延迟,综合映射为块 RAM)。系数库槽基址由 `k_r`
|
||||
运行时推导:Â 占 slot 0..K²-1,`slot_s=K²`、`slot_e=K²+K`、`slot_t=K²+2K`。
|
||||
|
||||
### 3.5 控制 FSM 与数据流
|
||||
|
||||
5-bit 状态机从 `ST_IDLE` 按锁存的 `op_r` 分支为三条数据通路:
|
||||
|
||||
**KeyGen(算法 16)**
|
||||
```
|
||||
G: (ρ,σ)=G(d‖K) SHA3-512
|
||||
A: Â[i][j]=SampleNTT(ρ‖j‖i) → bank_a
|
||||
C: s/e = CBD_η1(PRF(σ,·)) → bank_se
|
||||
N: ŝ=NTT(s), ê=NTT(e) 原地
|
||||
M: t̂=ê+Σⱼ Â∘ŝ 逐点乘+modQ 累加 → bank_t
|
||||
E: ek=Enc12(t̂)‖ρ, dk_pke=Enc12(ŝ) → ek/dkp_bram
|
||||
H: H(ek) 多块 SHA3-256
|
||||
dk = dk_pke‖ek‖H(ek)‖z
|
||||
```
|
||||
|
||||
**Encaps(算法 17)**
|
||||
```
|
||||
ENC_H/G: H(ek), (K,r)=G(m‖H(ek))
|
||||
ENC_LOAD/A/TDEC: ρ载入, Â重生成, t̂=byteDecode12(ek)
|
||||
ENC_C/N: y,e1,e2=CBD(PRF(r,·)), ŷ=NTT(y)
|
||||
ENC_U: u=INTT(Σ Âᵀ∘ŷ)+e1
|
||||
ENC_C1: c1=Enc_du(Compress_du(u))
|
||||
ENC_V: v=INTT(Σ t̂∘ŷ)+e2+Decompress1(m)
|
||||
ENC_C2: c2=Enc_dv(Compress_dv(v)); c=c1‖c2; K=共享密钥
|
||||
```
|
||||
|
||||
**Decaps(算法 18,FO 变换 + 隐式拒绝)**
|
||||
```
|
||||
DEC_DECOMP: u'/v' = Decompress(byteDecode(c)) D1
|
||||
DEC_SDEC/NTT: ŝ=byteDecode12(dk_pke), û=NTT(u') D2
|
||||
DEC_W: w=v'-INTT(Σⱼ ŝ∘û) D3
|
||||
DEC_MENC: m'=Enc1(Compress1(w)) D4
|
||||
DEC_G/J: (K',r')=G(m'‖h), K̄=J(z‖c) D5
|
||||
(重加密): c'=K-PKE.Encrypt(ek_pke,m',r') ←复用 Encaps 流水 D6
|
||||
DEC_CMP: ss = (c'==c) ? K' : K̄ D7
|
||||
```
|
||||
|
||||
**核心复用点**:D6 重加密整段复用 Encaps 的 `ENC_LOAD…ENC_C2`——m' 写入 `m_r`、
|
||||
r' 在 `r_r`、ek_pke 已在 `ek_bram`,前置条件天然就位,无需另起数据通路。
|
||||
D7 逐字节比较 `u_ct_bram`(c') 与 `u_c_in_bram`(c),恒定工作量,按 `dec_reject`
|
||||
在 `ss_r`(K') 与 `kbar_r`(K̄) 间选择:`ss_o = dec_reject ? kbar_r : ss_r`。
|
||||
|
||||
### 3.6 模运算策略
|
||||
|
||||
所有模 q(q=3329)约简采用 **Barrett 乘法**替代除法器:`floor(x/q) ≈ (x·5039)>>24`,
|
||||
其中 `5039 = floor(2²⁴/q)`,再做至多两次条件减校正。`q·x` 用移位加实现
|
||||
(3329 = 2048+512+256+1,无需第二个乘法器)。早期版本使用组合除法器,已于提交 `717a992`
|
||||
替换为 Barrett,显著缩短关键路径。按设计约束,**全部乘法标注 `use_dsp="no"`,不使用 DSP48**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 功能验证
|
||||
|
||||
### 4.1 验证策略
|
||||
|
||||
采用「分阶段中间量核对 + 端到端 KAT 比对」双层策略,全部对照 NIST FIPS 203 的 KAT 标准答案:
|
||||
|
||||
- **分阶段**:KeyGen 按 G/A/C/N/M/E/H、Encaps 按 E1–E7、Decaps 按 D0–D7 逐级验证中间多项式
|
||||
/哈希/编码,经调试抽头逐字节回读比对。
|
||||
- **端到端**:KeyGen 核对 `ek==pk`、`dk==sk`;Encaps 核对 `ss`、`c`;Decaps 核对最终 `ss`,
|
||||
并用 KAT 自带的损坏密文 `ct_n`/`ss_n` 验证隐式拒绝路径(`ss==ss_n=J(z‖ct_n)`)。
|
||||
|
||||
### 4.2 测试平台
|
||||
|
||||
| 测试平台 | 操作 | 覆盖 |
|
||||
|:---|:---|:---|
|
||||
| `tb_mlkem_kg_katK_xsim.v` | KeyGen | K=2/3/4 各 KAT 用例,`ek==pk`/`dk==sk` |
|
||||
| `tb_mlkem_enc_katK_xsim.v` | Encaps | E1–E7 分阶段 + `ss`/`c` |
|
||||
| `tb_mlkem_dec_katK_xsim.v` | Decaps | D0–D7 分阶段 + 接受/拒绝双路径 |
|
||||
| `tb_mlkem_hello_world_xsim.v` | 全流程(单实例) | KeyGen→Encaps→XOR→Decaps→XOR |
|
||||
| `tb_mlkem_two_inst_xsim.v` | 全流程(双实例) | 实例 A 做 KeyGen+Encaps,实例 B 做 Decaps |
|
||||
|
||||
参数化 TB 通过 `xelab -generic_top KP=2|3|4` 选等级,`+CASE=n` 选用例。统一脚本
|
||||
`run_tb.sh {top|enc|dec|hello}` 驱动。
|
||||
|
||||
### 4.3 验证结果
|
||||
|
||||
- **KeyGen / Encaps / Decaps** 三操作、K=2/3/4 三等级全部 KAT 用例逐字节 PASS。
|
||||
- **隐式拒绝**:损坏密文路径正确输出 K̄,`dec_reject=1`。
|
||||
- **端到端**:`hello_world` 单/双实例均通过,共享密钥与消息正确还原
|
||||
(`shared_key=ced0c031a4bee34a…`,`decrypted="hello world"`)。
|
||||
|
||||
### 4.4 增量验证里程碑(git 记录)
|
||||
|
||||
设计按阶段增量构建,每阶段独立提交并通过 KAT,历史可二分定位:
|
||||
|
||||
```
|
||||
KeyGen 各阶段 → Encaps E1–E7 (7228beb…) → Decaps D0–D7 (030931d…2b70431)
|
||||
→ hello_world 端到端 (f279222, ee2bf1c)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 综合与实现结果
|
||||
|
||||
### 5.1 资源占用(OOC 综合,xc7a200tfbg676-1)
|
||||
|
||||
| 资源 | 使用 | 可用 | 占用率 |
|
||||
|:---|:---:|:---:|:---:|
|
||||
| Slice LUTs(全为逻辑) | 34 318 | 134 600 | 25.5 % |
|
||||
| Slice Registers (FF) | 23 254 | 269 200 | 8.6 % |
|
||||
| F7 Muxes | 3 645 | 67 300 | 5.4 % |
|
||||
| F8 Muxes | 1 191 | 33 650 | 3.5 % |
|
||||
| Block RAM Tile | 5(RAMB36×2 + RAMB18×6) | 365 | 1.4 % |
|
||||
| **DSP48** | **0** | 740 | **0 %** |
|
||||
|
||||
面积占用低,DSP 完全未用(符合设计约束),器件资源充裕。
|
||||
|
||||
### 5.2 性能(周期数,实测)
|
||||
|
||||
| 操作 | 周期数(K=2,ML-KEM-512) |
|
||||
|:---|:---:|
|
||||
| KeyGen | ≈ 22 904 |
|
||||
| Encaps | ≈ 32 493 |
|
||||
| Decaps | ≈ 50 819 |
|
||||
|
||||
K=3/4 因模秩增大按比例上升。Decaps 最长,因其包含完整重加密(≈ 一次 Encaps)。
|
||||
|
||||
### 5.3 时序现状与瓶颈
|
||||
|
||||
当前对 **50 MHz(20 ns)** 目标**尚未收敛**:
|
||||
|
||||
| 指标 | 值 |
|
||||
|:---|:---|
|
||||
| WNS | -32.2 ns(关键路径实际 ≈ 52 ns) |
|
||||
| 失败端点 | 3 132 / 44 689 |
|
||||
| Hold (WHS) | +0.134 ns(无违例) |
|
||||
| 关键路径 | `u_pmul/mem_A_reg → u_pmul/c0_reg`,70 逻辑级 |
|
||||
|
||||
**根因**:`basecase_mul` 单周期组合计算 `c0=(a0·b0+(a1·b1)·zeta) mod q`,其中
|
||||
**两级 Barrett 模乘串联**(`t2=a1·b1` 再 `t2·zeta`)+ 模加;在 `use_dsp="no"` 约束下,
|
||||
每级 Barrett 约 24 ns,串联即 ≈ 52 ns。
|
||||
|
||||
**修复方向**(不使用 DSP,详见 `timing_analysis.md`):将 `barrett_mul` 改为 3 级内部流水
|
||||
(乘法 / ×K 移位 / ×q 约简各一拍),`basecase_mul` 的 c0 双乘级联为 6 拍、c1 对齐,
|
||||
`poly_mul_sync` 节拍相应加深。吞吐几乎不变(仅增加固定启动延迟,相对数万周期可忽略),
|
||||
WNS 预计转正。每步需重跑全部 KAT 确保功能不变。
|
||||
|
||||
---
|
||||
|
||||
## 6. 设计权衡与结论
|
||||
|
||||
### 6.1 主要权衡
|
||||
|
||||
| 决策 | 收益 | 代价 |
|
||||
|:---|:---|:---|
|
||||
| 单 FSM 串行调度 + 资源复用 | 面积小(LUT 25%)、控制清晰 | 串行执行,周期数较高 |
|
||||
| 共享单 Keccak 核 | 省大量面积 | 哈希/采样不能并行 |
|
||||
| Decaps 复用 Encaps 流水 | 省去独立重加密通路 | FSM 状态耦合较紧 |
|
||||
| 运行时选 k_i/op_i | 单比特流支持全部配置 | 存储按最坏情况分配 |
|
||||
| 不使用 DSP | 满足约束、可移植性强 | 乘法走 LUT,时序压力大 |
|
||||
|
||||
### 6.2 结论
|
||||
|
||||
`mlkem_top` 是一个**功能完整、KAT 全过**的 ML-KEM 硬件 IP,在单模块内支持 KeyGen/Encaps/Decaps
|
||||
三种操作与三种安全等级,面积占用低(LUT 25.5%、零 DSP)。设计经分阶段增量验证,正确性可靠。
|
||||
|
||||
当前唯一未达标项是 **50 MHz 时序收敛**:瓶颈明确(`basecase_mul` 双 Barrett 串联组合路径),
|
||||
修复方案已制定(纯流水化,不依赖 DSP),改动范围可控。完成该流水化改造并重跑 KAT 后,
|
||||
预计可收敛至 50 MHz 目标。
|
||||
|
||||
### 6.3 后续工作
|
||||
|
||||
1. 按 `timing_analysis.md` 实施 Barrett / basecase / poly_mul 流水化,收敛 50 MHz。
|
||||
2. 流水化后检查次要瓶颈(如 `comp_decomp` 的 Barrett),同法处理。
|
||||
3. 补充布局布线(implementation)后的时序签核,目前仅有综合后时序。
|
||||
4. 视吞吐需求,评估关键算子(NTT、采样)并行化以降低周期数。
|
||||
|
||||
---
|
||||
|
||||
## 附:复现命令
|
||||
|
||||
```bash
|
||||
source /opt/Xilinx/Vivado/2019.2/settings64.sh
|
||||
export LD_PRELOAD=/usr/lib64/libtinfo.so.5
|
||||
|
||||
# 功能验证
|
||||
./run_tb.sh top # KeyGen KAT (K=2/3/4)
|
||||
./run_tb.sh enc # Encaps KAT
|
||||
./run_tb.sh dec # Decaps KAT (含拒绝路径)
|
||||
./run_tb.sh hello # 端到端 hello_world
|
||||
|
||||
# 综合 + 时序报告
|
||||
vivado -mode batch -source synth_timing.tcl # → timing.rpt / timing_worst.rpt / util.rpt
|
||||
```
|
||||
|
||||
**相关文档**:`README.md`(使用说明)、`docs/mlkem_top_rtl.svg`(RTL 结构图)、
|
||||
`timing_analysis.md`(时序分析与修复方案)。
|
||||
229
docs/mlkem_top_rtl.svg
Normal file
229
docs/mlkem_top_rtl.svg
Normal file
@@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1480" height="1020" viewBox="0 0 1480 1020" font-family="'DejaVu Sans Mono','Consolas',monospace">
|
||||
<defs>
|
||||
<marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L7,3 L0,6 z" fill="#444"/>
|
||||
</marker>
|
||||
<marker id="arrB" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L7,3 L0,6 z" fill="#1763a6"/>
|
||||
</marker>
|
||||
<marker id="arrR" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L7,3 L0,6 z" fill="#a33"/>
|
||||
</marker>
|
||||
<style>
|
||||
.lbl{font-size:13px;fill:#111;}
|
||||
.sub{font-size:10.5px;fill:#555;}
|
||||
.port{font-size:11px;fill:#1763a6;}
|
||||
.net{font-size:10px;fill:#666;}
|
||||
.ttl{font-size:14px;font-weight:bold;fill:#111;}
|
||||
.big{font-size:20px;font-weight:bold;fill:#111;}
|
||||
.wire{stroke:#444;stroke-width:1.4;fill:none;}
|
||||
.wireB{stroke:#1763a6;stroke-width:1.4;fill:none;}
|
||||
.wireR{stroke:#a33;stroke-width:1.4;fill:none;}
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<rect x="0" y="0" width="1480" height="1020" fill="#fbfbf9"/>
|
||||
<text x="40" y="34" class="big">mlkem_top — ML-KEM KeyGen / Encaps / Decaps (op_i: 0/1/2, runtime k_i)</text>
|
||||
<text x="40" y="54" class="sub">实线=数据/系数通路 蓝=BRAM 端口 红=隐式拒绝 / 共享 keccak 仲裁 方框内为 RTL 实例名 / 信号名</text>
|
||||
|
||||
<!-- ================= INPUTS (left) ================= -->
|
||||
<rect x="24" y="90" width="200" height="318" rx="7" fill="#eef4fb" stroke="#9bb8d6"/>
|
||||
<text x="124" y="110" class="ttl" text-anchor="middle">输入端口</text>
|
||||
<text x="36" y="134" class="port">k_i[2:0] op_i[1:0]</text>
|
||||
<text x="36" y="154" class="port">start_i</text>
|
||||
<text x="36" y="178" class="lbl">d_i[255:0]</text>
|
||||
<text x="36" y="194" class="sub">KeyGen 种子 d</text>
|
||||
<text x="36" y="214" class="lbl">z_i[255:0]</text>
|
||||
<text x="36" y="230" class="sub">隐式拒绝种子 z</text>
|
||||
<text x="36" y="250" class="lbl">msg_i[255:0]</text>
|
||||
<text x="36" y="266" class="sub">Encaps 消息 m</text>
|
||||
<line x1="36" y1="280" x2="212" y2="280" stroke="#9bb8d6" stroke-dasharray="3 3"/>
|
||||
<text x="36" y="300" class="port">ek_in_* (Encaps)</text>
|
||||
<text x="36" y="316" class="sub">公钥 ek → u_ek_bram</text>
|
||||
<text x="36" y="338" class="port">dk_in_* (Decaps)</text>
|
||||
<text x="36" y="354" class="sub">私钥 dk → 各区路由</text>
|
||||
<text x="36" y="376" class="port">c_in_* (Decaps)</text>
|
||||
<text x="36" y="392" class="sub">密文 c → u_c_in_bram</text>
|
||||
|
||||
<!-- ================= FSM / CONTROL ================= -->
|
||||
<rect x="270" y="90" width="250" height="220" rx="8" fill="#fff3e0" stroke="#e0a440"/>
|
||||
<text x="395" y="112" class="ttl" text-anchor="middle">控制 FSM (st, st_next)</text>
|
||||
<text x="284" y="136" class="sub">KeyGen: G→A→C→N→M→E→H</text>
|
||||
<text x="284" y="153" class="sub">Encaps: ENC_H→G→LOAD→A→TDEC</text>
|
||||
<text x="284" y="167" class="sub"> →C→N→U→C1→E2MV→V→C2</text>
|
||||
<text x="284" y="184" class="sub">Decaps: DEC_LOAD→DECOMP→SDEC</text>
|
||||
<text x="284" y="198" class="sub"> →NTT→W→MENC→G→J→(重加密)→CMP</text>
|
||||
<line x1="284" y1="210" x2="506" y2="210" stroke="#e0a440" stroke-dasharray="3 3"/>
|
||||
<text x="284" y="230" class="lbl">相位选择 sel_*</text>
|
||||
<text x="284" y="246" class="sub">sel_sha3 / sel_snt / sel_cbd</text>
|
||||
<text x="284" y="266" class="lbl">op_r k_r (start 锁存)</text>
|
||||
<text x="284" y="286" class="lbl">busy_o = (st≠IDLE)</text>
|
||||
<text x="284" y="302" class="lbl">done_o = (st==DONE)</text>
|
||||
|
||||
<!-- registers -->
|
||||
<rect x="270" y="326" width="250" height="150" rx="8" fill="#fdeef0" stroke="#d68a96"/>
|
||||
<text x="395" y="346" class="ttl" text-anchor="middle">状态寄存器 (256b)</text>
|
||||
<text x="284" y="368" class="lbl">rho_r / sigma_r <tspan class="sub">(ρ,σ=G)</tspan></text>
|
||||
<text x="284" y="388" class="lbl">m_r <tspan class="sub">m / Decaps m'</tspan></text>
|
||||
<text x="284" y="408" class="lbl">r_r <tspan class="sub">PRF 种子 r / r'</tspan></text>
|
||||
<text x="284" y="428" class="lbl">hek_r <tspan class="sub">H(ek)</tspan> z_r <tspan class="sub">z</tspan></text>
|
||||
<text x="284" y="448" class="lbl">ss_r <tspan class="sub">K / K'</tspan> kbar_r <tspan class="sub">K̄=J(z‖c)</tspan></text>
|
||||
<text x="284" y="468" class="lbl">dec_reject <tspan class="sub">c'≠c 标志</tspan></text>
|
||||
|
||||
<!-- ================= SHARED KECCAK ================= -->
|
||||
<rect x="560" y="92" width="300" height="196" rx="8" fill="#fbecec" stroke="#c98b8b"/>
|
||||
<text x="710" y="114" class="ttl" text-anchor="middle">共享 Keccak (单核 + 相位 mux)</text>
|
||||
<rect x="586" y="128" width="248" height="44" rx="6" fill="#fff" stroke="#c98b8b"/>
|
||||
<text x="710" y="155" class="lbl" text-anchor="middle">u_keccak (keccak_core)</text>
|
||||
<text x="586" y="196" class="net">kc_state_i_mux / kc_valid_i_mux ◄ 3-way</text>
|
||||
<text x="586" y="214" class="net">kc_state_o / kc_valid_o ► 门控广播</text>
|
||||
<text x="586" y="236" class="net">kc_valid_o_sha3 · _snt · _cbd</text>
|
||||
<text x="586" y="258" class="sub">G/H/J、SampleNTT、CBD 分时复用 1 个核</text>
|
||||
<text x="586" y="276" class="sub">(相位互斥 → sel_sha3/snt/cbd 选通)</text>
|
||||
|
||||
<!-- ================= HASH ENGINE ================= -->
|
||||
<rect x="560" y="312" width="300" height="120" rx="8" fill="#eef7ee" stroke="#86b886"/>
|
||||
<text x="710" y="334" class="ttl" text-anchor="middle">u_sha3 (sha3_top_shared)</text>
|
||||
<text x="574" y="356" class="lbl">SHA3-512 G(·) → ρ‖σ / K‖r / K'‖r'</text>
|
||||
<text x="574" y="376" class="lbl">SHA3-256 H(ek) (多块吸收)</text>
|
||||
<text x="574" y="396" class="lbl">SHAKE-256 J(z‖c) → K̄ (多块)</text>
|
||||
<text x="574" y="416" class="sub">mb_en / mb_block_i 多块;mode 选 G/H/J</text>
|
||||
|
||||
<!-- ================= SAMPLERS ================= -->
|
||||
<rect x="560" y="456" width="300" height="76" rx="8" fill="#eef7ee" stroke="#86b886"/>
|
||||
<text x="710" y="478" class="ttl" text-anchor="middle">u_snt (sample_ntt_sync_shared)</text>
|
||||
<text x="574" y="498" class="lbl">Â[i][j] = SampleNTT(ρ‖j‖i) → bank_a</text>
|
||||
<text x="574" y="518" class="sub">snt_coeff / snt_valid / snt_last</text>
|
||||
|
||||
<rect x="560" y="548" width="300" height="76" rx="8" fill="#eef7ee" stroke="#86b886"/>
|
||||
<text x="710" y="570" class="ttl" text-anchor="middle">u_cbd (sample_cbd_sync_shared)</text>
|
||||
<text x="574" y="590" class="lbl">CBD_η: s/e (KeyGen), y/e1/e2 (Encaps)</text>
|
||||
<text x="574" y="610" class="sub">cbd_coeff → cbd_modq → bank_se / bank_t</text>
|
||||
|
||||
<!-- ================= ARITH ENGINES ================= -->
|
||||
<rect x="560" y="648" width="300" height="80" rx="8" fill="#e9f1f7" stroke="#7fa8cc"/>
|
||||
<text x="710" y="670" class="ttl" text-anchor="middle">u_ntt (ntt_core)</text>
|
||||
<text x="574" y="690" class="lbl">前向 NTT(mode0) / INTT(mode1, ×3303)</text>
|
||||
<text x="574" y="710" class="sub">ntt_in ◄ bank_se/bank_t;ntt_coeff ► 写回</text>
|
||||
|
||||
<rect x="560" y="744" width="300" height="80" rx="8" fill="#e9f1f7" stroke="#7fa8cc"/>
|
||||
<text x="710" y="766" class="ttl" text-anchor="middle">u_pmul (poly_mul_sync)</text>
|
||||
<text x="574" y="786" class="lbl">NTT 域逐点乘 Σ Â∘ŝ / Âᵀ∘ŷ / t̂∘ŷ / ŝ∘û</text>
|
||||
<text x="574" y="806" class="sub">pm_a_in ◄ bank_a, pm_b_in ◄ bank_se → pm_coeff</text>
|
||||
|
||||
<rect x="560" y="840" width="300" height="80" rx="8" fill="#e9f1f7" stroke="#7fa8cc"/>
|
||||
<text x="710" y="862" class="ttl" text-anchor="middle">u_comp (comp_decomp_sync)</text>
|
||||
<text x="574" y="882" class="lbl">Compress_d (mode0) / Decompress_d (mode1)</text>
|
||||
<text x="574" y="902" class="sub">Encaps C1/C2 压缩;Decaps DECOMP 解压</text>
|
||||
|
||||
<!-- accumulate / mod-add inline note -->
|
||||
<rect x="270" y="500" width="250" height="120" rx="8" fill="#f4f0fa" stroke="#a78bc9"/>
|
||||
<text x="395" y="522" class="ttl" text-anchor="middle">顶层内联运算</text>
|
||||
<text x="284" y="544" class="sub">modQ 累加 (ST_M / U / V / W)</text>
|
||||
<text x="284" y="562" class="sub">m_accq · u_accq · u_uq · u_vq · u_wq</text>
|
||||
<text x="284" y="582" class="sub">byteEncode12 (ST_E) e_wbyte</text>
|
||||
<text x="284" y="600" class="sub">byteDecode12 (TDEC/SDEC) td_c0/td_c1</text>
|
||||
<text x="284" y="618" class="sub">bit-packer cp_* / 解包 dec_* / 比较 cmp_*</text>
|
||||
|
||||
<!-- ================= STORAGE BANKS (right) ================= -->
|
||||
<rect x="900" y="90" width="340" height="470" rx="8" fill="#eef4fb" stroke="#9bb8d6"/>
|
||||
<text x="1070" y="112" class="ttl" text-anchor="middle">系数存储库 (sd_bram, 1R/1W, 1拍读)</text>
|
||||
|
||||
<rect x="922" y="128" width="296" height="92" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="934" y="148" class="lbl">u_bank_a <tspan class="sub">12×4096 (PA_AW=12)</tspan></text>
|
||||
<text x="934" y="167" class="sub">Â[i][j] 矩阵;Decaps 中转 ŝ / e2 / v'</text>
|
||||
<text x="934" y="185" class="net">ba_rd_addr/ba_rd_data ba_we/ba_wa/ba_wd</text>
|
||||
<text x="934" y="205" class="net">slot: i*K+j</text>
|
||||
|
||||
<rect x="922" y="230" width="296" height="92" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="934" y="250" class="lbl">u_bank_se <tspan class="sub">12×2048 (PSE_AW=11)</tspan></text>
|
||||
<text x="934" y="269" class="sub">ŝ/ê (KeyGen) · ŷ (Encaps) · û (Decaps)</text>
|
||||
<text x="934" y="287" class="net">bse_rd_addr/bse_rd_data bse_we/wa/wd</text>
|
||||
<text x="934" y="307" class="net">slot_s=K² slot_e=K²+K</text>
|
||||
|
||||
<rect x="922" y="332" width="296" height="92" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="934" y="352" class="lbl">u_bank_t <tspan class="sub">12×1024 (PT_AW=10)</tspan></text>
|
||||
<text x="934" y="371" class="sub">t̂ · psum · Encaps v · Decaps w</text>
|
||||
<text x="934" y="389" class="net">bt_rd_addr/bt_rd_data bt_we/wa/wd</text>
|
||||
<text x="934" y="409" class="net">slot_t=K²+2K UPSUM=rel1</text>
|
||||
|
||||
<rect x="922" y="434" width="143" height="58" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="934" y="453" class="lbl">u_ek_bram</text>
|
||||
<text x="934" y="469" class="sub">8×2048</text>
|
||||
<text x="934" y="485" class="sub">ek=Enc12(t̂)‖ρ</text>
|
||||
|
||||
<rect x="1075" y="434" width="143" height="58" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="1087" y="453" class="lbl">u_dkp_bram</text>
|
||||
<text x="1087" y="469" class="sub">8×2048</text>
|
||||
<text x="1087" y="485" class="sub">dk_pke=Enc12(ŝ)</text>
|
||||
|
||||
<rect x="922" y="500" width="143" height="50" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="934" y="519" class="lbl">u_ct_bram</text>
|
||||
<text x="934" y="537" class="sub">8×2048 c / c'</text>
|
||||
|
||||
<rect x="1075" y="500" width="143" height="50" rx="6" fill="#fff" stroke="#9bb8d6"/>
|
||||
<text x="1087" y="519" class="lbl">u_c_in_bram</text>
|
||||
<text x="1087" y="537" class="sub">8×2048 输入 c</text>
|
||||
|
||||
<!-- ================= OUTPUTS ================= -->
|
||||
<rect x="900" y="590" width="340" height="330" rx="8" fill="#eef9ee" stroke="#86b886"/>
|
||||
<text x="1070" y="612" class="ttl" text-anchor="middle">输出 / 回读</text>
|
||||
<text x="914" y="638" class="lbl">ss_o = dec_reject ? kbar_r : ss_r</text>
|
||||
<text x="914" y="654" class="sub">共享密钥 K (Encaps/Decaps)</text>
|
||||
<line x1="914" y1="666" x2="1226" y2="666" stroke="#86b886" stroke-dasharray="3 3"/>
|
||||
<text x="914" y="688" class="lbl">dbg_ct_o ◄ u_ct_bram</text>
|
||||
<text x="914" y="704" class="sub">密文 c 逐字节</text>
|
||||
<text x="914" y="726" class="lbl">dbg_byte_o ◄ ek / dk_pke</text>
|
||||
<text x="914" y="742" class="sub">sel: 0=ek_bram 1=dkp_bram</text>
|
||||
<text x="914" y="764" class="lbl">dbg_dk_o ◄ dk_pke‖ek‖H(ek)‖z</text>
|
||||
<text x="914" y="780" class="sub">完整 dk 逐字节 (1632/2400/3168B)</text>
|
||||
<text x="914" y="802" class="lbl">dbg_coeff_o ◄ bank_a/se/t</text>
|
||||
<text x="914" y="818" class="sub">按 dbg_slot_i 选库, 系数回读</text>
|
||||
<line x1="914" y1="830" x2="1226" y2="830" stroke="#86b886" stroke-dasharray="3 3"/>
|
||||
<text x="914" y="852" class="sub">调试抽头: dbg_rho_o dbg_sigma_o</text>
|
||||
<text x="914" y="868" class="sub"> dbg_r_o dbg_hek_o dbg_mprime_o</text>
|
||||
<text x="914" y="884" class="sub"> dbg_kbar_o dbg_decz_o dbg_dech_o</text>
|
||||
<text x="914" y="906" class="sub">done_o / busy_o</text>
|
||||
|
||||
<!-- ============ WIRES ============ -->
|
||||
<!-- inputs -> FSM/regs -->
|
||||
<path class="wire" d="M224,150 L268,150" marker-end="url(#arr)"/>
|
||||
<path class="wire" d="M224,182 L268,182 L268,378" marker-end="url(#arr)"/>
|
||||
<path class="wire" d="M224,218 L256,218 L256,440 L268,440" marker-end="url(#arr)"/>
|
||||
<path class="wire" d="M224,254 L260,254 L260,388 L268,388" marker-end="url(#arr)"/>
|
||||
|
||||
<!-- inputs(ek/dk/c) -> banks (blue) -->
|
||||
<path class="wireB" d="M224,300 L240,300 L240,68 L1300,68 L1300,460 L1218,460" marker-end="url(#arrB)"/>
|
||||
<path class="wireB" d="M224,338 L236,338 L236,72 L1296,72 L1296,463 L1218,463" marker-end="url(#arrB)"/>
|
||||
<path class="wireB" d="M224,376 L232,376 L232,76 L1292,76 L1292,525 L1218,525" marker-end="url(#arrB)"/>
|
||||
|
||||
<!-- FSM sel -> keccak mux (red) -->
|
||||
<path class="wireR" d="M520,230 L540,230 L540,180 L558,180" marker-end="url(#arrR)"/>
|
||||
<!-- keccak <-> sha3/snt/cbd -->
|
||||
<path class="wireR" d="M710,288 L710,310" marker-end="url(#arrR)"/>
|
||||
<path class="wireR" d="M560,210 L546,210 L546,494 L558,494" marker-end="url(#arrR)"/>
|
||||
<path class="wireR" d="M560,214 L544,214 L544,586 L558,586" marker-end="url(#arrR)"/>
|
||||
|
||||
<!-- regs <-> sha3 (rho/sigma/r/ss/kbar) -->
|
||||
<path class="wire" d="M520,372 L536,372 L536,360 L558,360" marker-end="url(#arr)"/>
|
||||
<path class="wire" d="M558,392 L538,392 L538,448 L520,448" marker-end="url(#arr)"/>
|
||||
|
||||
<!-- datapath engines -> banks (blue) -->
|
||||
<path class="wireB" d="M860,494 L884,494 L884,174 L920,174" marker-end="url(#arrB)"/>
|
||||
<path class="wireB" d="M860,590 L880,590 L880,276 L920,276" marker-end="url(#arrB)"/>
|
||||
<path class="wireB" d="M860,688 L876,688 L876,378 L920,378" marker-end="url(#arrB)"/>
|
||||
<!-- pmul reads bank_a/se -->
|
||||
<path class="wireB" d="M920,200 L888,200 L888,772 L860,772" marker-end="url(#arrB)"/>
|
||||
<path class="wireB" d="M920,300 L892,300 L892,776 L860,776" marker-end="url(#arrB)"/>
|
||||
<!-- comp <-> ct/c_in -->
|
||||
<path class="wireB" d="M860,884 L896,884 L896,524 L920,524" marker-end="url(#arrB)"/>
|
||||
|
||||
<!-- regs -> ss_o (red reject mux) -->
|
||||
<path class="wireR" d="M520,448 L528,448 L528,948 L898,948 L898,634 L912,634" marker-end="url(#arrR)"/>
|
||||
|
||||
<!-- banks -> outputs (data already adjacent; show coeff readback) -->
|
||||
<path class="wire" d="M1218,478 L1240,478 L1240,808 L1226,808" marker-end="url(#arr)"/>
|
||||
|
||||
<text x="40" y="1000" class="sub">注:同一套叶子算子 / 存储库被 KeyGen·Encaps·Decaps 三条数据通路按 FSM 相位分时复用;Decaps 重加密直接复用整条 Encaps 流水 (ENC_LOAD…ENC_C2)。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
101
docs/timing_analysis.md
Normal file
101
docs/timing_analysis.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# 50 MHz 时序收敛分析与修复方案
|
||||
|
||||
> 报告来源:`synth_timing.tcl`(OOC 综合 `mlkem_top`,器件 `xc7a200tfbg676-1`,
|
||||
> `sysclk` 20 ns / 50 MHz)。生成 `timing.rpt` / `timing_worst.rpt` / `util.rpt`。
|
||||
|
||||
## 一、现状
|
||||
|
||||
| 指标 | 值 |
|
||||
|:---|:---|
|
||||
| WNS | **-32.206 ns**(目标 20 ns,实际关键路径 ~52 ns) |
|
||||
| TNS | -37879 ns,失败端点 3132 / 44689 |
|
||||
| Hold (WHS) | +0.134 ns ✅(无 hold 违例) |
|
||||
| 关键路径 | `u_pmul/mem_A_reg[239][2]` → `u_pmul/c0_reg_reg[0]` |
|
||||
| 路径延迟 | 52.055 ns(逻辑 21.9 ns / 布线 30.1 ns),**70 逻辑级**(CARRY4×26 + LUT×43 + MUXF×3) |
|
||||
| 面积 | LUT 25.5%、FF 8.6%、BRAM ~5 片、**DSP 0 / 740(完全没用)** |
|
||||
|
||||
之前那份 `timing.rpt`(WNS -17.7 ns,关键路径在 comp_decomp 的组合除法器)已经过时——
|
||||
`717a992` 用 Barrett 乘法替换了组合除法器,comp_decomp 不再是瓶颈。本次重新综合后,
|
||||
**瓶颈转移到 `poly_mul` 的 basecase 乘法器 `u_pmul`**。
|
||||
|
||||
## 二、根因
|
||||
|
||||
`basecase_mul`(NTT 域 degree-1 乘法)单周期组合计算 c0/c1:
|
||||
|
||||
```
|
||||
c0 = (a0·b0 + (a1·b1)·zeta) mod Q
|
||||
c1 = (a0·b1 + a1·b0) mod Q
|
||||
```
|
||||
|
||||
c0 这条路径**串联了两级 Barrett 模乘**:先 `t2 = a1·b1 mod Q`,再 `t2_zeta = t2·zeta mod Q`,
|
||||
最后再做一次模加。每级 `barrett_mul` 含 12×12 乘 + ×K 乘 + ×Q 移位加 + 两次条件减,
|
||||
而且全局带 `(* use_dsp = "no" *)` —— 所有乘法都摊成 LUT+CARRY4 阵列。两级串联 ⇒ 70 级、52 ns。
|
||||
|
||||
**两个叠加的放大因素:**
|
||||
1. **串联两次 Barrett 模乘**(t2 → t2·zeta)挤在一个组合周期。
|
||||
2. **`use_dsp="no"`** 把每个乘法变成进位链,本可用的 740 个 DSP48 一个没用。
|
||||
|
||||
> 注:此前给乘法器加 `use_dsp="no"` 多半是为了规避 XSIM 仿真问题;但综合时这逼着工具
|
||||
> 用 LUT 搭乘法,正是当前 52 ns 关键路径的主因。
|
||||
|
||||
## 三、修复方案(约束:**不允许使用 DSP**,纯 LUT/CARRY4 流水化)
|
||||
|
||||
> 实测细节(timing_worst.rpt 逐级):一个 `barrett_mul` 单独就要 **~24 ns**
|
||||
> (t2 = a1·b1 走到 ~28 ns,其中乘法本体 + ×K + ×Q 约简占大头),c0 又把
|
||||
> **两个 Barrett 串联**(t2 → t2·zeta)+ 模加 ⇒ 52 ns。
|
||||
> 关键结论:**单级 Barrett(~24 ns)本身就超 20 ns**,所以光在两次乘法之间插一拍
|
||||
> (26 ns/级)不够,必须**在 `barrett_mul` 内部也切流水**。
|
||||
|
||||
### 推荐方案:三段式流水的 Barrett 模乘 + basecase 重构
|
||||
|
||||
把 `a·b mod Q` 拆成 3 个寄存级,每级 < ~12 ns:
|
||||
|
||||
```
|
||||
级1: p = a * b (12×12 → 24b 乘法,纯 LUT/CARRY4) → 寄存 p
|
||||
级2: qe = (p * K) >> 24 (24×13 乘法 + 移位) → 寄存 qe、p
|
||||
级3: r = p - qe*Q; 两次条件减 Q → 寄存 product
|
||||
```
|
||||
|
||||
- 单个乘法(12×12 或 24×13)在 LUT 上约 ~10–12 ns,加约简一拍单独走,各级都能压到 20 ns 内。
|
||||
- `barrett_mul` 从纯组合改成 **3 拍流水**(加 `clk`/`valid` 端口或用上层节拍计数)。
|
||||
|
||||
basecase 的 c0 双乘串联(`a1·b1` 再 `·zeta`)= 两个 3 级流水级联 = **6 拍**;
|
||||
c1 只有单乘 = 3 拍。让两条对齐到 6 拍输出。`poly_mul_sync` 现有
|
||||
`S_COMP_CALC → S_COMP_C0 → S_COMP_C1` 节拍改为:CALC 阶段等待乘法流水排空(固定 N 拍),
|
||||
再依次输出 c0/c1。**吞吐**:逐点乘本就 1 系数/多拍,加深流水只增加固定启动延迟(~6 拍/128 次
|
||||
basecase = 几百拍),相对 KeyGen ~22.9k、Decaps ~50.8k 周期可忽略。
|
||||
|
||||
### 同源风险:comp_decomp 的 Barrett
|
||||
|
||||
`comp_decomp_sync` 也用同样的 Barrett 结构(compress 路径 `dividend*5039>>24` + ×Q 约简),
|
||||
单条也可能逼近 20 ns。修好 basecase 后若它冒头,同样按“Barrett 内部 3 级流水”处理。
|
||||
其 5-phase 微序列(cd_valid 脉冲 + ph 等待)很容易吸收额外流水拍。
|
||||
|
||||
### 备选:更激进的乘法器结构(若 3 级仍不够)
|
||||
|
||||
- 12×12 乘法本身用 **2 级流水**(部分积分两半累加),把 Barrett 拉成 4–5 级;
|
||||
- 或对乘法做 **基-4/基-8 部分积 + 进位保存加法器(CSA)树**,减少 CARRY4 链深度。
|
||||
改动大,仅在 3 级流水实测仍 > 20 ns 时再考虑。
|
||||
|
||||
## 四、建议路线(不用 DSP)
|
||||
|
||||
1. 把 `barrett_mul` 改成 3 级流水版(带 clk/valid),单独综合确认单级 < 20 ns。
|
||||
2. 重构 `basecase_mul`:c0 路径两级 Barrett 级联(6 拍),c1 对齐;`poly_mul_sync` 节拍
|
||||
按固定流水深度调整(CALC 等 N 拍再出 c0/c1)。
|
||||
3. 全量 KAT 复测(`run_tb.sh top/enc/dec` + `hello`)确认功能不变 —— 流水加深会改变
|
||||
`poly_mul`/`ntt`/`comp_decomp` 的拍数,各 FSM 的 done/valid 判定需同步更新。
|
||||
4. 重综合看 WNS;若 comp_decomp 成新瓶颈,同法流水化。
|
||||
5. 迭代直到 WNS ≥ 0 @ 20 ns。
|
||||
|
||||
> 注意:本项目所有时序验证目前靠 XSIM 功能仿真 + KAT,**没有跑过布局布线后时序**。
|
||||
> 加流水属于改时序行为的大改,务必每步重跑全部 KAT,确保 ek/dk/ss/ct 仍逐字节正确。
|
||||
|
||||
|
||||
## 五、复现命令
|
||||
|
||||
```bash
|
||||
source /opt/Xilinx/Vivado/2019.2/settings64.sh
|
||||
export LD_PRELOAD=/usr/lib64/libtinfo.so.5
|
||||
vivado -mode batch -source synth_timing.tcl # 器件在脚本里:xc7a200tfbg676-1
|
||||
# 读 timing.rpt(摘要) / timing_worst.rpt(逐路径) / util.rpt(面积、DSP 占用)
|
||||
```
|
||||
Reference in New Issue
Block a user