官方论坛
官方淘宝
官方博客
微信公众号
点击联系吴工 点击联系周老师
您的当前位置:主页-old > 教程中心 > 问题解答 >

VERILOG语法问题【汇总贴】

发布时间:2023-08-11   作者:admin 浏览量:
Verilog知识点参考:书籍《FPGA至简设计原理与应用》第一篇FPGA基础知识第三章硬件描述语言Verilog

如果同学们的问题我们帖子里面没有的请第一时间联系我微信同步:18022857217吴老师,我们对新问题进行补充!


通过平时同学们反馈学习中经常用到的学习点,因此明德扬最近做了抖音系列短视频,都是一些FPGA学习技巧分享,大家感兴趣可以关注明德扬抖音号:87481069842。
内容不断更新!记得关注点赞学习不迷路!





【问题0】:关于阻塞赋值“=”和非阻塞赋值“<=”的讨论。

:其实使用“=”还是“<=”的规则非常简单,就是:组合逻辑用“=”,时序逻辑使用“<=”。其他使用方法,都不符合硬件特性的。

记住上面规则,完全够用了,如果还想深究,可以看这个帖子http://old.mdy-edu.com/zhijian/2021/0409/1255.html



【问题1】:关于 data[31 -cnt0*8 -:8]的含义。

答:简而言之,data[a -:b],是指最高位是a,并且往下数b个(包括a本身),等价于data[a : (a-b+1)]。

例1:data[15 -:8],就是最高位是15,往下数8个(包括15本身),即data[15 :8]。

例2:data[31-cnt0*8 -:8],是MDY很常用的选择语句,其中cnt0是计数器。当cnt0==0时,上式等于data[31 -:8] = data[31:24]。当cnt0==1时,上式等于data[23 -:8]=data[23 :16],依此类推。

更详细资料,请看MDY常用的数据选择语句  http://old.mdy-edu.com/wentijieda/20210409/1256.html



【问题1.1】请问:assign  a_data_ff[15-8*cnt -:8] = data_a[7:0] ;  不知道为什么会产生 连续赋值 出错问题呢 ? 

答:assign  a_data_ff[15-8*cnt -:8] = data_a[7:0]。 这种使用方法,放在组合逻辑是不合适的,这里隐含了锁存器。
可以仔细阅读这句代码,当cnt==0时,其代码是:assign a_data_ff[15:8] = data_a[7:0],问题是,此时a_data_ff[7:0]怎么办?这代码没有说明,这通常会认为是保持不变。
组合逻辑里保持不变,就是锁存器的意思,这是不需要的。





【问题2】:关于数组的含义,即reg[7:0]  data[3:0]的含义。
答:这个是verilog是数组的定义。按MDY的规则,其可以理解为:信号类型为reg[7:0]的类型,即8位reg型号线;后面的[3:0]是表示一共有4组。

然后data[0]是表示第0组reg[7:0] data的信号。

Verilog中数组的表示 http://old.mdy-edu.com/wentijieda/20210409/1257.html




【问题3】:VERILOG中正负数、小数的表示方法。
答:首先要明确,FPGA操作基本单位是“线”,这个线只有0或者1两种值,即可以认为FPGA操作基本单位是二进制值。其他如十进制数、十六进制表,均是设计师对二进制数的解释。

例如4'b1001,这是二进制值,在硬件表示有四根线,分别处于“高低低高”状态。

那么这四根线的“高低低高”是什么含义?设计师可以定义说,第一个高表示符号位,其他三个是数据值。设计师也可以说,前两根线表示整数,后两根线表示小数。

所以verilog的正负数、小数的表示方法,是没有约定的,是取决于工程师设计的。

关于更多的内容,可以参考下面贴子:FPGA中正负数和定点小数的表示方法  http://old.mdy-edu.com/zuixinyuanchuang/2019/1213/642.html



【问题4】:在设计文件中,如何确定信号是什么类型的?

答:在本模块中,用always设计的信号用reg型;在测试文件中,initial内部赋值的,用reg型;其他如例化信号、assign赋值的信号,都是用wire型。

注意,定义成reg型还是wire型,是没有物理意义,不要去强行解释为什么。

【技巧分享】在设计文件中,如何确定信号是reg型还是wire型?http://old.mdy-edu.com/wentijieda/20210408/1196.html

另外,对于没有定义的信号,默认为1比特wire型。


问题5】:我设计了一个模块,并且模块命名为latch,为什么软件会提示错误  

答:latch是VERILOG关键词,不能用于自己设计的模块命名或者信号名。所以要注意关键词。


【问题6:ALWAYS不写ESLE表示保持原来的值】:下面是一个ALWAYS语句,当rst_n==1、a==1时,led的值是多少?


答:当rst_n==1,a==1时,上图中第3、第6和第9行都不满足条件,因此第4、7、10行的赋值语句都不会执行。也就是说led值没有改变。所以,时钟上升沿之后,led还会保持原来的值。如果原来的led等于0,之后也是0;原来等于1,之后也是等于1.



【问题7】左移和右移,空出的位置是补0吗?

答:是的。左移就是低位补0,右移就是高位补0。



【问题8】为啥begin后面加这个冒号,以前没见到过。


答:begin后面加冒号,相当于这个begin end块起一个名字。起名字是做区分用,一般情况下,不对begin/end命名,所以这种写法很少见。



【问题9】在verilog中到底应不应该用for循环?

答:在硬件描述语言中for语句的使用较C语言等软件描述语言有较大的区别。在Verilog中除了在Testbench中使用for语句外,在RTL级编码中是却很少使用for循环语句。

另外,MDY不建议“硬件不熟练”的人使用for循环进行逻辑开发。因为FPGA设计,本身是硬件设计,即使用了for,也要清楚地知道会综合成什么样电路,有多少寄存器和加法器等,这是逻辑设计的最基本要求。

很多人为了求“脑力”的省事、不加理解就用for,会很容易写成不可综合的C语言代码,这本身就是不正确的。

还要明确一点QUARTUS、VIVADO甚至IC综合器,对for语法的解析流程。

首先,这些工具是先把带有for循环的verilog,转成不带for循环的verilog(注意此时还是verilog代码);然后再对转后的verilog进行综合,变成电路。

前面的for循环转换,其实就是对代码进行复制了。



【问题10】在Verilog中想要给一个信号赋值的位宽是可变的,应该怎么做?

答:可以使用下面这个赋值方法:{WID{1'b1}}举例:din <= {WID{1'b1}},当WID为8的时候,din <= 8'b1111_1111,通过修改WID的值,可使赋值的位宽发生变化。


【问题11】data[b+7:b]<=rx[a+7:a]

老师我想用for循环动态给data的区间赋值,但是报错说b不是常量怎么办?
答:verilog中不支持位宽选择时 上边界和下边界均为变量。另外:不要用软件的思维来做FPGA设计


【问题12】提示endmodule语法错误?这个能有什么错误呢?如下图:


答:像这种提示哪几种错误的,就打开代码,找到这一行,前前后后,检查代码有哪些与“平常”不一样的地方。如果 清楚,可以打开一个已经OK的代码,来代码下。



【问题13】请问以下变量后加个"-"意思是取这个变量的某几位吗?


答:上面的按减号带入结果就可以了,例如 data[7-1],就是data[6]。 data[7-1:0],就是data[6:0]。



【问题14
】问能不能在适中的下降沿采集数据呢,比如写成always@(negedge clk)

答:整体系统中,建议都使用时钟上升沿,不要使用下降沿,否则不符合设计规范,造成系统的不稳定。 FPGA系统会对全部路径进行路径分析,会计算两个D触发器之间的延时,确保这个时钟上升沿发出的数据,在下一个时钟上升沿能采到。
假如上升沿发数据,下降沿来采集(或者下降沿发数据,上升沿采集),相当于时钟周期减半了,时序要求更高了。



【问题15】
二进制000-二进制001=111  这个最高位怎么算的?

答:参考十进制加减的运算方法,如下图所示得到的。

所不同的是:二进制是 0-0=0,0-1=1,1-0=1,1-1=0。
如果保存结果的位宽只保留最低位的话,那就是111。
更多更详细的资料,请看《FPGA至简设计原理与应用》:http://old.mdy-edu.com/wentijieda/20210414/1331.html?1618393457,请看第一篇,第三章5.3 算术运算符的内容。



【问题16】
rst_n==1'b0 和!rst_n不同的问题。

 
LED灯设计为什么LED和计数器复位条件不一样?
答:这两个结果是一样的,都是当rst_n为1时复位。只是写法不同。



【问题17】请问各位老师同学 如何用modelsim获取一段代码的运行时间? 谢谢

答:verilog是硬件描述语言,不是软件。一般情况下,硬件的运行速度仅取决于系统时钟频率。但随着时钟频率的提高,关键路径成为制约硬件速度的瓶颈。至于最高速度,要基于具体的工艺库,并用DC、PT等专业软件做静态时序分析才能得出来。



【问题18】a[0:0]表示什么意思呢?

答:就是a[0]的意思


【问题19】data[0] <= data_b [0][2]表示什么意思?

答:将data_b看作一个矩阵,表示调用矩阵的第0行第2个数据。


【问题20:一个always里有多少信号时的理解问题】如下图所示,第9行代码里的key_reg值,是等于第8行的key的值还是key_reg的值。是先执行第8行,再执行第9行代码吗?


答:当一个always里设计了多个信号时,如上图中设计了key_reg和delay_cnt的值,其实质可拆分成如下代码。

答:当一个always里设计了多个信号时,如上图中设计了key_reg和delay_cnt的值,其实质可拆分成如下代码。

而众所周知,verilog代码中每个always都是独立并且同时执行的。

因此上图中第23行的代码和第32行的判断是同时进行的。假设当前key_reg等于0。在时钟上升沿前key等于1。那么第23行执行后,key_reg值更新为1。

同时第32行判断时key_reg值仍然为0,不是最新的值为1。

在此,MDY强烈建议,一个ALWAYS设计一个信号,有助于做逻辑设计,理清思路,避免很多理解上的问题。
而且事实上,一个always设计多个信号更像写“软件”的代码,是用软件思维在设计FPGA,而在FPAG中是不规范的。



【问题21】 always 语句中,不论是赋值 还是 比较,都是针对 时钟上升沿到来前的  前面一点点时刻的 寄存器中的数据 来赋值 和 比较的

答:是的。具体请看下面的波形图规则 :http://old.mdy-edu.com/plus/view.php?aid=1333




问题22】问一下关于敏感信号的事情,任何信号都可以被当作敏感信号吗?也就是always模块里面:always @(posedge din_vld or negedge rst_n)begin这样写可以吗?

答:语法上是可以的,但不符合FPGA和ASIC的设计规范。一般这个是写时钟和复位信号。不规范的话,会造成系统的不稳定



【问题23
】复位信号必须要放到敏感信号列表吗?

答:异步复位需要将复位信号加到敏感列表,同步信号不需要




【问题24】多个模块的输出信号,可以连到一起,共同驱动另一个模块吗?

答:遇到此问题,可以稍微推理一下就能清楚了。例如模块A有一个输出信号a,模块B有一个输出信号b,然后这两个信号连在一起(怎么做的不清楚,先假充有这种情况),

  共同均有一个模块C的输入信号c。那么存在这种情况,模块A要输出1,模块B要输出0给模块C,那么模块C收到的是0还是1呢?这种情况下,模块C就不清楚收到什么了。

  所以本题答案:两个模块的输出信号不能连在一起。




【问题25】组合逻辑电路可以有反馈吗?

答:组合逻辑不可以有反馈的。组合逻辑根据当前输入得到输出,而这个输出信号不能与输入相连,如果相连了,那么输出的值就不确定了。



【问题26】写的代码太复杂/未遇到的语法,不理解/,代码不知道哪里错了/等问题

答:FPGA的代码格式都是非常简单的,不推荐也不建议使用复杂的语法。如果使用了使用语法,又出错时,有如下建议
1. 将复杂代码,使用简单代码代替。
2. 或者,将代码分解,每添加一行看不行结果,以方便定位哪里有问题。



【问题27】什么时候使用组合逻辑,什么时候使用时序逻辑?

答:请看此篇文章,有详细解释:http://old.mdy-edu.com/wentijieda/20210410/1322.html



【问题28】VERILOG语法中,signed类型的作用。

答:

1.在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用$signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?

其实不是的,因为有符号数和无符号数据的加法强结果和乘法器结构是一样的,signed的真正作用是决定如何对操作数扩位的问题。

2.verilog中的加法和乘法操作前,会先对操作数据扩位成结果相同的位宽,然后进行加法或者乘法处理。比如a/b都为4位数据,c为5位数据,c = a + b,这个运算的时候会先把a和b扩位成5位,然后按照无符号加法进行相加。a/b没有被signed修饰的时候会按照无符号数的扩位方式进行扩位,即高位补0,加法的结果当然也是a、b为无符号数相加的结果。
3.如果想把a、b作为有符号数来相加,那么就得在a/b数据定义的时候用signed修改,或者在计算的时候用$signed()来修饰,这样在c = a + b,这个运算开始的扩位就会按照有符号数的方式进行扩位,在高位补符号位,加法得出的结果就是a、b视为有符号数的结果。当然c要视为有符号数据。https://www.cnblogs.com/yuandonghua/p/signed.html



【问题29】VERILOG中定义的类型,是怎么分辨是有符号数、无符号数、或者16进制数的。

答:要真正理解一点,FPGA的信号,其本质上是二进制数。例如4'b1010。至于这个二进制数,是有符号数,还是无符号数,都是取决于工程师的解释。例如4'b1010,可以理解为无符号数10,也可以理解为有符号数原码-2,也可以理解为有符号数补码-6。更多解释,请看《FPGA至简原理与应用》一书中关于verilog和补码由来这一部分:http://old.mdy-edu.com/zhijian/2021/0409/1239.html




【问题30】在FPGA计算中,对于a+b等,对a和b是根据无符号数,还是有符号数来计算的?

答:再次强调,真正理解:FPGA信号本质是二进制数。  无论a和b是什么类型的信号,最终都是换算成二进制来计算,自然的遵守二进制计算基本法则,

具体请看:http://old.mdy-edu.com/zhijian/2021/0409/1237.html



【问题31】请问generate的使用方法
答:可以参考如下文章: 【教程】generate语法_FPGA-明德扬/专业FPGA解决方案专家 (mdy-edu.com)




【问题32】请问信号定义时,输出类型的定义和信号类型的定义可以放到一起写吗?

答:可以的,举例:  output   reg    [7:0] dout;



【问题33】len <= {len[7:0],din},len信号的位宽为16bit,din的位宽为8bit,这段代码的意思是什么?

答:举例说明,假设din需要传输的数据为8’h55和8‘hd5,len初始为16’h0,则第一次进行赋值时,len[7:0]为8‘h0,din为8’h55,拼接之后赋值给len,此时len=16‘h0055;
第二次进行赋值时,len[7:0]为8’h55,din为8‘hd5,拼接之后赋值给len。此时len=16’h55d5。



【问题34】红色箭头指的那些语句是什么意思?

 
答:这是宏定义的的一种用法。此时表示该.v文件使用的是从“ 'ifndef SIMPLE”到“ 'endif”以外代码,如果把“' define SIMPLE”注释掉的话,使用的就是从“ 'ifndef SIMPLE”到“ 'endif”以内的代码。



【问题35】好多个模块是只编译顶层模块就可以了吗?

答:无论是仿真还是综合,其综合都是从顶层模块开始的。通过调用顶层模块,然后根据顶层模块的例化代码,就能找到下一层模块,逐级找下去,就能找到所有使用到的模块了



【问题36】
fpga乘法可以直接用*吗?

答:可以的.加法器 、减法器和乘法器是可以直接使用的,除法器由于占用资源比较大,不建议直接使用



【问题37】问:例化的时候,如果对接口留空是什么结果

答:例化的时候,如果是模块的输入信号,留空的话表示输入0。如果是输出信号,留空的话,没有影响。



【问题38】这个4bit MCU_FSMC_data[0], 拼接有简单的写法吗?
答:data_4 <= {4{MCU_FSMC_data[0]}};




【问题39】这是明德杨语法课的一段代码,左边的写法为什么是错误的呀?


答:那是软件思维,软件思维就是先执行第1行,再执行第2行;右边是硬件思维,在描述b信号的功能。



【问题40】ALWAYS里的 if  else是否有优化级?是按顺序判断的吗?
答:是否理解“else”的意思?中文含义是叫“否则”,否则是指一个条件的否则。也就是说前面条件不满足,然后再看此条件。

所以不用纠结于“顺序执行”、“优先级”概念,就按字面上的意思来理解就对了



【问题41】代码中,“if(0)”是什么含义?如下图。


答:verilog里面,if是条件判断语句,如果括号里为真,则执行,则假则不执行。if(0),括号里条件是假,所以不执行。
  因此上面代码中,条件写成if(0)就是表示永远不执行的意思。
  有人好奇为什么这么写?这不是毫无意义吗?嗯,具体原因可以问作者,可能是前期代码要用到,后期发现不用了,又懒得改太多,就写成0吧。



【问题42】FULL和是A_WIDTH都是parameter,FULL[A_WIDTH]是什么表达方式呢?
答: []在VERILOG里用于表示第几比特,例如a[0]表示a的比特0位,a[1]表示a的比特1位。程序里(包括verilog或者c语言)不管定义成什么类型,其最本质的就是二进制数。
使用parameter定义了FULL和A_WIDTH,其也是二进制数,所以FULL[A_WIDTH],自然就是FULL的比特A_WIDTH位。



【问题43】always那个括号里面的*号代表什么意思?

答:加“*”是组合逻辑的写法。当敏感信号非常多时很容易就会把敏感信号遗漏,为避免这种情况可以用“*”来代替。

这个“*”是指“程序语句”中所有的条件信号,即 a,b,d,sel (不包括c),也推荐这种写法。



【问题44】Verilog报错原因及解决方案
答:仿真注意点
1.interger赋值必须在always块之外
2.对变量赋值必须在always,initial之中。






问题45】Error (10663): Verilog HDL Port Connection error at wave.v(31): output or inout port "dataouthc" must be connected to 

a structural net expression模块例化时数据类型的错误。
答:
1.输入端口:从模块内部来讲,输入端口必须为线网型(不进行类型声明则默认为wire);从模块外部来看,输入端口可以连接到线网或reg型的变量。
2.输出端口:从模块内部来讲,输出端口可以是线网或reg型;从模块外部来看,输出端口必须连接到线网型的变量。为什么要这样定义,则需要理解fpga的硬件结构。






【问题46】请问阻塞和非阻塞赋值之间有什么区别?
答:个人觉得阻塞非阻塞是仿真电路下的描述,实际电路中是没有这个描述的。
实际的电路中只有组合逻辑和时序逻辑,不可能存在谁阻塞了谁。只是仿真中需要特别注意。按照书上的描述:阻塞相当于软件中的顺序执行,非阻塞相当于并发执行。
类比为阻塞就是一个人干活,如果一条语句为一个活,那么先干前面的活再干后面的活。非阻塞就是多个人一起干活,每一条语句都是一个人在干活,则为并发。





【问题47】Verilog中的task和function之间有什么区别?
答:Verilog中的task和function都可以实现常用功能,有助于代码的清晰和可维护,避免在不同位置复制大量代码。 
本质上,task和function都提供了在模块中不同位置重用相同代码段的“子程序”机制。但是,task和function在以下方面有所不同:






【问题48】
always_ff、always_comb、always_latch的用途是什么?
答:1.always_ff:专门用于建模触发器;


2.always_comb:专门用于建模组合逻辑;


 3.always_latch:专门用于建模锁存器;






问题49出现Error (10200): Verilog HDL Conditional Statement error at key_led.v(13): cannot match operand(s) 

  in the condition to the corresponding edges in the enclosing event control of the always construct怎么办?

答:问题出现在把复位信号设置成上升触发,而后又判断是否为低电平。将其改成:




问题50改动方式是加else语句 但是无任何操作这样就可以了,如图:

这个问题可以参考答疑帖:http://old.mdy-edu.com/wentijieda/20210410/1264.html



问题51】解决了语法错误后,为什么提示的错误数量更多了?
答:1. QUARTUS/VUVADI/MODELSIM报语法错误时,会提示哪一行出错。请注意,不仅要看这一行,也有可能是前面错误引起的。
2. 在修改语法错误的时候,一个错误解决了,必不一定意味提示的错误数量的减少,也有可能变多。因为之前的错误,掩盖了其他错误。



问题52
潘老师讲课不是说时序逻辑里面的变量才定义成reg型吗 为什么听 一位led灯案例 的时候变成了 只要always里面的变量就定义成reg型?
答:
只要always语句变量都定义成reg型。assign语句中变量都定义成wire型

【问题53】怎么理解位宽就是[?:0]的?
解答:假如有信号定义为  reg  [3:0]   data;那么信号data的位宽为4bits,能表示0~15一共16个数。如果信号data是一个状态信号,那么它就可以表示16种状态。




【问题54】问:上升沿检测,为什么不能直接使用posdedge来检测?
答:数字电路中,所有电路都是在时钟的节拍下进行工作。时钟是稳定并且有节奏的。对应的是代码ALWAYS中,
敏感列表里posedge中一般就连接clk,而不能连其他。如果连了其他,就不是稳定的数字系统



 德扬除了培训学习还有项目承接业务,擅长的项目
主要包括的方向有以下几个方面:


1. MIPI视频拼接

2. SLVS-EC转MIPI
接口(IMX472 IMX492)


3. PCIE采集系统


4. 图像项目


5. 高速多通道ADDA系统


6. 基于FPGA板卡研发


7. 前端模拟采集、射频、电荷灵敏前置放大器


需要了解相关信息可以联系:吴老师18022857217(微信同号)





   拓展阅读