ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

rtl低功耗除法器设计

2022-02-07 18:34:54  阅读:217  来源: 互联网

标签:除法器 val rtl 低功耗 b0 rem rst input cpt


对于在性能要求不高的地方,可以使用这种除法

 

其原理是每一拍除数减去被除数,直到被除数小于除数。减的次数为商,剩下的是余数。

对于a/b,假设a位宽为m,b位宽为n,则需要m拍出结果

算法原理:

对于无符号除法,其商不会超过m,余数一定不会超过n

定义变量

assign a_tmp = {n{1'b0},a}

assign b_tmp = {b,m{1'b0}}

在每个周期开始时,先将a_tmp左移一位,末尾补0,然后与b_tmp比较,是否大于b_tmp,是则a_tmp减去b_tmp将且加上1,否则继续往下执行。上面的移位、比较和减法(视具体情况而定)要执行m次,执行结束后a_tmp的高n位即为余数,低m位即为商

举例:

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

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQyMzMwMzA1,size_10,color_FFFFFF,t_70,g_se,x_16

 具体实现:

通常,商的位宽与被除数位宽一致,如图1中所示

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQyMzMwMzA1,size_11,color_FFFFFF,t_70,g_se,x_16

 

module    division_cmp    #(parameter    N    = 5,parameter    M    = 3)(    input                clk,    input                rst_n,    input                cpt_start,    input    [N-1:0]     dividend,    //被除数    input    [M-1:0]     divisor,     //除数    output   [N-1:0]     quotient,    //商    output   [M-1:0]     reminder,    //余数    output               cpt_end);assign    rem_mux = cmp_start ? {N{1'b0}} : cur_rem;localparam CW = log2(N);wire   [M-1:0]    rem_mux;reg    [M-1:0]    cur_val;reg    [M-1:0]    nxt_val;wire              cpt_val;reg    [CW-1:0]   cpt_cnt;wire   [N:0]      cpt_sub;reg               quo_val;wire              cpt_en;reg               cpt_en_ff;assign rem_mux = cpt_start ? {N{1'b0}} : cur_val;assign cpt_val = dividend[N-cpt_cnt-:1];assign cpt_sub = {rem_mux,cpt_val} - {1'b0,divisor};  //左移1位并相减always @ (*) begin  if(~cpt_sub[N]) begin         //相减后为正数    nxt_val = cpt_sub[N-1:0];   //取相减后的值    quo_val = 1'b1;             //商为1  end  else  begin                   //相减后为负数    nxt_val = {rem_mux[N-2:0],cpt_val};  //左移移1位    quo_val = 1'b0;             //商为0  endendalways @ (posedge clk or negedge rst_n) begin  if(~rst_n)Cur_val <= {M{1'b0}};cpt_en_ff <= 1'b0;  elseCur_val <= nxt_val;cpt_en_ff <= cpt_en;end//计数,需要M拍always @ (posedge clk or negedge rst_n) begin  if(~rst_n)cpt_cnt <= {CW{1'b0}};  else if(cpt_cnt==N-1)cpt_cnt <= {CW{1'b0}};  else if(cpt_start | (cpt_cnt>{CW{1'b0}}))     cpt_cnt <= cpt_cnt + 1'b1;endassign cpt_en = cpt_start | (cpt_cnt>{CW{1'b0}});always @ (posedge clk or negedge rst_n) begin  if(~rst_n)Quotient <= {M{1'b0}};  else if(cpt_en)Quotient[N-cpt_cnt-:1] <= quo_val;endassign cpt_end = (!cpt_en) & cpt_en_ff;        //下降沿assign reminder = cur_val; endmodule

当商的位宽与被除数位宽不一致时

如图2,说明除数一定大于1,上面的代码也能实现,只是需要拍数较多

此时需要将数据提前写入rem_mux中

module    division_cmp    #(parameter    N    = 5,parameter    M    = 3,parameter    P    = 4,)(    input                clk,    input                rst_n,    input                cpt_start,    input    [N-1:0]     dividend,    //被除数    input    [M-1:0]     divisor,     //除数    output   [P-1:0]     quotient,    //商    output   [M-1:0]     reminder,    //余数    output               cpt_end);localparam CW = log2(P);//..............//省略//..............assign rem_mux = cpt_start ? dividend[P+M:P] : cur_val;//..............//省略//..............//计数,需要P拍always @ (posedge clk or negedge rst_n) begin  if(~rst_n)cpt_cnt <= {CW{1'b0}};  else if(cpt_cnt==N-1)cpt_cnt <= {CW{1'b0}};  else if(cpt_start | (cpt_cnt>{CW{1'b0}}))     cpt_cnt <= cpt_cnt + 1'b1;endendmodule

当遇到图3的情况,也是提前把数据写入rem_mux,但不是完全提前,高位需要补0

module    division_cmp    #(parameter    N    = 5,parameter    M    = 3,parameter    P    = 4,)(    input                clk,    input                rst_n,    input                cpt_start,    input    [N-1:0]     dividend,    //被除数    input    [M-1:0]     divisor,     //除数    output   [P-1:0]     quotient,    //商    output   [M-1:0]     reminder,    //余数    output               cpt_end);localparam CW = log2(P);//..............//省略//..............assign rem_mux = cpt_start ? {{P+M-N}{1'b0},dividend[P+M:P]} : cur_val;//..............//省略//..............//计数,需要P拍always @ (posedge clk or negedge rst_n) begin  if(~rst_n)cpt_cnt <= {CW{1'b0}};  else if(cpt_cnt==N-1)cpt_cnt <= {CW{1'b0}};  else if(cpt_start | (cpt_cnt>{CW{1'b0}}))     cpt_cnt <= cpt_cnt + 1'b1;endendmodule

 

 

标签:除法器,val,rtl,低功耗,b0,rem,rst,input,cpt
来源: https://blog.csdn.net/weixin_42330305/article/details/122751358

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有