URL
https://opencores.org/ocsvn/signed_integer_divider/signed_integer_divider/trunk
Subversion Repositories signed_integer_divider
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/signed_integer_divider/trunk/divider_tb.v
0,0 → 1,135
module divider_tb(); |
|
reg clk=0,rst=0; |
always #1 clk=~clk; |
|
initial #10 rst=1; |
|
/// driver |
reg [31:0]dividend=0,divisor=0; |
reg start=0; |
wire ready; |
reg state_driver=0; |
always@(posedge clk) |
if(rst)begin |
case(state_driver) |
0:begin |
start<=1; |
state_driver<=1; |
dividend<=$random; |
divisor<=$random; |
end |
1:if(ready)begin |
start<=0; |
state_driver<=0; |
end |
endcase |
end |
|
/// |
|
/// monitor |
wire [31:0]quotient,remainder; |
reg state_m=0; |
|
always@(posedge clk) |
if(rst)begin |
case(state_m) |
0:if(start)begin |
if(dividend[31])$write("%6d dividend=-%d",$time,(~dividend)+1); |
else $write("%6d dividend=%d",$time,dividend); |
if(divisor[31])$write(" divisor=-%d\n",(~divisor)+1); |
else $write(" divisor=%d\n",divisor); |
state_m<=1; |
end |
1:if(ready)begin |
state_m<=0; |
if(quotient[31])$write("%6d quotient=-%d",$time,(~quotient)+1); |
else $write("%6d quotient=%d",$time,quotient); |
if(remainder[31])$write(" remainder=-%d\n",(~remainder)+1); |
else $write(" remainder=%d\n",remainder); |
end |
endcase |
end |
/// |
|
|
/// score board |
|
// test vector record |
integer DD_FH,DR_FH,Q_FH,R_FH; |
initial begin |
DD_FH=$fopen("F:/work/divider/test pattern/dividend.txt"); |
DR_FH=$fopen("F:/work/divider/test pattern/divisor.txt"); |
Q_FH=$fopen("F:/work/divider/test pattern/quotient.txt"); |
R_FH=$fopen("F:/work/divider/test pattern/remainder.txt"); |
end |
// |
wire sign_q,sign_r; |
assign sign_q=dividend[31]^divisor[31]; |
assign sign_r=dividend[31]; |
|
reg [62:0]PR=0; |
wire [31:0]DR; |
assign DR=divisor[31]?(~divisor)+1:divisor; |
|
reg [31:0]q_tb=0,r_tb=0; |
integer i; |
always@* begin |
PR={31'd0,dividend[31]?(~dividend)+1:dividend}; |
for(i=31;i>=0;i=i-1)begin |
if(PR[62:31]>=DR)begin |
PR[62:31]=PR[62:31]-DR; |
if(i!=0)PR=PR<<1; |
q_tb[i]=1; |
end |
else begin |
q_tb[i]=0; |
if(i!=0)PR=PR<<1; |
end |
end |
q_tb=sign_q?(~q_tb)+1:q_tb; |
r_tb=sign_r?(~PR[62:31])+1:PR[62:31]; |
$fwrite(DD_FH,",0x%h",dividend); |
$fwrite(DR_FH,",0x%h",divisor); |
$fwrite(Q_FH,",0x%h",q_tb); |
$fwrite(R_FH,",0x%h",r_tb); |
end |
/// |
|
/// checker |
always@(posedge clk) |
if(rst)begin |
if(ready)begin |
if(quotient==q_tb)$write("quotient match"); |
else begin |
$write("quotient mismatch"); |
if(q_tb[31])$write(" q_tb=-%d",(~q_tb)+1); |
else $write(" q_tb=%d",q_tb); |
end |
if(remainder==r_tb)$write(" remainder match\n"); |
else begin |
$write(" remainder mismatch"); |
if(r_tb[31])$write(" r_tb=-%d\n",(~r_tb)+1); |
else $write(" r_tb=%d\n",r_tb); |
end |
end |
end |
/// |
|
|
///DUT |
divider_dshift divider_0( |
clk, |
rst, |
dividend, |
divisor, |
start, |
ready, |
quotient, |
remainder |
); |
|
|
/// |
endmodule |
/signed_integer_divider/trunk/divider_dshift.v
0,0 → 1,273
module divider_dshift( |
input i_clk, |
input i_rst, |
input [31:0]i_dividend, |
input [31:0]i_divisor, |
input i_start, |
output o_ready, |
output reg [31:0]o_quotient, |
output reg [31:0]o_remainder |
); |
|
parameter |
state_1=1, |
state_2=2, |
state_3=4, |
state_4=8, |
state_5=16, |
state_6=32; |
|
|
reg [31:0]PR; //partial remainder |
reg signed[31:0]PR_1; |
reg [31:0]DR; //divisor |
reg [5:0]ct,ct_1; // ct: index for quotient bit under calculation ct_1: shift value for last PR |
reg ct_1_en,ct_1_en_1; // enable calculating of ct_1 |
reg DD_sign; //sign of dividend |
reg [5:0]state; |
reg ready; |
assign o_ready=ready?i_start:0; |
reg [30:0]nq; //negative quotient |
reg [30:0]q; //positive quotient |
wire [30:0]nqp1; // nq+1 |
wire [30:0]qp1; // q+1 |
assign nqp1=nq+1; |
assign qp1=q+1; |
|
wire [31:0]nDR; |
assign nDR=~DR; |
wire nsub; // not sub '1' means PR=PR+DR; |
// '0' means PR=PR-DR; |
assign nsub=PR[31]^DR[31]; |
|
|
/// over subtract detection during final results adjustment |
wire over_sub; |
//assign over_sub=(state==state_4)||(state==state_3)?DD_sign^PR[62]&(PR[62:31]!=0):0; |
assign over_sub=(DD_sign^PR[31])&(PR[31:0]!=0); |
//reg over_sub; |
wire addback_nDR; |
wire addback_DR; |
assign addback_nDR=over_sub&(~nsub); |
assign addback_DR=over_sub⊄ |
/// |
/// results adjustment |
wire [30:0]final_nq,final_q; |
assign final_nq=addback_DR?nqp1:nq; |
assign final_q=addback_nDR?qp1:q; |
wire [31:0]remainder_addback; |
assign remainder_addback= addback_DR?i_divisor: |
addback_nDR?~i_divisor:0; |
/// |
|
/// main subtractor |
wire [31:0]a,b; |
wire [31:0]sum; |
wire carry_in; |
wire carry_out; |
|
reg [31:0]reg_a,reg_b; |
reg reg_carry; |
reg [1:0]state_reg; |
|
///////////// Dynamic Shift ///////////// |
reg [4:0]shifted,shifted_1; |
reg [31:0]sdata; |
wire [31:0]sdata_o; |
wire [4:0]shifted_o; |
shifter shifter_0( |
sdata, |
sdata_o, |
shifted_o |
); |
|
/* |
assign a= |
state==state_4?{1'b1,~final_nq}: |
state==state_5?remainder_addback: |
nsub?DR:nDR; |
*/ |
assign a= ct_1_en?{27'd0,shifted_1}: |
state==state_4?{1'b1,~final_nq}: |
state==state_5?remainder_addback: |
nsub?DR:nDR; |
assign b= ct_1_en?{26'd0,ct_1}: |
state==state_4?{1'b0,final_q}: |
state==state_5?PR_1:PR; |
|
assign carry_in= ct_1_en?0: |
state==state_4?1: |
state==state_5? addback_nDR?1:0: |
nsub?0:1; |
|
adder_32bit adder_0( |
reg_a, |
reg_b, |
reg_carry, |
sum, |
carry_out |
); |
|
|
|
|
// ct calculation |
//reg UDR; // update Divisor |
wire [5:0]sum_ct; |
wire [25:0]sum_ct_h; |
wire carry_ct; |
adder_32bit adder_1( |
{26'd0,ct}, |
state[5]?{27'd0,shifted}:~{27'd0,shifted}, |
state[5]?1'b0:1'b1, |
{sum_ct_h,sum_ct}, |
carry_ct |
); |
|
|
|
|
|
|
/////////////////////////////////////////// |
|
always@(posedge i_clk or negedge i_rst) |
if(!i_rst)begin |
sdata<=0; |
shifted<=0; |
shifted_1<=0; |
PR<=0; |
PR_1<=0; |
DR<=0; |
//UDR<=0; |
ready<=0; |
ct<=0; |
ct_1<=0; |
ct_1_en<=0; |
ct_1_en_1<=0; |
state<=state_1; |
DD_sign<=0; |
o_quotient<=0; |
o_remainder<=0; |
nq<=0; |
q<=0; |
//over_sub<=0; |
reg_a<=0; |
reg_b<=0; |
reg_carry<=0; |
state_reg<=0; |
end |
else begin |
if(ready&&(!i_start))ready<=0; |
case(state_reg) |
0: |
case(state) |
state_1:if((!ready)&&i_start)begin |
sdata<=i_divisor; |
state<=state_6; |
q<=0; |
nq<=0; |
shifted<=0; |
//UDR<=1; |
end |
state_2:begin |
sdata<=i_dividend; |
PR_1<=i_dividend; |
DD_sign<=i_dividend[31]; |
state<=state_3; |
state_reg<=1; |
end |
state_3:begin |
if(ct[5])begin |
state<=state_4; |
ct<=0; |
state_reg<=2; |
end |
else begin |
ct_1_en<=1; |
shifted_1<=shifted; |
nq[ct]<=nsub; |
q[ct]<=~nsub; |
sdata<=sum; |
state_reg<=1; |
end |
end |
state_4:begin |
state<=state_5; |
o_quotient<=sum; |
PR_1<=PR_1>>>ct_1; |
state_reg<=2; |
end |
state_5:begin |
o_remainder<=sum; |
ct_1<=0; |
state<=state_1; |
ready<=1; |
end |
|
state_6:begin |
sdata<=sdata_o; |
shifted<=shifted_o; |
ct<=sum_ct; |
if(sdata[31]!=sdata[30])begin |
state<=state_2; |
DR<=sdata; |
end |
end |
/* |
state_6:begin |
//if(!over_sub)o_remainder<=sum>>>ct_1; |
o_remainder<=sum; |
ct_1<=0; |
state<=state_1; |
ready<=1; |
end |
|
*/ |
endcase |
1:begin |
PR<=sdata_o; |
PR_1<=sdata; |
/* |
if(UDR)begin |
UDR<=0; |
ct<=shifted; |
|
if(shifted==0)begin |
ct<=0; |
end |
else begin |
ct<=shifted-1; |
DR<={DR[31],DR[31:1]}; |
end |
|
end |
*/ |
shifted<=shifted_o; |
state_reg<=2; |
reg_a<=a; //calculate ct_1 |
reg_b<=b; |
reg_carry<=carry_in; |
ct_1_en<=0; |
ct_1_en_1<=ct_1_en; |
end |
2:begin |
if(state==state_3)begin |
ct<=sum_ct; |
end |
state_reg<=0; |
if(ct_1_en_1)begin |
ct_1<=sum[5:0]; |
end |
ct_1_en_1<=0; |
reg_a<=a; // calculate PR |
reg_b<=b; |
reg_carry<=carry_in; |
end |
endcase |
end |
|
|
|
|
endmodule |