HDL/FPGA学习笔记二十一:verilog 中的可综合与不可综合

一、什么是综合?

Verilog HDL或VHDL都只是一种硬件的描述语言,并且允许在不同的抽象层次上对电路进行建模。VerilogHDL侧重于电路级,可以在门级和寄存器传输级(RTL)描述硬件,也可以在算法级对硬件加以描述。而VHDL侧重于系统级。

HDL/FPGA学习笔记二十一:verilog 中的可综合与不可综合
综合就是将Verilog描述的RTL级的电路模型构造出门级网表的过程。综合只是个中间步骤,综合后生成的网表文件,就是由导线相互连接的寄存器传输级功能块 (像是触发器、算术逻辑单元和多路选择器等)组成的。这里就需要一个叫做RTL模块构造器的程序,用来针对用户指定的目标工艺从预定义元件库中构造或获取每一个必须的RTL功能模块。
HDL/FPGA学习笔记二十一:verilog 中的可综合与不可综合
综合产生网表文件后,逻辑优化器会读入网表,并且会按照用户提供的面积(即资源要求)和定时(时序要求)约束为目标来优化网表。并且,这些面积和定时约束也能够指导模块构造器恰当地选取或生成寄存器传输级功能块。

二、什么是不可综合?

上面我们提到了HDL的描述有不同的抽象层次,从门级、RTL级、行为级以及算法级进行建模。但是,并不是所有层次上的描述方式都可以被综合成想要的硬件元件,即不可综合。比如Verilog中存在一些用于仿真验证的子集,属于仿真验证语言,只在仿真时候使用,不能被综合成电路,因为没有相应的硬件元件与其对应。如系统任务$dsiplay(),initial语句等。

三、verilog中哪些结构可以综合,而哪些不可以?

  • 所有综合工具都支持的结构: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等。

  • 所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait等。

  • 有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while等。

不能综合的语句:

1、initial:只能在test bench中使用,不能综合。

2、events:event在同步test bench时更有用,不能综合。

3、real:不支持real数据类型的综合。

4、time:不支持time数据类型的综合。

5、force 和release:不支持force和release的综合。

6、assign 和deassign:不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。

7、fork join:不可综合,可以使用非块语句达到同样的效果。

8、primitives:支持门级原语的综合,不支持非门级原语的综合。

9、table : 不支持UDP 和table的综合。

10、敏感列表里同时带有posedge和negedge:如:always @(posedge clk or negedge clk) begin...end, 这个always块不可综合。

11、同一个reg变量被多个always块驱动。

12、延时:以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。如:a=#10 b;这里的#10是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于a=b。

13、与X、Z的比较:可能会有人喜欢在条件表达式中把数据和X(或Z)进行比较,殊不知这是不可综合的,综合工具同样会忽略。所以要确保信号只有两个状态:0或1。

四、建立可综合模型的原则

(1)不使用initial。

(2)不使用#10。

(3)不使用循环次数不确定的循环语句,如forever、while等。

(4)不使用用户自定义原语(UDP元件)。

(5)尽量使用同步方式设计电路。

(6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。

(7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。

(8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。

(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。

(10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。

(11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。

(12)避免混合使用上升沿和下降沿触发的触发器。

(13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。

(14)避免在case语句的分支项中使用x值或z值。