Verilog | 基4 booth乘法器

news/2024/11/15 3:04:08/

上接乘法器介绍

原理

跟基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 / 1psmodule 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 @* beginnext_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;endcaseendalways @(posedge clk or negedge rstn) beginif (!rstn) begin{add1, sub1, add_x2, sub_x2, p_dct, count, done} <= 0;end else begincase (current_state)IDLE: beginadd1   <= {{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;endADD: begincase (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;endcasecount <= count + 1;endSHIFT: 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: begindone <= 1;endendcaseendendassign mul_out = p_dct[WIDTH_M+WIDTH_R:1];endmodule

testbench:

`timescale 1ns / 1psmodule booth4_mul_tb ();`define TEST_WIDTH 8parameter 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 beginclk          = 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) beginfor (j = 0; j < (1 << `TEST_WIDTH); j = j + 1) beginvld_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 beginnum_good = num_good + 1;endmultiplicand = multiplicand + 1;endmultiplier = multiplier + 1;end$display("sim done. num good = %d", num_good);$finish;endbooth4_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();endendmodule

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


http://www.ppmy.cn/news/450715.html

相关文章

Python入门(二十四)异常(一)

异常&#xff08;一&#xff09; 1.概述2.处理ZeroDivisionError异常3.使用try-except代码块4.使用异常避免崩溃 1.概述 Python使用称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时&#xff0c;它都会创建一个异常对象。如果你编写了处理该…

Comet OJ - Contest #10 C.鱼跃龙门

传送门 题意&#xff1a; 求最小的\(x\)&#xff0c;满足\(\frac{x(x1)}{2}\% n0,n\leq 10^{12}\)。 多组数据&#xff0c;\(T\leq 100\)。 思路&#xff1a; 直接考虑模运算似乎涉及到二次剩余什么的&#xff0c;但比较复杂。注意到比较特殊的就是&#xff0c;最后结果为\(0\)…

power的数据库设计MySQL_使用 PowerDesigner 设计数据库 - ~~鱼跃~~ - 博客园

数据库的结构(例如表、关系、视图和触发器)称为数据库模式。可使用 SQL 语句创建这些元素并按照所需的方式进行排列&#xff0c;但是如果不使用图形工具&#xff0c;则可能会造成混淆。 PowerDesigner 提供了一种数据库结构的图形表示。只需绘制新表或输入信息&#xff0c;即可…

业绩突出的鱼跃医疗:研发费用占比较低,财报发布后大跌接近4%

10月22日&#xff0c;鱼跃医疗&#xff08;SZ:002223&#xff09;披露2020年第三季度财报。财报显示&#xff0c;该公司2020年前三季度营收48.48亿元&#xff0c;同比增长36.33%&#xff1b;净利润15.1亿元&#xff0c;同比增长111.84%。 根据财报&#xff0c;鱼跃医疗预计其2…

Comet OJ - Contest #10鱼跃龙门

题目来源&#xff1a;https://www.cometoj.com/contest/65/problem/C?problem_id3684 题意&#xff1a;求k*(k1)/2%n0的最小k。 由k与k1可以想到设置未知数&#xff1a;k1px,kqy,可列得方程&#xff1a;px-qy1&#xff0c;由此扩展欧几里得方程&#xff0c; 原方程为px*qy/…

CometOJ-[Contest #10]鱼跃龙门【exgcd】

正题 题目链接:https://cometoj.com/problem/1479 题目大意 给出 n n n求一个最小的 x ( x > 0 ) x(x>0) x(x>0)满足 ( ∑ i 1 x i ) ≡ 0 ( m o d n ) \left(\sum_{i1}^xi\right)\equiv 0(\mod n) (i1∑x​i)≡0(modn) 1 ≤ n ≤ 1 0 12 , 1 ≤ T ≤ 100 1\leq n…

【gmoj】 【扩欧】 鱼跃龙门

【gmoj】 【扩欧】 鱼跃龙门 题目 解题思路 题意 就是求1~x的和能整除n 高斯求和公式是x&#xff08;x1&#xff09;/2 也就是说x&#xff08;x1&#xff09;/2n 移项x(x1)2n 设apx1&#xff0c;bqx ap-bqgcd(a,b) 要求出最小的bq&#xff08;x&#xff09; 已知b&#xff0…

JDK 内置图形界面工具:海阔凭鱼跃,天高任鸟飞

GUI 图形界面工具,主要是 3 款:JConsole、JVisualVM、JMC。其实这三个产品可以说是 3 代不同的 JVM 分析工具。 这三个工具都支持我们分析本地 JVM 进程,或者通过 JMX 等方式连接到远程 JVM 进程。当然,图形界面工具的版本号和目标 JVM 不能差别太大,否则可能会报错。 下…