rtl低功耗除法器设计

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

 

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

对于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位后左右两边分别就是余数和商。

rtl低功耗除法器设计

 具体实现:

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

rtl低功耗除法器设计

 

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

 

 

上一篇:keras中Model模型的定义与使用


下一篇:Qt移植到ARN