在补码一位除法中必须比较被除数(余数)和除数的大小,并根据比较的结果上商。另外,未了避免溢出,商的绝对值不能大于1,即被除数的绝对值一定要小于除数的绝对值。
补码加减交替法的算法规则如下:
(1)
求第一位商要被除数和除数数符号的同异,被除数x与除数y同号,被除数x加[-y]补;被除数x与除数y异号,被除数x加[y]补,得z。
(2)余数z左移一位,上商,余数z与除数y同号,商q[0]=1,z=z+[-y]补。余数z与除数y异号,商q[0]=0,z=z+[y]补.q左移一位.转(3)
(3)重复步骤(2),包括符号位在内,共做n+1步。转(4)
(4)一般情况采用未位恒置“1”的方式进行舍入。
如果需要进一步以高精度,可以不用未位恒置“1”的方式舍入,而按上述法则多求一位后,再采用如下修正方法对商进行处理:
(1) 刚好能除尽时,如果除数为正,商不必修正;如果除数为负,则商加2-n.
(2) 不能除尽时,如果商为正,则不必修正,如果商为负,则商加2-n.
module div25(
done,
c,
a,
b,
start,
clk
);
parameter N=25;
output done;
output [N-1:0]c;
input [N-1:0]a;
input [N-1:0]b;
input start;
input clk;
reg [4:0]index;
reg [N:0]z;
reg [N:0]x;
reg [N:0]y;
reg [N:0]y_c;
reg finished;
reg [1:0]current_state,next_state;
parameter Init=0,Load=1,Acc=2,Done=3;
always @(posedge clk or negedge start)
if (!start)
current_state<=Init;
else
current_state<=next_state;
always @(current_state or index or over)
case (current_state )
Init :
begin
next_state=Load;
end
Load:
begin
if (over)
next_state=Done;
else
next_state=Acc;
end
Acc :
begin
if(index==5'h18)
begin
next_state=Done;
end
end
endcase
always @(current_state or index)
case (current_state)
Init:
begin
finished=0;
end
Load:
begin
y={b[N-1],b[N-1:0]};
y_c=~{b[N-1],b[N-1:0]}+1;
x=0;
if(a[N-1]==b[N-1])
z[N:0]={a[N-1],a[N-1:0]}+y_c;
else
z[N:0]={a[N-1],a[N-1:0]}+y;
$display("z=%b,x=%b,y=%b,y_c=%b",z,x,y,y_c);
end
Acc:
begin
if(z[N]==y[N])
begin
z={z[N-1:0],1'b0}+y_c;
x[0]=1;
$display("Same-After adding :z=%b,x=%b",z,x);
end
else
begin
z={z[N-1:0],1'b0}+y;
x[0]=0;
$display("Different-After adding y:z=%b,x=%b",z,x);
end
x={x[N-1:0],1'b0};
end
default:
begin
finished=1;
x[0]=1;
$display("c=%b",c);
end
endcase
always @(posedge clk)
if (current_state==Acc)
index<=index+1;
else
index<=0;
assign done=finished;
assign c[N-1:0]=x[N:1];
endmodule | module test_div25_v;
// Inputs
reg [24:0] a;
reg [24:0] b;
reg start;
reg clk;
// Outputs
wire done;
wire [24:0] c;
// Instantiate the Unit Under Test (UUT)
div25 uut (
.done(done),
.c(c),
.a(a),
.b(b),
.start(start),
.clk(clk)
);
initial begin
// Initialize Inputs
a = 0;
b = 0;
start = 0;
clk = 0;
// Wait 100 ns for global reset to finish
#100;
start=1;
// Add stimulus here
a=25'h0_80_00_00;
b=25'h1_60_00_00;
a=25'h0_90_00_00;
b=25'h0_b0_00_00;
end
always #10 clk=~clk;
endmodule |