Verilog - 如何取反数组?
Verilog - how to negate an array?
reg a[4:0];
reg inv_a[4:0];
assign inv_a = ~a; //This doesn't work.
当我用上面的语句尝试 modelsim 时,它抛出:"Illegal operation on unpacked types"
有人可以指出如何在 Verilog 中正确取反数组吗?
编辑:提供更多信息,这会改变任何建议吗?
module router_main(
input bustorouter_ready[4:0],
);
wire inv_bustorouter_ready[4:0];
assign inv_bustorouter_ready = ~bustorouter_ready; //Still doesn't work.
将您的 reg
更改为 wire
,因为 assign
需要:
reg [4:0] a;
wire [4:0] inv_a;
assign inv_a = ~a; //This should work.
或者,如果您使用 always
块,您可以将 inv_a
保留为 reg
:
reg [4:0] a;
reg [4:0] inv_a;
always @*
inv_a = ~a; //This should work.
reg a[4:0]
好像和reg [4:0] a
;
不一样
reg a[4:0]
与 reg [0:0] a[4:0]
相同:一个包含 5 个寄存器的数组,每个寄存器 1 位。
reg [4:0] a
是一个5位寄存器。
归约运算符以及一元逆变器运算符(这是按位的)仅对单个向量(寄存器)进行运算。您的第一个声明声明了 5 个向量。
尝试在组合过程中使用 for
循环:
always_comb
for (int i = 0; i <= 4; i++)
inv_a[i] = ~a[i];
因为我猜你是在做设计,所以你需要检查你的综合工具是否支持这个结构。
或者您可以使用 generate
:
genvar i;
for (i = 0; i <= 4; i++)
always_comb
inv_a[i] = ~a[i];
您只能对压缩数组(位向量)执行逻辑运算。对整个解包数组唯一允许的操作是复制和比较。
如果您必须在一行中执行此操作,您可以将解压缩数组转换为压缩数组并返回。
typedef logic ua5[5];
typedef logic bit [4:0] pa5;
ua5 a; // same as reg a[4:0]
ua5 inv_a;
assign inv_a = ua5'(pa'(~a));
否则,我会推荐一个 foreach 循环
always_comb foreach (a[i]) inv_a[i] = ~a;
一种通过比特流实现的反转解压缩数组的单行解决方案(参考IEEE Std 1800-2012 & sect; 11.4.14 流运算符(pack/unpack) 了解详细信息)
logic a[4:0];
logic inv_a[4:0];
assign {<<{inv_a}} = ~{<<{a}}; // bit streaming
比特流仅适用于 SystemVerilog。如果您仅限于使用 Verilog,那么您必须使用 for-loop 或 generate-for-loop(参见 Tudor 的 )。
要考虑的另一件事是是否需要解包数组。打包数组允许访问整个数组。 Verilog 不允许通过端口连接传递未打包的数组,但允许打包数组。 SystemVerilog 支持打包在未打包的数组中作为端口。
reg [4:0] a;
reg [4:0] inv_a;
assign inv_a = ~a; // pack array
一般归结为您希望如何访问数组。如果你想被当作一个数字,使用压缩数组;仍然允许访问单个元素。如果您只想访问数组中的单个元素,请使用 unpacked。有关打包与未打包的更多信息,请参阅这些较早回答的问题:
- SystemVerilog packed array vs unpacked array memory footprint
- packed vs unpacked vectors in system verilog
你可以用一个数组对它进行异或:
assign inv_a = a ^ {WIDTH{1'b1}};
您可以通过对压缩数组使用逻辑运算来进行反转。
assign inverted_a = ((a)^(4'b1111));
X (XOR) 1 = ~X
然后您可以将二进制数编辑为您输入或寄存器的宽度
像 7'b11111111
或 3'b111
.
reg a[4:0];
reg inv_a[4:0];
assign inv_a = ~a; //This doesn't work.
当我用上面的语句尝试 modelsim 时,它抛出:"Illegal operation on unpacked types"
有人可以指出如何在 Verilog 中正确取反数组吗?
编辑:提供更多信息,这会改变任何建议吗?
module router_main(
input bustorouter_ready[4:0],
);
wire inv_bustorouter_ready[4:0];
assign inv_bustorouter_ready = ~bustorouter_ready; //Still doesn't work.
将您的 reg
更改为 wire
,因为 assign
需要:
reg [4:0] a;
wire [4:0] inv_a;
assign inv_a = ~a; //This should work.
或者,如果您使用 always
块,您可以将 inv_a
保留为 reg
:
reg [4:0] a;
reg [4:0] inv_a;
always @*
inv_a = ~a; //This should work.
reg a[4:0]
好像和reg [4:0] a
;
reg a[4:0]
与 reg [0:0] a[4:0]
相同:一个包含 5 个寄存器的数组,每个寄存器 1 位。
reg [4:0] a
是一个5位寄存器。
归约运算符以及一元逆变器运算符(这是按位的)仅对单个向量(寄存器)进行运算。您的第一个声明声明了 5 个向量。
尝试在组合过程中使用 for
循环:
always_comb
for (int i = 0; i <= 4; i++)
inv_a[i] = ~a[i];
因为我猜你是在做设计,所以你需要检查你的综合工具是否支持这个结构。
或者您可以使用 generate
:
genvar i;
for (i = 0; i <= 4; i++)
always_comb
inv_a[i] = ~a[i];
您只能对压缩数组(位向量)执行逻辑运算。对整个解包数组唯一允许的操作是复制和比较。
如果您必须在一行中执行此操作,您可以将解压缩数组转换为压缩数组并返回。
typedef logic ua5[5];
typedef logic bit [4:0] pa5;
ua5 a; // same as reg a[4:0]
ua5 inv_a;
assign inv_a = ua5'(pa'(~a));
否则,我会推荐一个 foreach 循环
always_comb foreach (a[i]) inv_a[i] = ~a;
一种通过比特流实现的反转解压缩数组的单行解决方案(参考IEEE Std 1800-2012 & sect; 11.4.14 流运算符(pack/unpack) 了解详细信息)
logic a[4:0];
logic inv_a[4:0];
assign {<<{inv_a}} = ~{<<{a}}; // bit streaming
比特流仅适用于 SystemVerilog。如果您仅限于使用 Verilog,那么您必须使用 for-loop 或 generate-for-loop(参见 Tudor 的
要考虑的另一件事是是否需要解包数组。打包数组允许访问整个数组。 Verilog 不允许通过端口连接传递未打包的数组,但允许打包数组。 SystemVerilog 支持打包在未打包的数组中作为端口。
reg [4:0] a;
reg [4:0] inv_a;
assign inv_a = ~a; // pack array
一般归结为您希望如何访问数组。如果你想被当作一个数字,使用压缩数组;仍然允许访问单个元素。如果您只想访问数组中的单个元素,请使用 unpacked。有关打包与未打包的更多信息,请参阅这些较早回答的问题:
- SystemVerilog packed array vs unpacked array memory footprint
- packed vs unpacked vectors in system verilog
你可以用一个数组对它进行异或:
assign inv_a = a ^ {WIDTH{1'b1}};
您可以通过对压缩数组使用逻辑运算来进行反转。
assign inverted_a = ((a)^(4'b1111));
X (XOR) 1 = ~X
然后您可以将二进制数编辑为您输入或寄存器的宽度
像 7'b11111111
或 3'b111
.