DAY 27
1
Software Development

## 【Day27】線性收斂除法器實作

`N/D = Q..R，其中|R|<D`

`N = D x Q + R`

## 實作方法

``````/*-------localparam-------*/
localparam IDLE    = 2'd0;
localparam SUB     = 2'd1;
localparam RESTORE = 2'd2;
localparam FINISH  = 2'd3;
``````

``````module divRes(
clkSys,
en,
rst_n,
dividend,
divisor,
r_out,
q_out,
done
);
/*-------ports declarations-------*/
input        clkSys;
input        en;
input        rst_n;
input  [7:0] dividend;
input  [5:0] divisor;
output [5:0] r_out;
output [7:0] q_out;
output       done;
reg    [5:0] r_out;
reg    [7:0] q_out;
reg          done;
``````

``````/*-------variables-------*/
reg    [1:0] fstate;
reg    [3:0] count;
reg    [7:0] q;
reg   [13:0] d;
reg signed [13:0] r;
``````

``````/*-------fstate state-------*/
always@(posedge clkSys or negedge rst_n)begin
if(!rst_n)fstate <= IDLE;
else begin
case(fstate)
IDLE:begin
if(en)fstate <= SUB;
else  fstate <= IDLE;
end
SUB:fstate <= RESTORE;
RESTORE:begin
if(count == 4'd8)fstate <= FINISH;
else             fstate <= SUB;
end
FINISH:fstate <= IDLE;
default:fstate <= IDLE;
endcase
end
end
``````

``````/*-------fstate output-------*/
always@(posedge clkSys or negedge rst_n)begin
if(!rst_n)begin
count <= 4'd0;
r_out <= 6'd0;
q_out <= 8'd0;
q     <= 8'd0;
r     <= 14'd0;
d     <= 14'd0;
done  <= 1'b0;
end
else begin
case(fstate)
IDLE:begin
count <= 4'd0;
q     <= 8'd0;
d     <= divisor << 7;//load divisor
r     <= dividend;//Remainder = dividend
done  <= 1'b0;
end
SUB:begin
r     <= r - d;
count <= count + 4'd1;
end
RESTORE:begin
if(r<0)begin
r <= r + d;
q <= q << 1;//left shift and LSB = 0
end
else begin
r <= r;
q <= {q[6:0], 1'b1};//left shift and LSB = 1
end
d <= d >> 1;
end
FINISH:begin
q_out <= q;
r_out <= r[5:0];
done  <= 1'b1;
end
default:begin
count <= 4'd0;
r_out <= 6'd0;
q_out <= 8'd0;
q     <= 8'd0;
r     <= 14'd0;
d     <= 14'd0;
done  <= 1'b0;
end
endcase
end
end
endmodule
``````

## TestBench

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

reg        clkSys;
reg        en;
reg        rst_n;
reg  [7:0] dividend;
reg  [5:0] divisor;
wire [5:0] r_out;
wire [7:0] q_out;
wire       done;

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

initial begin
clkSys = 0;
rst_n  = 0;
repeat(2)@(posedge clkSys)rst_n = 0;
rst_n = 1;
test(234,50);
test(196,20);
test(97 ,15);
test(200,11);
test(19 ,50);
test(192 ,1);
test(64 ,2);
#1000 \$stop;
end

always #10 clkSys = ~clkSys;

input [7:0]a;
input [5:0]b;
begin
dividend = a;
divisor  = b;
#40 en = 1;
#20 en = 0;

wait (done == 1);
end