verilog实现除法器运算

verilog实现除法器运算

本文通过verilog实现了一个位宽参数可配置的除法运算模块

1, 设计思路

我们要计算 a_data/b_data = div_data ----remain_data;

  • 🌿 确定位宽:若a_data的位宽为A_WIDTH, b_data的位宽为B_WIDTH;则div_data的最大位宽为A_WIDTH, remain_data的位宽为B_WIDTH;

  • 🍃 计算div_data的最高位:若a_data >= (b_data<<(A_WIDTH-1)), 则div_data的最高位div_data[A_WIDTH-1]为1,否则div_data[A_WIDTH-1]为0; 即div_data[A_WIDTH-1] = a_data > (b_data<<(A_WIDTH-1)) ? 1‘b1 : 1’b0;

  • 🌾 计算div_data的次高位:若div_data的最高位div_data[A_WIDTH-1]为1,则a_data_tmp = a_data – (b_data<<(A_WIDTH-1)); 否则a_data_tmp = a_data; 次高位div_data[A_WIDTH-2] = a_data_tmp >= (b_data<<(A_WIDTH-2)) ? 1‘b1 : 1’b0;

  • 🌴 依次类推,可 计算出完整的div_data;

  • 🌲. 计算完div_data后,可用 remain_data = a_data – b_data*div_data获取余数

举个例子,计算8/3 也就是 4’b1000/3’b011 = 3’b010;

  • 🥝 div_data[3] = 4’b1000 > (3’b011 << 3) ? 1’b1 : 1’b0 ; 由于div_data[3]为0,所以a_data_tmp为4‘b1000;

  • 🥑 div_data[2] = 4’b1000 > (3’b011 << 2) ? 1’b1 : 1’b0; 由于div_data[2]为0,所以a_data_tmp为4‘b1000;

  • 🍇 div_data[1] = 4’b1000 > (3’b011 << 1) ? 1’b1 : 1’b0; 由于div_data[1]为1,所以a_data_tmp为4‘b1000-(3’b011 << 1) = 4’b0010;

  • 🍒 div_data[0] = 4’b0010 > (3’b011 << 0) ? 1’b1 : 1’b0;

  • 🍐所以 div_data = 4‘b0010 = 2;

  • 🌼 remain_data = a_data – b_data*div_data = 8 – 3 * 2 = 2 = 3’b010;

2, Verilog代码

// Filename      : div.v
// Author        : ppkuan
module div(/*autoarg*/
    //Inputs
    clk, rst_n, in_vld, a_data, b_data, 

    //Outputs
    out_vld, remain_data, div_data
);

parameter   A_WIDTH = 10;
parameter   B_WIDTH = 5;
// a_data/b_data = div_data------remain_data

input                             clk         ;
input                             rst_n       ;
input                             in_vld      ;
input       [A_WIDTH - 1 : 0]     a_data      ;
input       [B_WIDTH - 1 : 0]     b_data      ;

output reg                        out_vld     ;
output reg  [B_WIDTH - 1 : 0]     remain_data ;
output reg  [A_WIDTH - 1 : 0]     div_data    ;


wire   [A_WIDTH - 1 : 0]                             div_data_tmp    ;
wire   [A_WIDTH - 1 : 0] [A_WIDTH + B_WIDTH - 1 : 0] ab_data_tmp     ;
wire   [A_WIDTH - 1 : 0] [A_WIDTH - 1 : 0]           a_data_tmp      ; 
wire   [B_WIDTH - 1 : 0]                             remain_data_tmp ;

assign  ab_data_tmp[A_WIDTH - 1]   = b_data << (A_WIDTH - 1);
assign  div_data_tmp[A_WIDTH - 1]  = {{B_WIDTH{1'b0}}, a_data} >= ab_data_tmp[A_WIDTH - 1] ? 1'b1 : 1'b0;
assign  a_data_tmp[A_WIDTH - 1]    = div_data_tmp[A_WIDTH - 1] ? {{B_WIDTH{1'b0}},a_data} - ab_data_tmp[A_WIDTH - 1] : a_data;

genvar i;
generate 
    for(i = A_WIDTH - 2; i >= 0; i--)
        begin:div
            assign ab_data_tmp[i]  = (b_data << i);
            assign div_data_tmp[i] = {{B_WIDTH{1'b0}}, a_data_tmp[i+1]} >= ab_data_tmp[i] ? 1'b1 : 1'b0;
            assign a_data_tmp[i]   = div_data_tmp[i] ? {{B_WIDTH{1'b0}},a_data_tmp[i+1]} - ab_data_tmp[i] : a_data_tmp[i + 1];
        end
endgenerate

assign remain_data_tmp = {{B_WIDTH{1'b0}}, a_data} - div_data_tmp * b_data;

always@(posedge clk or negedge rst_n)
    if(!rst_n)
    begin
        out_vld     <= 'b0            ;
        remain_data <= 'd0            ;
        div_data    <= 'd0            ;
    end
    else if(in_vld)
    begin
        out_vld     <= 'b1            ;
        remain_data <= remain_data_tmp;
        div_data    <= div_data_tmp   ;
    end
    else 
    begin
        out_vld     <= 'b0            ;
    end
endmodule

3, 测试用例:

module test;

wire         clk         ;
wire         rst_n       ;
wire         in_vld      ;
wire [9 : 0] a_data      ;
wire [4 : 0] b_data      ;
wire         out_vld     ;
wire [9 : 0] div_data    ;
wire [4 : 0] remain_data ;

reg         clk_r       ;
reg         rst_n_r     ;
reg         in_vld_r    ;
reg [9 : 0] a_data_r    ;
reg [4 : 0] b_data_r    ;
 
assign clk    = clk_r    ;
assign rst_n  = rst_n_r  ;
assign in_vld = in_vld_r ;
assign a_data = a_data_r ;
assign b_data = b_data_r ;

div#(
    .A_WIDTH(10),
    .B_WIDTH(5)) 
    u_div(/*autoinst*/
    // a_data/b_data = div_data------remain_data

    .clk                            (clk                                        ), // input 
    .rst_n                          (rst_n                                      ), // input 
    .in_vld                         (in_vld                                     ), // input 
    .a_data                         (a_data[9 : 0]                              ), // input 
    .b_data                         (b_data[4 : 0]                              ), // input 

    .out_vld                        (out_vld                                    ), // output
    .remain_data                    (remain_data[4 : 0]                         ), // output
    .div_data                       (div_data[9 : 0]                            )  // output
);

initial
begin
clk_r =    0;
in_vld_r = 0;
rst_n_r =  1;
#10
rst_n_r =  0;
#10
rst_n_r =  1;
#10
in_vld_r = 1;
a_data_r = 10'd57;
b_data_r = 5'd8;
#10
in_vld_r = 0;
$finish;
end

always #5 clk_r = !clk_r;

endmodule

测试结果如图所示

请添加图片描述

57/8 = 7—1;计算正确;

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Verilog实现除法器可以使用硬件实现或软件实现。下面分别介绍两种实现方式。 1. 硬件实现 硬件实现除法器使用组合逻辑电路和时序逻辑电路来实现除法运算。其中,组合逻辑电路用于计算除数和被除数的比值,时序逻辑电路用于控制除法器的各个阶段和输出结果。 下面是一个简单的硬件实现除法器Verilog代码: ``` module divider(input clk, input [7:0] dividend, input [7:0] divisor, output reg [7:0] quotient, output reg [7:0] remainder); reg [7:0] temp; always @(posedge clk) begin temp <= dividend; for (int i = 7; i >= 0; i = i-1) begin if (temp >= divisor) begin temp <= temp - divisor; quotient[i] <= 1; end else begin quotient[i] <= 0; end end remainder <= temp; end endmodule ``` 其中,输入参数包括时钟信号`clk`,被除数`dividend`和除数`divisor`,输出结果包括商`quotient`和余数`remainder`。 2. 软件实现 软件实现除法器使用CPU的指令集来模拟除法运算,可以采用被除数不断减去除数的方式进行计算,直到被除数小于除数为止。下面是一个简单的软件实现除法器Verilog代码: ``` module divider(input clk, input [7:0] dividend, input [7:0] divisor, output reg [7:0] quotient, output reg [7:0] remainder); reg [7:0] temp; always @(posedge clk) begin temp <= dividend; for (int i = 7; i >= 0; i = i-1) begin while (temp >= divisor) begin temp <= temp - divisor; quotient[i] <= 1; end quotient[i] <= 0; end remainder <= temp; end endmodule ``` 与硬件实现相比,软件实现除法器需要更多的CPU计算资源,但是相对简单易实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮皮宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值