商震 发表于 2021-8-6 18:01:33

verilog语法中信号位宽常见问题解析

很多同学在Verilog中定义多位宽变量时,会有许多疑问,现在把一些常见疑问进行罗列解答:1、位宽不能为变量,在程序生成代码时,位宽需为定值。例如:我们有如下错误位宽定义:


如上图,图中的变量cnt2的位宽cnt,被定义为了变量,并且在always语句中进行了赋值操作,进行编译时,编译器对cnt2的定义行(23)报错。
那是不是说明位宽定义必须为纯数字呢?事实上不是,实际运用过程中,位宽被定义为参数的情况,还是比较常见的。


例如在OV5640摄像头的rgb初始化table中,对输出的寄存器初始化参数,将位宽定义为参数形式,能更好的保持程序的扩展应用性。

2、位宽的选择,要以够用为标准,过多的位宽会占用过多的FPGA逻辑资源。例如:在led闪烁实验中,我们将计数器cnt的值位宽从修改为





可以看到,在资源使用统计报告中,消耗的逻辑资源和寄存器数量,均随位宽的使用增加。

3、仿真中,如果定义的位宽大于源文件中的位宽,则仿真输出的数据会变成蓝色波形,多出的位为高阻态。





如上图,当仿真的位宽大于源程序位宽时,整个输出的数据会呈现特别颜色(默认为蓝色)。多出的位宽,会以Z的形式显示。可以通过这种方法,确定是否位宽定义过大。

4、在多层级的复杂工程中,如果数据通过模块传递时,中途有某一层级位宽忘记定义,则在这一级以后驱动的数据,位宽均默认为1位有效,并且编译器不会报错。例如,我们制造一个经过四级传递的计数器控制led闪烁实验来说明问题。经过了四级传递。正常情况下,计数器的值能够从底层正常传递到顶层,并传递给仿真或外设(此处以led为例)。





但是,在中途传递过程中,有一级cnt的位宽忘记写了,如果没有仿真,则看起来一切正常,并且编译能够通过了,但是上板子就是不能正常运行。通过仿真,能够找到问题的根源在于位宽不正常,从底层到顶层传递过程中,位宽在中途其中一层,定义不正常。情况如下:




从宏观来看,位宽异常导致led闪烁的功能没有实现。仿真图如下:



这一方面说明了位宽定义的重要性,二方面说明了仿真的重要性。所以,对于传递信号,特别是地址、数据信号,一定要记得对对位宽进行定义。

5、在有符号数的表示过程中,最高位为符号位,如果进行有符号位运算,则应当在确定好的位宽后,再加1,保证符号位的正确表达。例如:我们做一个简单的减法运算如下:






从上述案例中可以看到,如果对输出结果的位宽定义不足,没有考虑到符号位的存在,则不但无法获取正确结果,甚至连得到结果的绝对值都是错误的。如c和d,虽然表示的四位位宽能装下数字11,但是如果作为有符号数运算没有考虑多放符号位位宽,则结果错误。所以遇到这种情况,应该如e和f一样,至少多放一个位宽,以保证符号位的充分表达。






admin 发表于 2021-8-7 11:56:18

标题改为:verilog语法中信号位宽常见问题解析,是否更加准确精炼和直击目标。

很多同学在使用verilog进行变量定义时(描述是否恰当?改为在Verilog中定义多位宽变量时,是否更为合理),会有许多疑问,现在把一些常见疑问进行罗列解答:
1、位宽不能为变量,在程序生成代码时,位宽为定值。(什么意思?没看懂,请补充说明)
2、位宽的选择,要以够用为标准,过多的位宽会占用过多的FPGA逻辑资源。(请举例说明)
3、仿真中,如果定义的位宽大于源文件中的位宽,则仿真输出的数据会变成蓝色波形,多出的位为高阻态。(请举例说明)
4、在多层级的复杂工程中,如果数据通过模块传递时,中途有某一层级位宽忘记定义,则在这一级以后驱动的数据,位宽均默认为1位,并且编译器不会报错。(如何去查看,这个问题是有警告的,通过rtl视图也可以查看)
5、在有符号数的表示过程中,最高位为符号位,如果进行有符号位运算,则应当在确定好的位宽后,再加1,保证符号位的正确表达。(此项是否确定,有没有案例证明)

admin 发表于 2021-8-9 20:27:15

帖子开头一句话,我给了修改建议,暂未发现修改。

第二点,确定是呈线性增加,不是指数?你只列举了2种情况,相当于坐标系中2个点,你拟合得到的函数是根本不可靠的。

第三点,这建议用原色图,否则无法看到你说的蓝色现象等。

第4点,使用的例子不恰当,不了解这个工程,不完全对着这个工程源码看很难和你的文字描述对应上,建议重写一个非常简单的代码案例来做演示,并想办法在信号名命名时候就能体现其所在的层级。


第5点,使用例子不恰当,c和d都只有1位,1位数据谈正负,太没意义了,建议用8位或以上的数据做例子。


另外,请将使用参数形式定义位宽的方法写在帖子里,不明白的可以先学习max发在群里的那个链接。

盛志超 发表于 2021-8-26 12:16:46

位宽为变量的表示形式:Abase_addr为起始地址,+/-表示方向,Width为位宽,例 i=1,A就是A,A就是A

商震 发表于 2021-8-26 15:34:20

盛志超 发表于 2021-8-26 12:16
位宽为变量的表示形式:Abase_addr为起始地址,+/-表示方向,Width为位宽,例 i=1,A就是A, ...

您说的这种情况,是位宽为固定参数的情况吧?这种情况编译器可以接受。但是编译器无法接受一种位宽为赋值寄存器的形式。在程序的不同阶段(典型如状态机的不同状态)下,如果位宽被赋予了不同的值,这种情况,是不能被编译器编译的。:handshake
页: [1]
查看完整版本: verilog语法中信号位宽常见问题解析