【问题标题】:Taylor Series in VerilogVerilog 中的泰勒级数
【发布时间】:2018-01-22 21:25:55
【问题描述】:

我正在 Verilog 中做我的第一个学生项目。我的项目是在定点算术(s4.27)中使用“泰勒级数”计算以 2 为底的对数。我在我的代码中也实现了 Horner 方法。

总体来说是这样的:

log=c0+(q*(c1+(q*(c2+(q*(c3+(q*(c4(q*(c5+(q*c6))))))))));

最后 log_base_2=log*con;

`timescale 10ns/10ns

module log (q ,clk,log_result);

input clk;
input [31:0] q; // q=x-a; x=user input, a=1.5 (Taylor series is calculated around point "a")

output [31:0] log_result;

localparam con= 32'h0B8AA3B0; //1.44269504088895
localparam c0 = 32'h033E647C; //0.40546510810816
localparam c1 = 32'h05555558; //0.66666666666666
localparam c2 = 32'hFE38E38E; //-0.222222222222
localparam c3 = 32'h00CA4588; //0.0987654321
localparam c4 = 32'hFF9ADD3C; //-0.04938271605
localparam c5 = 32'h0035F068; //0.02633744856
localparam c6 = 32'hFFE208AA; //-0.01463191587

wire [31:0] x0,x1,x2,x3,x4,x5,x6;
wire [31:0] y0,y1,y2,y3,y4,y5,y6;

multiplier  #(27,32) m6(.i_multiplicand(q),.i_multiplier(c6),.o_result(x6));
adder       #(27,32) a6 (.a(x6),.b(c5),.c(y6));
multiplier  #(27,32) m5(.i_multiplicand(q),.i_multiplier(y6),.o_result(x5));
adder       #(27,32) a5 (.a(x5),.b(c4),.c(y5));
multiplier  #(27,32) m4(.i_multiplicand(q),.i_multiplier(y5),.o_result(x4));
adder       #(27,32) a4 (.a(x4),.b(c3),.c(y4));
multiplier  #(27,32) m3(.i_multiplicand(q),.i_multiplier(y4),.o_result(x3));
adder       #(27,32) a3 (.a(x3),.b(c2),.c(y3));
multiplier  #(27,32) m2(.i_multiplicand(q),.i_multiplier(y3),.o_result(x2));
adder       #(27,32) a2 (.a(x2),.b(c1),.c(y2));
multiplier  #(27,32) m1(.i_multiplicand(q),.i_multiplier(y2),.o_result(x1));
adder       #(27,32) a1 (.a(x1),.b(c0),.c(y1));
multiplier  #(27,32) (.i_multiplicand(con),.i_multiplier(y1),.o_result(x0));

assign log_result = x0;

endmodule

测试台代码:

`timescale 10ns/10ns

module tb_log ();

reg clk;
reg [ 31 : 0 ] q;

wire [ 31 : 0 ] log_result;

log log_i (
    .q(q),
    .clk(clk),
    .log_result(log_result)     
    );

parameter CLKPERIODE = 100;

initial clk = 1'b1;
always #(CLKPERIODE/2) clk = !clk;

initial begin

$dumpfile("log_wave.vcd");
$dumpvars(1);


$monitor ("Q=%h,Log2=%h ", q, log_result);

#1
  #(CLKPERIODE)
  q = 32'hFC000000; // q=1-1.5=-0.5;
  $finish();

end

endmodule

所以我期望结果接近于零。但不幸的是,我得到了 9B917CED。当我尝试包含时钟时,发生了一个名为“格式错误的语句”的错误。我正在使用 Icarus verilog 进行编译。

Code for fixed-point multiplier(qmult) and adder(qadd)

我确定有错误,但目前我的菜鸟眼睛无法注意到它。 我错过了什么?

【问题讨论】:

    标签: verilog fixed-point taylor-series


    【解决方案1】:

    我建议你只做一次乘法和一次加法,然后检查结果。应该很好地检查定点乘法是否溢出,我非常怀疑这里就是这种情况!

    这是我一次又一次看到的问题:所有 Verilog 示例中的乘法器采用两个 N 位数并产生 2N 结果。很少有来源解决例如一个 20 级 FIR 滤波器,其中有 20 个乘法器,每个乘法器使用两个 16 位数字。按照“示例”代码,您最终会得到 52 位宽的结果。


    为防止溢出,乘法的每个参数应小于 16 位。 (当您使用 32 位结果时)。然后,每次添加时,您都需要额外的一点。因此,要么您的数据在流的下游变得更宽,要么您必须从足够小的开始,以使其适合 32 位的最终结果。

    如果您有恒定值并且知道结果的范围是多少,您可以进行补偿。例如在数字滤波器中,所有系数加起来为 1,它们通常是正的、负的、正的、负的,因此加法不会一直递增。

    欢迎来到硬件整数运算的世界!

    【讨论】:

      猜你喜欢
      • 2014-02-23
      • 2014-04-03
      • 2016-08-09
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 2018-10-07
      • 2016-07-26
      • 2018-06-23
      相关资源
      最近更新 更多