原理参考
module div_top #(
parameter M = 5,
parameter N = 3
)
(
input clk,
input rst,
input en,
input [M-1:0] divided,
input [N-1:0] divisor,
output [M-1:0] quotient,
output [N-1:0] remainder
);
//save quotient and remainder lever by lever
wire [M-1:0] quotient_co [M-1:0];
wire [N-1:0] remainder_co [M-1:0];
//tansfer divided and divisor
wire [M-1:0] divided_kp [M-1:0];
wire [N-1:0] divisor_kp [M-1:0];
//the first level
div_initial #( .M(5),
.N(3)
)
u1 (
.clk(clk),
.rst(rst),
.en(en),
.divided_fir({{(N-1){1'b0}},divided[M-1]}),
.divided(divided),
.divisor(divisor),
.divided_kp(divided_kp[0]),
.divisor_kp(divisor_kp[0]),
.quotient_co(quotient_co[0]),
.remainder_co(remainder_co[0])
);
//use loop to generate next level
genvar i;
generate
for (i=1; i <= M-1; i=i+1) begin:div_bit
div_cell #( .M(5),
.N(3)
)
u2 (
.clk(clk),
.rst(rst),
.en(en),
.divided_bit(divided_kp[i-1][M-i-1]),
.divided(divided_kp[i-1]),
.divisor(divisor_kp[i-1]),
.divided_kp(divided_kp[i]),
.divisor_kp(divisor_kp[i]),
.quotient_ci(quotient_co[i-1]),
.remainder_ci(remainder_co[i-1]),
.quotient_co(quotient_co[i]),
.remainder_co(remainder_co[i])
);
end
endgenerate
assign quotient = quotient_co[M-1];
assign remainder = remainder_co[M-1];
endmodule
.divided_bit(divided_kp[i-1][M-i-1])//可实现二维下标访问
module div_initial #(
parameter M = 5,
parameter N = 3
)
(
input clk,
input rst,
input en,
input [M-1:0] divided,
input [N-1:0] divisor,
input [N-1:0] divided_fir,
output reg [M-1:0] divided_kp,
output reg [N-1:0] divisor_kp,
output reg [M-1:0] quotient_co,
output reg [N-1:0] remainder_co
);
always@(posedge clk or negedge rst) begin
if (!rst) begin
quotient_co <= 'b0;
remainder_co <= 'b0;
end
else if (en) begin
//tansfer divided and divisor
divided_kp <= divided;
divisor_kp <= divisor;
if (divided_fir>= divisor) begin
quotient_co <= 'b1;
remainder_co <= divided_fir - divisor;
end
else begin
quotient_co <= 'b0;
remainder_co <= divided_fir;
end
end
else begin
quotient_co <= 'b0;
remainder_co <= 'b0;
end
end
endmodule
module div_cell #(
parameter M = 5,
parameter N = 3
)
(
input clk,
input rst,
input en,
input divided_bit,
input [M-1:0] divided,
input [N-1:0] divisor,
input [M-1:0] quotient_ci,
input [N-1:0] remainder_ci,
output reg [M-1:0] divided_kp,
output reg [N-1:0] divisor_kp,
output reg [M-1:0] quotient_co,
output reg [N-1:0] remainder_co
);
always@(posedge clk or negedge rst) begin
if (!rst) begin
quotient_co <= 'b0;
remainder_co <= 'b0;
end
else if (en) begin
//tansfer divided and divisor
divided_kp <= divided;
divisor_kp <= divisor;
if ({remainder_ci,divided_bit} >= divisor) begin
quotient_co <= (quotient_ci<<1) + 1'b1; //quotient plu 1
remainder_co <= {remainder_ci,divided_bit} - divisor; //calculate remainder
end
else begin
quotient_co <= quotient_ci<<1;
remainder_co <= {remainder_ci,divided_bit};
end
end
else begin
quotient_co <= 'b0;
remainder_co <= 'b0;
end
end
endmodule
quotient_co <= (quotient_ci<<1) + 1’b1; //注意优先级()标注
module test ;
parameter M = 5 ;
parameter N = 3 ;
reg clk;
reg rst ;
reg en;
reg [M-1:0] divided ;
reg [N-1:0] divisor ;
wire [M-1:0] quotient ;
wire [N-1:0] remainder ;
div_top #( .M(5),
.N(3)
)
u1 (
.clk(clk),
.rst(rst),
.en(en),
.divided(divided),
.divisor(divisor),
.quotient(quotient),
.remainder(remainder)
);
//clock
always begin
clk = 0 ; #5 ;
clk = 1 ; #5 ;
end
//driver
initial begin
rst = 1'b0 ;
#8 ;
rst = 1'b1 ;
#55 ;
@(negedge clk ) ;
en = 1'b1 ;
divided = 27; divisor = 5;
#10 ; divided = 20; divisor = 3;
#10 ; divided = 30; divisor = 4;
#10 ; divided = 19; divisor = 4;
#10 ; divided = 14; divisor = 1;
repeat(32) #10 divided = divided + 1 ;
divisor = 7;
repeat(32) #10 divided = divided + 1 ;
divisor = 5;
repeat(32) #10 divided = divided + 1 ;
divisor = 4;
repeat(32) #10 divided = divided + 1 ;
divisor = 6;
repeat(32) #10 divided = divided + 1 ;
end
initial begin
$fsdbDumpfile("div_top.fsdb");
$fsdbDumpvars;
#40000 $finish;
end
endmodule