Reputation: 3347
I'm writing some synthesizable Verilog. I need to create a value to use as a mask in a larger expression. This value is a sequence of 1's, when the length is stored in some register:
buffer & {offset{1'h1}};
where buffer
and offset
are both registers. What I expect is for buffer
to be and
ed with 11111...
of width offset
. However, the compiler says this illegal in verilog, since offset
needs to be constant.
Instead, I wrote the following:
buffer & ~({WIDTH{1'h1}} << offset)
where WIDTH
is a constant. This works. Both expressions are equivalent in terms of values, but obviously not in terms of the hardware that would be synthesized.
What's the difference?
Upvotes: 0
Views: 1367
Reputation: 42623
The difference is because of the rules for context-determined expressions (detailed in sections 11.6 and 11.8 of the IEEE 1800-2017 LRM) require the width of all operands of an expression be known at compile time.
Your example is too simple to show where the complication arises, but let's say buffer
was 16-bit signed variable. To perform bitwise-and (&
), you first need to know size of both operands, then extend the smaller operand to match the size of the larger operand. If we don't know what the size of {offset{1'h1}}
is, we don't know whether it needs to 0-extended, or buffer
needs to be sign-extended.
Of course, the language could be defined to allow this so it works, but synthesis tools would be creating a lot of unnecessary additional hardware. And if we start applying this to more complex expressions, trying to determine how the bit-widths propagate becomes unmanageable.
Upvotes: 1
Reputation: 12344
Both parts of your question impliy the replication
operator. The operator requires you to use a replication constant
to show how many times to replicate. So, the first part of your example is illegal. The offset
must be a constant, not a reg.
Also, the constant is not a width of something, but a number of times the {1}
is repeated. So, the second part of the example is correct syntactically.
Upvotes: 0