在systemverilog中显示分数

时间:2016-09-20 17:15:36

标签: floating-point verilog system-verilog

我想做一个分数算术,然后显示结果。我知道$ display以整数形式显示。但是显示确切数量的解决方案是什么,例如我想显示10/3 = 3.3但是我显示3.0000。这是我的代码。我不想在这里使用真实数据类型。

`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

我得到的输出是a = 3.000000,b = 11.700000,c = 0.000000,d = 0.000000

我的期望是a = 3.333333,b = 11.700000,c = 6.666666,d = 12.700000

2 个答案:

答案 0 :(得分:1)

我之前有关于此主题Verilog Fractional multiplication?的答案,应该可以作为此问题的背景。另一个涉及how precision is required的答案。

继续使用4位整数4位小数后,这些位代表:

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

应该开始明白,这是一个问题,你的例子期望'3.333333'作为答案,除非你实现一个合理的分频器,它将分子和分母保持为单独的数字,二元系统不可能保持价值'1/3'我们可以非常接近,但从来没有完全。另一方面1/4很容易。

在使用整数执行定点数学运算时,可以按所需的小数位数进行缩放,例如:

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

答案 1 :(得分:1)

您需要使用定点算术。见http://amakersblog.blogspot.com/2008/07/fixed-point-arithmetic-with-verilog.html 例如

`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