12

Consider an expression like:

assign x = func(A) ^ func(B);

where the output of the func is 32 bits wide, and x is a wire of 16 bits. I want to assign only the lowest 16 bits of the resulting xor.

I know the above code already does that, but it also generates a warning. The "obvious" approach doesn't work:

assign x = (func(A) ^ func(B))[15:0]; // error: '[' is unexpected
user23106
  • 123
  • 1
  • 1
  • 5

3 Answers3

9

You can use another variable, though this is not particularly elegant.

wire[31:0] y;

assign y = func(A) ^ func(B);
assign x = y[15:0];

A better approach would be to use a function.

function [15:0] trunc_32_to_16(input [31:0] val32);
  trunc_32_to_16 = val32[15:0];
endfunction

assign x = trunc_32_to_16(func(A) ^ func(B));
dwikle
  • 976
  • 7
  • 7
  • I was hoping there would be something nicer than that... Oh well, I'll just create a large number of truncating functions. – user23106 Apr 26 '13 at 15:06
5

In your example, you are implicitly truncating bits.

Making the truncation explicit can often remove the warnings in simulation/lint/synthesis.

One way to do this in-line is to use a cast operator, e.g.:

typedef logic [15:0] HALF_WORD;
assign x = HALF_WORD'((func(A) ^ func(B));

This approach may make sense if it is obvious from the context that all the bits being dropped are 0's.

If some of the bits may be nonzero then I would suggest still using an intermediate net like @dwikle suggested in a previous answer, since it makes it more clear that you are actually throwing away bits. Here it is again for reference.

wire[31:0] y;

assign y = func(A) ^ func(B);
assign x = y[15:0];
mattgately
  • 226
  • 2
  • 7
  • 2
    I think that would only work in SystemVerilog. Interesting non-the-less. – Tom Carpenter Jan 19 '16 at 19:50
  • 1
    @TomCarpenter, are you wanting to limit yourself to the subset of Verilog available in the IEEE Std 1364-2005, rather than using the full set of synthesizable verilog available in one of the newer unified IEEE Std 1800 revisions? You may want to say Verilog-2005 or something to clarify, since the Verilog standard was subsumed into the unified SystemVerilog standard in 2009. – mattgately Jul 29 '16 at 13:33
  • In SystemVerilog, you could simply do assign x = {func(A) ^ func(B)}[15:0]; – dave_59 Nov 27 '23 at 18:16
3

I think that this might help keep the line count down.

wire [15:0] not_used ;

assign {not_used, x} = (func(A) ^ func(B));

Not sure if that is valid with assigns though.

pre_randomize
  • 1,220
  • 7
  • 11