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

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

When I tried modelsim with above statement, it throw: "Illegal operation on unpacked types"

Can someone please point out how to correctly negate an array in Verilog?


Edit: Give more information, does this change any recommendation?

module router_main(
    input bustorouter_ready[4:0],
);

  wire inv_bustorouter_ready[4:0];

  assign inv_bustorouter_ready = ~bustorouter_ready; //Still doesn't work.
Patrick
  • 4,186
  • 9
  • 32
  • 45

6 Answers6

5

A one-line solution to invert an unpacked array achievable via bit streaming (refer to IEEE Std 1800-2012 & sect; 11.4.14 Streaming operators (pack/unpack) for full details)

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

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

Bit streaming only works in SystemVerilog. If you are limited to only Verilog, then you must use a for-loop or generate-for-loop (see Tudor's answer).

Another thing to consider is if unpacked arrays are necessary. Packed arrays allow access the array as a whole. Verilog does not allow passing unpacked arrays through port connections, packed arrays are allowed. SystemVerilog supports both packed in unpacked arrays as ports.

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

assign inv_a = ~a; // pack array

General it comes down to how you want to access the array. Use packed arrays if you want to be treated as one number; individual elements access is still allowed. Use unpacked if you only intend to access individual elements in the array. For more on packed vs unpacked, refer to these earlier answered questions:

Greg
  • 18,111
  • 5
  • 46
  • 68
4

Try using a for loop in a combinatorial process:

always_comb
  for (int i = 0; i <= 4; i++)
    inv_a[i] = ~a[i];

Since I guess you're doing design, you'll need to check if your synthesis tool supports this construct.

Alternatively you could use a generate:

genvar i;
for (i = 0; i <= 4; i++)
  always_comb
    inv_a[i] = ~a[i];
Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
  • This is essentially what I'm doing now. I suppose if there is no one liner for this in a few days, I'll accept your answer! – Patrick Apr 05 '15 at 18:23
3

Change your reg for a wire, as assign needs that:

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

assign inv_a = ~a; //This should work.

Alternatively, you can keep inv_a as reg if you use an always block:

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

always @*
  inv_a = ~a; //This should work.

reg a[4:0] seems to no be the same as reg [4:0] a;

reg a[4:0] is the same as reg [0:0] a[4:0] : an array of 5 registers of 1 bit each.

reg [4:0] a is a 5 bit register.

Reduction operators, as well as the unary inverter operator (this is bit-wise) operate only on a single vector (register). Your first declaration declared 5 vectors.

mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
  • Please see my updated question. I tried your recommendation, but it still doesn't work. I added more information about my code, please see if your suggestion still apply? – Patrick Apr 05 '15 at 18:04
  • 3
    You shouldn't use `always @*`, as the associated block doesn't get called at time 0. You should use `always_comb` if you are using SystemVerilog. – Tudor Timi Apr 05 '15 at 18:11
  • For my design, I actually needs an array of 5 registers as the signal are coming from different modules. – Patrick Apr 06 '15 at 18:33
2

You can only perform logical operations on packed arrays(bit-vectors). The only operations allowed on unpacked arrays as a whole are copy and compare.

If you must do this in one line, you can cast the unpacked array to a packed array and back.

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));

Otherwise, I would recommend a foreach loop

always_comb foreach (a[i]) inv_a[i] = ~a;
dave_59
  • 39,096
  • 3
  • 24
  • 63
0

You can xor it with an array of ones:

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

You can do inversion by using logical operations on packed array.

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

Then you can edit the binary number into the width of your input or register like 7'b11111111 or 3'b111.

zx485
  • 28,498
  • 28
  • 50
  • 59