I want to do a fraction arithmetic and then display the results. I know that $display displays in integer. But what is the solution to display the exact amount as eg I want to display 10/3 = 3.3 but I get displayed 3.0000. This is my code. I do not want to use real data type here.
`timescale 1ns/1ps
module fp_check
(a,b,c,d);
input logic signed [7:0] a;
input real b;
output real c;
output logic [7:0] d;
assign c = a*2;
assign d = b+1;
endmodule
module fp_test;
logic signed [7:0] a;
real b;
real c;
logic signed [7:0] d;
initial
begin
a = 3.3333;
b = 11.7;
$display("a =%f, b=%f,c=%f,d=%f", a,b,c,d);
end
fp_check s (.a(a), .b(b), .c(c), .d(d));
endmodule
The output I get is a =3.000000, b=11.700000,c=0.000000,d=0.000000
What I expect is a =3.333333, b=11.700000,c=6.666666,d=12.700000
I have a previous answer on this subject Verilog Fractional multiplication? which should serve well as background for this problem. Another answer that deals with how precision is required .
Following on from them with 4 bit integer 4 bit fractional numbers the bits represent:
Base 2: Twos complement 4 integer, 4 bit frational
-2^3 2^2 2^1 2^0 . 2^-1 2^-2 2^-3 2^-4
-8 4 2 1 . 0.5 0.25 0.125 0.0625
It should start to become clear that here is an issue with your example expecting '3.333333' as an answer, unless your implementing a rational divider which keeps numerator and denominators held as separate numbers it is impossible for a binary system to hold the value '1/3' We can get very close but never exactly. On the other hand 1/4 is easy.
On way of performing the fixed point maths with integers is to scale by the number of fractional bits you want, for example:
integer a = 10;
integer b = 3;
localparam FRAC = 4;
initial begin
#1;
//Scaling to the power of 2.0 not 2. This forces a real evaluagion of the number for display.
$display("No Scaling down : %f", (a*2.0**FRAC / b*2.0**FRAC));
//Scaling back down by 4 to the power because of fractional bit growth
$display("Scaled back down : %f", (a*2.0**FRAC / b*2.0**FRAC)*4.0**-FRAC);
end
You need to use fixed point arithmetic. See http://amakersblog.blogspot.com/2008/07/fixed-point-arithmetic-with-verilog.html For example
`timescale 1ns/1ps
package fixed_point;
parameter M = 8;
parameter F = 12;
typedef bit signed [M-1:-F] fp_t;
function fp_t real2fp(real value);
return value*2.0**F;
endfunction : real2fp
function real fp2real(fp_t value);
return value/2.0**F;
endfunction : real2fp
endpackage : fixed_point
import fixed_point::*;
module fp_check (
input fp_t a,
input fp_t b,
output fp_t c,
output fp_t d);
assign c = a*2;
assign d = b+real2fp(1);
endmodule
module fp_test;
fp_t a,b,c,d;
initial
begin
a = real2fp(3.3333);
b = real2fp(11.7);
$strobe("a =%f, b=%f,c=%f,d=%f", fp2real(a),fp2real(b),fp2real(c),fp2real(d) );
end
fp_check s (.a(a), .b(b), .c(c), .d(d));
endmodule : fp_test
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.