遇到了一个输入的除数和被除数位宽(64~256)都很大,组合逻辑导致时序不满足要求的问题,根据恢复余数法想出这样一个解决方式:
Y / D =Q……….R
Y:被除数
D:除数
Q:商
R:余数
对于一个n位的被除数Y,m位的除数D,若想求出余数,可通过恢复余数算法实现,个人的理解是这个求商貌似不太好用,求余数倒是好用的很!
其实现方式是,将除数左移到与被除数位宽相同,将移位的结果与被除数进行比较,如果被除数大于等于移位结果,说明商的对应位为1,将被除数减去移位结果得到新一轮的被除数,之后除数继续移位,移位到与新的被除数位宽相同…..当被除数小于D时候即为余数,解释起来有点麻烦,上代码。
以一个被除数位宽为4,除数位宽为2的输入为例:
工程代码:
代码语言:javascript复制module chufa(
clk,
rst_n,
en, //计算使能信号
Y, //被除数
D, //除数
R //余数
);
input clk;
input rst_n;
input en;
input [3:0]Y;
input [1:0]D;
output reg[3:0]R;
reg [3:0]state;
parameter S0=4'b0001;
parameter S1=4'b0010;
parameter S2=4'b0100;
parameter S3=4'b1000;
reg [3:0]Y2,Y3,Y4;
reg [3:0]D1,D2;
reg o_en;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
state<=S0;
o_en<=1'b0;
end
else begin
case (state)
S0:begin
o_en<=1'b0; //余数输出不使能
if(en)begin
state<=S1;
D1<=(D<<2); //移位至与被除数位宽相同,第一次移位操作
end
end
S1:
begin
D2=(D<<1); //除数左移一位,第二次移位操作
if(Y>=D1)
Y2<=Y-D1; //下一次迭代的被除数
else
Y2<=Y;
state<=S2;
end
S2:
begin
if(Y2>=D2)
Y3<=Y2-D2;
else //最高位没有被整除
Y3<=Y2;
state<=S3;
end
S3:
begin
if(Y3>=D) //最后一轮的迭代比较
Y4<=Y3-D;
else
Y4<=Y3;
o_en<=1'b1;
state<=S0;
end
endcase
end
always@(posedge clk or negedge rst_n)
if(!rst_n)
R<=4'd0;
else if(o_en)
R<=Y4;
endmodule
仿真代码:
代码语言:javascript复制`timescale 1ns / 1ps
module tb();
reg clk;
reg rst_n;
reg en;
reg [3:0]Y;
reg [1:0]D;
wire[3:0]R;
chufa cf(
.clk(clk),
.rst_n(rst_n),
.en(en), //计算使能信号
.Y(Y), //被除数
.D(D), //除数
.R(R) //余数
);
initial clk=0;
always #5 clk=~clk;
initial begin
rst_n=0;
Y=13;
en=0;
D=3;
#100;
rst_n=1;
#100;
en=1;
#100;
end
endmodule
仿真结果: