I have two signals of type "reg" with different bit lengths:
reg [15:0] A;
reg [11:0] B;
I want to display the value of A+B
during the simulation while we know it might overflow. I know there are many ways to do this by using a sign extension or using additional temporary registers with larger bit sizes. But, I don't want to use these ways. Is there a way to display the actual value of A+B
with more than 16 bits? The following code does not meet my expectation:
$display("Actual value of A+B is: %8x", A+B);
It just prints the corrupted sum value (due to overflow) in 8 hexadecimal characters. For example in the case of "A=16'hfffd" and "B=16'h0006" the result would be "
The actual value of A+B is 00000003
Whereas I was expecting 00010003
How can I tell Cad Tool to treat A+B
as a 17-bit signal?
3 Answers 3
You say you don't want to use extra temporary register or larger bit sizes, but why not? This is exactly how you make the result wider, but making the calculation wider. There are no two ways about it.
Given also that $display
is a simulation-only construct, storing the sum result in a temporary variable would not lead to any performance penalty.
If you want the result to be wider without changing the input operand sizes, assign it to a wire of the desired width first before feeding to the display command. The tools should infer the result with from the output width.
For example:
wire [16:0] sum;
assign sum = a + b;
Alternatively, you can force the result width to be wider by making the inputs wider. If you don't want to make A or B registers wider, you can do this with a simple concatenation:
$display("result: %d", {1'b0, A} + B); // Unsigned
$display("result: %d", {A[15], A} + B); // Signed
This will force the A input of the sum to be 17 bit wide and so the width of the result will then be 17 bit also.
-
\$\begingroup\$ Thanks for your reply You said "in simulation storing the sum in a temporary variable does not lead to a performance penalty". Although it is true, but what about the implementation and large scale of the same issue? Doesn't it result in using a large FGPA area due to using a large number of programmable registers or wires? \$\endgroup\$Saeed Jazaeri– Saeed Jazaeri2024年05月06日 11:14:23 +00:00Commented May 6, 2024 at 11:14
-
\$\begingroup\$ If you aren't using the extra bits in the synthesis design (e.g. if you only do something with the lower 16bit of the result), then the tools are clever enough to completely optimise away the unused MSBs. \$\endgroup\$Tom Carpenter– Tom Carpenter2024年05月06日 11:23:13 +00:00Commented May 6, 2024 at 11:23
You can add 17 bits of 0:
module tb;
reg [15:0] A = 16'hfffd;
reg [11:0] B = 12'h006;
initial $display("Actual value of A+B is: %8x", A + B + {17{1'b0}});
endmodule
Output:
Actual value of A+B is: 00010003
Refer to IEEE Std 1800-2023, section 11.6.1 Rules for expression bit lengths
SystemVerilog evaluates expressions in a self- or assigment- context determined fashion. Bit lengths of results are defined by Table 11-21—Bit lengths resulting from self-determined expressions in the IEEE 1800-2023 SystemVerilog LRM.
The arguments to a $display
statement are all self-determined. Therefore the width of the result from A+B
is the width of the largest operand.
You can change the context by using a cast which effectively treats the expression in an assignment context to a variable of the target type without actually creating an extra variable.
$display("Actual value of A+B is: %8x", int'(A+B));
Explore related questions
See similar questions with these tags.