Verilog - 如何否定数组?

时间:2015-04-05 16:49:30

标签: verilog system-verilog

reg a[4:0];
reg inv_a[4:0];

assign inv_a = ~a; //This doesn't work.

当我尝试使用带有上述语句的modelsim时,它会抛出:"对解压缩类型的非法操作"

有人可以指出如何正确否定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.

6 个答案:

答案 0 :(得分:4)

一种单线解决方案,用于反转通过比特流实现的解压缩阵列(请参阅IEEE Std 1800-2012& sect; 11.4.14 流媒体运营商(打包/解压缩)以获取完整详细信息)

logic a[4:0];
logic inv_a[4:0];

assign {<<{inv_a}} = ~{<<{a}}; // bit streaming

比特流仅适用于SystemVerilog。如果您仅限于Verilog,则必须使用for循环或generate-for-loop(请参阅Tudor&#39; s answer)。

另一件需要考虑的事情是,是否需要解包数组。打包的阵列允许整体访问阵列。 Verilog不允许通过端口连接传递解压缩的数组,允许打包数组。 SystemVerilog支持将打包的数组打包为端口。

reg [4:0] a;
reg [4:0] inv_a;

assign inv_a = ~a; // pack array

一般来说,它取决于您希望如何访问阵列。如果您希望被视为一个数字,请使用压缩数组;仍然允许单个元素访问。如果您只想访问数组中的各个元素,请使用unpacked。有关打包和解压缩的更多信息,请参阅前面已回答的问题:

答案 1 :(得分:3)

尝试在组合过程中使用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];

答案 2 :(得分:2)

更改reg的{​​{1}},因为wire需要:{/ p>

assign

或者,如果您使用reg [4:0] a; wire [4:0] inv_a; assign inv_a = ~a; //This should work. 块,则可以将inv_a保留为reg

always

reg [4:0] a; reg [4:0] inv_a; always @* inv_a = ~a; //This should work. 似乎与reg a[4:0];

不同

reg [4:0] areg a[4:0]相同:一个包含5个寄存器的数组,每个寄存器为1位。

reg [0:0] a[4:0]是一个5位寄存器。

减少运算符以及一元逆变器运算符(这是逐位运算的)仅在单个向量(寄存器)上运行。你的第一个声明声明了5个向量。

答案 3 :(得分:2)

您只能对压缩数组(位向量)执行逻辑运算。整个解压缩阵列允许的唯一操作是复制和比较。

如果必须在一行中执行此操作,则可以将解压缩的数组转换为打包数组并返回。

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;

答案 4 :(得分:0)

你可以用一系列的x来对它进行xor:

assign inv_a = a ^ {WIDTH{1'b1}};

答案 5 :(得分:-1)

您可以通过对打包数组使用逻辑运算来进行反转。

assign inverted_a = ((a)^(4'b1111));
X (XOR) 1 = ~X 

然后,您可以将二进制数编辑为输入或寄存器的宽度 例如7'b111111113'b111