# How to truncate an expression bit width in Verilog?

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


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

• I was hoping there would be something nicer than that... Oh well, I'll just create a large number of truncating functions. Apr 26 '13 at 15:06

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

• I think that would only work in SystemVerilog. Interesting non-the-less. Jan 19 '16 at 19:50
• @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. Jul 29 '16 at 13:33

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.