Creating data masks is a very common task in the life of a verification engineer.
While doing that I came across one very interesting gotcha.
I wanted to obtain a data mask for the second least significant byte of a word: 32’h0000FF00
Pretty simple stuff, right?
Here is the code that I did for this:
1 2 3 4 5 6 7 | byte mask_byte = 8'hFF; int unsigned mask_word = mask_byte; mask_word = mask_word << 8; //this will NOT display 32'h0000FF00 $display("mask_word: %08X", mask_word); |
As the comment says, this code will NOT display 32’h0000FF00.
It will display 32’hFFFFFF00
You can give it a try yourself on EDA Playground.
This is because of the sign extension rules in SystemVerilog. In SystemVerilog Language Reference Manual it is stipulated:
Automatic type conversions from a smaller number of bits to a larger number of bits involve zero extensions if unsigned or sign extensions if signed, and do not cause warning messages.
Because byte is a “8 bit signed integer” its sign bit is used to extend it to an int unsigned (the type of wask_word variable).
One quick solution is to declare the mask_byte as a byte unsigned:
1 2 3 4 5 6 7 | byte unsigned mask_byte = 8'hFF; int unsigned mask_word = mask_byte; mask_word = mask_word << 8; //this will display 32'h0000FF00 $display("mask_word: %08X", mask_word); |
You can get more interesting examples on this gotcha from this paper from Sutherland HDL.
Thanks a lot for sharing.
Thank you for sharing. I am a NCG so pardon if my question is not appropriate.
Why there is a need of shifting to create a mask?
Why can’t we just create a constant mask word?
Hi Vicky,
In some cases you need to generate a mask based on the current needs.
For example, for AHB protocol, you must generate a mask for the data line based on the address of the transfer, the data width and the size of the transfer.