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)编码操作
0000
001+B
010+B
011+2B
100-2B
101-B
110-B
1110
所有操作过后都会移位两次。

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

仿真波形图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/31231.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ARIMA-LSTM】合差分自回归移动平均方法-长短期记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于Nginx1.22+PHP8+MySQL8安装Discuz! X3.5

基于Nginx1.22PHP8MySQL8安装Discuz! X3.5 1. 安装PHP82. 安装MySQL83. 配置Nginx1.224. 安装Discuz! X3.5 1. 安装PHP8 更新系统&#xff1a; yum update安装EPEL存储库&#xff1a; yum install epel-release安装Remi存储库&#xff08;提供了最新的 PHP 版本&#xff09;&…

阿里云主机详解:ECS/轻量/虚拟主机/GPU/裸金属/云电脑详解

阿里云云主机分为云虚拟主机、云服务器ECS、轻量应用服务器、GPU云服务器、弹性裸金属服务器、专有宿主机、FPGA云服务器、高性能计算E-HPC、无影云电脑等&#xff0c;阿里云百科来详细说下阿里云云主机详解&#xff1a; 目录 阿里云云主机 云服务器ECS 轻量应用服务器 云…

python数字猜谜2.0

改进了一下数字猜谜&#xff1a; 开头&#xff0c;可选等级&#xff1a; import random guess -1 c 0 print("数字猜谜游戏&#xff01;") n input("选择等级 A B C&#xff1a;") if (n "A") or (n "a"):guess random.randint…

学习css样式的第二章

1.CSS 布局 - display 属性 display 属性是用于控制布局的最重要的 CSS 属性。 display 属性 display 属性规定是否/如何显示元素。 每个 HTML 元素都有一个默认的 display 值&#xff0c;具体取决于它的元素类型。大多数元素的默认 display 值为 block 或 inline 块级元素…

JavaEE课程设计——校园招聘管理系统(vue框架分析)

目录 Vue架构 登录 Vue架构 前端执行命令 npm run serve 这是整个前端的目录结构 vue.config.js是对前端vue的一个配置&#xff0c; // var webpack require(webpack); const path require(path)function resolve(dir) {return path.join(__dirname, dir) }function pu…

centos下的Nginx的安装

1.Nginx简介 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。其特点是占有内存少&#xff0c;并发能力强。 其他服务器介绍&#xff1a;Apache服务器、Tomcat服务器、Lighttpd服务器 2.nginx依赖安装 yum -y instal…

【数据分享】1929-2022年全球站点的逐月平均海平面压力数据(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 对于具体到监测站点的气象数据&#xff0c;之前我们分享过1929-2022年全球气象…

Opencv-C++笔记 (9) : opencv-多通道分离和合并

文章目录 一、概论二、多通道分离函数split()三、多通道合并函数merge()四、图像多通道分离与合并例程 一、概论 在图像颜色模型中不同的分量存放在不同的通道中&#xff0c;如果我们只需要颜色模型的某一个分量&#xff0c;例如只需要处理RGB图像中的红色通道&#xff0c;可以…

数据结构与算法之堆排序

目录 堆排序概述代码实现时间复杂度堆排序概述 堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。…

基于SSM的电影院购票系统开源啦

大家好&#xff0c;今天给大家带来一款SSM的电影院售票系统&#xff0c;非常不错的一个项目&#xff0c;学习javaweb编程必备。 下载地址在文末 1.SpringMVC Spring MVC属于SpringFrameWork的后续产品&#xff0c;已经融合在Spring Web Flow 里面。Spring 框架提供了构建 Web …

香橙派4 2. 驱动usb2.0芯片cy7c68013

0. 环境 - 香橙派4&#xff08;Orangepi4_2.1.2_ubuntu_bionic_desktop_linux4.4.179.img&#xff09; - EZ-USB FX2LP CY7C68013A USB 核心板 1. 下载FX3_SDK_1.3.4_linux EZ-USB™ FX3 Software Development Kit https://www.infineon.com/cms/en/design-support/tools/sdk…

实时在线云消费机、考勤门禁控制器、网络读卡器服务端C# Socket源码

消费机UDP通讯协议介绍&#xff1a; 设备向服务器发送的指令格式&#xff0c;每个字段用半角逗号(,)分隔。序号指令名称指令格式指令说明示例1响应服务器的搜索100,包序列号,终端IP,子网掩码,网关IP,远程电脑主机IP,端口号,终端硬件号响应电脑发出的搜寻局域网内所有终端设备指…

VCL界面控件DevExpress VCL v23.1.3全新首发 - 支持Windows 11新主题

DevExpress VCL Controls是Devexpress公司旗下最老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下…

设计模式之模板方法模式笔记

设计模式之模板方法模式笔记 说明Template Method(模板方法)目录模板方法模式示例类图抽象类包菜类菜心类测试类 说明 记录下学习设计模式-模板方法模式的写法。JDK使用版本为1.8版本。 Template Method(模板方法) 意图:定义一个操作中的算法骨架&#xff0c;而将一些步骤延…

LeetCode - #81 搜索旋转排序数组 II

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…

redis缓存设计-Redis(八)

上篇文章介绍了redis缓存设计&#xff0c;热点key&#xff0c;bigkey注意事项。 原创 redis缓存设计-Redis&#xff08;七&#xff09;https://blog.csdn.net/ke1ying/article/details/131268967 命令使用 hgetall&#xff0c;lrange&#xff0c;smembers&#xff0c;zrange…

兼容性测试如何提高网站的安全性?

兼容性测试如何提高网站的安全性? 在今天的互联网时代&#xff0c;随着各种网络攻击和黑客活动的频繁发生&#xff0c;网站的安全性问题越来越引起人们的关注。而在提高网站安全性方面&#xff0c;兼容性测试是一个非常重要的环节。本文将从什么是兼容性测试、为什么兼容性测试…

Excel 2021入门指南:详细解读常用功能

软件安装&#xff1a;办公神器office2021安装教程&#xff0c;让你快速上手_正经人_____的博客-CSDN博客 一、 新建工作表 打开Excel 2021后&#xff0c;可以看到左上角的“文件”选项&#xff0c;在弹出的菜单中选择“新建”选项&#xff0c;然后可以选择使用空白工作表或者…

软考A计划-系统集成项目管理工程师-一般补充知识-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…