Verilog generate块genvar位宽、隐式变量与assign语句疑问
参考问题涉及的原代码如下:
module xxx ( input wire [`NUM+7:0] dec_in, output wire [`NUM-1:0] dec ); generate genvar i; for (i=0; i < `NUM; i=i+1) begin : assign base = (dec_of_onehot >= i[`NUM-1:0]); assign bound = (dec_of_onehot <= i[`NUM-1:0]); assign onehot_of_dec[i] = (base == 1'b1) && (bound == 1'b1); end endgenerate endmodule
1. assign语句的具体作用与含义
assign是Verilog的连续赋值关键字,专门用来驱动wire类型的线网信号,赋值关系是实时并行生效的——只要等号右侧的表达式结果发生变化,左侧信号会立刻同步更新,不存在软件代码里的顺序执行逻辑。
这段generate循环里的三行assign,会在综合时被展开成NUM组并行的判断逻辑,具体含义:
- 第一行判断解码得到的数值信号
dec_of_onehot是否大于等于当前循环下标i的值,结果存到1位信号base中; - 第二行判断
dec_of_onehot是否小于等于当前循环下标i的值,结果存到1位信号bound中; - 第三行做逻辑与运算,只有当base和bound同时为1(也就是
dec_of_onehot等于i)时,把独热码输出的第i位拉高,其余位拉低,本质是实现数值到独热码的转换逻辑。
2. base、bound未显式定义却可正常工作的原因
这是Verilog标准自带的隐式线网声明规则导致的:
如果代码中没有提前定义某个标识符,且没有开启default_nettype none编译指令,直接对该标识符做连续赋值时,EDA工具会自动将其推断为1位宽的wire类型信号。
这段代码里的base、bound都是每个循环分支里的临时判断信号,工具自动完成了隐式声明,所以可以正常编译。但这种写法非常不推荐,很容易因为标识符拼写错误引入隐蔽的逻辑bug,正规项目一般都会全局加default_nettype none指令,强制所有信号必须显式定义后才能使用。
3. genvar循环变量i加位宽指定i[NUM-1:0]`的含义
genvar是generate循环专用的变量类型,循环展开时它的值是编译阶段就确定的无符号整数常数,默认位宽和仿真器/综合器的整数位宽一致(通常是32位)。
给i加位宽选择的作用,是把这个整数值显式转换为位宽等于NUM位的无符号常数,和参与比较的dec_of_onehot信号位宽对齐,避免Verilog表达式位宽匹配规则导致的隐式位宽扩展问题,减少不必要的编译警告,也能规避潜在的比较逻辑错误。
举个例子:如果宏NUM定义为8,循环到i=3时,i[7:0]就是8位常数8'b00000011,和8位宽的dec_of_onehot比较时两边位宽完全一致,不会因为i默认是32位整数导致异常。
内容的提问来源于stack exchange,提问作者donat jack

