quartusii 中“/”是可以综合的,不过特别耗费资源。这时候在运算速度要求不是很高的前提下,自行实现除法器就是很有意义的事情了。
此除法器完成一次运算需要耗费18个时钟周期。赋值缓存一个时钟周期,移位减法16个时钟周期,输出一个时钟周期。为什么要缓存呢(a需要缓存到ax,b需要缓存到bx)?因为如果不做缓存,在运算期间a,b值改变会影响结果的正确性。
这是我第一次写博客,请大神们不要喷。
/**************************************************************
例如:10000/17
被除数得到被比较值
除数左移15位得到比较值
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
当被比较值大于等于比较值,下一个时钟周期的被比较值就是此时的被比较值减去比较值,否则下一个时钟的被比较值就是此时的被比较值。
下一个时钟周期的比较值就是此时的比较值又移一位。
被比较值 比较值 当前计算值 累计值 下一次被比较值
10000 17<<15 0 0 10000
10000 17<<14 0 0 10000
10000 17<<13 0 0 10000
10000 17<<12 0 0 10000
10000 17<<11 0 0 10000
10000 17<<10 0 0 10000
10000 17<<9 (1<<9)=512 0+512=512 10000-(17<<9)=1296
1296 17<<8 0 512 1296
1296 17<<7 0 512 1296
1296 17<<6 (1<<6)=64 512+64=576 1296-(17<<6)=208
208 17<<5 0 576 208
208 17<<4 0 576 208
208 17<<3 (1<<3)=8 576+8=584 208-(17<<3)=72
72 17<<2 (1<<2)=4 584+4=588 72-(17<<2)=4
4 17<<1 0 588 4
4 17<<0 0 588 4
/*****************************************************************************************/
10000/17=588......4
************************************************************/
//a/b=c......d.
//flag_ok上升沿就代表完成了一次除法
module my_div_t(clk,a,b,c,d,flag_ok);
input clk;
input [15:0]a;
reg [15:0]ax;
input [15:0]b;
reg [31:0]bx;
reg [15:0]c_buff;
output [15:0]c;
reg [15:0]c;
output [15:0]d;
reg [15:0]d;
output flag_ok;
reg flag_ok;
reg [1:0]state=0;
reg [4:0]cnt;
always@(posedge clk)
begin
case(state)
0:begin
state<=1;
ax<=a;
bx<=b<<15;
cnt<=1;
c_buff<=0;
flag_ok<=0;
end
1:begin
cnt<=cnt+1;
if(cnt==16)
state<=2;
if(ax>=bx)
begin
ax<=ax-bx;
bx<=bx>>1;
c_buff<=(1<<(16-cnt))+c_buff;
end
else
begin
bx<=bx>>1;
end
end
2:begin
d<=ax;
c<=c_buff;
state<=0;
flag_ok<=1;
end
endcase
end
endmodule