Verilog | 基4 booth乘法器

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

上接乘法器介绍

原理

跟基2的算法一样,假设A和B是乘数和被乘数,且有:

A = ( a 2 n + 1 a 2 n ) a 2 n − 1 a 2 n − 2 … a 1 a 0 ( a − 1 ) B = b 2 n − 1 b 2 n − 2 … b 1 b 0 \begin{align}A=&(a_{2n+1}a_{2n})a_{2n−1}a_{2n−2}…a_1a_0(a_{−1})\\ B=&b_{2n−1}b_{2n−2}…b_1b_0\end{align} A=B=(a2n+1a2n)a2n1a2n2a1a0(a1)b2n1b2n2b1b0

其中, a − 1 a_{−1} a1是末尾补的0, a 2 n , a 2 n + 1 a_{2n},a_{2n+1} a2n,a2n+1是扩展的两位符号位。可以将乘数A表示为:

A = ( − 1 ⋅ a 2 n − 1 ) 2 2 n − 1 + a 2 n − 2 ⋅ 2 2 n − 2 + ⋯ + a 1 ⋅ 2 + a 0 A=(−1⋅a_{2n−1})2^{2n−1}+a_{2n−2}⋅2^{2n−2}+⋯+a_1⋅2+a_0 A=(1a2n1)22n1+a2n222n2++a12+a0

同样可以将两数的积表示为:

A B = ( a − 1 + a 0 − 2 a 1 ) × B × 2 0 + ( a 1 + a 2 − 2 a 3 ) × B × 2 2 + ( a 3 + a 4 − 2 a 5 ) × B × 2 4 + … + ( a 2 n − 1 + a 2 n − 2 a 2 n + 1 ) × B × 2 2 n = B × [ ∑ k = 0 n ( a 2 k − 1 + a 2 k − 2 a 2 k + 1 ) ⋅ 2 2 k ] = B × V a l ( A ) \begin{align}AB&=(a_{−1}+a_0−2a_1)×B×2^0+(a_1+a_2−2a_3)×B×2^2\\ &+(a_3+a_4−2a_5)×B×2^4+…\\ &+(a_{2n−1}+a_{2n}−2a_{2n+1})×B×2^{2n}\\ &\red{=B×[∑_{k=0}^n(a_{2k−1}+a_{2k}−2a_{2k+1})⋅2^{2k}]}\\ &=B×Val(A)\end{align} AB=(a1+a02a1)×B×20+(a1+a22a3)×B×22+(a3+a42a5)×B×24++(a2n1+a2n2a2n+1)×B×22n=B×[k=0n(a2k1+a2k2a2k+1)22k]=B×Val(A)

红色部分即为基4booth的编码方式。

算法实现

乘数位 ( a 2 k − 1 + a 2 k − 2 a 2 k + 1 ) (a_{2k−1}+a_{2k}−2a_{2k+1}) (a2k1+a2k2a2k+1) 编码操作
000 0
001 +B
010 +B
011 +2B
100 -2B
101 -B
110 -B
111 0
所有操作过后都会移位两次。

Verilog 代码

`timescale 1ns / 1ps

module booth4_mul #(
    parameter WIDTH_M = 8,
    parameter WIDTH_R = 8
) (
    input                            clk,
    input                            rstn,
    input                            vld_in,
    input      [        WIDTH_M-1:0] multiplicand,
    input      [        WIDTH_R-1:0] multiplier,
    output     [WIDTH_M+WIDTH_R-1:0] mul_out,
    output reg                       done
);
    parameter IDLE = 2'b00, ADD = 2'b01, SHIFT = 2'b11, OUTPUT = 2'b10;

    reg [1:0] current_state, next_state;

    reg [WIDTH_M+WIDTH_R+2:0] add1;
    reg [WIDTH_M+WIDTH_R+2:0] sub1;
    reg [WIDTH_M+WIDTH_R+2:0] add_x2;
    reg [WIDTH_M+WIDTH_R+2:0] sub_x2;
    reg [WIDTH_M+WIDTH_R+2:0] p_dct;
    reg [        WIDTH_R-1:0] count;

    always @(posedge clk or negedge rstn)
        if (!rstn) current_state = IDLE;
        else if (!vld_in) current_state = IDLE;
        else current_state <= next_state;

    always @* begin
        next_state = 2'bx;
        case (current_state)
            IDLE:    if (vld_in) next_state = ADD;
	 else next_state = IDLE;
            ADD:     next_state = SHIFT;
            SHIFT:   if (count == WIDTH_R / 2) next_state = OUTPUT;
 else next_state = ADD;
            OUTPUT:  next_state = IDLE;
            default: next_state = IDLE;
        endcase
    end

    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            {add1, sub1, add_x2, sub_x2, p_dct, count, done} <= 0;
        end else begin
            case (current_state)
                IDLE: begin
                    add1   <= {{2{multiplicand[WIDTH_R-1]}}, multiplicand, {WIDTH_R + 1{1'b0}}};
                    sub1   <= {-{{2{multiplicand[WIDTH_R-1]}}, multiplicand}, {WIDTH_R + 1{1'b0}}};
                    add_x2 <= {{multiplicand[WIDTH_M-1], multiplicand, 1'b0}, {WIDTH_R + 1{1'b0}}};
                    sub_x2 <= {-{multiplicand[WIDTH_M-1], multiplicand, 1'b0}, {WIDTH_R + 1{1'b0}}};
                    p_dct  <= {{WIDTH_M + 1{1'b0}}, multiplier, 1'b0};
                    count  <= 0;
                    done   <= 0;
                end
                ADD: begin
                    case (p_dct[2:0])
                        3'b000, 3'b111: p_dct <= p_dct;
                        3'b001, 3'b010: p_dct <= p_dct + add1;
                        3'b101, 3'b110: p_dct <= p_dct + sub1;
                        3'b100:         p_dct <= p_dct + sub_x2;
                        3'b011:         p_dct <= p_dct + add_x2;
                        default:        p_dct <= p_dct;
                    endcase
                    count <= count + 1;
                end
                SHIFT: p_dct <= {p_dct[WIDTH_M+WIDTH_R+2], p_dct[WIDTH_M+WIDTH_R+2], p_dct[WIDTH_M+WIDTH_R+2:2]};

                OUTPUT: begin
                    done <= 1;
                end
            endcase
        end
    end

    assign mul_out = p_dct[WIDTH_M+WIDTH_R:1];

endmodule

testbench:

`timescale 1ns / 1ps

module booth4_mul_tb ();
    `define TEST_WIDTH 8

    parameter WIDTH_M = `TEST_WIDTH;
    parameter WIDTH_R = `TEST_WIDTH;

    reg                               clk;
    reg                               rstn;
    reg                               vld_in;
    reg         [        WIDTH_M-1:0] multiplicand;
    reg         [        WIDTH_R-1:0] multiplier;

    wire        [WIDTH_M+WIDTH_R-1:0] mul_out;
    wire                              done;
    //输入 :要定义有符号和符号,输出:无要求
    wire signed [    `TEST_WIDTH-1:0] m1_in;
    wire signed [    `TEST_WIDTH-1:0] m2_in;

    reg signed  [  2*`TEST_WIDTH-1:0] product_ref;
    reg         [  2*`TEST_WIDTH-1:0] product_ref_u;

    assign m1_in = multiplier[`TEST_WIDTH-1:0];
    assign m2_in = multiplicand[`TEST_WIDTH-1:0];

    always #1 clk = ~clk;
    integer i, j;
    integer num_good;
    initial begin
        clk          = 0;
        vld_in       = 0;
        multiplicand = 0;
        multiplier   = 0;
        num_good     = 0;
        rstn         = 1;
        #4 rstn = 0;
        #2 rstn = 1;
        repeat (2) @(posedge clk);
        for (i = 0; i < (1 << `TEST_WIDTH); i = i + 1) begin
            for (j = 0; j < (1 << `TEST_WIDTH); j = j + 1) begin
                vld_in = 1;
                wait (done == 0);
                wait (done == 1);
                product_ref   = m1_in * m2_in;
                product_ref_u = m1_in * m2_in;
                if (product_ref != mul_out) begin
                    $display("multiplier = %d multiplicand = %d proudct =%d", m1_in, m2_in, mul_out);
                    @(posedge clk);
                    $stop;
                end else begin
                    num_good = num_good + 1;
                end
                multiplicand = multiplicand + 1;
            end
            multiplier = multiplier + 1;
        end
        $display("sim done. num good = %d", num_good);
        $finish;

    end

    booth4_mul #(
        .WIDTH_M(WIDTH_M),
        .WIDTH_R(WIDTH_R)
    ) U_BOOTH_RADIX4_0 (
        .clk         (clk),
        .rstn        (rstn),
        .vld_in      (vld_in),
        .multiplicand(multiplicand),
        .multiplier  (multiplier),
        .mul_out     (mul_out),
        .done        (done)
    );

    initial begin
        $fsdbDumpfile("tb.fsdb");
        $fsdbDumpvars;
        $fsdbDumpMDA();
        $dumpvars();
    end

endmodule

仿真波形图:
Verilog | 基4 booth乘法器文章来源地址https://www.toymoban.com/news/detail-495318.html

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

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

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

相关文章

  • verilog编程之乘法器的实现

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

    2024年04月12日
    浏览(26)
  • 基于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日
    浏览(38)
  • m基于FPGA的半带滤波器verilog设计,对比普通结构以及乘法器复用结构

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

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

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

    2024年01月17日
    浏览(33)
  • 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日
    浏览(26)
  • Logism · 原码一位乘法器 实验

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

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

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

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

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

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

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

    2024年02月21日
    浏览(39)
  • 补码一位乘法(Booth算法)

    在补码一位乘法的求解过程中我们需要的东西:[X]补,[Y]补以及被乘数的相反数的补码[-X]补 一.运算规则 1.符号位参与计算 2.采用补码进行计算 3.被乘数X 一般取双符号位参与计算,并且让部分积初始值为0,长度与被乘数X相同,乘数Y 可取单符号位 4.开始计算时,乘数Y 末尾

    2024年02月11日
    浏览(30)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包