Verilog可综合语法
目录
EDA综合工具都支持的语法有
可综合原则
组合逻辑可综合描述
时序逻辑可综合描述
Verilog HDL具有完整的语法,用于数字系统的仿真与综合。但需要注意的是,IEEE Std 1364-1995/2001标准中定义的语法都可以用于仿真分析,只有一小部分可以综合为硬件电路。
Verilog HDL可综合的语法由IEEE Std 1364-2002(简称Verilog-2002)标准定义。Verilog-2002定义了Verilog-2001标准中哪些语法可综合,哪些语法不可以综合。另外,部分EDA综合工具可以综合Verilog-2002标准中未定义的可综合语法,但综合效果不佳,应谨慎使用。
EDA综合工具都支持的语法有
☆ 模块声明: module…endmodule。
☆ 端口声明:input,output,inout。其中inout比较特殊,应用时应特别注意。
☆ 线网类型:wire,tri。其中tri不常用。
☆ 变量类型:reg和integer。其中integer用于for语句中,其它情况不用。
☆ 参数定义:parameter和localparam。
☆ 运算符和操作符:支持大部分运算符和操作符,但不包括case等式运算符。☆ 条件语句:if,if ...else...和if ...else if...。
☆ 分支语句:case...endcase和default。
☆ 连续赋值语句:assign
☆ always语句:支持电平敏感事件和边沿触发(posedge/negedge)事件。
☆ 语句块:支持顺序语句块begin……end。
☆ 基元:and,or,not,nand,nor,xor,xnor,bufif0/1,notif0/1, supply0/1。
☆ 函数定义:function……endfuction。
☆ 循环语句:for语句应用很少,但在一些特定的设计中有事半功倍的效果。
☆ 过程赋值语句:阻塞赋值(= )和非阻塞赋值 (<=)两种方式。
☆ 生成语句:generate for、generate if和generate case。
部分综合工具支持的语法有:real,casex,casez,wand,triand,wor,trior,task...endtask,repeat,while。 所有综合工具都不支持的语法有:time,defparam,$finish,fork,join,initial,UDP和延迟量定义。
可综合原则
为了确保编写Verilog HDL代码能够综合出硬件电路,应注意以下可综合原则:
(1)不使用initial语句。因为过程语句initial只能用于仿真,是不可综合的。
(2)不使用延时量定义。因为延迟量只能用于仿真,综合时将被忽略。
(3)不使用循环次数不确定的循环语句,如while和forever。因为循环次数不确定,综合工具难以综合为硬件电路。
(4)内部模块不能设计为三态接口(tri),描述时也不能包含x和z。因为FPGA内部的LUT无法实现x和z。
(5)只使用wire和reg,不使用real,尽量避免使用integer类型(循环变量除外)。
(6)用always语句描述组合逻辑电路时,应牢记将所有参与赋值的量都列在事件列表中,否则会综合出时序电路。
(8)描述时序逻辑电路时,推荐应用同步时序逻辑,尽量避免使用异步逻辑。
(9)不使用纯异步复位信号。建议使用异步复位同步释放信号作为系统复位信号,以确保系统内部寄存器复位后,释放时避免时序违例。
(10)对于过程赋值语句,建议描述组合逻辑电路时使用阻塞赋值,描述时序逻辑电路时使用非阻塞赋值。
(11)在同一个过程语句中,不能同时使用阻塞赋值和非阻塞赋值。
(12)对于同一个赋值对象,不能既使用阻塞式赋值,又使用非阻塞式赋值。
(13)推荐一个过程语句只处理一个信号,一个信号只能在一个过程语句中产生。因为在多个过程语句同时对一个信号赋值时,会产生多重赋值问题,综合时会产生错误。但是,如果一组信号为平行关系,则可以在一个过程语句中同时进行处理。
(14)描述组合逻辑电路时,必须防止意外综合出锁存器。为此,在if语句的所有条件或者case语句的所有分支中对变量都有明确的赋值。
(15)避免一个过程语句中混合使用同一时钟的上升沿和下降沿。例如: always @( posedge clk or negedge clk ) 语句块;
组合逻辑可综合描述
组合逻辑电路即可以应用连续赋值语句进行描述,也可以应用always过程语句进行描述,还可以应用基元进行结构进行描述。 应用连续赋值语句描述组合逻辑电路时,被赋值对象必须定义为线网类型,既可以通过函数表达式对线网进行赋值,也可以通过操作符/运算符对线网进行赋值。
应用操作符描述4选一数据选择器:
input d0,d1,d2,d3;
input [1:0] a;
output wire y;
assign y = a[1] ? (a[0] ? d3 : d2 ): (a[0] ? d1: d0);
应用数据流方式描述4选一数据选择器:
input d0,d1,d2,d3;
input [1:0] a;
output wire y;
wire atmp,btmp,ctmp,dtmp;
assign atmp = d0 && !a[1] && !a[0];
assign btmp = d1 && !a[1] && a[0];
assign ctmp = d2 && a[1] && !a[0];
assign dtmp = d3 && a[1] && a[0];
assign y = atmp || btmp || ctmp || dtmp;
用行为方式描述4选一数据选择器:
input d0,d1,d2,d3;
input [1:0] a;
output reg y;
always @(d0 or d1 or d2 or d3 or a)begincase (a) // 分支语句2'b00: y = d0;2'b01: y = d1;2'b10: y = d2;2'b11: y = d3;default: y = d0;endcaseend
用结构方式描述4选一数据选择器:
input d0,d1,d2,d3;
input [1:0] a;
output wire y;
wire a0n,a1n;
wire atmp,btmp,ctmp,dtmp;
not (a0n,a[0]); not (a1n,a[1]);
and (atmp,d0,a1n,a0n); // 调用基元and,实现atmp=D0A1'A0'
and (btmp,d1,a1n, a[0]); // 调用基元and,实现btmp=D1A1'A0
and (ctmp,d2, a[1],a0n); // 调用基元and,实现ctmp=D2A1A0'
and (dtmp,d3, a[1], a[0]); // 调用基元and,实现dtmp=D3A1A0'
// 调用基元or,实现Y=D0A1'A0'+D1A1'A0+D2A1A0'+D3A1A0
or (y,atmp,btmp,ctmp,dtmp);
一般地,数字系统的底层模块建议应用数据流或者行为方式进行描述。结构化描述方式通常应用在上层电路中,描述模块之间的连接关系。
时序逻辑可综合描述
时序逻辑电路主要应用行为描述方式,在always过程语句体内应用if语句和case语句描述模块的逻辑功能。
同步复位时序电路描述模板如下:
input clk, rst_n;
always @( posedge clk ) beginif ( rst_n == 1'b0 ) 语句/语句块;else语句/语句块;end
异步复位时序电路描述模板如下:
input clk, rst_n;
always @( posedge clk or negedge rst_n ) beginif ( rst_n == 1'b0 ) 语句/语句块;else 语句/语句块;end
应用数据流或者结构方式描述的时序逻辑电路虽然可综合,但综合出的电路结构通常不理想。因此,对于可综合时序逻辑电路设计,建议使用行为描述方式描述时序逻辑电路。