DAY 28
1
Software Development

## 【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;

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

endmodule

``````

Wave