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
3 Answers 3
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));
-
\$\begingroup\$ I was hoping there would be something nicer than that... Oh well, I'll just create a large number of truncating functions. \$\endgroup\$user23106– user231062013年04月26日 15:06:11 +00:00Commented Apr 26, 2013 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];
-
2\$\begingroup\$ I think that would only work in SystemVerilog. Interesting non-the-less. \$\endgroup\$Tom Carpenter– Tom Carpenter2016年01月19日 19:50:14 +00:00Commented Jan 19, 2016 at 19:50
-
1\$\begingroup\$ @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. \$\endgroup\$mattgately– mattgately2016年07月29日 13:33:57 +00:00Commented Jul 29, 2016 at 13:33
-
\$\begingroup\$ In SystemVerilog, you could simply do
assign x = {func(A) ^ func(B)}[15:0];
\$\endgroup\$dave_59– dave_592023年11月27日 18:16:15 +00:00Commented Nov 27, 2023 at 18:16
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.