iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
Software Development

verilog or very lag系列 第 28

【Day28】2次收斂除法器實作

接下來探討一種透過牛頓法來找到相除解的方法

收斂除法

  • Step1 : 規格化 N 和 D,令 D 趨近於 1,例如 0.5 <= D < 1 or 1 <= D < 2
  • step2 : 初始化 x0 = Nt0 = D
  • step3 : 重複如下循環,直到 xk 滿足所需精度
    • fk = 2 - tk
    • xk+1 = xk * fk
    • tk+1 = tk * fk

次數通常為:上高斯的(根號(bit 數))

宣告狀態

/*------localparam------*/
localparam IDLE   = 2'd0;
localparam CAL    = 2'd1;
localparam FINISH = 2'd2;

宣告輸入輸出

module divAegp(
  clkSys,
  en,
  rst_n,
  dividend,
  divisor,
  q_out,
  done
);
/*------ports declarations------*/
input        clkSys;
input        en;
input        rst_n;
input  [8:0] dividend;
input  [8:0] divisor;
output [8:0] q_out;
output       done;
reg    [8:0] q_out;
reg          done;

宣告變數

  • tempX 及 tempT 用來存放乘法後結果,需要兩倍寬的 bit 數
/*------variables------*/
reg    [1:0] fstate;
reg    [1:0] count;
reg    [9:0] x;
reg    [9:0] t;
reg    [9:0] f;
reg   [17:0] tempX;
reg   [17:0] tempT;

狀態邏輯

/*-------fstate state-------*/
always@(posedge clkSys or negedge rst_n)begin
  if(!rst_n)fstate <= IDLE;
  else begin
    case(fstate)
      IDLE:begin
        if(en)fstate <= CAL;
        else  fstate <= IDLE;
      end
      CAL:begin
        if(count == 2'd1)fstate <= FINISH;
        else             fstate <= CAL;
      end
      FINISH:fstate <= IDLE;
      default:fstate <= IDLE;
    endcase
  end
end

輸出邏輯

/*-------fstate output-------*/
always@(posedge clkSys or negedge rst_n)begin
  if(!rst_n)begin
    q_out <= 9'd0;
    x     <= 10'd0;
    t     <= 10'd0;
    f     <= 10'd0;
    tempX <= 18'd0;
    tempT <= 18'd0;
    count <= 2'd0;
    done  <= 1'b0;
  end
  else begin
    case(fstate)
      IDLE:begin
        count <= 2'd0;
        x     <= {1'b0, dividend};
        t     <= {1'b0, divisor};
        done  <= 1'b0;
      end
      CAL:begin
        f = 10'd512 - t;
        tempX = (x * f);
        tempT = (t * f);
        x     <=  tempX >> 8;
        t     <=  tempT >> 8;
        count <= count + 2'd1;
      end
      FINISH:begin
        q_out <= x[8:0];
        done  <= 1'b1;
      end
      default:begin
        q_out <= 9'd0;
        x     <= 10'd0;
        t     <= 10'd0;
        f     <= 10'd0;
        tempX <= 18'd0;
        tempT <= 18'd0;
        count <= 2'd0;
        done  <= 1'b0;
      end
    endcase
  end
end
endmodule

TestBench


`timescale 1ns/1ns
module tb_divAegp();

reg        clkSys;
reg        en;
reg        rst_n;
reg  [8:0] dividend;
reg  [8:0] divisor;
wire [8:0] q_out;
wire       done;

divAegp UUT(
  .clkSys(clkSys),
  .en(en),
  .rst_n(rst_n),
  .dividend(dividend),
  .divisor(divisor),
  .q_out(q_out),
  .done(done)
);

initial begin
  clkSys = 0;
  en = 0;
  rst_n = 0;
  repeat(5)@(posedge clkSys)rst_n = 0;
  rst_n = 1;
  test(384, 307);//320
  test(360, 300);//307
  test(350, 310);//289
  test(400, 257);//398#
  #1000 $stop;
end

always #10 clkSys = ~clkSys;

task test;
input [8:0]a;
input [8:0]b;
  begin
    dividend = a;
    divisor  = b;
    #100 en = 1;
    #40  en = 0;
    wait (done == 1);
  end
endtask

endmodule

Wave

舉個例子:
第一筆測試資料為 1.5(384/256) 除以 1.2(307/256) 應該要得到的答案是 1.25(320),後面的例子以此類推~~

那麼今天的教學就到這邊嘍~~


上一篇
【Day27】線性收斂除法器實作
下一篇
【Day29】Cordic 演算法的實現
系列文
verilog or very lag30

尚未有邦友留言

立即登入留言