1.乘法原理

二进制数乘法的显著特点就是可以将乘法转换为移位,乘2就是左移一位,乘2^n就是左移n位。而一个二进制数又可以看成是由若干个2的i次方的和。

设被乘数和乘数分别为M、N,且都是32位的二进制数,乘积结果为64位 的向量CO则

所以乘法可以由移位电路和加法器完成。计算有两种方式:串行和并行。

串行计算是每进行一次移位,将结果相加,计算一次乘法总共需要n+1个时钟周期,n次移位和n次加法。

而并行则是需要两个时钟周期,n个移位电路分别移位之后,将n个结果相加。而第二个周期的n个数相加这一步会需要非常长的计算延时,导致电路时序(建立时间、保持时间)很难满足要求,且风险很高

流水线乘法器则是在串行计算的基础上将每次移位和加法的结果暂存,并且第一级电路计算完成之后可以直接开始下一组数据的乘法计算。对于4位的数据乘法,在延迟后电路会源源不断地输出数据,而普通的并行方式的乘法器则是每两个周期计算一次乘法。

2.模块编写

2.1 底层模块multi_cell

首先我们需要设计一个底层模块用于输出移位和相加结果,并且加上valid和ready信号作为握手协议,valid拉高时输入数据有效

算法中每次被乘数M的移位都是递增,可以将4位的M先拓展成8位的{4'b0,M}作为multi_cell的输入,每级移位一次。对于N,虽然我们可以将N的每一位作为multi_cell的输入,但是这设计时就固定了电路适合的位数。比如4位的代码无法进行8位的计算,需要修改。

所以为了增加设计的通用性,我们将乘数N进行右移,每级移位一次并全部取第0位。当乘法器位宽改变时,只需要修改参数M、N即可。

需要多少级multi_cell由乘数N的位数决定, 对于第i级模块,输入为移位了i次的M,对应的是移位了i次的N,此时第0位即为原N的第i位。在计算加法时,如果移位后的N第0位是1,则上一级和与当前M相加,否则加0。(级数由0开始)

下面是multi_cell的verilog代码

module multi_cell #
(parameter M = 4,parameter N = 4
)
(//input clk,rst_n,multi_M,multi_N,multi_acci,valid,//outputmulti_shift_M,multi_shift_N,multi_acco,ready
);input wire clk;input wire rst_n;input wire [M+N-1:0] multi_M;input wire [N-1:0]   multi_N;input wire [N+M-1:0] multi_acci;output reg [M+N-1:0] multi_shift_M;output reg [N-1:0]   multi_shift_N;output reg [M+N-1:0] multi_acco;//protocalinput wire valid;output reg ready;always @(posedge clk or negedge rst_n) beginif(!rst_n)beginready <= 1'b0;multi_shift_M <= {(M+N){1'b0}};multi_shift_N <= {(N){1'b0}};multi_acco    <= {(M+N){1'b0}};endelse if(valid)beginready <= 1'b1;multi_shift_M <= (multi_M << 1);multi_shift_N <= (multi_N >> 1);if(multi_N[0])multi_acco <= multi_acci + multi_M;elsemulti_acco <= multi_acci;endelse beginready <= 1'b0;multi_shift_M <= {(M+N){1'b0}};multi_shift_N <= {(N){1'b0}};multi_acco    <= {(M+N){1'b0}};endend
endmodule

2.2 顶层模块设计

顶层模块将multi_cell级联即可,将每一级输出的移位之后M的结果作为下一级被乘数的输入,N同理。acco作为下一级的acci。

需要注意的是第0级的acci为0.同时需要消耗寄存器储存每一次的输出(移位输出和acco)。并且由于握手协议的存在,每一级的ready信号作为下一级的valid,并且需要逐级储存,第一级的valid由输入决定,最后一级的ready和累加和连接到输出。

下面是multiplier的顶层代码

`timescale 1ns/1nsmodule multi_pipe#(parameter M = 4,parameter N = 4
)(//input clk,rst_n,multi_M,multi_N,valid,//outputmulti_o,ready
);    input wire clk;input wire rst_n;input wire [M-1:0] multi_M;input wire [N-1:0] multi_N;input wire valid;output wire [N+M-1:0] multi_o;output wire ready;wire [N+M-1:0] multi_shift_M [N-1:0];wire [N+M-1:0] multi_shift_N [N-1:0];wire [N+M-1:0] multi_acco [N-1:0];wire [N-1:0] valid_array;multi_cell#(.M(M),.N(N))multi_cell_0(.clk               (clk                ),.rst_n             (rst_n              ),.multi_M           ({{N{1'b0}},multi_M}),.multi_N           (multi_N            ), .multi_acci        ({(M+N){1'b0}}      ),.valid             (valid              ),.multi_shift_M     (multi_shift_M[0]   ),.multi_shift_N     (multi_shift_N[0]   ),.multi_acco        (multi_acco[0]      ),.ready             (valid_array[0]     ));genvar i;generate for(i=1;i<N;i=i+1)begin:multi_cell_xmulti_cell#(.M(M),.N(N))multi_cell_x(.clk               (clk                ),.rst_n             (rst_n              ),.multi_M           (multi_shift_M[i-1] ),.multi_N           (multi_shift_N[i-1] ), .multi_acci        (multi_acco[i-1]    ),.valid             (valid_array[i-1]   ),.multi_shift_M     (multi_shift_M[i]   ),.multi_shift_N     (multi_shift_N[i]   ),.multi_acco        (multi_acco[i]      ),.ready             (valid_array[i]     ));endendgenerateassign multi_o = multi_acco[N-1];assign ready = valid_array[N-1];
endmodule

3.testbench验证

testbench如下所示,经过延迟后,持续输出数据

`timescale 1ns/1ps
module Top_tb #(parameter M = 4,parameter N = 4
)
();reg          clk;reg          rst_n;reg          data_rdy ;reg [N-1:0]  mult1 ;reg [M-1:0]  mult2 ;wire                 res_rdy ;wire [N+M-1:0]       res ;//driverinitial beginclk = 0;rst_n = 0;#55 ;rst_n = 1;@(negedge clk ) ;data_rdy  = 1'b1 ;mult1  = 25;      mult2      = 5;#10 ;      mult1  = 16;      mult2      = 10;#10 ;      mult1  = 10;      mult2      = 4;#10 ;      mult1  = 15;      mult2      = 7;mult2      = 7;   repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 1;   repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 15;  repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 3;   repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 11;  repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 4;   repeat(32)    #10   mult1   = mult1 + 1 ;mult2      = 9;   repeat(32)    #10   mult1   = mult1 + 1 ;#500 $stop;end//对输入数据进行移位,方便后续校验reg  [N-1:0]   mult1_ref [M-1:0];reg  [M-1:0]   mult2_ref [M-1:0];always @(posedge clk) beginmult1_ref[0] <= mult1 ;mult2_ref[0] <= mult2 ;endgenvar         i ;generatefor(i=1; i<=M-1; i=i+1) beginalways @(posedge clk) beginmult1_ref[i] <= mult1_ref[i-1];mult2_ref[i] <= mult2_ref[i-1];endendendgenerate//自校验reg  error_flag ;always @(posedge clk) begin# 1 ;if (mult1_ref[M-1] * mult2_ref[M-1] != res && res_rdy) beginerror_flag <= 1'b1 ;endelse beginerror_flag <= 1'b0 ;endend//module instantiationmulti_pipe  #(.N(N), .M(M))uut(.clk               (clk),.rst_n             (rst_n),.valid             (data_rdy),.multi_M           (mult1),.multi_N           (mult2),.ready             (res_rdy),.multi_o           (res));always #5 clk = ~clk;
endmodule

流水线乘法器的原理及verilog代码相关推荐

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

    1.booth乘法器原理 对于一个n位的有符号二进制数B,首位是0则B可以表示为: 首位是1,B[n-2:0]是实际数字的补码,所以可以得到 . 可以得到合并的公式如下所示: 将公式展开: 除了n-1 ...

  2. D触发器的工作原理以及Verilog代码(二/二)

    2.  D触发器的verilog代码实现 Verilog实现D触发器的方式有很多,这块主要介绍行为级描述方式: 2.1  基本边沿触发的D触发器 //基本正边沿触发的D触发器 module trigg ...

  3. booth乘法器的原理与verilog实现

    ​ 一.乘法原理 如图所示,二进制乘法和十进制乘法类似,都是单bit相乘,移位后相加 ​​​​​​ 如a(4bit)*b(4bit) 将上图中所有数相加时,我们会用到阵列乘法器 其中,HA表示半加器, ...

  4. Verilog编程-2. 流水线乘法器设计

    Verilog编程-2. 流水线乘法器设计 1. 背景 ​ 在Verilog中,我们一般使用乘法器时直接用*来直接完成,或者调用相关IP核来生成高性能乘法器,但是归根到底Verilog描述的是硬件电路 ...

  5. FPGA学习之路—应用程序—原码二位乘法器及Verilog代码分析

    FPGA学习之路--原码二位乘法器及Verilog代码分析 原理 原码乘法可以分为原码一位乘和原码二位乘,两者在实现规则上大同小异.原码一位乘每次判断乘数的最低位,对被乘数和部分积进行相应操作.而原码 ...

  6. FPGA系统性学习笔记连载_Day8【4位乘法器、4位除法器设计】 【原理及verilog实现、仿真】篇

    FPGA系统性学习笔记连载_Day8[4位乘法器.4位除法器设计] [原理及verilog实现.仿真]篇 连载<叁芯智能fpga设计与研发-第8天> [4位乘法器.4位除法器设计] [原理 ...

  7. fpga驱动oled iic显示代码_【接口时序】6、IIC总线的原理与Verilog实现

    欢迎FPGA工程师加入官方微信技术群 点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群 一. 软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE ...

  8. 异步FIFO的原理以及可综合的Verilog代码

    异步FIFO的原理以及可综合的Verilog代码 一.FIFO的定义 二.FIFO的应用场景 三.FIFO的分类 FIFO的参数 FIFO的设计难点 一.FIFO的定义 _ First In Firs ...

  9. 基于多相滤波器的数字信道化算法详解(Python, Verilog代码已开源)

    基于多相滤波器的数字信道化算法详解 推导过程 总结 仿真 本文详细介绍了基于多相滤波器的数字信道化算法的推导过程, 如果您在阅读的过程中发现算法推导过程中有任何错误, 请不吝指出. 此外, 进入我的G ...

最新文章

  1. P1102 A-B 数对(二分,映射)难度⭐
  2. JAVA IO - RandomAccessFile Seek学习
  3. linux:交叉编译后程序的下载方式
  4. JRE与JDK,SDK的区别
  5. 商场专柜私收银现象治理要点
  6. SpringBoot启动流程是怎样的
  7. jsp内置对象--response
  8. 大数据_Flink_数据处理_运行时架构8_数据传输和任务链---Flink工作笔记0023
  9. SPOJ LCMSUM - LCM Sum
  10. Unity3D基础34.1:打砖块小游戏优化
  11. .Net Core中对FluentEmail.Smtp进行封装使用
  12. 《Using OpenRefine》翻译~8
  13. 小程序AppId-当前开发者未绑定此AppId,请到小程序管理后台操作后重试
  14. 错误:PriviledgedActionException as:LCH (auth:SIMPLE) cause:0: No such file or directory
  15. 会议panel是什么意思中文_会议形式有哪些?
  16. 额温枪方案工作流程、测温原理、功能
  17. 很不错的SQLite工具 SQLiteSpy
  18. 计算机毕业设计Java高校学生综合评价系统(源码+系统+mysql数据库+Lw文档)
  19. flutter 常用的插件
  20. discuz7.2帖子管理

热门文章

  1. 用python庆祝生日_古天乐50大寿,郑秀文杜琪峰设宴庆祝,网友重提30年前那件事...
  2. 智能合约的编译与ABI
  3. Mybatis 框架
  4. 海贼王顶上战争篇OP歌词
  5. Mac OS 下使用OBS 推流到斗鱼直播平台
  6. 使用批处理添加受信任站点和设置ie安全级别
  7. 浅谈分享果实生长传感器适用于植物根茎果实生长大小变化的测量
  8. 一个 15 年 SAP ABAP 开发人员分享的 SAPGUI 一些个性化设置和实用小技巧试读版
  9. 网上开店流程及注意事项
  10. 联想卡位战:得模块化手机者得未来物联网天下?