Verilog向量片选+变量隐式声明的危害

Verilog向量片选+变量隐式声明的危害

变量的隐式声明是 Verilog 中 BUG 的一大来源。

信号变量有两种声明方式:

1. 一是使用 wire 或者 assign 语句进行显示声明和定义;
2. 二是综合器的隐式声明和定义;

当你将一个未定义声明的信号连接到模块的输入输出端口时,综合器会热心地帮助你声明这个信号;
但综合器没有厉害到能通过上下文察言观色,“热心而正确”地帮你声明信号;
它只会将其声明为 1 bit wire 型信号!
当你本来需要使用一个超过 1 bit 的向量,但又忘记声明时,综合器往往就好心办坏事了。

(当然综合器会在这个生成 Warning,所以查看下 Warning 是查找 BUG 的好办法

	wire [2:0] a, c;         // Two vectors 
	assign a = 3'b101;       // a = 101 
	assign b = a;            // b =   1  隐式声明并定于了 b
	wire assign c = b;       // c = 001  <-- bug 来了 b 被 coder 默认为和 a 相同的 3'b101,
	                            但其实 b 只有 1bit宽
	my_module i1 (d,e);      // d e 都被隐式声明为 1bit wire
                             //如果模块期望的是 vector 那么 BUG 就产生了

隐式声明的错误很容易在连接 IP 核的时候产生,从 IP 核模板文件复制来 IP 核模块后。
往往会忘记声明连接 IP 模块之间的中间变量,而这些变量的隐式声明就可能被综合器“好心办了坏事”。

通过添加default_nettype none宏定义会关闭隐式声明功能,
那么这样一来,使用未声明的变量就会变成一个 Error 而不再只是 Warning

	reg [7:0] mem [255:0];   // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
	reg mem2 [28:0];         // 29 unpacked elements, each of which is a 1-bit reg.

简单得说定义在向量名之前的是向量的位宽,定义在向量名之后的维度可以理解为向量数组的长度;
同 C 语言中的数组长度概念相同,一般用来对存储器建模。

获取向量元素:片选

  1. 在 assign 赋值操作中,如果等号左右两侧信号的位宽不同,那么就会进行截断或者补零操作;
  2. 左侧信号位宽大于右侧信号位宽,右值的低位赋予左值对应的低位,左值高位的部分赋零
  3. 左侧信号位宽小于右侧信号位宽,右值的低位赋予左值对应的低位,右值高位的部分直接被截断。即保留右值的低位;
使用 [ ] 可以对信号进行片选,选择信号中特定几位比特,以下是一些片选的例子:
	w[3:0]      // Only the lower 4 bits of w
	x[1]        // The lowest bit of x
	x[1:1]      // ...also the lowest bit of x
	z[-1:-2]    // Z 最低两位
	b[3:0]      // 如果 b 在声明时 声明为 wire [0:3] b;则不能使用 b [3:0]进行选择
	b[0:3]      // b的高四位.
	assign w[3:0] = b[0:3];    // 将 b 的高位赋予 w 的低位 w[3]=b[0], w[2]=b[1], etc.

版权声明:本文为weixin_42535005原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。