阅读(1564) (1)

Verilog 可综合性设计

2022-05-20 14:27:08 更新

Verilog 主要用于数字电路设计的描述,但不是所有的描述方式都可以被综合成实际的硬件电路。例如一些用于仿真验证的关键字,属于仿真验证语言,只能在仿真时使用,不能被综合成电路,如系统任务 $dsiplay, initial 语句等。所以使用 Verilog 设计数字电路时,一定要注意电路的可综合性。testbench 可以随心所欲,只要能构造出需要的仿真激励条件即可。

可综合与不可综合结构

所有综合工具都支持的结构

结构类型 关键字 描述
端口信号 inout,input,output 端口信号只有 3 种
参数 parameter, localparam ---
信号变量 wire, reg, tri, integer ---
模块 module ---
门级原语 and,nand,or,nor,xor,xnor,buf,not,bufif0,bufif1,notif0,notif1,supply0,supply1 直接调用例化即可
例化 --- 支持模块例化、门级原语例化等
函数与任务 function, task 支持不含时序结构的表述
连续赋值 assign 不支持带有延迟的表述
过程赋值 always, begin, end 可设计时序逻辑或组合逻辑
条件语句 if, case, default 条件中不能包含"z"或"x"的比较
循环语句 for, while, forever while, forever 必须包含 @(posedge clk) 或 @(negedge clk), 避免组合逻辑回路
边沿触发 negedge,posedge ---
操作符 --- 支持除 "===" 与 "!==" 以外的所有操作符

所有综合工具都不支持的结构

结构类型 关键字 描述
变量类型 time 仿真时使用的时间型变量
系统任务 --- 大多数系统任务都是辅助仿真,不能综合为实际电路
例如 $display, $fopen, $finish 等。
过程结构 initial initial 常用作仿真时信号赋初值操作
或控制激励信号的时序
并行语句 fork, join 常用作仿真时并行结构的描述
always @(posedge clk) 描述的并行结构可综合
延迟语句 # 所有带延迟标志"#"的表述均不可综合
但仿真时电路中会有延时,综合时也不会报错
电平敏感触发 wait 多用于仿真中信号的检测启动
强制赋值和释放 force, release 多用于仿真中阻断其他驱动源,对信号进行强制赋值

综合工具可能支持的结构

结构类型 关键字 描述
x/z 条件语句 casex, casez 有些综合工具能识别该语句中的非"x/z"比较逻辑
不同强度的线网 wand,triand,wor,trior 当信号有多个驱动源时需要使用
但现在数字设计基本摒弃了这些变量类型
实数变量 real 往往用于仿真时的精确计算
过程终止 disable 终止过程块执行,大多数综合工具不支持该命令
循环语句 repeat, while, forever repeat 常用作仿真中语句循环执行固定次数
while, forever 循环次数为常量时也可能可综合
用户自定义原语 UDP 其实目前大多数综合工具都支持 UDP
只是某些古老的综合工具不会识别
过程连续赋值 assign, deassign 工具大多不支持该操作下 reg 数据类型的综合
支持该操作下 wire 数据类型的综合

可综合设计建议

使用 Verilog 进行数字设计时,需要遵循以下原则:可综合的结构可大胆使用,不可综合的结构仿真中使用,有些综合工具支持有些不支持的结构尽量不使用。

除非某些特殊设计,例如 clkgate, 时钟切换等电路等,否则设计中不要编写潜在的会被综合成 Latch 的逻辑。详见《Verilog 教程》章节《Verilog 避免 Latch》

变量声明时不要学 C 语言格式对寄存器变量进行赋初值操作。仿真时变量会有设置的初值,综合后寄存器初值是不确定的。如果信号初值会影响逻辑功能,则仿真过程可能会因验证不充分而错过查找出逻辑错误的机会。

所有内部寄存器都应该使用复位进行赋初值操作,以确保系统复位时各寄存器都有稳定的状态。因为没有复位端,综合后电路中寄存器的初始值不能确定,可能会导致功能错误。

组合逻辑使用阻塞赋值,时序逻辑使用非阻塞赋值。组合逻辑一般使用连续赋值语句 assign 描述,always 描述的电路也能被综合成组合逻辑,例如"与逻辑"可以描述如下:

    reg     F ; //注意一定要是 reg 型变量
    always @(*) begin
        F = A & B ;
    end

always 语句中被赋值的信号一定要声明为 reg 型,在组合逻辑中该 reg 变量会被综合成线网,在时序逻辑中该 reg 变量会被综合成触发器。

同一个变量不能受多个时钟(或 always 块)控制,也不能受时钟的双边沿控制。此类描述也是不可综合的。

避免设计中出现 ​X​ 或 ​Z​ 值,因为综合工具只能识别 ​0​ 或 ​1​ 的逻辑值。