11
\$\begingroup\$

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
\$\endgroup\$

3 Answers 3

8
\$\begingroup\$

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));
\$\endgroup\$
1
  • \$\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
    Apr 26, 2013 at 15:06
5
\$\begingroup\$

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];
\$\endgroup\$
2
  • 2
    \$\begingroup\$ I think that would only work in SystemVerilog. Interesting non-the-less. \$\endgroup\$ 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
    Jul 29, 2016 at 13:33
3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.