Verilog floating point arithmetic at compile time? - verilog

My Verilog testbench code defines a module with these parameters:
parameter PHASE_BITS = 32;
parameter real MAX_PHASE = 1 << PHASE_BITS;
I cannot get MAX_PHASE to have the expected value 4294967296 or its approximation; ModelSim shows me 0 instead. This despite the fact that MAX_PHASE is declared real.
I guess there's some integer overflow involved, because it works fine if PHASE_BITS is lowered to 31.
How do I make this parameter be equal to 2 to the power of another parameter?

The problem lies in the right-hand expression itself:
1 << PHASE_BITS
It is evaluated before considering the type of the variable it is stored into. Because 1 is an integer literal and integers in Verilog are signed 32 bits, the << operator (left shift operator) will output an integer of the same type, and will cause an overflow if PHASE_BITS is higher than 31.
We could force 1 to be a real literal instead:
1.0 << PHASE_BITS
But this causes a compile time error, as << is not defined for real values.
Let's use plain 2-power-to-N:
2.0 ** PHASE_BITS
This will yield the desired result, 4.29497e+09.

Related

Signed and Unsigned Multiplication Problem in Verilog

I have been working on approximate multiplication recently and I want to write a Verilog code for dynamic segment multiplication (DSM) . It suggest that you find the first index in you number which has a value of 1 and then take other 3 indexes next to it to form a 4 bit number that represent an 8 bit number then you should multiply these 4 bit numbers instead of 8 bits then some shifts to have the final result it helps a lot on hardware actually.. but my problem is about multiplication of these segments because sometimes they should be considered signed and some time unsigned I have the last 3 lines of my code: (a and b are input 8 bit numbers) and m1 and m2 are segments I wrote m,m2 as reg signed [3:0] and a and b as input signed [7:0]
Here is my code:
assign out = ({a[7],b[7]}==2'b11)||({a[7],b[7]}==2'b00) ? ($unsigned(m1)*$unsigned(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b01) ? ($signed({1'b0,m1})*$signed(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b10) ? ($signed(m1)*$signed({1'b0,m2})) << (shift_m1+shift_m2) : 16'dz;
But in simulation Verilog always considers segments as unsigned and does unsigned multiplication even though I noted signed or unsigned mark...
Can anyone help? I read all of the questions about this problem in stackoverflow and other places but still cannot solve this issue...
The rules for non-self determined operands say that if one operand is unsigned, the result is unsigned. 16'dz is unsigned.
The conditional operator i ? j : k has the condition operand i self-determined, but the two selections j and k are in a context based on the assignment or expression it is a part of. The shift operator i << j has the shift amount operand j self-determined.
All of the context rules are explained in section 11.6.1 Rules for expression bit lengths in the IEEE 1800-2017 SystemVerilog LRM.
You can get your desired result by using the signed literal 16'sdz.
However the logic you wrote may not be synthesizable for certain technologies that do not allow using a z state inside your device. The correct and more readable way is using a case statement:
alway #(*) case({a[7],b[7]})
2'b00,
2'b11: out = $unsigned(m1)*$unsigned(m2) << shift_m1+shift_m2;
2'b01: out = $signed({1'b0,m1})*m2 << shift_m1+shift_m2;
2'b10: out = m1*$signed({1'b0,m2}) << shift_m1+shift_m2;
endcase

Basic questions about Verilog

Why adding the concatenation operator can rand a postive value from 0~59?
reg [23:0] rand;
rand = {$random} % 60;
Why the concatenation operator {} can make such difference?
from IEEE-1364
17.9.1 $random function. The system function $random provides a mechanism for generating random numbers. The function returns a new 32-bit random number each time it is called. The random number is a signed integer; it can be positive or negative.
Result of concatenation {} is always an unsigned number. This is not spelled explicitly in the standard, but even the example (from the standard) which you cited implies it.
There is no difference between signed and unsigned numbers in their bit representations. Only certain operation care about the signs of the operands, including %.
A 32-bit signed integer can represent values between -2,147,483,648 and 2,147,483,647, therefore the results of $random % 60 will be between -59 and 59.
A 32 bit unsigned integer can represent values between 0 and 4,294,967,295, therefore the result of {$random} % 60 will be from 0 to 59.

Verilog operation unexpected result

I am studying verilog language and faced problems.
integer intA;
...
intA = - 4'd12 / 3; // expression result is 1431655761.
// -4’d12 is effectively a 32-bit reg data type
This snippet from standard and it blew our minds. The standard says that 4d12 - is a 4 bit number 1100.
Then -4d12 = 0100. It's okay now.
To perform the division, we need to bring the number to the same size. 4 to 32 bit. The number of bits -4'd12 - is unsigned, then it should be equal to 32'b0000...0100, but it equal to 32'b1111...10100. Not ok, but next step.
My version of division: -4d12 / 3 = 32'b0000...0100 / 32'b0000...0011 = 1
Standart version: - 4'd12 / 3 = 1431655761
Can anyone tell why? Why 4 bit number keeps extra bits?
You need to read section 11.8.2 Steps for evaluating an expression of the 1800-2012 LRM. They key piece you are missing is that the operand is 4'd12 and that it is sized to 32 bits as an unsigned value before the unary - operator is applied.
If you want the 4-bit value treated as a signed -3, then you need to write
intA = - 4'sd12 / 3 // result is 1
here the parser interprets -'d12 as 32 bits number which is unsigned initially and the negative sign would result in the negation of bits. so the result would be
negation of ('d12)= negation of (28 zeros + 1100)= 28ones+2zeros+2ones =
11111111111111111111111111110011. gives output to 4294967283 . if you divide this number (4294967283) by 3 the answer would be 1,431,655,761.
keep smiling :)

Using " * " for multiplication of binary numbers, only gives me addition, why? (Code here)

I'm learning operations with " + ", " - " and " * ", addition and subtraction works well, but multiplication gives me only additions, link for the code:
http://www.edaplayground.com/x/NvT
I checked the code, can't understand what's going on. I gave enough space (bits) the result variable.
BTW, It's a code intended for fixed-point operations including fractional numbers, but everything is calculated as integers.
Your select signal is only on 1bit.
Then when you set select = 2 it assigns the lower bit of 2(2'b10) i.e. 0.
You should change select declaration by :
input [1:0] select; // In the module
reg [1:0] select; // In the testbench
To avoid such errors I would advise you to use the complete notation of values:
x'tnnn...nnn
where x is the width of the signal, t is the type (d for decimal, h for hexa, b for binary,...) and nnn...nnn the value in the type specified.
For example for the decimal value 2 you will have several notations that will make sense in certain situations:
2'd2 //2 bits decimal
2'h2 //2 bits hexadecimal
2'b10//2 bits binary
For more informations about these notations you can read this pdf.

Verilog shift extending result?

We have the following line of code and we know that regF is 16 bits long, regD is 8 bits long and regE is 8 bits long, regC is 3 bits long and assumed unsigned:
regF <= regF + ( ( regD << regC ) & { 16{ regE [ regC ]} }) ;
My question is : will the shift regD << regC assume that the result is 8 bits or will it extended to 16 bits because of the bitwise & with the 16 bit vector?
The shift sub-expression itself has a width of 8 bits; the bit width of a shift is always the bit width of the left operand (see table 5-22 in the 2005 LRM).
However, things get more complicated after that. The shift sub-expression appears as an operand of the & operator. The bit length of the & expression is the bit-length of the largest of the 2 operands; in this case, 16 bits.
This sub-expression now appears as an operand of the + expression; the result width of this expression is again the maximum width of the two operands of the +, which is again 16.
We now have an assignment. This is not technically an operand, but the same rules are used; in this case, the LHS is also 16 bits, so the size of the RHS is unaffected.
We now know that the overall expression size is 16 bits; this size is propagated back down to the operands, except the 'self-determined' operands. The only self-determined operand here is the RHS of the shift expression (regC), which isn't extended.
The signedness of the expressions is now determined. Propagation happens in the same way. The overall effect here, since we have at least one unsigned operand, is that the expression is unsigned, and all operands are coerced to unsigned. So, all (non-self-determined) operands are coerced to unsigned 16-bit before any operation is actually carried out.
So, in other words, the shift sub-expression actually ends up as a 16-bit shift, even though it appears to be 8-bit at first sight. Note that it's not 16-bit because the RHS of the & is 16-bit, but because the entire sizing process - the width propagation up the expression - came up with an answer of 16. If you'd assigned to an 18-bit reg, instead of the 16-bit regF, then your shift would have been extended to 18 bits.
This is all very complicated and non-intuitive, at least if you have any experience of mainstream languages. It's explained (more or less) in sections 5.4 and 5.5 of the 2005 LRM. If you want any advice, then never write expressions like this. Write defensively - break everything down to individual sub-expressions, and then combine the sub-expressions.

Resources