verilog乘法器的设计

在verilog编程中,常数与寄存器变量的乘法综合出来的电路不同于寄存器变量乘以寄存器变量的综合电路。知乎里的解释非常好https://www.zhihu.com/question/45554104,总结乘法器模块的实现https://blog.csdn.net/yf210yf/article/details/70156855

乘法的实现是移位求和的过程

乘法器模块的实现主要有以下三种方法

1.串行实现方法

占用资源最多,需要的时钟频率高些,但是数据吞吐量却不大

两个N位二进制数x、y的乘积用简单的方法计算就是利用移位操作来实现。

其框图如下:

其状态图如下:

代码:

module multi_CX(clk, x, y, result);
02

03
    input clk;
04
    input [7:0] x, y;
05
    output [15:0] result;
06

07
    reg [15:0] result;
08

09
    parameter s0 = 0, s1 = 1, s2 = 2;
10
    reg [2:0] count = 0;
11
    reg [1:0] state = 0;
12
    reg [15:0] P, T;
13
    reg [7:0] y_reg;
14

15
    always @(posedge clk) begin
16
        case (state)
17
            s0: begin
18
                count <= 0;
19
                P <= 0;
20
                y_reg <= y;
21
                T <= {{8{1‘b0}}, x};
22
                state <= s1;
23
            end
24
            s1: begin
25
                if(count == 3‘b111)
26
                    state <= s2;
27
                else begin
28
                    if(y_reg[0] == 1‘b1)
29
                        P <= P + T;
30
                    else
31
                        P <= P;
32
                    y_reg <= y_reg >> 1;
33
                    T <= T << 1;
34
                    count <= count + 1;
35
                    state <= s1;
36
                end
37
            end
38
            s2: begin
39
                result <= P;
40
                state <= s0;
41
            end
42
            default: ;
43
        endcase
44
    end
45

46
endmodule

慢速信号处理中常用到的。

2.并行流水线实现方法

将操作数的N位并行提交给乘法器,这种方法并不是最优的实现架构,在FPGA中进位的速度远大于加法的速度,因此将相临的寄存器相加,相当于一个二叉树的结构,实际上对于n位的乘法处理,需要logn级流水来实现。

一个8位乘法器,其原理图如下图所示:

其实现的代码如下:

module multi_4bits_pipelining(mul_a, mul_b, clk, rst_n, mul_out);
input [3:0] mul_a, mul_b;
input  clk;
input  rst_n;
output [15:0] mul_out;

reg [15:0] mul_out;
reg [15:0] stored0;
reg [15:0] stored1;
reg [15:0] stored2;
reg [15:0] stored3;
reg [15:0] stored4;
reg [15:0] stored5;
reg [15:0] stored6;
reg [15:0] stored7;

reg [15:0] mul_out01;
reg [15:0] mul_out23;

reg [15:0] add01;
reg [15:0] add23;
reg [15:0] add45;
reg [15:0] add67;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
mul_out <= 0;
        stored0 <= 0;
        stored1 <= 0;
stored2 <= 0;
stored3 <= 0;
stored4 <= 0;
        stored5 <= 0;
stored6 <= 0;
stored7 <= 0;

add01 <= 0;
add23 <= 0;
add45 <= 0;
add67 <= 0;
    end
else begin
stored0 <= mul_b[0]? {8‘b0, mul_a} : 16‘b0;
stored1 <= mul_b[1]? {7‘b0, mul_a, 1‘b0} : 16‘b0;
stored2 <= mul_b[2]? {6‘b0, mul_a, 2‘b0} : 16‘b0;
stored3 <= mul_b[3]? {5‘b0, mul_a, 3‘b0} : 16‘b0;
stored4 <= mul_b[0]? {4‘b0, mul_a, 4‘b0} : 16‘b0;
stored5 <= mul_b[1]? {3‘b0, mul_a, 5‘b0} : 16‘b0;
stored6 <= mul_b[2]? {2‘b0, mul_a, 6‘b0} : 16‘b0;
stored7 <= mul_b[3]? {1‘b0, mul_a, 7‘b0} : 16‘b0;
add01 <= stored1 + stored0;
add23 <= stored3 + stored2;
add45 <= stored5 + stored4;
add67 <= stored7 + stored6;

mul_out01 <= add01 + add23;
mul_out23 <= add45 + add67;

mul_out <= mul_out01 + mul_out23;

    end
end
endmodule

流水线乘法器比串行乘法器的速度快很多很多,在非高速的信号处理中有广泛的应用。至于高速信号的乘法一般需要利用FPGA芯片中内嵌的硬核DSP单元来实现。

3.booth算法

看了原文献,有基2和基4两种实现

最常用的主要还是基2实现也就是用被除数的每两位做编码,Booth算法对乘数从低位开始判断,根据两个数据位的情况决定进行加法减法还是仅仅移位操作。判断的两个数据位为当前位及其右边的位(初始时需要增加一个辅助位0),移位操作是向右移动。

在Booth算法中,操作的方式取决于表达式(y【i+1】-y【i】)的值,这个表达式的值所代表的操作为:

0 无操作

+1 加x

-1 减x

Booth算法操作表示

yi yi+1 操作 说明

0 0 无 处于0串中,不需要操作

0 1 加x 1串的结尾

1 0 减x 1串的开始

1 1 无 处于1串中,不需要操作

乘法过程中,被乘数相对于乘积的左移操作可表示为乘以2,每次循环中的运算可表示为对于x(y(i+1)-yi)2^31-i项的加法运算(i=3l,30,…,1,0)。这样,Booth算法所计算的结果 可表示为:

x×(0-y31)×2^0

+x×(y31-y30)×2^1

+x×(y30-y29)×2^2

+x×(y1-y0)×2^31 [1]

=x×(-y0×2^31 +y1×2^30 +y2×2^29+.......+y31×2^0)

=x×y

代码

module booth( start_sig, a, b, done_sig , product)
wire [1:0] start_sig;
wire [7:0] a;
wire [7:0] b;
wire [15:0] product;
/********************************/
reg[3:0] i;
reg[7:0] ra;
reg[7:0] rs;
reg[16:0] rp;
reg[3:0] x;
reg isdone;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
         i<=4‘d0;
         ra<=8‘d0;
         rs<=8‘d0;
         rp<=17‘d0;
         x<=4‘d0;
         isdone<=1‘b0;
end
else if(start_sig)
        case(i)
        0:
           begin
                ra<=a;
                rs<=(~a+1);
                rp<={8‘d0,b,1‘b0};
                i<=i+1;
            end
        1:
           if(x==8)
                  begin
                       x<=4‘d0;
                        i<=i+2;
                  end
            else if(rp[1:0]==2‘b01)
                  begin
                        rp<={rp[16:9]+ra,rp[8:0]};
                         i<=i+1;
                  end
           else if(rp[1:0]==2‘b10)
                  begin
                         rp<={rp[16:9]+rs,rp[8:0]};
                         i<=i+1;
                  end
           else
                  i<=i+1;
        2:
            begin
                  rp<={rp[16],rp[16:1]};
                  x<=x+1;//返回去检测对应寄存器值的方法
                  i<=i-1;
            end
        3:
            begin
                  isdone<=1‘b1;
                  i<=i+1;
             end
        4:
             begin
                  isdone<=1‘b0;
                  i<=4‘d0;
             end
        endcase
assign product=rp[16:1];
assign done_sig=isdone;
endmodule

例1.38 设被乘数M=0111(7),乘数Q=1101(-3),相乘过程如下:A为开始补加的零,

A         Q Q-1

0000 1101 0 初始值

1001 1101 0 A=A-M=0000-0111=1001

1100 1110 1 右移(第1次循环)/2

0011 1110 1 A=A + M=1100+0111=0011

0001 1111 0 右移(第2次循环)/2

1010 1111 0 A=A-M=0001-0111=1010

1101 0111 1 右移(第3次循环)/2

1110 1011 1 右移(第4次循环)/2

乘积=11101011=(-21)(十进制)

其中的移位是算数移位.

被乘数n位要移位3次.

原文地址:https://www.cnblogs.com/Dinging006/p/9465355.html

时间: 2024-10-06 03:57:41

verilog乘法器的设计的相关文章

Verilog代码可移植性设计(转自特权同学博客http://bbs.ednchina.com/BLOG_ARTICLE_1983188.HTM)

最近开始学习FPGA,之前项目中仅用过parameter,在CrazyBingo的<FPGA设计技巧与案例开发例程详解>中看到使用localparam,以及在366页中简单介绍了下‘define,parameter和localparam的区别.查找特权同学博客发现其曾经讲诉过.文中红色阴影处为文中错误. Verilog代码可移植性设计 1.       参数定义 localparam,实例代码如下: module tm1( clk,rst_n, pout ); input clk; input

转载Verilog乘法器

1. 串行乘法器 两个N位二进制数x.y的乘积用简单的方法计算就是利用移位操作来实现. module multi_CX(clk, x, y, result); input clk; input [7:0] x, y; output [15:0] result; reg [15:0] result; parameter s0 = 0, s1 = 1, s2 = 2; reg [2:0] count = 0; reg [1:0] state = 0; reg [15:0] P, T; reg [7:

8421BCD转余3码Verilog HDL的设计(2)

接着上节8421BCD转余3码Verilog HDL的设计(1),分析另一条路径A-C分支 (1)在C状态,t1时刻Bin输入的值可能为0或者1:当bin输入0时,进入F状态:当bin输入1时,进入G状态,比特流Bin二进制为t3t2t1t0的可能性如下: C状态(t1时刻,Bin=0),Bout=0 C状态(t1时刻,Bin=1),Bout=1 t3t2t1t0 T3T2T1T0 下一状态为F状态 t3t2t1t0 T3T2T1T0 下一状态为G状态 0001 0100 0011 0110 0

Verilog学习笔记设计和验证篇(三)...............同步有限状态机的指导原则

因为大多数的FPGA内部的触发器数目相当多,又加上独热码状态机(one hot code machine)的译码逻辑最为简单,所以在FPGA实现状态机时,往往采用独热码状态机(即每个状态只有一个寄存器置位的状态机).建议采用case语句来建立状态机的模型,因为这些语句表达清晰明了,可以方便的由当前状态转向下一个状态并设置输出.记得:不要忘记在case语句的最后写上default分支,并将状态设置为'bx这就等于告诉综合器case语句已经指定了所有的状态.这样综合器就可以删除不必要的译码电路使生成

基于verilog的分频器设计(奇偶分频原理及其电路实现:上)

在一个数字系统中往往需要多种频率的时钟脉冲作为驱动源,这样就需要对FPGA的系统时钟(频率太高)进行分频.分频器主要分为奇数分频,偶数分频,半整数分频和小数分频,在对时钟要求不是很严格的FPGA系统中,分频器通常都是通过计数器的循环来实现的. 偶数分频:假设为N分频,由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数.以此循环下去.这种方法可以实现任意的偶数分频.如图所示,两个D触发器级联实现四分频电路,原理:来一个

基于verilog的分频器设计(半整数分频,小数分频:下)

半整数分频器:计数器是通过上升沿触发,故在计数为N-1时对计数触发进行翻转,时钟的下降沿变为上升沿,因此计数值为0,所以每产生n+0.5分频时钟的周期,触发时钟都要翻转一次.如图所示,采用异或门和2分频模块设计脉冲扣除电路,脉冲扣除是输入频率和2分频输出相异或的结果. module fenpin(clk,rst_n,clk_out); input clk; input rst_n; output clk_out; reg clk_out2; wire clk_out1; reg [1:0] cn

Verilog学习笔记设计和验证篇(五)...............层次化事件队列

详细的了解层次化事件队列有助于理解Verilog的阻塞赋值和非阻塞赋值功能.所谓层次化事件队列指的是用于调度仿真时间的不同Verilog事件队列.在IEEE的5.3节中定义了层次化事件队列在逻辑上分为用于当前仿真事件的4个不同队列,和用于下一段仿真事件的若干个附加队列: 1)动态事件队列(下列事件队列的执行顺序可以随意安排) a)阻塞赋值 b)计算非阻塞赋值的RHS  c)连续赋值  d)执行$display命令  e)计算原语的输入输出变化 2)停止运行的事件队列: #0延时阻塞赋值 3)非阻

verilog 奇数分频设计

module tw(clk,k_or,k1,k2); input clk; output k_or,k1,k2; reg [2:0] c1,c2; reg m1,m2; initial begin c1=0; c2=0; m1=0; m2=0; end always @(posedge clk) begin if(c1==a) c1<=0;else c1<=c1+1; if(c1==1) m1=~m1;else if(c1==b) m1=~m1;end always @(negedge clk

明德扬至简设计法--verilog综合器和仿真器

Verilg是硬件描述语言,顾名思义,就是用代码的形式描述硬件的功能.而我们最终是要在电路上实现该功能的.当Verilog描述出硬件功能后,我们需要综合器对Verilog代码进行解释,将代码转化成实际的电路来表示,最终实际的电路,我们称之为网表.这种将Verilog代码转成网表的工具,就是综合器.上图左上角是一份verilog代码,该代码描述了一个加法器功能.该代码经过综合器解释后,转化成一个加法器电路.QUARTUS.ISE和VIVADO都是综合器,集成电路常用的综合器是DC. 我们在FPGA