Verilog可综合与不可综合语句汇总
可综合的Verilog语法子集总汇

常用的RTL语法结构如下:☆模块声明:module……endmodule☆端口声明:input,output,inout(inout的用法比较特殊,需要注意)☆信号类型:wire,reg,tri等,integer常用语for语句中(reg,wire时最常用的,一般tri和integer 不用)☆参数定义:parameter☆运算操作符:各种逻辑操作符、移位操作符、算术操作符大多时可综合的(注:===与!==是不可综合的)☆比较判断:if……else,case(casex,casez)……default endcase☆连续赋值:assign,问号表达式(?:)☆always模块:(敏感表可以为电平、沿信号posedge/negedge;通常和@连用)☆begin……end(通俗的说,它就是C语言里的“{ }”)☆任务定义:task……endtask☆循环语句:for(用的也比较少,但是在一些特定的设计中使用它会起到事半功倍的效果)☆赋值符号:= 和<= (阻塞和非阻塞赋值,在具体设计中时很有讲究的)可综合的语法时verilog可用语法里很小的一个子集,用最精简的语句描述最复杂的硬件,这也正是硬件描述语言的本质。
对于做RTL级设计来说,掌握好上面这些基本语法是很重要。
相信大家在看了这么多了verilog语法书籍以后一定有点烦了,那么现在我告诉大家一个好消息,对于一个RTL级的设计来说,掌握了上面的语法就已经足够了,无论多么牛逼的工程师,在他的代码里无非也就是上面一些语法而已。
当然了,对于一个能够进行很好的仿真验证的代码,一般还需要在RTL级的设计代码中添加一些延时之类的语句,比如大家一定知道#10的作用,就是延时10个单位时间,这个语句虽然在仿真的时候是实实在在的延时,但是这个语句在综合后是会被忽略的,也就是说在我们综合并且布局布线最后烧进FPGA里,这个#10的延时是不会在硬件上实现的。
所以说,上面给出的这些语法才是可以最后在硬件上实现的,其它的语法大多会在综合后被忽略。
可综合的verilog

Function和task有的工具支持,有的工具不支持,一般函数描述纯组合逻辑可以综合。
1. 可综合1. 所有综合工具都支持的结构[plain]view plaincopy1.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有些工具支持,有些工具不支持:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repreat,task,while 2. 建立可综合模块的原则1. 不要用initial(FPGA上电时初始状态不定,一般需要上电复位信号,在复位信号有效的时候进行初始化,上电复位信号可以由外部手动输入,也可以系统自己产生,转一篇博客,P.S.现在的综合软件功能已经足够强大,即使写了initial语句,在ISE13.3中仍然是可综合的,而且没有warning和info的提示)2. 不使用#10(在仿真中有用,实际在硬件上不会实现)3. 不使用循环次数不定的循环语句,如forever、while等4. 不使用用户自定义原语(UDP原件)5. 除非是关键路径设计,一般不采用调用门级原件描述的设计的方法,建议采用行为语句完成设计6. 尽量使用同步方式设计电路7. 用always语句描述组合逻辑时,在敏感信号列表中要列出所有输入信号8. 所有的内部寄存器都应该可以被复位,在FPGA设计时应尽量使用器件的全局复位端信号作为系统的总复位9. 时序逻辑使用非阻塞赋值,组合逻辑使用阻塞赋值,同一过程块中不要同时使用阻塞和非阻塞两种方式10. 不要在不同的always过程块中对同一变量赋值(否则综合时会提示有多驱动源错误,multiple source),对同一赋值对象,不能既使用阻塞赋值,又使用非阻塞赋值11. 如果不打算把变量综合成锁存器,在if语句或case语句的所有分支中都要对变量明确赋值(不能省去else或default,原理:在省去的情况下,变量的值会保持原来的值不变,所以系统会综合出一个锁存器)12. 避免混合使用上升沿和下降沿触发器13. 同一变量的赋值不能受多个时钟控制,也不能受两种不同时钟条件(或不同时钟沿)控制14. 避免在case语句中使用x或z值2. 不可综合1. 所有综合工具都支持的结构[plain]view plaincopy1.time,defparam,$finish,fork,join,initial,delays,UDP,wait2. 不可综合语句1. initial 只能在Testbench中使用,不能综合2. events 在Testbench中更有用,不能综合3. real 不支持real类型的综合4. time 不支持time类型的综合5. force 和release6. assign 和deassign不支持对reg类型的数据进行assign和deassign综合,支持对wire类型进行assign和deassign的综合7. fork join 不可综合,可以用非块语句达到同样的效果8. primitives 支持门级原语综合,不支持非门级原语综合9. table 不支持table和UDP的综合10. 敏感符列表中同时有posedge和negedge,如always @ ( posedgeclk ornegedgeclk ) begin ...end11. 同一个reg被多个always块驱动12. 延时,不可综合为硬件电路延时,综合工具会忽略延时,但是不会报错13. 与x、z比较,综合工具会忽略,所以要保证信号只有两个状态,0或1。
verilog语言的综合与不可综合

Verilog的综合与不可综合综合说明编的代码可以对应出具体的电路,不可综合说明没有对应的电路结构。
不可综合的代码编译通过,只能看到输出,不能实现电路,就是不能用来制作具体的芯片。
一、基本Verilog中的变量有线网类型和寄存器类型。
线网型变量综合成wire,而寄存器可能综合成WIRE,锁存器和触发器。
二:verilog语句结构到门级的映射1、连续性赋值:assign连续性赋值语句逻辑结构上就是将等式右边的驱动左边的结点。
因些连续性赋值的目标结点总是综合成由组合逻辑驱动的结点。
Assign语句中的延时综合时都将忽视。
2、过程性赋值:过程性赋值只出现在always语句中。
阻塞赋值和非阻塞赋值就该赋值本身是没有区别的,只是对后面的语句有不同的影响。
建议设计组合逻辑电路时用阻塞赋值,设计时序电路时用非阻塞赋值。
过程性赋值的赋值对象有可能综合成wire,latch,和flip-flop,取决于具体状况。
如,时钟控制下的非阻塞赋值综合成flip-flop。
过程性赋值语句中的任何延时在综合时都将忽略。
建议同一个变量单一地使用阻塞或者非阻塞赋值。
3、逻辑操作符:逻辑操作符对应于硬件中已有的逻辑门4、算术操作符:Verilog中将reg视为无符号数,而integer视为有符号数。
因此,进行有符号操作时使用integer,使用无符号操作时使用reg。
5、进位:通常会将进行运算操作的结果比原操作数扩展一位,用来存放进位或者借位。
如:Wire [3:0] A,B;Wire [4:0] C;Assign C=A+B;C的最高位用来存放进位。
6、关系运算符:关系运算符:<,>,<=,>=和算术操作符一样,可以进行有符号和无符号运算,取决于数据类型是reg,net还是integer。
7、相等运算符:==,!=注意:===和!==是不可综合的。
可以进行有符号或无符号操作,取决于数据类型8、移位运算符:左移,右移,右边操作数可以是常数或者是变量,二者综合出来的结果不同。
Verilog设计的可综合性与问题分析

Verilog设计的可综合性与问题分析前⾔⽤Verilog HDL编写的设计模块最终要⽣成实际⼯作的电路,因此,设计模块的语法和编写代码风格会对后期电路产⽣影响,所以,若要编写可实现的设计模块,就需要注意⼀些问题可综合语法可综合的设计是最终实现电路所必需的,所以弄清哪些语法是可综合的,哪些语法是不可综合的⾮常有必要,⽽且设计者也必须知道⼀个代码能否被综合成最终电路;例如:写⼀个简单的除法a/b,想妄图直接通过综合⼯具⽣成⼀个除法器是不现实的,还有有符号数和浮点数的时候也需要注意。
总之,设计者的思路定要从软件⾓度转变到硬件⾓度,很多在软件中可以直接使⽤的情况到了硬件电路就需要从很底层的⾓度来编写。
可综合的语句有:1)module 与 endmodule 模块声明的关键字2)输⼊input,输出output和双向端⼝inout的声明3)变量类型reg,wire,integer4)参数parameter和宏定义define5)所有的Verilog HDL内建门,如:add,or之类的门6)数据流语句assign语句7)⾏为级中敏感列表⽀持电平和边沿变化,类似posedge,negedge8)always,function可以被综合,task中如果不含延迟可以被综合9)顺序块begin……end可以被综合10)if和 case语句可以被综合不可被综合的语句在Verilog HDL中不可被综合的语法这⾥也简单列出来:(1)初始化initial结构不能被综合,电路中不会存在这样的单元。
电路中⼀旦通电就会⾃动获得初始值,除此之外时序电路可以⽤复位端完成初始化组合,电路不需要初始化(2)#带来的延迟不可被综合。
电路中同样也不会存在这样简单的延迟电路,所有的延迟都要通过计时电路或交互信号来完成(3)并⾏块fork…join不可被综合,并⾏块的语义在电路中不能被转化(4)⽤户⾃定义原语UP不可被综合(5)时间变量time和实数变量real不能被综合(6) wait ,event , repeat ,forever等⾏为级语法不可被综合(7)⼀部分操作符可能不会被综合,例如,除法/操作和求余数%操作补充:综合⼯具也在不断更新和加强,有些现在不能被综合的语法慢慢地会变得可以综合,像⽐较简单的initial结构在⼀些 FPGA⼯具中也可以被识别,同时能被转化为电路形式。
可综合的verilog语句

可综合的verilog语句(原创版)目录1.Verilog 语言概述2.Verilog 语句的分类3.可综合的 Verilog 语句4.应用举例正文1.Verilog 语言概述Verilog 是一种硬件描述语言,主要用于数字系统硬件的描述、模拟和验证。
它最初由 Phil Moorby 在 1983 年开发,后来由 Cadence 公司进行商业化推广。
Verilog 具有易学易用、功能强大的特点,广泛应用于集成电路设计、计算机体系结构、数字信号处理等领域。
2.Verilog 语句的分类Verilog 语句主要分为两大类:行为描述语句(Behavioral Description)和结构描述语句(Structure Description)。
行为描述语句主要用于描述数字电路的功能和行为,包括 always 语句、initial 语句等;结构描述语句主要用于描述数字电路的物理结构,包括 module 语句、wire 语句等。
3.可综合的 Verilog 语句可综合的 Verilog 语句是指在数字集成电路设计中,可以被合成器(Synthesizer)转换为实际硬件电路的 Verilog 语句。
这类语句主要包括以下几类:(1)简单的逻辑门和寄存器:如与门、或门、非门、与非门、或非门、异或门等,以及触发器、计数器、寄存器等。
(2)各种运算和操作:如算术运算(加、减、乘、除等)、关系运算(大于、小于、等于、不等于等)、位运算(按位与、按位或、按位异或、取反等)、移位运算等。
(3)控制结构:如 if-else 语句、case 语句、for 循环、while 循环等。
(4)其他:如声明、实例化、端口定义、模块调用等。
4.应用举例以下是一个可综合的 Verilog 语句示例,用于实现一个 4 位全加器的功能:```verilogmodule full_adder(input a, input b, input cin, output sum, output cout);assign sum = a ^ b ^ cin; // 异或运算实现和assign cout = (a & b) | (a & cin) | (b & cin); // 与、或运算实现进位endmodule```在这个例子中,我们声明了一个名为 full_adder 的模块,包含两个输入端口 a、b,一个输入端口 cin,以及两个输出端口 sum 和 cout。
Verilog可综合与不可综合语句汇总

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。
(2) 所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。
(3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。
建立可综合模型的原则要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:(1)不使用initial。
(2)不使用#10。
(3)不使用循环次数不确定的循环语句,如forever、while等。
(4)不使用用户自定义原语(UDP元件)。
(5)尽量使用同步方式设计电路。
(6) 除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
(7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。
(8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。
(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。
对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。
但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。
(10)不能在一个以上的always过程块中对同一个变量赋值。
Verilog语法知识点总结(转)

Verilog语法知识点总结(转)1.1 概述条⽬说明分类1>> ⾯向设计的语句; // 可综合。
2>> ⾯向测试的语句; //testbench ,不可综合。
特点设计语句 assign , always ,模块例化,都对应实际电路,并⾏执⾏。
构造1.2 模块 Module条⽬说明模块名(端⼝列表)整个电路的外特性,抽象为⿊盒⼦;端⼝⽅向input , output ; inout ;端⼝类型wire , reg ;端⼝类型是 wire 时可以省略。
例: input a ; // 端⼝⽅向为输⼊,类型默认为 wire ;1.3 数据类型1.3.1 wire/reg 线⽹wire 和 reg 都是线类型,⼯程上没区别;只是 always/initial 模块中输出定义需要为 reg 型;注意:不要将 reg 类型与 D 触发器混淆, reg 理解为因为代码所产⽣的。
例如:wire [7:0] a; // 定义了 8 位的 wire 型数据wireb; // 定义了 1 位的 wire 型数据reg [3:0]sum ; // 定义了⼀个 4 位的 reg 型数据1.3.2 常量类型格式说明parameter parameter 数据名 = 表达式parameterMSB = 7 ;// 定义参数 MSB 为常量 7 ;推荐⼤写;常量< 位宽 >< 进制 >< 数字 >⼆进制: B 或 b ;⼗进制: D 或 d ;⼋进制: O 或 o ;⼗六进制: H 或 h ;8’b1010_1100 (‘b 表⽰⼆进制 )下画线“ _”, 提⾼阅读性。
< 数字 >默认⼗进制;4 值逻辑0 : Logic Low低电平;1 : Logic High⾼电平;x : Unknow ;不确定;z : High Impedance ;⾼阻态; // 三态门1.4 运算符1.4.1 概述运算符说明算术运算符+ ( 加 ) , - (减), * (乘), / (除), % (取模);每个运算符在电路中都是个模块,如加法器,减法器;!注意:除法,除 2^n ,是移位运算,浮点运算就复杂了,因此浮点运算要专⽤除法器;关系运算符>, <, >=, <= , == (相等),! = (不相等);逻辑运算符&& (逻辑与) . || (逻辑或) , ! (逻辑⾮);条件判断语句中,为避免歧义,逻辑运算符⼆边推荐为 1bit ;位运算符& (与), | (或), ~ (⾮) , ^ (异或) ; ~^ (同或);移位运算符<< (左移), >> (右移);归约操作& , ~& , | , ~| , ^, ~^;//unary reduction ;条件运算符?:拼接运算符{}//{3{a[0]}}: 代表 3 根同样的 a[0] 线, {a[0],a[0],a[0]} 1.5 设计语句1.5.1 assign (连续赋值)实例说明assigny = ~ b ;assign out = a==1 && c==1 ;assign f =sel ? a : b ;>> 实现可以⽤布尔函数描述的组合逻辑电路;>>“=” 后⾯可以是任何布尔函数;>> 并⾏执⾏;典型错误 1 :assigna = b + a;避免出现反馈电路:变为了不可知时序逻辑电路;1.5.2 always (过程块)a、赋值赋值⽅式说明= ,阻塞赋值always @ ( a or b or C or … )begin语句块( = , if 语句, case 语句)end实现:组合逻辑电路;(注意!禁⽌⽤于时序逻辑电路)always 块内,阻塞赋值:是顺序执⾏(类似 C );敏感表: @ ( * ) //“*” ⾃动添加相关输⼊信号;敏感表: @ ( * ) //“*” ⾃动添加相关输⼊信号;避免出现 Latch (锁存器)分⽀语句( if 语句, case 语句)条件不满时,会在电路中⾃动⽣成锁存器来保存不满⾜条件的值,因此要补全 if-else ,和 case 的 defalut 语句;<= ,⾮阻塞赋值always @ ( posedge clk or negedge rst_n )begin语句块( <= , if 语句, case 语句)end实现:时序逻辑电路;(注意!禁⽌⽤于组合逻辑电路)always 块内,阻塞赋值:并⾏执⾏;b、if 语句条⽬说明格式 1if( 条件 )begin 语句 1;语句 2 ;endelse begin语句 1 ;语句 2 ;end格式 2if( 条件 )begin 语句 1;语句 2 ;endelse if begin 语句 1 ;语句 2 ;endelse begin语句 1 ;语句 2end特点分⽀语句,各个分⽀条件不同;顺序执⾏判断;注意if-else 成对使⽤;c、case 语句条⽬说明格式case( 表达式 )常量表达式 1:begin 语句;end常量表达式 2:begin 语句;end常量表达式 3:begin 语句;enddefault :语句;endcase特点分⽀语句,各个分⽀条件相同;并⾏执⾏判断;注意default 语句不可省略;d、代码 & 硬件条⽬说明映射赋值语句 -> 逻辑函数; // 加法器,减法器等;边沿型条件分⽀ -> D 触发器;条件分⽀ -> 多路选择器;⽰例1.5.3 模块例化a、作⽤系统设计时,建议遵循以下设计原则:b、常见的典型错误如下所⽰:1.5.4 全加器全加器顶层: w1 , w2 , w3 :模块之间连线;半加强: 2 种描述⽅法,如下:描述⽅式描述⽅式说明位置关联AND u1(a, b, and_out);名字关联AND u1(.a(a), .b(b), .o ( and_out ) ); // 推荐使⽤1.6 测试语句1.6.1 结构Testbench1.6.2 特殊符号语句说明`< 标识符 >表⽰:编译引导语,⽤于指导仿真编译器在编译时采取⼀些特殊处理;编译引导语句⼀直保持有效,直到被取消或重写;`timescale `timescale < 时间单位 >/< 时间精度 >例 1 :`timescale 1ns/1ns // 时间单位 1ns ;时间精度 1ns ;#2 // 延时 2 ×1=2ns ;#2.1// 延时 2.1 × 1 = 2.1ns, 精确到 1ns ,为 2ns ;例 2 :`timescale 1ns/100ps // 时间单位 1ns ;时间精度 100ps ;#2 // 延时 2 ×1= 2ns ;#2.1// 延时 2.1 × 1 = 2.1ns, 精确到 100s ,为 2.1ns ;`define`include`include “global.v”包含另⼀个⽂件,完整拷贝过来;`restall把所有设置的编译引导恢复到缺省状态;#<num>;#10; // 延迟 10 个时间单位1.6.3 语句语句说明initial 块语句:只执⾏⼀次, always 循环执⾏;不可综合;作⽤:initial产⽣激励信号;检查输出波形;赋初值;forever // 产⽣周期信号:intial beginclk = 0 ;forever#10 clk = ~clk; // 时钟信号end1.6.4 系统任务和函数条⽬说明$< 标识符 >表⽰ Verilg 的系统任务和函数$time当前的仿真时间$display 显⽰信号值变化:只执⾏⼀次,打印当前时刻;$display($time, “b% %b %b” , rst,clk,dout);$monitor 监视信号值变化:所有过程时刻;$monitor($time, “b% %b %b” , rst,clk,dout);$stop暂停仿真$finish结束仿真,释放电脑资源;1.7 代码模板1.7.1 组合逻辑电路条⽬说明assign assign add_cnt = flag==1; // ⽤于简单的组合逻辑电路;always always @(*)begin// 统⼀采⽤“ *” 为敏感列表;( =,if,case )语句; // 只能使⽤“ =” 赋值end1.7.2 时序逻辑电路a、计数器模板 13 段式模板模板 1always @( posedge cllk or negedge rst_n) begin1计数段always @( posedge cllk or negedge rst_n) begin if (!rst_n)cnt <= 0; // 初值规定为 0else if (add_cnt)begin// 【位置 1 】if(end_cnt)cnt <= 0;elsecnt <= cnt + 1;endend2加 1 条件assingadd_cnt = d==1; //d==1 :什么时候开始数脉冲3结束条件assing end_cnt = add_cnt&& cnt == X-1; // X: 数多少个脉冲b、计数器模板 23 段式模板模板 11计数段always @( posedge cllk or negedge rst_n) begin if (!rst_n)cnt <= 0; // 初值规定为 0else if (add_cnt) begin// 【位置 1 】if(end_cnt)cnt <= 0;elsecnt <= cnt + 1;endelsecnt <= 0; // 不连续,需要清 0 时,使⽤模板 2 ;end2加 1 条件assingadd_cnt = d==1; //d==1 :什么时候开始数脉冲3结束条件assing end_cnt = add_cnt&& cnt == X-1; // X: 数多少个脉冲c、 4 段式状态机模板段号代码// 初始化,次态赋值给现态,明确当前状态;1always @(posedge clk or negedge rst_n) begin if(!rst_n)state_c <= S00;// 初始状态elsestate_c <= state_n;end2always @( * ) begin // 组合逻辑,描述状态转换⽬标case(state_c)S00: beginif(s00_s20_start) // 条件名 S00->S20state_n = S20;elsestate_n = state_c; // ⽅便拷贝endS20: beginif(s20_s21_start)state_n = S21;elsestate_n = state_c;endS21: beginif(s21_s00_start)state_n = S00;elsestate_n = state_c;enddefault: beginstate_n = S00;endendcaseend3// 具体的转换条件内容assign s00_s20_start = state_c==S00&& ( 条件 ) ;assign s20_s21_start = state_c==S20&& ( 条件 ); assign s21_s20_start = state_c==S21&& ( 条件 );4根据转态设计输出:1 个 always 设计 1 个输出信号;1.7.3 Testbencha、框架条⽬内容模块名`timescale 1 ns/1 nsmodule testbench_name();信号定义reg clk ; // 时钟reg rst_n; // 复位reg[3:0] din0 ; //uut 的输⼊信号,定义为 reg 型,在 initial 中reg din1 ;wire dout0;//uut 的输出信号,定义为 wire 型wire[4:0] dout1;parameter CYCLE = 20; // 参数定义,⽅便修改;parameter RST_TIME = 3 ;待测模块例化module_name uut( // 统⼀采⽤名字关联.clk ( clk ),.rst_n ( rst_n ),.din0 ( din0 ),.din1 ( din1 ),.dout0 ( dout0 ),.dout1 ( dout1 ));激励产⽣// 复位,时钟,等显⽰输出结果$display // 类似 printf ;b、复位复位initial beginrst_n = 1;#2;rst_n = 0;#(CYCLE*RST_TIME);rst_n = 1;endc、仿真时钟仿真时钟initial beginclk = 0;forever#(CYCLE/2)clk=~clk;endd、激励信号激励信号initial begin#1;// ⽅便观测din1 = 0; // 赋初值#(10*CYCLE);// 开始赋值end以上就是总结的 Verilog 语法相关知识点,转⾃明德扬论坛。
verilog语句可综合vs不可综合

1)所有综合工具都支持的结构:always,assign,begin,end,case,wire,tri,supply0,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。
2)所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。
3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。
建立可综合模型的原则要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:1)不使用initial。
2)不使用#10。
3)不使用循环次数不确定的循环语句,如forever、while等。
4)不使用用户自定义原语(UDP元件)。
5)尽量使用同步方式设计电路。
6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。
8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。
9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。
对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。
但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。
10)不能在一个以上的always过程块中对同一个变量赋值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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。
(2)所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。
(3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。
建立可综合模型的原则要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:(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值。
不可综合verilog语句1、initial只能在test bench中使用,不能综合。
(我用ISE9.1综合时,有的简单的initial也可以综合,不知道为什么)2、eventsevent在同步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。
如:常用的RTL语法结构如下:☆模块声明:module……endmodule☆端口声明:input,output,inout(inout的用法比较特殊,需要注意)☆信号类型:wire,reg,tri等,integer常用语for语句中(reg,wire时最常用的,一般tri和integer 不用)☆参数定义:parameter☆运算操作符:各种逻辑操作符、移位操作符、算术操作符大多时可综合的(注:===与!==是不可综合的)☆比较判断:if……else,case(casex,casez)……default endcase☆连续赋值:assign,问号表达式(?:)☆always模块:(敏感表可以为电平、沿信号posedge/negedge;通常和@连用)☆begin……end(通俗的说,它就是C语言里的“{ }”)☆任务定义:task……endtask☆循环语句:for(用的也比较少,但是在一些特定的设计中使用它会起到事半功倍的效果)☆赋值符号:= 和<= (阻塞和非阻塞赋值,在具体设计中时很有讲究的)可综合的语法时verilog可用语法里很小的一个子集,用最精简的语句描述最复杂的硬件,这也正是硬件描述语言的本质。
对于做RTL级设计来说,掌握好上面这些基本语法是很重要。
相信大家在看了这么多了verilog语法书籍以后一定有点烦了,那么现在我告诉大家一个好消息,对于一个RTL级的设计来说,掌握了上面的语法就已经足够了,无论多么牛逼的工程师,在他的代码里无非也就是上面一些语法而已。
当然了,对于一个能够进行很好的仿真验证的代码,一般还需要在RTL级的设计代码中添加一些延时之类的语句,比如大家一定知道#10的作用,就是延时10个单位时间,这个语句虽然在仿真的时候是实实在在的延时,但是这个语句在综合后是会被忽略的,也就是说在我们综合并且布局布线最后烧进FPGA里,这个#10的延时是不会在硬件上实现的。
所以说,上面给出的这些语法才是可以最后在硬件上实现的,其它的语法大多会在综合后被忽略。
这么一来大家就要问了,为什么语法书里又要给出这么多的语法呢?呵呵,它们大都是为仿真验证是写testbench 准备的,先点到为止,下集继续!对于模型(module)的建立,要保证可综合性应该注意:(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值。
但是在仿真验证程序中,一般VerilogHDL语法都是容许的。
Verilog语法需要注意的一些要点1.Testbench中时钟和数据比特流的简单设计方法always clock = ~clock;always @(posedge clock)begindata_in_a = {$radom} % 2; // 产生-1到1之间随机的比特流data_in_b = 16’b1101_1011_1110_0011; // 产生固定的比特流$display(“a= %d\n”, a); // 与C语言类似end2.Verilog语法中的并行与顺序模块(1)连续赋值语句、always模块之间、实例模块之间都是并行语句(2)always模块内部是分情况而定,对于if…else…而言,总是有优先级的顺序的,对于case而言,无优先级,是完全顺序执行的,此外,还要对阻塞语句和非阻塞语句具体分析。
3.Verilog中四种最常见的变量(1)wire,即线网形变量,它不能存储值,必须受到驱动器或者连续赋值语句的驱动,如果没有驱动,那么它将会是高阻态(2)reg是数据存储单元的抽象,通过赋值语句可以改变寄存器存储的值,其作用与改变触发器存储的值相当。
寄存器变量的初时值为不确定态。
在always内部用到的变量必须是reg型的。
(3)prarmeter相当与VHDL中的constant4.注意区分集中容易混淆的运算符(1)位运算符,按位操作,~,|,&,^,其输出与输出一样位宽(2)逻辑运算符,输出0或者1,&&,||,!(3)缩减运算符,按位递归运算,&,|,!,其输出仅仅是1或者05.阻塞语句(blocking)与非阻塞赋值语句(non-blocking)(1)非连续赋值语句(non-blocking)(b <= a)在always块结束后才完成赋值操作,并且赋值后b不是立即就改变,在时序逻辑或者既有时序逻辑也有组合逻辑中一定要用这种赋值方式(2)阻塞语句(blocking)(b = a)赋值之后,b就立即改变,也就是在赋值语句完成以后,always才结束,在综合时,如果不注意,将产生意想不到的结果一个非常典型的例子:always @(clock)beginb = a;c = b;endalways @(clock)beginc = b;b = a;endalways @(clock)beginb <= a;c <= b;end6.使用if或者是case进行综合时,一定要覆盖所有可能的情况,防止锁存器的综合7.写testbench一些常见的保留字$display(“print_word_value = %d”, print_word_value); // 与C语言类似$display(“%h, %o”, 12’b1101_0100_0111); // 结果是0xD47和o6507 $monitoron; // 监控开始$mointor($time, “rxd = %b”, “txd = %b”, rxd, txd); // 打印当前时刻的监控值$monitoroff;$finish; // 仿真结束$readmemb(“数据文件名”, 存储器名); // 把数据读入到当前指定的存储器内rand_data = {random} % 60; // 产生-59到59之间的随机数8.比较下面代码,分别综合出什么,可能出现什么问题module dff_en(I_en, I_data, I_clock, O_data);input I_clock;input I_en;input I_data;output O_data;reg R_data;assign O_data = R_data;always @(I_clock)beginif (I_en == 1) R_data <= I_data;endendmodule有以下告警(用synplify综合)(1)Incomplete sensitivity list - assuming completeness(2)Referenced variable I_en is not in sensitivity list(3)Referenced variable I_data is not in sensitivity list(4)Latch generated from always block for signal如果改always @(I_clock)为always @(posedge I_clock)就可以避免,并产生一个带使能的DFF 9.下面逻辑有没有问题?module dff_en(I_reset1, I_reset2, I_data, I_clock, O_data);input I_clock;input I_reset1;input I_reset2;input I_data;output O_data;reg R_data;assign O_data = R_data;always @(negedge I_reset1 or posedge I_clock) // 敏感变量I_reset2在时钟beginif (I_reset1 == 0) R_data <= 0;else if (I_reset2 == 0) R_data <= 1;else R_data <= I_data;endendmodule综合时不会有告警,产生一个带复位和置位的DFF,最好改always @(negedge I_reset1 or posedge I_clock)为always @(negedge I_reset1 or negedge I_reset2 or posedge I_clock)10.逻辑综合结果是什么?module mux2s1(I_sel, I_a, I_b, O_c, O_d)input I_sel, I_a, I_b;output O_c, O_d;reg R_c;reg R_d;assign O_c = R_c;assign O_d = R_d;always @(I_sel, I_a, I_b)begincase (I_sel)1'b0: R_c = I_a; // 综合出latch1'b1: R_d = I_b; // latchendcaseendendmodule该逻辑将产生锁存器。