fpga中除法器的设计
在fpga中除法器可通过位移比较实现,通过触发器的设计使面积功耗不会因为位数的变化有较大的变动,位数设置最好用参数进行设置这样可以在上层模块中对位数进行重定义,防止对引脚的浪费。
算法解析
当输入确认信号来临时,商和余数,及所有寄存器被全部清零,新一轮计算开始,计数器cnt赋值size+1,当cnt为1时,将temp[2*size-1:size]赋值到余数,temp[size-1:0]赋值到商,当cnt值大于0时对tempa_r进行处理,如果这个寄存器小于被除数,则对它进行左移,将除数的每一位从高到低依次赋值给tempa_r,同时计数器减1,否则令tempa_r与被除数相减。
`timescale 1ns/1ns
module div_move(
clk, //时钟信号
tempa, //除数
tempb, //被除数
value, //商
value_r //余数
);
parameter size=8;
input clk;
input [size-1:0]tempa;
input [size-1:0]tempb;
output reg [size-1:0]value;
output reg [size-1:0]value_r;
reg [size-1:0]tempa_value;
reg [2*size-1:0]tempb_value;
reg [2*size-1:0]tempa_r;
reg [7:0]cnt;
reg [size-1:0]tempa_1;
reg [size-1:0]tempb_1;
wire ack;
initial
begin
cnt<=0;
tempa_1<=0;
tempb_1<=0;
tempa_value<=0;
tempa_r<=0;
tempb_value<=0;
value<=0;
value_r<=0;
end
always@(posedge clk)
begin
if(cnt==0)begin
tempa_1<=#20 tempa;
tempb_1<=#20 tempb;
end
end
assign ack=((tempa_1!=tempa)|(tempb_1!=tempb));
wire cmp;
assign cmp=(tempa_r<tempb_value);
always@(posedge clk)
begin
if(ack)begin
cnt<=size+1;
end
else if(cmp)begin
cnt<=cnt-1;
end
end
always@(posedge clk )
begin
if(ack)begin //输入确认信号到来时赋值
tempa_r<={{size{1'b0}},tempa};
tempa_value<=tempa;
tempb_value<={tempb,{size{1'b0}}};
value<={size{1'b0}};
value_r<={size+2{1'b0}};
end
else begin
if(cnt>0)begin //cnt大于0时对数据处理
if(cmp)begin
tempa_r<={tempa_r[2*size-2:0],1'b0}; //tempa_r小于tempb_value时左移
end
else begin //否则tempa_r与tempb_value相减,最低为赋值1
tempa_r<=tempa_r-tempb_value;
tempa_r[0]<=1'b1;
end
if(cnt1==1)begin
value_r<=tempa_r[2*size-1:size]; //cnt1等于1时给余数和商赋值
value<=tempa_r[size-1:0];
end
end
end
end
endmodule
```