FPGA 时序图文档标准

本文档定义了在 LLD(底层设计)文档中创建、复用和发布 FPGA 时序图的标准工作流程。目标是实现所有 FPGA 子项目的一致性,并通过模板复用实现零成本的图表编写。


1. LLD 时序图模板策略

1.1 黄金法则:先拷贝,后微调

永远不要从零开始编写时序图。 始终从共享模板库 ip_common/doc/timing/ 中的现有图表开始。这保证了仓库中每份设计文档的信号命名约定、时钟域符号和视觉风格一致。

1.2 模板库结构


ip_common/doc/timing/
├── _templates/
│   ├── axi4-stream.wave.json        # AXI4-Stream 握手(TVALID/TREADY/TDATA)
│   ├── axi4-lite.wave.json          # AXI4-Lite 读写事务
│   ├── avalon-mm.wave.json          # Avalon-MM 突发读取
│   ├── spi-master.wave.json         # SPI 主机(CPOL=0, CPHA=0)
│   ├── i2c-read.wave.json           # I2C 读事务
│   ├── uart-frame.wave.json         # UART 8N1 帧
│   ├── memory-rw.wave.json          # 简单内存读写(addr/rden/wren/rdata/wdata)
│   ├── pipe-valid.wave.json         # 通用 valid/ready 流水线阶段
│   └── reset-release.wave.json      # 异步复位解除 + PLL 锁定
├── README.md                         # 模板使用指南
└── Makefile                          # 批量渲染所有模板为 SVG

1.3 拷贝-微调工作流程(分步说明)


# 第 1 步:选择最接近的模板
ls ip_common/doc/timing/_templates/

# 第 2 步:拷贝到你的模块文档目录中
cp ip_common/doc/timing/_templates/axi4-stream.wave.json \
my_module/doc/timing/my_module_tx.wave.json

# 第 3 步:在 JSON 中仅编辑信号名称(不改变结构)
vim my_module/doc/timing/my_module_tx.wave.json

编辑时,遵循以下规则:
可以修改的内容 必须保留的内容
信号名称(如 m_axis_tdata 改为 s_axis_tdata 信号排列顺序(先 clk,再控制信号,最后数据信号)
数据通道数量(如 8 位改为 32 位) 时钟周期 / tick 间距
Testbench 实例前缀 wavedrom 根结构
颜色提示(每个信号的 #RRGGBB 值) 阶段标签(CfgWaitBurst

2. Wavedrom 格式时序图编写

2.1 最小 Wavedrom JSON 骨架


{
  "signal": [
    { "name": "clk",        "wave": "p......", "period": 2 },
    { "name": "reset_n",    "wave": "0.1...." },
    { "name": "valid",      "wave": "0.10..1", "node": ".A.B..C" },
    { "name": "ready",      "wave": "1.0.10." },
    { "name": "data[7:0]",  "wave": "x.=.=.x", "data": ["A5", "3C", "F0"] }
  ],
  "head": { "text": "My Module: Write Transaction" },
  "foot": { "text": "tick = 10 ns", "tock": 1 }
}

2.2 Wavedrom 波形字符参考

字符 含义
p 正时钟沿(clk 前半周期为高)
n 负时钟沿
P 正时钟沿带箭头
N 负时钟沿带箭头
0 低电平(逻辑 0)
1 高电平(逻辑 1)
x 无关/未知(灰色填充)
z 高阻态(三态,中间虚线)
= 数据总线(该 tick 取 data 数组中的值)
2 值为 2 的数据总线
3, 4, 5 = 的彩色变体(谨慎使用)
. 重复上一个状态
| 间隙分隔符(跳过半个 tick)

2.3 实用示例:AXI4-Stream 握手


{
  "signal": [
    { "name": "aclk",            "wave": "p..............", "period": 2 },
    { "name": "aresetn",         "wave": "0.1............" },
    { "name": "s_axis_tvalid",   "wave": "0.....10..10...", "node": "..A....B..C.D" },
    { "name": "s_axis_tready",   "wave": "1..0..10.10.10." },
    { "name": "s_axis_tdata",    "wave": "x..=.=.=.=.=.=.",
      "data": ["D0", "D1", "D2", "D3", "D4", "D5"] },
    { "name": "s_axis_tlast",    "wave": "0.............10" },
    { "name": "s_axis_tkeep",    "wave": "x..=.=.=.=.=.=.",
      "data": ["FF", "FF", "FF", "FF", "FF", "0F"] }
  ],
  "head": { "text": "AXI4-Stream: 5-beat Burst with Backpressure" },
  "foot": { "text": "Burst length = 5; D4 triggers backpressure deassertion on TREADY" },
  "edge": ["A~>B TREADY deasserts", "C->D TREADY reasserts"],
  "config": { "hscale": 1.5 }
}

2.4 添加边沿和箭头


"edge": [
  "P->Q Clock crossing event",
  "A~>B Setup time check",
  "C-~>D Hold time check",
  "E->F Propagation delay: 3.2 ns max"
]

边沿符号:->(实线箭头)、~>(虚线箭头)、-~>(点线箭头)。


3. Mermaid 图表嵌入与渲染

3.1 何时使用 Mermaid vs Wavedrom

图表类型 工具 理由
时序波形(信号随时间变化) Wavedrom 专为数字时序设计
框图、架构图 Mermaid(flowchart/graph) 自动布局整洁
状态机 Mermaid(stateDiagram) 标准 UML 符号
序列图 Mermaid(sequenceDiagram) 模块交互流程
流水线阶段 Mermaid(graph LR) 从左到右的数据流

3.2 在 Markdown 中嵌入

Wavedrom(使用 wavedrom 代码块): %%FENCED_5%%wavedrom { "signal": [ { "name": "clk", "wave": "p...." }, { "name": "data", "wave": "x.=.x", "data": ["A5"] } ] } %%FENCED_6%% Mermaid(使用 mermaid 代码块): %%FENCED_7%%mermaid sequenceDiagram participant CPU participant DMA participant DDR

CPU->>DMA: Configure descriptor
DMA->>DDR: Read burst (4 beats)
DDR-->>DMA: Return data
DMA->>CPU: IRQ: transfer done
%%FENCED_8%%

3.3 Mermaid 跨时钟域图示例

%%FENCED_9%%mermaid graph TB subgraph clk_100MHz ["Domain: 100 MHz"] TX[TX FSM] FIFO_W[Async FIFO<br/>Write Side] end

subgraph clk_150MHz ["Domain: 150 MHz"]
FIFO_R[Async FIFO<br/>Read Side]
RX[RX FSM]
end

TX -->|wr_data[31:0]| FIFO_W
FIFO_W -.->|CDC crossing| FIFO_R
FIFO_R -->|rd_data[31:0]| RX
%%FENCED_10%%


4. md2html 一键转换工作流

4.1 前置条件

md2html 工具可以在一次处理中同时完成 Wavedrom 和 Mermaid 的渲染:

# 安装 md2html 工具(如果尚未安装)
cd /home/user/tools/
git clone https://github.com/BuckHuang/md2html.git
cd md2html && make install

4.2 使用方法


# 转换单个 .md 文件(自动检测 Wavedrom + Mermaid 代码块)
md2html my_module/doc/my_module_lld.md

# 转换目录树中的所有 .md 文件
md2html --recursive my_module/doc/

# 输出到指定目录
md2html my_module/doc/my_module_lld.md -o /var/www/html/docs/

# 监视模式(保存时自动转换)
md2html --watch my_module/doc/

4.3 md2html 内部工作原理

4.4 典型 LLD 文档目录布局


my_module/doc/
├── timing/
│   ├── my_module_rx.wave.json          # Wavedrom 源文件(可编辑)
│   └── my_module_tx.wave.json
├── images/
│   ├── block_diagram.mmd               # Mermaid 源文件(可编辑)
│   └── state_machine.mmd
├── my_module_lld.md                     # 主设计文档(引用以上文件)
└── html/                                # 生成的输出(提交以供审查)
    └── my_module_lld.html


5. 文档版本递增

5.1 规则

> 每次编辑 Markdown 文档,必须将版本号递增 1 并更新时间戳。

这适用于 doc/ 目录下或任何用于 HTML 渲染目录下的所有 .md 文件。

5.2 版本块格式

将此内容放在每份文档的顶部,紧跟标题之后:


> **Version:** 3 | **Date:** 2026-07-24 | **Author:** huanghm

每次进行任何编辑后,将 Version 递增 1,并将 Date 更新为当天日期。

5.3 示例

修改前:


> **Version:** 3 | **Date:** 2026-07-20 | **Author:** huanghm

修改后(例如,修复了 Wavedrom 代码块中的信号名称):


> **Version:** 4 | **Date:** 2026-07-24 | **Author:** huanghm

5.4 自动化脚本


#!/bin/bash
# /home/user/tools/bump-version.sh
# 用法: bump-version.sh my_doc.md

FILE="$1"
if [ ! -f "$FILE" ]; then
echo "Usage: bump-version.sh <markdown-file>"
exit 1
fi

TODAY=$(date +%Y-%m-%d)

# 匹配版本行并递增版本号
sed -i -E "s/\*\*Version:\*\* ([0-9]+)/\*\*Version:\*\* $(( \1 + 1 ))/" "$FILE"

# 更新日期
sed -i -E "s/\*\*Date:\*\* [0-9]{4}-[0-9]{2}-[0-9]{2}/\*\*Date:\*\* $TODAY/" "$FILE"

echo "Bumped $(basename "$FILE") to version $(grep -oP 'Version:\*\* \K[0-9]+' "$FILE")"


6. 故障排查

症状 原因 修复方法
Wavedrom 渲染为空白框 JSON 语法错误(缺少逗号/花括号) 使用 python -m json.tool file.wave.json 验证
Mermaid 图表不渲染 mmdc 未安装 npm install -g @mermaid-js/mermaid-cli
边沿箭头方向错误 节点标签 AB 等未按顺序排列 从左到右重命名节点
HTML 输出缺少图表 Wavedrom/Mermaid 代码块未被识别 检查代码块标签是否精确使用了 wavedrommermaid
HTML 中 SVG 太小 内联 SVG 缺少 viewBox 在 Wavedrom JSON 中添加 "config": { "hscale": 2 }