FPGA基础 -- Verilog 禁止语句
关于 Verilog 中“禁止语句”的详细培训讲解**,结合可综合设计与仿真行为的角度,深入讲解 Verilog 中的“禁止类语句”(即综合时应避免或仅用于仿真的语句):
一、Verilog 中的“禁止语句”概念
所谓“禁止语句”(或说非综合语句),是指 不能被综合工具(如 Vivado、Quartus、Synplify)综合到门级电路中,仅用于仿真或调试目的的语法结构。使用这些语句不会被转换为实际的逻辑门或触发器电路。
这些语句一般包括:
- 延迟控制语句(
#
) - 系统任务与函数(如
$display
,$finish
,$stop
,$time
) - 初始化行为(
initial
块中不可综合的内容) - 文件操作(如
$readmemh
,$fopen
,$fdisplay
等)
二、常见禁止语句汇总
类别 | 示例 | 用途 | 是否可综合 |
---|---|---|---|
延迟控制 | #10 a = 1'b1; | 仿真中添加时间延迟 | ❌ 禁止综合 |
时间函数 | $time , $stime | 获取当前仿真时间 | ❌ 禁止综合 |
显示输出 | $display , $monitor , $write | 打印调试信息 | ❌ 禁止综合 |
仿真控制 | $stop , $finish | 控制仿真结束 | ❌ 禁止综合 |
文件操作 | $readmemh , $fwrite , $readmemb | 读取或写入文件数据 | ❌ 禁止综合 |
initial 中行为 | initial a = 1'b0; | 初始化变量(综合视角中不能使用) | ❌ 一般禁止(除 LUT 初始化等特例) |
三、为什么这些语句被禁止综合?
原因:
- 没有对应硬件结构:比如
#10
是等待 10 单位时间,但实际硬件中没有“等待器”这种逻辑。 - 属于软件行为:如
$display
是“调试信息打印”,与硬件结构完全无关。 - 在综合工具中没有实现路径:工具会忽略或直接报错,无法映射为电路。
✅ 四、仿真专用 vs 综合可用
类型 | 说明 | 示例 | 建议 |
---|---|---|---|
仿真专用语句 | 不用于硬件生成,仅供行为验证使用 | $display , #10 , $stop | ✅ 用于 testbench 中 |
综合语句 | 可综合映射为门电路/触发器 | always @(posedge clk) , if , case , assign | ✅ 用于设计模块 |
条件允许语句 | 在特定上下文可用 | initial begin $readmemh(...) end | ✅ 在初始化 BRAM 时使用 |
五、典型错误示例与修正建议
示例 1:使用 #10
延迟
always @(posedge clk) begin#10 a = 1; // ❌ 错误:不能综合
end
✅ 改为:
always @(posedge clk) begina <= 1; // 正确:同步逻辑
end
示例 2:使用 $display
always @(posedge clk) beginif (a == 1) $display("a is 1"); // ❌ 错误:调试语句
end
✅ 改为(若要调试):
// 在 testbench 文件中使用 $display,而不要在 RTL 代码中用
示例 3:初始化 ROM 内容
reg [7:0] rom[0:255];
initial begin$readmemh("rom_init.hex", rom); // ✅ 仅用于仿真或特殊综合支持(如 BRAM)
end
✅ 注意:
- Vivado 可以综合该
initial
行为并映射为初始化的 ROM。 - 需要
readmemh
形式正确,ROM 不能是组合逻辑。
六、如何定位禁止语句?
综合工具一般会给出如下错误或警告提示:
- Vivado:
Cannot synthesize non-constant delay expression
- Quartus:
Unsupported system task or function
- Synplify:
Unsupported delay control #
建议做法:
- 在 RTL 中使用严格的时序风格(同步时序 + 异步复位)
- 所有调试、打印、文件操作,全部在 testbench 中完成
- 利用
ifdef SYNTHESIS
屏蔽仿真语句
示例:
`ifndef SYNTHESIS$display("Debug Message");
`endif
七、总结
内容分类 | 是否可综合 | 典型例子 |
---|---|---|
行为级仿真语句 | ❌ 不可综合 | $display , # , $stop , initial a=1 |
初始化内存 | 有条件 ✅ | $readmemh (ROM 初始化时) |
可综合语句 | ✅ | always @(posedge clk) , assign , case , if , FSM |