无符号乘法器的两种写法:移位相加和流水线

相比于有符号乘法器,无符号乘法器就不需要考虑符号位的判断,直接计算即可。乘法器简单理解也就是每一位相乘过后相加取和的结果,唯独需要考虑的是:“每一位相乘”,这就需要考虑进行移位操作。而两种不同的写法就是是否添加了寄存器,有符号乘法器的详细例子:https://www.cnblogs.com/shadow-fish/p/13368689.html

1:两个N位二进制数相乘结果为2N位。

 out_c = out_c + ((b_in[i]==1'b1)?({4'b0,a_in}<<i):0); //这个跟下方的主要部分是一致的。

移位相加型乘法器

module shift_add(a,b,out);

input [3:0]a;
input [3:0]b;
output [7:0]out;

reg [7:0]out_c;
integer i;
always@(a or b) begin
    out_c = 8'b0;
    for(i=0;i<=3;i=i+1) begin
        out_c = out_c + ((b[i]==1'b1)?(a<<i):0);
    end
end
assign out = out_c;
endmodule

tb文件:

`timescale 1ns/1ps
module shift_add_tb;
reg [3:0]a;
reg [3:0]b;

wire [7:0]out;

shift_add u1(
    .a(a),
    .b(b),
    .out(out)
);
initial begin
    a=4'b1101;
    b=4'b0011;
    #20;
    a=4'b1011;
    b=4'b1100;
end
endmodule

 

 

流水线设计--添加寄存器:先将相邻的乘积进行相加,然后再输出最终结果

module pipline_add (
    clk,rst,a,b,out
);
    input clk;
    input rst;
    input [3:0]a; //被乘数
    input [3:0]b; //乘数
    output [7:0]out;

    reg [7:0]out;
    reg [7:0]out_1;
    reg [7:0]out_2;
    reg [7:0]out_3;
    reg [7:0]out_4;
    reg [7:0]out_5;
    reg [7:0]out_6;

    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            out <= 8'b0;
            out_1 <= 8'b0;
            out_2 <= 8'b0;
            out_3 <= 8'b0;
            out_4 <= 8'b0;
            out_5 <= 8'b0;
            out_6 <= 8'b0;
        end
        else begin
            out_1 <= ((b[0]==1'b1)?({4'b0,a}):8'b0); //判断乘数位是否为1,若是,则结果进行对应位的移位
            out_2 <= ((b[1]==1'b1)?({3'b0,a,1'b0}):8'b0);
            out_3 <= ((b[2]==1'b1)?({2'b0,a,2'b0}):8'b0);
            out_4 <= ((b[3]==1'b1)?({1'b0,a,3'b0}):8'b0);

            out_5 <= out_1 + out_2; //添加流水线
            out_6 <= out_3 + out_4;

            out <= out_5 + out_6;
        end
    end
endmodule

tb文件:

`timescale 1ns/1ps
module pipline_add_tb;

    reg clk;
    reg rst;
    reg [3:0]a;
    reg [3:0]b;
    
    wire [7:0]out;

    pipline_add u1(
        .clk(clk),
        .rst(rst),
        .a(a),
        .b(b),
        .out(out)
    );
    
    initial begin
        clk = 1'b0;
        rst = 1'b0;
        #5;
        rst = 1'b1;
    end

    always #5 clk = ~clk;

    initial begin
        a = 4'b1101;
        b = 4'b1000;
        #60;
        a = 4'b0110;
        b = 4'b1001;
        #80;
        $stop();
    end
endmodule

此上均是只进行了功能仿真,未进行时序仿真。

 

posted @ 2020-08-03 21:06  影-fish  阅读(1315)  评论(0编辑  收藏  举报