1. 可综合不可综合的定义
HDL有两种基本的用途:系统仿真和设计实现。所有的HDL都可用于仿真,但并非所有的HDL描述都可综合。例如行为级语法就是一种不可综合的代码,通常用于写仿真测试文件。
- 可综合: 所编写的代码有对应具体的电路结构。
- 不可综合: 所编写代码没有对应的具体的电路结构。
2. 可综合语句与不可综合语句
2.1 所有综合工具都支持的结构
always,assign,begin,end,case,wire,tri,aupply0,supply1,reg,integer,default,for,function,and,nand,or,nor,xor,xnor,buf,not,bufif0,bufif1,notif0,notif1,if,inout,input,instantitation,module,negedge,posedge,operators,output,parameter.
| 结构类型 |
关键字 |
描述 |
| 端口信号 |
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 |
— |
| 操作符 |
支持除===和!==以外的所有操作符 |
— |
2.2 综合工具可能支持的的结构
casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while.
| 结构类型 |
关键字 |
描述 |
| x/z |
条件语句casex, casez |
有些综合工具能识别该语句中的非”x/z”比较逻辑 |
| 不同强度的线网 |
wand,triand,wor,trior |
当信号有多个驱动源时需要使用但现在数字设计基本摒弃了这些变量类型 |
| 实数变量 |
real |
往往用于仿真时的精确计算 |
| 过程终止 |
disable |
终止过程块执行,大多数综合工具不支持该命令 |
| 循环语句 |
repeat, while, forever |
repeat常用作仿真中语句循环执行固定次数,while, forever循环次数为常量时也可能可综合 |
| 用户自定义原语 |
UDP |
其实目前大多数综合工具都支持UDP,只是某些古老的综合工具不会识别 |
| 过程连续赋值 |
assign, deassign |
工具大多不支持该操作下reg数据类型的综合,支持该操作下wire数据类型的综合。 |
2.3 所有综合工具都不支持的结构
time,defparam,$finish,fork,join,initial,delays,UDP,wait,#.
| 结构类型 |
关键字 |
描述 |
| 变量类型 |
time |
仿真时使用的时间型变量 |
| 系统任务 |
— |
大多数系统任务都是辅助仿真,不能综合为实际电路。例如 $display, $fopen, $finish 等。 |
| 过程结构 |
initial |
initial常用作仿真时信号赋初值操作或控制激励信号的时序 |
| 并行语句 |
fork, join |
常用作仿真时并行结构的描述always @(posedge clk) 描述的并行结构可综合 |
| 延迟语句 |
# |
所有带延迟标志”#”的表述均不可综合,但仿真时电路中会有延时,综合时也不会报错 |
| 电平敏感触发 |
wait |
多用于仿真中信号的检测启动 |
| 强制赋值和释放 |
force, release |
多用于仿真中阻断其他驱动源,对信号进行强制赋值 |
3. 设计可综合语句的要点
使用 Verilog 进行数字设计时,需要遵循以下原则:可综合的结构在设计实现中使用,不可综合的结构在仿真中使用,有些综合工具支持有些不支持的结构尽量不使用。
- 不使用initial初始化语句。
- 不使用带有延时(# 10)的描述。
- 不使用循环次数不确定的循环语句,forever、while和repeat。
- 尽量采用同步方式设计电路。
- 除非是关键路径设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
- 用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。
- 所有的内部寄存器都应该能够被复位,应尽量使用器件的全局复位端作为系统总的复位。
- 用户自定义原语(UDP元件)是不可综合的,它只能用来建立门级元件的仿真模型。
- 对时序逻辑描述和建模,应使用非阻塞赋值(<=) 。对组合逻辑描述和建模,用阻塞赋值(=)。但在同一个过程块中,两种赋值方式不能混用。
- 不能在一个以上的always过程块中对同一个变量赋值,并且对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。
- 组合电路如果不打算把变量推导成锁存器(latch),那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。
- 避免混合使用上升沿(posedge)和下降沿(negedge)触发的触发器。
- 同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。
- 避免在case语句的分支项中使用x值或z值。
4. 参考文献
- verilog之可综合与不可综合
- Verilog 可综合性设计
- FPGA建立可综合模型的原则