Basically I'm trying to code a synthesizable module in verilog which performs division between 2 numbers and rounds off the result . For example, if I'm doing 56/30 then resulting value is 1.86 and this value should be rounded off to 2 or if I'm doing 42/30 , the resulting value is 1.4 which should be rounded off to 1 . Can synthesizable code be written in verilog to achieve this?
The value of the answers LSB is determined by the input format. If you change the numerator input to Fixed point with at least 1 Fractional bit rather than integers, your output will have a bit representing 0.5 which you can use to control truncate (round down) or round up.
module test;
reg[4:0] a = 5'b0011_0; //3 with 1 Fractional bit
reg[4:0] b = 5'b00010; //2 no fractional bits
reg[9:0] c;
initial begin
c = a/b ; //LSB => 0.5
// c= 5'b01_1 => 1.5
#1 $display("C = %b", c);
end
endmodule
Verilog truncates the end of a number if <size> is smaller than the value returned. So if you divide 42/30, the value returned is 1.4. Simply define the <size> as 1, and the decimal will be truncated.
However, keep in mind that this solution truncates the decimal, and doesn't round it up. I'm not an expert at Verilog, but you could refer here to further solve your problem.
Related
I am new to Verilog/System Verilog and I wanted to implement the square and cube a fractional number. Consider the following example
module test(
input wire [31:0] input,
output reg [63:0] output
);
reg [63:0] temp;
always # (*) begin
temp = input*input;
output <= temp*input;
end
endmodule
So, when my input is 32'h0_C7AE147 (0.78 in the hexadecimal number system using the 32 bits representation and assuming _ is the equivalent of . in Verilog) I expect an output of 32'h0_797C3D6 (0.4745 in decimal number system)
But I am getting an output of 64'hD546_4A9C_ED94_2917
Also, how to handle the increasing bit sizes in a multiplication?
When we multiply two N-bit wide operands, we get an output of width 2N-bits. When we multiply this 2N-bit wide number with a k bit wide number, we get a number of widths 2N+k-bit wide and this process goes on.
You mean you want to represent fractional number in 32-bit fixed point notation with 4-bit integer part + 28-bit fractional part? And why do you need 64 bits for output?
Anyway I think you need to shift the product to the right by 28 bits for each multiplication.
Try:
temp = input * input >> 28;
output <= temp * input >> 28;
If you need proper rounding, do it before each shifting.
when I try to write to a[b+1] where the bits of b are all '1' ,the value of the reg a[0] do not update,but when I try a[b+1'b1],it updated
awaddr_wa <= awaddr_wa + 2;
awaddr[awaddr_wa] <= AWADDR_M;
awlen [awaddr_wa] <= 4'd0;
awaddr[awaddr_wa+6'd1] <= AWADDR_M+16;
awlen [awaddr_wa+6'd1] <= 4'd0
so ,why?
Here is a reproducible example:
module M;
integer a[0:7] = {0,1,2,3,4,5,6,7};
reg [2:0] b = -1;
initial
begin
$display("a[b+1]=", a[b+1]);
$display("a[b+1'b1]=", b+1'b1);
end
endmodule
https://www.edaplayground.com/x/26Za
(Your question would be better had it included this)
You will see that the output is something like:
a[b+1]= x
a[b+1'b1]=0
1 is 32 bits wide. (All unbased literals in Verilog are 32 bits
wide.)
When you mix bit widths like this in Verilog, Verilog must
decide how many bits to use.
When you index an array out of range in Verilog this is not a catastrophe like it is in C. Instead the default value for the type of the array is returned. a is an array of integers, whose default value is 32'bx.
With a[b+1], Verilog will take the wider of 3 bits (b) and 32 bits (1), ie 32 bits. So, with b=3'b111, 1 is added to b using 32-bit arithmetic. In 32-bit arithmetic, 7+1 is 8, so a[b+1] is the same as a[8] which is out of range and hence 32'bx.
With a[b+1'b1], Verilog will take the wider of 3 bits (b) and 1 bit (1'b1), ie 3 bits. So, with b=3'b111, 1'b1 is added to b using 3-bit arithmetic. In 3-bit arithmetic, 7+1 is 0, so a[b+1'b1] is the same as a[0] which is not out of range and is 32'b0 in my example.
This is a classic trap in Verilog. It is an example of a Verilog self-determined expression. A self-determined expression is one where the number of bits used for the calculation depends only the widths of the operands. There are also context-determined expressions (eg F = A + B) where the number of bits also depends on the width of the variable (or net) being assigned to.
Two 8-bit inputs are fed to the comparator, and if first one is greater than second, they are supposed to be subtracted, else they are supposed to be added. But, > and < operators aren't supposed to be used to compare them.
So, I have written my logic as:
input[7:0] in1,in2;
output select;
assign select=(in1-in2)?0:1;
It is always subtracting, unless difference equals 0. If I use division, 0 cannot be an input or my program can crash. Any suggestions on how to solve this problem?
Thanks a lot for your time.
Remember that the leftmost bit of a negative number is aways 1. So you can use it to check the sign of the difference.
input[7:0] in1,in2;
output select;
wire [7:0] difference = in1-in2;
wire sign_of_difference = difference[7];
assign select = sign_of_difference? 0:1;
This is the simple code I wrote.From 'outt' I get 122116. But if I change 'outt' width to be 33 bits ([32:0]) then code seems to work and give the correct answer -140028. What is the reason for this behaviour??
`timescale 1ns / 1ps
module valu_parser(clk,outt);
input clk;
reg signed [31:0] r_1;
reg signed [31:0] r_2;
output reg signed [31:0] outt;
initial begin
r_1 = -47938;
r_2 = -150096;
end
always # (posedge clk) begin
outt <= ((r_1 + r_2)* 11585 + 8192)>>>14;
end
endmodule
You are performing an operation that needs at least 33 bits (the temporary result before the right shift uses 33 bits) and theoretically it could need 32+"the size of the multiplicand constant" assuming that r_1 and r_2 are not constants.
If you think of the hardware your code will generate, these bits needs to be stored somewhere temporarily to allow the hardware to first perform multiplication, then addition followed by the right shift.
This will do the trick, but will also generate more registers than you wanted initially. If you are using this module to generate a constant, I would recommend hard-coding the constant.
module valu_parser(clk,outt);
input clk;
reg signed [31:0] r_1;
reg signed [31:0] r_2;
reg signed [32:0] temp;
output reg signed [31:0] outt;
initial begin
r_1 = -47938;
r_2 = -150096;
end
always # (posedge clk) begin
temp <= ((r_1 + r_2)* 11585 + 8192);
end
assign outt = temp>>>14;
endmodule
The concept can be seen here: https://www.edaplayground.com/x/3BXy.
In an expression Verilog needs to decide how many bits to use in the calculation.
The + and * operators result in what are called context-determined expressions. With the expression F = A + B; the number of bits used is the maximum of F, A, and B. This usually works fine, because normally you would ensure that F was wide enough to store the result of adding A and B. Likewise with the expression F = A * B; would usually work fine, because normally you would ensure that F was wide enough to store the result of multiplying A and B.
However, by adding the shift right operator you have been able to make the variable being assigned narrower than the number of bits actually needed to calculate the expression on the left of the shift operator. The number of bits Verilog uses in the calculation is the maximum of the width of outt, r_1, r_2, 11585 and 8192. All of these are 32 bits wide (including 11585 and 8192), so 32 bits are used in the calculation. As you have discovered, 32 bits is not enough, but, with the values you have chosen, 33 bits is. With other values, 33 bits wouldn't be enough either. For a completely flexible solution, you should be using 66 bits (32 + 32 + 1 + 1) - 32 bits + 32 bits for the multiplication plus 1 more bit for each addition.
The solution to your problem is to make r_1 and/or r_2 wider or to use an intermediate value (as suggested by Hida's answer here).
When you multiply -198034 (r1+r1) on 11585 you have in result highest bit is 0 (outt[31]), then if you have 32bit signed value its start be positive and in answer you have positive result. And when you change it for 33bit your highest bit is 1 (outt[32]) and result is negative value and you have correct answer.
I'm sqauring a 16.16 fixed point binary number and then compare the result with an integer. The 16.16 number becomes a 64 Bit binary number after squaring.
I don't know exactly if my code is correct and every square of a 16.16 fixed point number is within range.
Also I cannot setup the right statement to represent the 32.32 fixed point result.
Pseudo code
reg [31:0] n; //the 32 Bit number we want to square
reg [63:0] res; //out result register after squaring n
integer i;
...
res = n * n; // squaring n
i = 1;
/* compare with some integer - bigger than i */
if( res[63:32] >= i && res[31:0] > 0)
begin ...do something ... end
/* compare with some integer - less/equal than i */
if( (res[63:32] < i && res[31:0] >= 0) || (res[63:32] <= i && res[31:0] == 0))
begin ...do something... end
...
In the testbench I'm trying to represent the result as a 32.32 fixed point binary number - but this representation won't give me the right float value when displaying:
res[63:32] + $bitstoreal({1'b0,15'b011111111111111,{fer3[31:0],{81{1'b0}} }) -1;
There is a similar question which discusses fixed point widths, ... multiply a 32 bit by 32 bit the answer would fit into 64bits. Your correct with 16.16 x 16.16 is 32.32.
verilog conversion to reals can be automatic, if done correctly, to scale a number for display n * 2**-16 does not work. n * 2.0**-16 Does because we used 2.0 the calculation is done using floating point instead of integer.
NB: 2**n is 2 to the power of n. 2^n in some languages but ^ is XOR in verilog.
A quick example of scaling for comparison using a real:
reg [31:0] n; //16.16
reg [63:0] n_sq; //32.32
real n_sq_real; // Floating Point
always #* begin
n_sq = n * n;
end
initial begin
#1ps;
n = { 16'd2, 16'b1000_0000_0000_0000}; //2.5
#1ns;
$display("n %f, n squared %f", (n * 2.0**-16), n_sq * 2.0**-32);
n_sq_real = n_sq * 2.0**-32 ;
$display("n_sq_real %f", n_sq_real);
end
Returns:
# n 2.500000, n squared 6.250000
# n_sq_real 6.250000
The example on EDA Playground.
If it is just for comparison to an integer you can just truncate your number by shifting out the fractional bits ie n_sq * 2.0**-32 becomes n_sq >> 32
Or you could scale the integer by the number of fractional bits.
n_sq >= i<<32 ;
At the end of the day fixed point numbers in verilog are just integers scaled by a power of 2 to thats some bits can represent fractional information.