问题描述
我在将 SystemVerilog 文件转换为来自 GitHub 项目的 Verilog-2001 文件时遇到问题。似乎在 Verilog-2001 中,不可能在函数中放置一个表的展开循环:
function [31:0] gen_val;
input [31:0] old_val;
input [31:0] new_val;
input [3:0] be;
integer n;
for (n = 0 ; n < 4 ; n = n + 1)
gen_val[n*8+8:n*8] = be[n] ? new_val[n*8+8:n*8] : old_val[n*8+8:n*8];
endfunction
使用 Icarus Verilog (iverilog) 进行编译时,我收到多个错误消息:
./tb_tiny.v:39: error: A reference to a wire or reg (`n') is not allowed in a constant expression.
./tb_tiny.v:39: error: Part select expressions must be constant.
./tb_tiny.v:39: : This lsb expression violates the rule: (n)*('sd8)
./tb_tiny.v:39: error: A reference to a wire or reg (`n') is not allowed in a constant expression.
./tb_tiny.v:39: error: Part select expressions must be constant.
./tb_tiny.v:39: : This msb expression violates the rule: ((n)*('sd8))+('sd8)
.....
有人知道如何在 Verilog-2001 中解决这个问题吗?
问候
解决方法
IEEE Verilog HDL 标准 (IEEE Std 1364-2001) 条款 4.2.1 定义了两种类型的部分选择:常量部分选择和索引部分选择。
... 使用以下语法给出向量 reg 或 net 的常量部分选择:
vect[msb_expr:lsb_expr]
两个表达式都应该是常量表达式。 ...
向量网络、向量 reg、整数变量或时间变量的索引部分选择使用以下语法给出:
reg [15:0] big_vect;
reg [0:15] little_vect;
big_vect[lsb_base_expr +: width_expr]
little_vect[msb_base_expr +: width_expr]
big_vect[msb_base_expr -: width_expr]
little_vect[lsb_base_expr -: width_expr]
width_expr 应该是一个常量表达式。它也不受运行时参数分配的影响。 lsb_base_expr 和 msb_base_expr 可以在运行时变化。 ...
您的函数可以使用索引部分选择重写:
function [31:0] gen_val;
input [31:0] old_val;
input [31:0] new_val;
input [3:0] be;
integer n;
for (n = 0 ; n < 4 ; n = n + 1)
gen_val[n*8 +: 8] = be[n] ? new_val[n*8 +: 8] : old_val[n*8 +: 8];
endfunction