代码编织梦想

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;计算正确;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/kuan__/article/details/129565825

verilog实现加减乘除运算_漫步人生只为寻你的博客-爱代码爱编程_verilog 加法运算

用Verilog实现,两个16位输入,一个32位输出的四则运算模块,这里我是使用的调用IP核的方式,毕竟人家官方推出的要比我们自个写的要稳定一点,这里调用了加法器,减法器,乘法器,触发器的IP核。 代码如下: module jisuan(     //input pin;     Clk,     Rst_n,     data_A,     data

除法器的verilog实现-爱代码爱编程

网上转载,参考链接:https://www.cnblogs.com/Dinging006/p/9382657.html 除法器在FPGA里怎么实现呢?当然不是让用“/”和“%”实现。 在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运

verilog 实现8位无符号除法器-爱代码爱编程

一、算法(非原创) 在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。即使可以综合,也需要比较多的资源。 最简单的方法就是减法实现除法器(比如十进制中的a/b,可先比较a与b的大

verilog 除法_数字IC设计校招基础知识点复习(十)——除法器-爱代码爱编程

1.除法器 二进制除法器的本质是多次减法,直到余数小于除数为止。对应的两个N bit二进制数的除法算法如下。 设置2N bit寄存器A的低N位存放被除数,设置2N bit寄存器B的高N位存放除数,设置N bit寄存器C存放商,设置计数器cnt。将A左移一位,与B比较高N位大小,若 ,则令 ,令C左移一

二进制除法移位相减_verilog移位相减实现除法(转载)-爱代码爱编程

引言 除法器在FPGA里怎么实现呢?当然不是让用“/”和“%”实现。 在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。即使可以综合,也需要比较多的资源。对于这种情况,一般使

基本除法器的Verilog HDL实现-爱代码爱编程

        主题 使用Verilog HDL 实现最基本的除法运算。 问题分析 以32位除法器为例,介绍其verilog语言实现的原理 首先个人认为该方法是受到除法手工计算方法的启发。对于32位的无符号数,其商和余数的位数都不会超过32位,首先将被除数a扩展为64位的temp_a = {32'h0000,a},将除数b扩展为6

C语言设计一除法器,verilog 除法器-爱代码爱编程

verilog 除法器:利用二进制的除法翻译过来的硬件电路 1.1 实现算法 基于减法的除法器的算法: 对于32的无符号除法,被除数a除以除数b,他们的商和余数一定不会超过32位。首先将a转换成高32位为0,低32位为a的temp_a。把b转换成高32位为b,低32位为0的temp_b。在每个周期开始时,先将temp_a左移一位,末尾补0,然后与

Verilog无符号除法器-流水线实现-爱代码爱编程

文章目录 1、运算模块2、测试模块3、仿真结果4、总结  在前一篇文章中提到了除法器模块的状态机实现,状态机实现可以使用最少的资源实现除法功能,随之带来的是每次只能运算一次结果,下一次除法运算需要等上一个运算结束后进行,而流水线模式则很好的避免了这个问题,可以连续输入需要运算的数据,运算结果流水输出,缺点是需要大量的逻辑资源,也就是所谓的面积换速

FPGA实现除法器(verilog)-爱代码爱编程

前言 Verilog语法中有“/”和“%”运算符,分别表示除法运算和取余运算,但是FPGA实现除法器时,是否可以直接使用这两个运算符呢?答案是否定的。 FGPA的综合工具中,对Verilog的除法指令进行编译时,有以下几种情况: 1、如果被除数和除数均为固定数,编译中,借助计算机的除法运算能力,直接将除法运算结果赋给变量; 2、如果除数是2的幂次方,编译

verilog除法器设计-爱代码爱编程

除法器原理 和十进制除法类似,计算 27 除以 5 的过程如下所示: 除法运算过程如下: (1) 取被除数的高几位数据,位宽和除数相同(实例中是 3bit 数据)。 (2) 将被除数高位数据与除数作比较,如果前者不小于后者,则可得到对应位的商为 1,两者做差得到第一步的余数;否则得到对应的商为 0,将前者直接作为余数。 (3) 将上一步中的余数与被除数剩

除法器的verilog rtl实现_闲庭信步sss的博客-爱代码爱编程

除法运算过程 和十进制除法一样,其实除法是一个移位并比较大小的过程 下图为二进制的除法运算(27/5) 除法运算过程如下: 1.取被除数的高几位数据,位宽和除数相同(上述为3bit数据)。 2.将被除数高位数据与除数作比较,如果前者不小于后者,则可得到对应位的商为1,两者做差得到第一步的余数;否则得到对应的商为0,将前者直接作为余数。 3.将上一步中的