verilog编程之乘法器的实现

这篇具有很好参考价值的文章主要介绍了verilog编程之乘法器的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

知识储备
首先来回顾一下乘法是如何在计算机中实现的。
假设现在有两个32位带符号定点整数x和y,我们现在要让x和y相乘,然后把乘积存放在z中,大家知道,两个32位数相乘,结果不会超过64位,因此z的长度应该为64位。
z = x * y中,x是被乘数,在Verilog代码中 multiplicand表示,y是乘数,在代码中用multiplier表示。因为x和y都是带符号数,所以应该是用补码乘法,但是如果对x和y求绝对值,让两个绝对值相乘,然后再判断正负,效果和补码乘法是相同。后面给出的Verilog代码就是基于这种思路编写的。两个32位整数相乘,实际上是进行了32次加法操作。下面以两个4位二进制数相乘来说明乘法实现的过程。

数字信号处理信号两组信号相乘verilog代码示例,verilog,stm32,fpga开发

从上图中可以看到,被乘数x为1000,乘数y为1001,上面的乘法过程是手工运算的一个步骤,而计算机在做乘法时就是模拟上述手工运算的执行过程。因为是两个4位数相乘,所以结果应该是四个数加和得到的。先判断y的最低位是0还是1,如果是1,则需要把x加到部分积上,若为0,则需要把0加到部分积上(实际上加0的这个过程计算机并不执行,因为加0对部分积没有任何影响),x左移一位,之后再让y右移一位,若y为0,则循环结束,否则继续此循环过程。流程图如下。

数字信号处理信号两组信号相乘verilog代码示例,verilog,stm32,fpga开发

流程图中,x因为需要左移,所以32位长度的x应该用一个64位寄存器来存储,这样才能保证x左移后不会发生高位丧失。

代码实现与分析
multiply.v文件如下

`timescale 1ns / 1ps
//*************************************************************************
//   > 文件名: multiply.v
//   > 描述  :乘法器模块,低效率的迭代乘法算法,使用两个乘数绝对值参与运算
//   > 作者  : LOONGSON
//   > 日期  : 2016-04-14
//*************************************************************************
module multiply(              // 乘法器
    input         clk,        // 时钟
    input         mult_begin, // 乘法开始信号
    input  [31:0] mult_op1,   // 乘法源操作数1
    input  [31:0] mult_op2,   // 乘法源操作数2
    output [63:0] product,    // 乘积
    output        mult_end   // 乘法结束信号
);
    //乘法正在运算信号和结束信号
    reg mult_valid;
    assign mult_end = mult_valid & ~(|multiplier); //乘法结束信号:乘数全0
    always @(posedge clk)   //①
    begin
        if (!mult_begin || mult_end)    //如果没有开始或者已经结束了
        begin
            mult_valid <= 1'b0;     //mult_valid 赋值成0,说明现在没有进行有效的乘法运算
        end
        else
        begin
            mult_valid <= 1'b1;
       //     test <= 1'b1;
        end
    end

    //两个源操作取绝对值,正数的绝对值为其本身,负数的绝对值为取反加1
    wire        op1_sign;      //操作数1的符号位
    wire        op2_sign;      //操作数2的符号位
    wire [31:0] op1_absolute;  //操作数1的绝对值
    wire [31:0] op2_absolute;  //操作数2的绝对值
    assign op1_sign = mult_op1[31];
    assign op2_sign = mult_op2[31];
    assign op1_absolute = op1_sign ? (~mult_op1+1) : mult_op1;
    assign op2_absolute = op2_sign ? (~mult_op2+1) : mult_op2;
    //加载被乘数,运算时每次左移一位
    reg  [63:0] multiplicand;
    always @ (posedge clk)  //②
    begin
        if (mult_valid)
        begin    // 如果正在进行乘法,则被乘数每时钟左移一位
            multiplicand <= {multiplicand[62:0],1'b0};  //被乘数x每次左移一位。
        end
        else if (mult_begin) 
        begin   // 乘法开始,加载被乘数,为乘数1的绝对值
            multiplicand <= {32'd0,op1_absolute};
        end
    end

    //加载乘数,运算时每次右移一位,相当于y
    reg  [31:0] multiplier;
    
    always @ (posedge clk)  //③
    begin
    if(mult_valid)
    begin       //如果正在进行乘法,则乘数每时钟右移一位
         multiplier <= {1'b0,multiplier[31:1]}; //相当于乘数y右移一位
    end
    else if(mult_begin)
    begin   //乘法开始,加载乘数,为乘数2的绝对值
        multiplier <= op2_absolute;
        end
    end
    // 部分积:乘数末位为1,由被乘数左移得到;乘数末位为0,部分积为0
    wire [63:0] partial_product;
    assign partial_product = multiplier[0] ? multiplicand:64'd0;        //若此时y的最低位为1,则把x赋值给部分积partial_product,否则把0赋值给partial_product
    
    //累加器
    reg [63:0] product_temp;        //临时结果
    always @ (posedge clk)  //④//clk信号从0变为1时,激发此段语句的执行,但语句的执行需要时间
    begin
        if (mult_valid)
        begin
            product_temp <= product_temp + partial_product;
        end      
        else if (mult_begin)
        begin
        product_temp <= 64'd0;
        end
     end
     
    //乘法结果的符号位和乘法结果
    reg product_sign;    //乘积结果的符号
    always @ (posedge clk)  // 乘积⑤
    begin
        if (mult_valid)
        begin
              product_sign <= op1_sign ^ op2_sign;
        end
    end 
    //若乘法结果为负数,则需要对结果取反+1
    
    assign product = product_sign ? (~product_temp+1) : product_temp;
endmodule


要看懂这段程序,很重要的一点是要弄明白Verilog语言中always语句的并发执行,这和我们以前接触过的高级语言不同,Verilog代码中的语句可以不按顺序执行,这个有点像多线程,也就是说多个任务同时进行。
上面的代码中共有5个always语句,每个always语句都是时钟信号clk的上跳沿触发,也就是说当clk从0变为1的时候,会触发always语句的执行。
下面介绍一下每个always语句的功能。
1.第一个always块

 always @(posedge clk)   //①
    begin
        if (!mult_begin || mult_end)    //如果没有开始或者已经结束了
        begin
            mult_valid <= 1'b0;     //mult_valid 赋值成0,说明现在没有进行有效的乘法运算
        end
        else
        begin
            mult_valid <= 1'b1;
       //     test <= 1'b1;
        end
    end

如果乘法还没开始(mult_begin == 0)或者乘法已经结束(mult_end == 1),则乘法有效信号(mult_valid)赋值0,也就是说此时没有进行有效的乘法。否则,乘法有效信号(mult_valid)赋值1。
2.第二个always块

always @ (posedge clk)  //②
    begin
        if (mult_valid)
        begin    // 如果正在进行乘法,则被乘数每时钟左移一位
            multiplicand <= {multiplicand[62:0],1'b0};  //被乘数x每次左移一位。
        end
        else if (mult_begin) 
        begin   // 乘法开始,加载被乘数,为乘数1的绝对值
            multiplicand <= {32'd0,op1_absolute};
        end
    end

如果乘法有效(mult_valid == 1),则被乘数(multiplicand)左移一位。如果乘法无效且乘法刚开始(mult_begin == 1),那么初始化被乘数(multiplicand)为mult_op1的绝对值。
3.第三个always块

 always @ (posedge clk)  //③
    begin
    if(mult_valid)
    begin       //如果正在进行乘法,则乘数每时钟右移一位
         multiplier <= {1'b0,multiplier[31:1]}; //相当于乘数y右移一位
    end
    else if(mult_begin)
    begin   //乘法开始,加载乘数,为乘数2的绝对值
        multiplier <= op2_absolute;
        end
    end

如果乘法有效(mult_valid == 1),乘数右移一位。如果乘法无效且乘法刚开始(mult_begin == 1),初始化乘数(multiplier)为mult_op2的绝对值。

4.第四个always块

 always @ (posedge clk)  //④//clk信号从0变为1时,激发此段语句的执行,但语句的执行需要时间
    begin
        if (mult_valid)
        begin
            product_temp <= product_temp + partial_product;
        end      
        else if (mult_begin)
        begin
        product_temp <= 64'd0;
        end
     end

如果乘法有效,则让临时结果(product_temp)加上部分积(partial_product),如果乘法无效且乘法刚开始(mult_begin == 1),那么初始化临时结果为0。部分积的内容在程序中的第71行


如果乘数y的最低位为0,则把0赋值给部分积,否则把乘数x赋值给部分积。
5.第五个always块

 always @ (posedge clk)  // 乘积⑤
    begin
        if (mult_valid)
        begin
              product_sign <= op1_sign ^ op2_sign;
        end
    end 

如果乘法有效,则计算乘积的符号,计算方法为乘数的符号和被乘数的符号进行异或。

编写思路
程序仿真开始时,bestbench.v文件会对输入信号进行初始化。使得mult_begin为1,并且给出两个操作数mult_op1和mult_op2分别作为乘数和被乘数。时钟信号clk每5ns变化一次,也就是说五个always块每隔10ns被触发一次。对mult_op1和mult_op2进行分解,分解出他们的符号和绝对值,后面的运算是让mult_op1和mult_op2的绝对值进行运算,相当于是两个无符号数的乘法。当乘法信号有效后,也就是说乘法开始之后,把x的绝对值赋值给一个64位的reg型变量multiplicand,把y的绝对值赋值给一个32位reg型变量multiplier,根绝multiplier最低位是0还是1,决定着64位wire型变量partial_product赋值0还还是赋值multiplicand。临时结果product_temp加上部分积之后再把加的结果赋值给自己,根据mult_op1和mult_op2的符号计算乘积结果的符号。最终的乘积结果(product)是wire型变量,用assign赋值,每当临时结果(product_temp)发生改变时,product也立即发生变化。

提示
reg型变量必须通过过程赋值语句赋值!不能通过assign语句赋值!而wire型数据不能放在过程块内赋值。

最后附上本实验用到的所有文件:

https://www.cnblogs.com/lures/p/14525787.html

可以使用百度云进行免费下载
链接:https://pan.baidu.com/s/1W3yFQ0kzJQfnkI4VyKyyJg
提取码:83lj

如果本篇文章对你有所帮助,欢迎使用CSDN下载来支持我
链接:https://download.csdn.net/download/weixin_43074474/13728746
链接:https://blog.csdn.net/weixin_43074474/article/details/90473709文章来源地址https://www.toymoban.com/news/detail-848994.html

到了这里,关于verilog编程之乘法器的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于FPGA的64bit算术乘法器设计Verilog代码Quartus仿真

    名称:基于FPGA的64bit算术乘法器设计Verilog代码Quartus仿真(文末获取) 软件:Quartus 语言:Verilog 代码功能: Verilog HDL设计64bits算术乘法器 基本功能 1.用 Veriloghdl设计实现64bit二进制整数乘法器,底层乘法器使用16*168*88*328*16小位宽乘法器来实现底层乘法器可以使用FPGA内部P实现

    2024年02月19日
    浏览(50)
  • m基于FPGA的半带滤波器verilog设计,对比普通结构以及乘法器复用结构

    目录 1.算法描述 2.仿真效果预览 3.verilog核心程序 4.完整FPGA         HBF模块由半带滤波器(HBF)和抽取模块组成。该模块的任务是实现2倍抽取进一步降低信号采样速率。由于HBF的冲激响应h(k)除零点外其余偶数点均为零,所以用HBF实现2倍抽取可以节省一半的运算量,对增强软

    2023年04月08日
    浏览(77)
  • FPGA中除法器IP核乘法器IP核使用

    1.除法器IP核有两种,3.0是最大支持32bit的被除数除数;4.0是最大支持64bit的被除数除数;研究电机时需要计算步数,都仅仅需要32bit因此选择3.0; 2.有两种类型 (1)remainder 余数 (2)fractional:小数 (3)dividend:被除数 (4)divisior: 除数 (5)quotient : 商 选择无符号数据,余

    2024年02月01日
    浏览(40)
  • 定点乘法器----基4booth算法

    本篇文章将介绍如何使用 基4 booth算法( 赛题中介绍了 )来生成部分积,在开始之前,简要介绍一下定点乘法器的计算流程: 对 乘数 进行booth编码 — 利用得到的 编码值 和 被乘数 生成 部分积 ---- 对 部分积 进行压缩求和。 基4 booth(后面简称为 booth2 )算法用来完成前面的两步。

    2024年02月06日
    浏览(58)
  • Logism · 原码一位乘法器 实验

    8位无符号的原码一位乘法器的实现 通过时钟驱动右移,模拟运算过程 实现脉冲控制,位移指定次数后要及时停止 结果输出给到乘积隧道         A.掌握寄存器、分离器、比较器等一系列新的逻辑元件使用方法         B.学习并运用计算机原码乘法原理,在硬件电路中

    2023年04月25日
    浏览(41)
  • 计算机组成原理3个实验-logisim实现“七段数码管”、“有限状态机控制的8*8位乘法器”、“单周期MIPS CPU设计”。

    目录 标题1.首先是七段数码管   标题二:有限状态机控制的8*8位乘法器 标题三:单周期MIPS CPU设计 1看一下实验要求:    2.接下来就是详细设计: 1. 组合逻辑设计        由于7段数码管由7个发光的数码管构成,因为我们想用二进制将0-9这几个数字表示出来。所以他需要

    2024年01月17日
    浏览(48)
  • 基于FPGA的任意位宽乘法器VHDL代码Quartus仿真

    名称:基于FPGA的任意位宽乘法器VHDL代码Quartus仿真(文末获取) 软件:Quartus 语言:VHDL 代码功能: 任意位宽乘法器 设计一个任意位宽乘法器,通过可调参数N,可以配置为任意位宽,N可以自由修改 可调参数N定义如下: N : INTEGER := 16--N位乘法器,N可以自由修改,默认为16位

    2024年02月21日
    浏览(41)
  • xilinx FPGA 乘法器ip核(multipler)的使用(VHDL&Vivado)

    一、创建除法ip核  可以选择两个变量数相乘,也可以选择一个变量输入数据和一个常数相乘 可以选择mult(dsp资源)或者lut(fpga资源) 可以选择速度优先或者面积优先 可以自己选择输出位宽 还有时钟使能和复位功能  二、编写VHDL程序:声明和例化乘法器ip核 三、编写仿真程

    2024年02月11日
    浏览(62)
  • 基于FPGA的3位二进制的乘法器VHDL代码Quartus 开发板

    名称:基于FPGA的3位二进制的乘法器VHDL代码Quartus  开发板(文末获取) 软件:Quartus 语言:VHDL 代码功能: 3位二进制的乘法器 该乘法器实现两个三位二进制的乘法,二极管LED2~LED0显示输入的被乘数,LED5~LED3显示乘数,数码管显示相应的十进制输入值和输出结果 本代码已在开

    2024年02月21日
    浏览(54)
  • 数字IC经典电路(3)——经典除法器的实现(除法器简介及Verilog实现)

    除法器是一种用于执行除法运算的电路或器件。在数字电路中,除法器经常被用作重要的计算单元,其主要功能是将一个数除以另一个数并给出商和余数。 与加法器和减法器类似,除法器也属于算术逻辑单元(ALU)的一种。不同的是,加法器和减法器能够执行加法和减法运算,

    2024年02月02日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包