基2-booth乘法器原理及verilog代码

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

1.booth乘法器原理

对于一个n位的有符号二进制数B,首位是0则B可以表示为:

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

首位是1,B[n-2:0]是实际数字的补码,所以可以得到

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

可以得到合并的公式如下所示:

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

将公式展开:

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

除了n-1项外的每一项乘2之后再减去本身:

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

根据2^i重构公式:

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

为了统一形式,添加一项B[-1],初始值为0.注意这里的B[-1]是一个单独的寄存器,与B并没有关系则B可以修改为

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

booth乘法器,乘法器,fpga开发,51单片机,stm32,单片机,Powered by 金山文档

2.乘法器模块设计

对于上一章节的B的公式我们可以看出,实际关注的是B中相邻两位的大小,所以可以对B进行移位处理即可每次只关注B[0]B[-1],同时A乘的2的i次方也是对A进行移位。综上我们可以构建一个新的向量array,用来移位和计算累加和。

从i=0开始计算累加和,对累加和的计算总共有三种情况:

  1. { B[i],B[i-1] } = 2'b00或2'b11 :B[i-1]-B[i] = 0,无操作

  1. { B[i],B[i-1] } = 2'b01 :B[i-1]-B[i] = 1,相加

  1. { B[i],B[i-1]} = 2'b10 :B[i-1]-B[i] = -1,相减

不妨设计算两个四位的二进制数相乘,首先定义一个四位的寄存器Q用来计算累加和。在这里可能会有个疑问,四位二进制数相加结果应该是五位的数,为什么这里只需要设四位。

所以array的实际组成是array = {Q,B,B[-1]};Q和B[-1]的初始值都是0.每次计算都是先根据B[0]B[-1]的结果,计算Q的值,然后进行算术右移。并定义一个计数器用来计算执行次数,总次数即为B的位数。

我们可以发现第一次计算的Q到最后是移位到了最末端,这种计算方式和普通移位的区别是,普通方法是将2^i,左移i次,而本节的方式是将数从高位右移,实际结果相同。

下面给出7*(-5)的例子作为参考

-----------------------------------------初始化------------------------------------------

设4-bit A , 4-bit B , 4-bit Q ,1-bit B[-1]

A = 0111(7);

-A = 1001;

B = 1011(-5);

Q = 0000;

B[-1] = 0;

B[0]B[-1] = 10;

{Q,B,B[-1]} = 0000_1011_0;

-----------------------------------------count = 3---------------------------------------

----------------------------------------计算累加和---------------------------------------

B = 1011;

B[-1] = 0;

B[0]B[-1] = 10;

Q = Q - A = 1001;

{Q,B,B[-1]} = 1001_1011_0

--------------------------------------------移位-----------------------------------------

{Q,B,B[-1]} = 1100_1101_1

-----------------------------------------count = 2---------------------------------------

-----------------------------------------计算累加和-------------------------------------

Q = 1100;

B = 1101;

B[-1] = 1;

B[0]B[-1] = 11;无操作

Q = Q = 1100;

{Q,B,B[-1]} = 1100_1101_1

--------------------------------------------移位-----------------------------------------

{Q,B,B[-1]} = 1110_0110_1

-----------------------------------------count = 1---------------------------------------

-----------------------------------------计算累加和-------------------------------------

Q = 1110;

B = 0110;

B[-1] = 1;

B[0]B[-1] = 01;相加

Q = Q + A = 1110 + 0111 = 0101;

{Q,B,B[-1]} = 0101_0110_1

--------------------------------------------移位-----------------------------------------

{Q,B,B[-1]} = 0010_1011_0

-----------------------------------------count = 0---------------------------------------

-----------------------------------------计算累加和-------------------------------------

Q = 0010;

B = 1011;

B[-1] = 0;

B[0]B[-1] = 10;相减

Q = Q - A = 0010 + 1001 = 1011;

{Q,B,B[-1]} = 1011_1011_1;

--------------------------------------------移位-----------------------------------------

{Q,B,B[-1]} = 1101_1101_1;

--------------------------------------------输出-----------------------------------------

CO = 1101_1101;

3.verilog代码与testbench

3.1 verilog代码

module boothmultiplier_radix2#(
    parameter size = 4 
)
(
    clk,
    rst_n,
    valid_i,
    receive_i,
    multiplicand_i,
    multiplier_i,
    busy_o,
    ready_o,
    result_o
);
    input wire clk;
    input wire rst_n;
    input wire valid_i;
    input wire receive_i;
    input wire signed [size-1:0] multiplicand_i;
    input wire signed [size-1:0] multiplier_i;
    output reg busy_o;
    output reg ready_o;
    output wire signed [2*size-1:0] result_o;

    reg signed [2*size:0] array;
    reg [size-1:0] M;
    reg [size-1:0] Q;
    reg [1:0] count;

    localparam STATE_IDLE  = 2'b00;
    localparam STATE_CALC  = 2'b01;
    localparam STATE_SHIFT = 2'b10;
    localparam STATE_END   = 2'b11;

    reg [1:0] state,next_state;

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            state <= STATE_IDLE;
        end else begin
            state <= next_state;
        end
    end

    always@(*)begin
        if(!rst_n)begin
            next_state = STATE_IDLE;
        end else begin
            case (state)
                STATE_IDLE: begin
                    if(valid_i)begin
                        next_state = STATE_CALC;
                    end else begin
                        next_state = STATE_IDLE;
                    end
                end
                STATE_CALC: begin
                        next_state = STATE_SHIFT;
                end
                STATE_SHIFT: begin
                    if(count == 0)begin
                        next_state = STATE_END;
                    end else begin
                        next_state = STATE_CALC;
                    end
                end
                STATE_END: begin
                    if(receive_i)begin
                        next_state = STATE_IDLE;
                    end else begin
                        next_state = STATE_END;
                    end
                end
                default: next_state = STATE_IDLE;
            endcase
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)begin
            array <= 'b0;
            M <= 'b0;
            Q <= 'b0;
            ready_o <= 1;
            busy_o <= 0;
            count <= 0;
        end else begin
            case(state)
                STATE_IDLE: begin
                    if(valid_i)begin
                        ready_o <= 0;
                        busy_o <= 1;
                        M <= multiplicand_i;
                        Q <= multiplier_i;
                        count <= 2'd3;
                        array <= {4'b0,multiplier_i,1'b0};
                    end else begin
                        array <= 'b0;
                        M <= 'b0;
                        Q <= 'b0;
                        ready_o <= 1;
                        busy_o <= 0;
                        count <= 2'b0;
                    end
                end
                STATE_CALC: begin
                    case({array[1:0]})
                        2'b00,2'b11:begin
                            array <= array;
                        end
                        2'b01:begin
                            array <= (array + {M[size-1:0],{(size+1){1'b0}}});
                        end
                        2'b10:begin
                            array <= (array - {M[size-1:0],{(size+1){1'b0}}});
                        end
                    endcase
                end
                STATE_SHIFT: begin
                    if(count != 0)begin
                        count <= count -1; 
                    end else begin
                        count <= 2'd3;
                        busy_o <= 0;
                        ready_o <= 1;
                    end
                    array <= array >>> 1;
                end
                STATE_END: begin
                    if(receive_i)begin
                        busy_o <= 0;
                        ready_o <= 1;
                    end else begin
                        busy_o <= 1;
                        ready_o <= 0;
                    end
                end
                default: begin
                    array <= 'b0;
                    M <= 'b0;
                    Q <= 'b0;
                    busy_o <= 0;
                    count <= 2'd3;
                end
            endcase
        end
    end

    assign result_o = (state == STATE_END)?array[8:1]:0;
endmodule

3.2 testbench

module Top_tb
();
    reg clk;
    reg rst_n;
    reg valid_i;
    reg signed [3:0] multiplicand_i;
    reg signed [3:0] multiplier_i;
    reg receive_i;

    wire [3:0]result_o;
    wire ready_o;
    wire busy_o;
    boothmultiplier_radix2#(
        .size(4)
    )
    UUT(
        .clk(clk),
        .rst_n(rst_n),
        .valid_i(valid_i),
        .receive_i(receive_i),
        .multiplicand_i(multiplicand_i),
        .multiplier_i(multiplier_i),
        .busy_o(busy_o),
        .ready_o(ready_o),
        .result_o(result_o)
    );
    
    initial begin
        clk = 0;
        rst_n = 0;
        #100
        rst_n = 1;
        #100
        wait(clk);
        multiplicand_i = 4'b0111;
        multiplier_i = 4'b1011;
        valid_i = 1;
        #20
        valid_i = 0;
        wait(ready_o);
        receive_i = 1;
        multiplicand_i = 4'b0101;
        multiplier_i = 4'b1001;
        valid_i = 1;
        #1000
        $stop;
    end

    always #10 clk = ~clk;
endmodule

4.评价与展望

1、由于计算和移位在同一周期内实现并不是很好写,也为了更加直观,代码中将计算和移位分在两个周期中完成,导致计算速度会将近降了一倍。

2、输出result_o采用的是wire类型输出,也可修改为reg输出,更加稳定。

3、后续可加入流水线,增加数据吞吐量。

4、testbench并不完整,只是给了个框架,有兴趣的朋友可以完善一下。文章来源地址https://www.toymoban.com/news/detail-775379.html

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

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

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

相关文章

  • 基于FPGA的3位二进制的乘法器VHDL代码Quartus 开发板

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

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

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

    2023年04月08日
    浏览(80)
  • 基于FPGA的任意位宽乘法器VHDL代码Quartus仿真

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

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

    数字电路中乘法器是一种常见的电子元件,其基本含义是将两个数字相乘,并输出其乘积。与加法器不同,乘法器可以实现更复杂的运算,因此在数字电路系统中有着广泛的应用。 乘法器的主要用途是在数字信号处理、计算机科学以及其他数字电路应用中进行精确的数字乘法

    2024年02月06日
    浏览(67)
  • verilog编程之乘法器的实现

    知识储备 首先来回顾一下乘法是如何在计算机中实现的。 假设现在有两个32位带符号定点整数x和y,我们现在要让x和y相乘,然后把乘积存放在z中,大家知道,两个32位数相乘,结果不会超过64位,因此z的长度应该为64位。 z = x * y中,x是被乘数,在Verilog代码中 multiplicand表示

    2024年04月12日
    浏览(38)
  • 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日
    浏览(42)
  • xilinx FPGA 乘法器ip核(multipler)的使用(VHDL&Vivado)

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

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

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

    2024年01月17日
    浏览(50)
  • Logism · 原码一位乘法器 实验

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

    2023年04月25日
    浏览(42)
  • FPGA流水线除法器(Verilog)原理及实现

      除法器的计算过程如下图所示。 假设数值的位宽为N。 Step1:分别将被除数和除数扩展至原来2倍位宽(2N),被除数在其左边补N位0,除数在其右边补N位0; Step2:将被除数依次左移(每次左移1位),末位补数值(该数值为被除数高N位与除数高N位的商),高N位为被除数高

    2024年02月11日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包