Серия Тейлора в Verilog

Я делаю свой первый студенческий проект в Verilog. Мой проект состоит в том, чтобы вычислить логарифмическую базу 2, используя «ряд Тейлора» в арифметике с фиксированной точкой (s4.27). Я также реализовал метод Хорнера в своем коде.

В целом это выглядит так:

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 для компиляции.

Код для множителя с фиксированной точкой (qmult) и сумматора (qadd)

Я уверен, что есть ошибки, но в настоящее время мои глаза новичка не могут их заметить. Что мне не хватает?


person Shaown    schedule 22.01.2018    source источник


Ответы (1)


Я предлагаю вам сделать только одно умножение и один сумматор и проверить результат. Умножения с фиксированной точкой должны быть очень хорошо проверены на переполнение, что, как я очень сильно подозреваю, здесь имеет место!

Это проблема, с которой я сталкивался снова и снова: множители во всех примерах Verilog берут два N битных числа и дают результат 2N. Очень немногие источники затрагивают, например, 20-ступенчатый КИХ-фильтр, в котором у вас есть двадцать множителей, каждый из которых использует два 16-битных числа. Следуя «примеру» кода, вы получите 52-битный результат.


Для предотвращения переполнения каждый аргумент умножения должен быть ‹16 бит. (Поскольку вы используете 32-битные результаты). Затем каждый раз, когда вы добавляете, вам нужен еще один дополнительный бит. Таким образом, либо ваши данные становятся шире дальше по потоку, либо вы должны начать с достаточно малого размера, чтобы он соответствовал конечному результату в 32 бита.

Вы можете компенсировать, если у вас есть постоянные значения и вы знаете, каков диапазон результата. например в цифровом фильтре все коэффициенты в сумме дают 1, и они часто бывают положительными, отрицательными, положительными, отрицательными, поэтому дополнения не все время увеличиваются.

Добро пожаловать в мир аппаратной целочисленной арифметики!

person Oldfart    schedule 22.01.2018