Quick Start
- 准备环境:安装支持SystemVerilog的仿真器(如Vivado Simulator 2023.2+、QuestaSim 2023.3+),确保工程已包含待测RTL和SystemVerilog testbench。
- 创建死锁检测模块:新建文件
deadlock_monitor.sv,定义检测器接口和超时计数器。 - 编写检测逻辑:使用
always_ff块监控关键握手信号(valid/ready/ack),当信号在指定时钟周期内无变化时触发死锁标志。 - 集成到testbench:在顶层testbench中实例化检测模块,连接待测模块(DUT)的接口信号。
- 设置仿真运行时间:运行仿真至少10μs或直到所有事务完成。
- 观察结果:仿真结束时检查日志中是否有“DEADLOCK DETECTED”输出,若无则通过。
前置条件与环境
| 项目 | 推荐值 | 说明 | 替代方案 |
|---|---|---|---|
| 器件/板卡 | Xilinx Artix-7 (XC7A35T) | 用于综合验证,仿真无关 | 任何FPGA型号 |
| EDA版本 | Vivado 2023.2 | 内置仿真器支持SystemVerilog 2012 | QuestaSim 2023.3+ / VCS 2023+ |
| 仿真器 | Vivado Simulator (xsim) | 默认集成,无需额外安装 | ModelSim / QuestaSim |
| 时钟/复位 | 100MHz时钟,同步高有效复位 | 检测器使用同一时钟域 | 异步复位需额外同步 |
| 接口依赖 | AXI4-Stream或自定义valid-ready握手 | 检测逻辑基于信号变化 | 其他握手协议需调整 |
| 约束文件 | 无需XDC(仅仿真) | 仅用于RTL仿真 | 上板时需时序约束 |
目标与验收标准
- 功能点:自动检测仿真中因握手信号卡死导致的死锁,并报告具体信号和时间。
- 性能指标:检测延迟不超过10个时钟周期,误报率低于1%(在正常握手下)。
- 资源/Fmax:检测模块综合后LUT小于50,FF小于30,不影响DUT时序。
- 验收方式:仿真日志中出现“DEADLOCK DETECTED”且波形中信号无变化超过超时阈值。
实施步骤
工程结构如下:
project/
├── rtl/
│ ├── dut.sv # 待测模块
│ └── deadlock_monitor.sv # 死锁检测器
├── tb/
│ └── tb_top.sv # 顶层testbench
└── sim/
└── run_sim.tcl # 仿真脚本逐行说明
- 第1行:
project/为工程根目录,组织RTL、testbench和仿真脚本。 - 第2行:
rtl/存放设计源文件,包括DUT和检测器。 - 第3行:
dut.sv是待测模块,包含可能死锁的握手逻辑。 - 第4行:
deadlock_monitor.sv是核心检测模块,实现自动化监控。 - 第5行:
tb/存放testbench文件。 - 第6行:
tb_top.sv实例化DUT和检测器,连接信号。 - 第7行:
sim/存放仿真脚本。 - 第8行:
run_sim.tcl用于自动化编译和运行仿真。
关键模块:死锁检测器
// deadlock_monitor.sv
module deadlock_monitor #(
parameter int TIMEOUT_CYCLES = 1000,
parameter int NUM_SIGNALS = 4
)(
input logic clk,
input logic rst_n,
input logic [NUM_SIGNALS-1:0] signals
);
logic [NUM_SIGNALS-1:0] prev_signals;
logic [31:0] idle_counter;
logic deadlock_flag;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
prev_signals <= '0;
idle_counter <= '0;
deadlock_flag <= 1'b0;
end else begin
prev_signals <= signals;
if (signals == prev_signals) begin
if (idle_counter >= TIMEOUT_CYCLES) begin
deadlock_flag <= 1'b1;
end else begin
idle_counter <= idle_counter + 1;
end
end else begin
idle_counter <= '0;
deadlock_flag <= 1'b0;
end
end
end
endmodule逐行说明
- 第1行:注释,指明文件名
deadlock_monitor.sv。 - 第2行:模块定义开始,模块名为
deadlock_monitor。 - 第3行:参数声明开始,
TIMEOUT_CYCLES默认值为1000,表示超时时钟周期数。 - 第4行:参数
NUM_SIGNALS默认值为4,表示监控的信号数量。 - 第5行:端口列表开始。
- 第6行:输入端口
clk,时钟信号。 - 第7行:输入端口
rst_n,低电平有效复位信号。 - 第8行:输入端口
signals,宽度为NUM_SIGNALS的向量,表示待监控的握手信号。 - 第9行:端口列表结束。
- 第11行:内部寄存器
prev_signals,用于存储上一时钟周期的信号状态。 - 第12行:内部寄存器
idle_counter,32位计数器,记录信号无变化的时钟周期数。 - 第13行:内部寄存器
deadlock_flag,死锁标志位。 - 第15行:时序逻辑块开始,敏感列表为时钟上升沿或复位下降沿。
- 第16行:复位条件判断,若
rst_n为低电平则执行复位操作。 - 第17行:复位时
prev_signals清零。 - 第18行:复位时
idle_counter清零。 - 第19行:复位时
deadlock_flag清零。 - 第20行:非复位分支开始。
- 第21行:将当前
signals赋值给prev_signals,用于下一周期比较。 - 第22行:判断当前信号是否与上一周期相同(即无变化)。
- 第23行:若信号无变化,检查
idle_counter是否达到超时阈值。 - 第24行:若达到阈值,将
deadlock_flag置为1,表示检测到死锁。 - 第25行:否则,计数器加1。
- 第26行:信号有变化的分支开始。
- 第27行:计数器清零,因为信号已变化。
- 第28行:死锁标志清零。
- 第29行:时序逻辑块结束。
- 第31行:模块定义结束。
验证结果
仿真运行后,检查日志文件。若出现“DEADLOCK DETECTED”信息,说明死锁被成功捕获;否则,握手信号在超时阈值内持续变化,系统正常运行。建议在波形中手动验证信号停滞时间是否与计数器值一致。
排障指南
- 误报:若正常握手下仍触发死锁,可增大
TIMEOUT_CYCLES参数,或检查复位后信号初始化时序。 - 漏报:若死锁未被检测,确认
signals端口是否连接了所有关键握手信号(如valid、ready、ack)。 - 仿真崩溃:检查时钟域是否一致,异步复位需额外同步逻辑。
- 计数器溢出:若仿真时间极长,
idle_counter可能溢出,可将位宽扩展至64位。
扩展与优化
- 多协议支持:修改检测逻辑,适配AXI4全握手、握手请求-应答等协议。
- 层次化监控:实例化多个检测器,分别监控不同子模块或总线。
- 自动报告:在
deadlock_flag置位时,通过$display或$fwrite输出信号名称和时间戳。 - 动态阈值:通过参数化或外部寄存器动态调整超时周期,适应不同仿真场景。
参考
- IEEE Std 1800-2017: SystemVerilog Language Reference Manual
- Xilinx UG900: Vivado Design Suite User Guide - Logic Simulation
- Mentor Graphics QuestaSim User's Manual
附录:仿真脚本示例
# run_sim.tcl
create_project -force deadlock_demo ./deadlock_demo
add_files -norecurse {../rtl/dut.sv ../rtl/deadlock_monitor.sv ../tb/tb_top.sv}
set_property top tb_top [current_fileset]
launch_simulation -mode behavioral
run 10 us
close_sim将上述脚本置于 sim/ 目录下,在Vivado Tcl控制台执行 source run_sim.tcl 即可自动运行仿真。



