在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2103|回复: 0

[转贴] 基于减法操作除法器的算法---Verilog实现

[复制链接]
发表于 2020-9-29 09:41:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x

verilog hdl语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。即使可以综合,也需要比较多的资源。对于这种情况,一般使用相应的算法来实现除法,分为两类:基于减法操作和基于乘法操作的算法;

实现算法

基于减法的除法器的算法:
        对于32的无符号除法,被除数a除以除数b,他们的商和余数一定不会超过32位。首先将a转换成高32位为0,低32位为a的temp_a。把b转换成高32位为b,低32位为0的temp_b。在每个周期开始时,先将temp_a左移一位,末尾补0,然后与b比较,是否大于b,是则temp_a减去temp_b将且加上1,否则继续往下执行。上面的移位、比较和减法(视具体情况而定)要执行32次,执行结束后temp_a的高32位即为余数,低32位即为商;

算法推倒(非原创):
假设4bit的两数相除 a/b,商和余数最多只有4位 (假设1101/0010也就是13除以2得6余1)

我们先自己做二进制除法,则首先看a的MSB,若比除数小则看前两位,大则减除数,然后看余数,以此类推直到最后看到LSB;而上述算法道理一样,a左移进前四位目的就在于从a本身的MSB开始看起,移4次则是看到LSB为止,期间若比除数大,则减去除数,注意减完以后正是此时所剩的余数。而商呢则加到了这个数的末尾,因为只要比除数大,商就是1,而商0则是直接左移了,因为会自动补0。这里比较巧因为商可以随此时的a继续左移,然后新的商会继续加到末尾。经过比对会发现移4位后左右两边分别就是余数和商。

画个简单的图:


                               
登录/注册后可看大图

1.时序逻辑除法



  • module div_timing_logic(



  •                         input               I_clk,



  •                         input               I_rst_p,



  •                         input               I_data_valid,



  •                         input       [7:0]   I_data_a,



  •                         input       [7:0]   I_data_b,



  •                         output reg          O_data_valid,



  •                         output reg [7:0]    O_data_shang,



  •                         output reg [7:0]    O_data_yushu







  •     );



  • reg  [7:0]   tempa;



  • reg  [7:0]   tempb;



  • reg  [15:0]  temp_a;



  • reg  [15:0]  temp_b;



  • reg          div_start;



  • reg          div_start_d1;



  • wire         div_start_neg;



  • reg  [4:0]   div_cnt;







  • always@(posedge I_clk or posedge I_rst_p)



  •    begin



  •       if(I_rst_p)



  •          begin



  •             tempa <= 8'h0;            



  •             tempb <= 8'h0;            



  •          end



  •       else if(I_data_valid)



  •          begin



  •             tempa <= I_data_a;            



  •             tempb <= I_data_b;            



  •          end



  •       else



  •          begin



  •             tempa <= tempa;            



  •             tempb <= tempb;            



  •          end



  •    end







  • always@(posedge I_clk or posedge I_rst_p)



  •    begin



  •       if(I_rst_p)



  •          div_start <= 1'b0;



  •       else if(I_data_valid && div_start == 1'b0)



  •          div_start <= 1'b1;



  •       else if(div_cnt == 5'd16 )



  •          div_start <= 1'b0;



  •       else



  •           div_start <= div_start;



  •    end



  • //========================================================div_cnt



  • always@(posedge I_clk or posedge I_rst_p)



  •    if(I_rst_p)



  •       div_cnt <= 5'd0;



  •    else if(div_start)



  •       div_cnt <= div_cnt + 1;



  •    else



  •       div_cnt <= 5'd0;



  • //=======================================================           



  • always@(posedge I_clk or posedge I_rst_p)



  •    begin



  •       if(I_rst_p)



  •          begin



  •             temp_a <= 16'h0;



  •             temp_b <= 16'h0;            



  •          end



  •       else if(div_start )



  •          if(div_cnt == 4'd0)



  •             begin



  •                temp_a <= {8'h0,tempa};



  •                temp_b <= {tempb,8'h0};



  •             end



  •          else if(div_cnt[0] == 1'b1)



  •             begin



  •                temp_a <= {temp_a[14:0],1'b0};



  •             end



  •          else



  •             begin



  •                temp_a <= (temp_a[15:8] >= temp_b[15:8])?(temp_a - temp_b + 1):temp_a;//如果比temp_b大,则减去temp_b然后加1



  •             end



  •       else



  •          begin



  •             temp_a <= 16'h0;



  •             temp_b <= 16'h0;              



  •          end







  •    end



  • always@(posedge I_clk)



  •    begin



  •       div_start_d1 <= div_start;



  •    end



  • assign div_start_neg = div_start_d1 & (~div_start);//下降沿检测







  • always@(posedge I_clk or posedge I_rst_p)



  •    begin



  •       if(I_rst_p)



  •          begin



  •             O_data_valid <= 1'b0;



  •             O_data_shang <= 1'b0;



  •             O_data_yushu <= 1'b0;         



  •          end



  •       else if(div_start_neg)



  •          begin



  •             O_data_valid <= 1'b1;



  •             O_data_shang <= temp_a[7:0];



  •             O_data_yushu <= temp_a[15:8];              



  •          end



  •       else



  •          begin



  •             O_data_valid <= 1'b0;



  •             O_data_shang <= 1'b0;



  •             O_data_yushu <= 1'b0;         



  •          end



  •    end



  • endmodule


2.纯组合逻辑



  • module div_combinatory_logic



  • (



  •            input       [7:0]        a,//被除数



  •            input       [7:0]        b,//除数



  •            output reg  [7:0]        y_shang,//商



  •            output reg  [7:0]        y_yushu//余数



  • );







  • reg [7:0] tempa;



  • reg [7:0] tempb;



  • reg [15:0] temp_a;



  • reg [15:0] temp_b;







  • integer i;







  • always@(*)



  •    begin



  •       tempa = a;



  •       tempb = b;



  •    end







  • always@(*)



  •    begin



  •       temp_a = {8'h0,tempa};



  •       temp_b = {tempb,8'h0};



  •       for(i = 0; i < 8; i = i+1)         //注意是移动8次



  •          begin:shift_left



  • //            temp_a = temp_a << 1 ;



  •             temp_a = {temp_a[14:0],1'b0}  ;



  •             if(temp_a[15:8] >= temp_b[15:8] )//temp_b的低8位都是0,所以只需要比较高八位



  •                temp_a = temp_a - temp_b + 1;



  •             else



  •                temp_a = temp_a;



  •          end



  •        y_shang = temp_a[7:0];//商在低位



  •        y_yushu = temp_a[15:8];//余数在高位



  •    end











  • endmodule




您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /3 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-20 12:56 , Processed in 0.022714 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表