verilog实现32位有符号流水乘法器

1.4bit乘法流程

1.无符号X无符号二进制乘法器

以下为4bit乘法器流程(2X6)

	0 0 0 0 0 0 1 0     (2)
X 0 0 0 0 0 1 1 0 (6)
---------------------
0 0 0 0 0 0 0 0 (0)
0 0 0 0 0 1 0 0 (4)
0 0 0 0 1 0 0 0 (8)
0 0 0 0 0 0 0 0 (0)
0 0 0 0 0 0 0 0 (0)
0 0 0 0 0 0 0 0 (0)
0 0 0 0 0 0 0 0 (0)
0 0 0 0 0 0 0 0 (0)
---------------------
0 0 0 0 1 1 0 0 (12)

注:4bit乘4bit的乘法器,其最大结果位宽为8,即4+4,所用在计算的时候,需要将乘数和被乘数通过符号位扩展到8bit,当然,对于无符号乘法来说,扩展的没有作用,但是对于有符号来说,是必须的,设计的模块为有符号和无符号通用的寄存器,所用建议无符号也进行位宽扩展。

2.有符号X有符号二进制乘法器

以下为4bit乘法器流程(-2 X -6)

	1 1 1 1 1 1 1 0     (-2)
X 1 1 1 1 1 0 1 0 (-6)
---------------------
0 0 0 0 0 0 0 0
1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 0 0 0 0 0
1 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
---------------------
0 0 0 0 1 1 0 0 (12)

3.有符号X无符号二进制乘法器

 	1 1 1 1 1 1 1 0     (-2)
X 0 0 0 0 0 1 1 0 (6)
---------------------
0 0 0 0 0 0 0 0
1 1 1 1 1 1 0 0
1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
---------------------
1 1 1 1 0 1 0 0 (-12)

4.无符号X有符号二进制乘法器

 	0 0 0 0 0 0 1 0     (2)
X 1 1 1 1 1 0 1 0 (-6)
---------------------
0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
---------------------
1 1 1 1 0 1 0 0 (-12)

2.流程简化

由上面4种情况可以总结出一个规律,符号不影响计算流程,只影响截位位置。

​ 例如无符号X有符号二进制乘法器为例:bin(00000010) = dec(2),但是对于bin(11111010)将其当作有符号数来说为dec(-6),当作无符号来说为dec(250),即dec(2)*dec(250)的结果只取低8位的话,当作有符号数即为bin(11110100) = dec(-12)。那么以为着计算有符号数乘法的时候,只需要将其当作无符号数进行计算,最后控制截位位置就可以计算有符号计算器。

那么以下将对16bit乘法进行简化,以-1000 X -1200

1.位宽扩展

dec(-1000) = bin(11111111111111111111110000011000) = dec(4294966296)
dec(-1200) = bin(11111111111111111111101101010000) = dec(4294966096)

2.乘数指数分解

dec(4294966096) = 1*2^31 + 1*2^30 + 1*2^29 + 1*2^28 +
1*2^27 + 1*2^26 + 1*2^25 + 1*2^24 + 1*2^23 + 1*2^22 +
1*2^21 + 1*2^20 + 1*2^19 + 1*2^18 + 1*2^17 + 1*2^16 +
1*2^15 + 1*2^14 + 1*2^13 + 1*2^12 + 1*2^11 + 0*2^10 +
1*2^9 + 1*2^8 + 0*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 +
0*2^2 + 0*2^1 + 0*2^0
则:
dec(4294966296) * dec(4294966096) = dec(4294966296)*2^31 + dec(4294966296)*2^30 +
dec(4294966296)*2^29 + dec(4294966296)*2^28 + dec(4294966296)*2^27 +
dec(4294966296)*2^26 + dec(4294966296)*2^25 + dec(4294966296)*2^24 +
dec(4294966296)*2^23 + dec(4294966296)*2^22 + dec(4294966296)*2^21 +
dec(4294966296)*2^20 + dec(4294966296)*2^19 + dec(4294966296)*2^18 +
dec(4294966296)*2^17 + dec(4294966296)*2^16 + dec(4294966296)*2^15 +
dec(4294966296)*2^14 + dec(4294966296)*2^13 + dec(4294966296)*2^12 +
dec(4294966296)*2^11 + 0*2^10 + dec(4294966296)*2^9 + dec(4294966296)*2^8 +
0*2^7 + dec(4294966296)*2^6 + 0*2^5 + dec(4294966296)*2^4 + 0*2^3 +
0*2^2 + 0*2^1 + 0*2^0

这公式看着复杂一大堆,但是如果把指数看作左移运算符,那么,乘法就转化为左移和加法了。

3.流水线加法

假设num = a + b + c + d + e + f + g + h,将其转化为流水线加法

a

a

b

b

c

c

d

d

e

e

f

f

g

g

h

h

dig0

dig0

dig1

dig1

dig2

dig2

dig3

dig3

dig4

dig4

dig5

dig5

dig6

dig6

num

numText is not SVG - cannot display

4.按需截位

dec(4294966296) * dec(4294966096) = hex(FFFFF76800124F80)
其中16bit乘16bit的乘法器,最大位宽为32bit,取后32bit,即
hex(00124F80) = dec(1200000)

一个完整的乘法流程就算完成了。

3.verilog实现

16位有符号乘法器代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/03/28 22:54:41
// Design Name:
// Module Name: multiplier_16
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies: 16位有符号乘法器
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module multiplier_16
#(
parameter A_WIDTH = 16 ,//数据A的位宽
parameter A_SIGNED = 1 ,//数据A是否有符号
parameter B_WIDTH = 16 ,//数据B的位宽
parameter B_SIGNED = 1 //数据B是否有符号
)
(
input clk ,
input rst ,
input [A_WIDTH-1:0] A,
input [B_WIDTH-1:0] B,
output [A_WIDTH + B_WIDTH - 1:0] P
);
wire [32-1:0] C;
wire [32-1:0] D;
assign C = A_SIGNED?{{32-A_WIDTH{A[A_WIDTH-1]}},A}:{{32-A_WIDTH{1'b0}},A};
assign D = B_SIGNED?{{32-B_WIDTH{B[B_WIDTH-1]}},B}:{{32-B_WIDTH{1'b0}},B};
//*************************************************
genvar i0;
reg [31:0] sum0 [15:0];
generate
for (i0 = 0;i0<=15 ;i0=i0+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum0[i0] <= 0;
end
else begin
case({D[2*i0+1],D[2*i0]})
2'b00:begin
sum0[i0] <= 0 << (2*i0);
end
2'b01:begin
sum0[i0] <= (0 + C) << (2*i0);
end
2'b10:begin
sum0[i0] <= ({C[30:0],1'b0} + 0) << (2*i0);
end
2'b11:begin
sum0[i0] <= ({C[30:0],1'b0} + C) << (2*i0);
end
endcase
end
end
end
endgenerate
genvar i1;
reg [31:0] sum1 [7:0];
generate
for (i1 = 0;i1<=7 ;i1=i1+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum1[i1] <= 0;
end
else begin
sum1[i1] <= sum0[2*i1] + sum0[2*i1+1];
end
end
end
endgenerate
genvar i2;
reg [31:0] sum2 [3:0];
generate
for (i2 = 0;i2<=3 ;i2=i2+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum2[i2] <= 0;
end
else begin
sum2[i2] <= sum1[2*i2] + sum1[2*i2+1];
end
end
end
endgenerate
genvar i3;
reg [31:0] sum3 [1:0];
generate
for (i3 = 0;i3<=1 ;i3=i3+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum3[i3] <= 0;
end
else begin
sum3[i3] <= sum2[2*i3] + sum2[2*i3+1];
end
end
end
endgenerate
reg [31:0] sum4;
always @(posedge clk)begin
if(rst)begin
sum4 <= 0;
end
else begin
sum4 <= sum3[0] + sum3[1];
end
end
assign P = sum4;
endmodule
32位有符号乘法器代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/09/11 22:21:12
// Design Name:
// Module Name: multiplier_pp
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module multiplier
#(
parameter A_WIDTH = 32 ,//数据A的位宽
parameter A_SIGNED = 1 ,//数据A是否有符号
parameter B_WIDTH = 32 ,//数据B的位宽
parameter B_SIGNED = 1 //数据B是否有符号
)
(
input clk ,
input rst ,
input [A_WIDTH-1:0] A,
input [B_WIDTH-1:0] B,
output [A_WIDTH + B_WIDTH - 1:0] P
);
wire [64-1:0] C;
wire [64-1:0] D;
assign C = A_SIGNED?{{64-A_WIDTH{A[A_WIDTH-1]}},A}:{{64-A_WIDTH{1'b0}},A};
assign D = B_SIGNED?{{64-B_WIDTH{B[B_WIDTH-1]}},B}:{{64-B_WIDTH{1'b0}},B};
//*************************************************
genvar i0;
reg [63:0] sum0 [31:0];
generate
for (i0 = 0;i0<=31 ;i0=i0+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum0[i0] <= 0;
end
else begin
case({D[2*i0+1],D[2*i0]})
2'b00:begin
sum0[i0] <= 0 << (2*i0);
end
2'b01:begin
sum0[i0] <= (0 + C) << (2*i0);
end
2'b10:begin
sum0[i0] <= ({C[62:0],1'b0} + 0) << (2*i0);
end
2'b11:begin
sum0[i0] <= ({C[62:0],1'b0} + C) << (2*i0);
end
endcase
end
end
end
endgenerate
genvar i1;
reg [63:0] sum1 [15:0];
generate
for (i1 = 0;i1<=15 ;i1=i1+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum1[i1] <= 0;
end
else begin
sum1[i1] <= sum0[2*i1] + sum0[2*i1+1];
end
end
end
endgenerate
genvar i2;
reg [63:0] sum2 [7:0];
generate
for (i2 = 0;i2<=7 ;i2=i2+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum2[i2] <= 0;
end
else begin
sum2[i2] <= sum1[2*i2] + sum1[2*i2+1];
end
end
end
endgenerate
genvar i3;
reg [63:0] sum3 [3:0];
generate
for (i3 = 0;i3<=3 ;i3=i3+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum3[i3] <= 0;
end
else begin
sum3[i3] <= sum2[2*i3] + sum2[2*i3+1];
end
end
end
endgenerate
genvar i4;
reg [63:0] sum4 [1:0];
generate
for (i4 = 0;i4<=1 ;i4=i4+1 ) begin
always @(posedge clk)begin
if(rst)begin
sum4[i4] <= 0;
end
else begin
sum4[i4] <= sum3[2*i4] + sum3[2*i4+1];
end
end
end
endgenerate
reg [63:0] sum5;
always @(posedge clk)begin
if(rst)begin
sum5 <= 0;
end
else begin
sum5 <= sum4[0] + sum4[1];
end
end
assign P = sum5;
endmodule

verilog实现32位有符号流水乘法器的更多相关文章

  1. JavaScript 32位整型无符号操作

    在 JavaScript 中,所有整数字变量默认都是有符号整数,这意味着什么呢? 有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1 表示负数. 数值范围从 -2^ ...

  2. 编译器是如何实现32位整型的常量整数除法优化的?[C/C++]

    引子 在我之前的一篇文章[ ThoughtWorks代码挑战——FizzBuzzWhizz游戏 通用高速版(C/C++ & C#) ]里曾经提到过编译器在处理除数为常数的除法时,是有优化的,今 ...

  3. 64位与32位编程的数据类型区别(C/C++)

    C/C++仅仅定义了这些基本数据类型之间的关系,并没有定义严格定义它们的字长.在不同的平台上,根据编译器不同的实现,它们的字长如下表所示: 数据类型 LP64 ILP64 LLP64 ILP32 LP ...

  4. PHP长整型在32位系统中强制转化溢出

    CleverCode近期遇到一个PHP项目整形转化问题,mysql有一个字段id是bigint的,里面有长整型,如id = 5147486396.可是php代码因为历史原因却部署在多台机器中,当中A机 ...

  5. 发现Xilinx Virtex 5 FPGA中单个DSP乘法器只支持17位无符号乘法

    发现Xilinx Virtex 5 FPGA中,单个DSP乘法器只支持17位无符号乘法.如果令18位乘数相乘,结果会与正确的乘积不同.

  6. (面试题)请用C语言实现在32位环境下,两个无符号长整数相加的函数,相加之和不能存储在64位变量中

    分析:长整数相加,将结果分为高位和低位部分,分别保存在两个32整数中. 比如:unsigned int a = 0xFFFFFFFF, unsigned int b = 0x1, 结果用unsigne ...

  7. 32位嵌入式微处理器(processor)一览

    32位嵌入式微处理器(processor)一览 由于嵌入式系统的专用型与定制性,与全球PC市场不同,没有一种微处理器或者微处理器公司可以主导嵌入式系统.本文分析了当前市场上主流的一些32位嵌入式微处理 ...

  8. verilog实现16位五级流水线的CPU带Hazard冲突处理

    verilog实现16位五级流水线的CPU带Hazard冲突处理 该文是基于博主之前一篇博客http://www.cnblogs.com/wsine/p/4292869.html所增加的Hazard处 ...

  9. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

  10. Win10 PC一周年更新正式版14393.447 32位/64位更新补丁KB3200970下载 Flash补丁Kb3202790下载

    微软在今天凌晨推送了Win10 PC一周年更新正式版14393.447,本次更新补丁代号为KB3200970,面向Win10一周年更新正式版的PC用户. 更新日志 • 提升了多媒体音频.远程桌面以及I ...

随机推荐

  1. ForkJoin全解2:forkjoin实际工作流程与实现

    1.相关概念解释 1.1 "内部"和外部 当一个操作是在非ForkjoinThread的线程中进行的,则称该操作为外部操作.比如我们前面执行pool.invoke,invoke内又 ...

  2. java加密算法入门(四)-加密算法汇总

    如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorit ...

  3. 转换流:InputStreamReader、OutputStreamWriter

    1.转换流涉及到的类:属于字符流InputStreamReader:将一个字节的输入流转换为字符的输入流解码:字节.字节数组 --->字符数组.字符串 OutputStreamWriter:将一 ...

  4. React中的数据流管理

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:霜序 前言 为什么数据流管理重要? React 的核心思想 ...

  5. AI编程:Coze + Cursor实现一个思维导图的浏览器插件

    这是小卷对AI编程工具学习的第3篇文章,今天以实际开发一个思维导图的需求为例,了解AI编程开发的整个过程 1.效果展示 2.AI编程开发流程 虽然AI编程知识简单对话就行,不过咱要逐步深入到项目开发中 ...

  6. Redis缓存异常及解决方案

    本文分享自天翼云开发者社区<Redis缓存异常及解决方案>,作者:l****n 本文向读者解释了Redis使用过程中,数据不一致.缓存雪崩.缓存击穿和缓存穿透等问题的定义,并给出对应的解决 ...

  7. Linux VXLAN小实验

    本文分享自天翼云开发者社区<Linux VXLAN小实验>,作者:李****一 前言 VXLAN在云网络中应用十分广泛.本文介绍一种方法在两台Linux主机之间建立简单的VXLAN隧道,以 ...

  8. JavaScript数组(包括上一笔记都是ECMAScript对象),BOM对象,DOM对象,html DOM Enent(事件)

    JavaScript数组(包括上一笔记都是ECMAScript对象),BOM对象,DOM对象,html DOM Enent(事件) 1.Arrary; var ret = new Arrary(1,2 ...

  9. 聊聊GRPO算法——从Open R1来看如何训练DeepSeek R1模型

    概述 首发自个人公众号:阿郎小哥的随笔驿站 DeepSeek R1系列建议阅读之前的系列文章: 聊聊DeepSeek R1的一些总结 聊聊DeepSeek R1的开源复现库--Open R1之合成数据 ...

  10. split 命令分割超大日志文件

    split 命令分割超大日志文件 split -l 1000000 jmeter1432.log part_ 在Windows系统中也可以通过gitbash执行此命令 运行结果: