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'b111111113'b111.