循环型的除法器,如果用笔者的话来说,就是位操作的除法器。循环型的除法器是典型的硬件除法器,假设除数和被除数的位宽为N 位,那么除法器就需要循环N 次完成除法操作,结果取得“N 位商和N 位余”。假设被除数A =10,除数B = 3,为了使除数B大于除数A,让B‘ = B*2^m, 假设m = 6,R为余数,Q为商。
循环结束,R = 64*2 =128 ,正确的R '= R/2^(m+1) = 128/128 =1,Q = 0000011
/*************************************************************************************************************
作者:冬瓜
时间:2015.7.16
功能:两个8位数(整数)的除法,
************************************************************************************************************/
module cycle_divider
(
clk,rst_n,
a,b,c,d,
is_start_sig,
is_done_sig
);
input clk,rst_n;//时钟,复位信号
input [ 7:0 ]a;//被除数
input [ 7:0 ]b;//除数
output [ 7:0 ]c,d;//商,余数
input is_start_sig;//开始信号
output is_done_sig;//结束信号
reg [ 3:0 ]state;
reg [ 7:0 ]s;
reg [ 7:0 ]q;
reg [ 15:0 ]_s;
reg rDone,rNeg;
reg [ 15:0 ]r;
always @( posedge clk or negedge rst_n )
if( !rst_n )
begin
state <= 'd0;
s <= 'd0;
_s <= 'd0;
r <= 'd0;
q <= 'd0;
rDone <= 'd0;
rNeg <= 'd0;
end
else if( is_start_sig )
case( state )
'd0: begin
rNeg <= a[ 7 ]^b[ 7 ];
s <= b[ 7 ]? ( ~b + 1'b1 ): b;//取除数的绝对值
state <= state + 1'b1;
_s <= b[ 7 ]?{ 8'hff,b }:{ 8'hff,~b + 1'b1 };
r <= a[ 7 ]?{ 8'd0,~a + 1'b1 }:{ 8'd0,a }; end
'd1,'d2,'d3,'d4,
'd5,'d6,'d7,'d8:
if( r < ( s<<7 ) ) begin q[ 8-state ] <= 1'b0; r <= r<<1; state <= state + 1'b1; end
else begin q[ 8-state ] <= 1'b1; r <= ( r + ( _s<<7) )<<1; state <= state + 1'b1; end
'd9: begin rDone <= 1'b1; state <= state + 1'b1; end
'd10:begin rDone <= 1'b0; state <= 'd0; end
default: state <= 'd0;
endcase
assign c = rNeg ? ( ~q + 1'b1 ): q;
assign d = r[ 15:8 ];
assign is_done_sig = rDone;
endmodule
//激励文件
`timescale 1ns / 1ns
module cycle_divider_test();
reg [ 7:0 ]a,b;
reg clk,rst_n;
reg is_start_sig;
wire [ 7:0 ]c,d;
wire is_done_sig;
cycle_divider I1
(
.clk( clk ),
.rst_n( rst_n ),
.a( a ),
.b( b ),
.c( c ),
.d( d ),
.is_start_sig( is_start_sig ),
.is_done_sig( is_done_sig )
);
initial
begin
clk = 0;
rst_n = 1;
#200;
rst_n = 0;
#200;
rst_n = 1;
forever #20 clk = ~clk;
end
reg [ 3:0 ]i;
always @( posedge clk or negedge rst_n )
if( !rst_n )
begin
i <= 'd0;
is_start_sig <= 'd0;
a <= 'd0;
b <= 'd0;
end
else
case( i )
'd0: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= 'd12; b <= 'd3; end
'd0: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= -'d25; b <= 'd5; end
'd1: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= 'd36; b <= 'd6; end
'd2: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= 'd12; b <= 'd5; end
'd3: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= -'d34; b <= -'d3; end
'd4: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= 'd67; b <= 'd7; end
'd5: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= -'d19; b <= 'd8; end
'd6: if( is_done_sig ) begin is_start_sig <= 1'b0; i <= i+ 1'b1; end
else begin is_start_sig <= 1'b1; a <= -'d19; b <= 'd38; end
'd7: i <= 'd7;
default: i <= 'd0;
endcase
endmodule