运用加法器实现两个5位有符号数相乘-verilog

module sign_pipline_muli (
    clk,rst,mul_a,mul_b,mul_out
);
    input clk;
    input rst;
    input [4:0]mul_a;
    input [4:0]mul_b;
    output [8:0]mul_out;

    reg [8:0]mul_out;
    reg mul_out_H;  //输出符号位判断
    reg mul_out_H0;//输出符号为延时,使其与数据位保持时序一致
    reg mul_out_H1;
    reg mul_out_H2;
    reg mul_out_H3;
    
    reg [4:0]mul_a_1;//判断输入数据是正还是负,正则为其本身;负则保留符号位,数据位转为补码
    reg [4:0]mul_b_1;

    reg [7:0]stored0;//采用移位相加,流水线设计
    reg [7:0]stored1;
    reg [7:0]stored2;
    reg [7:0]stored3;

    reg [7:0]add0;
    reg [7:0]add1;
    reg [7:0]add2;

    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            mul_out <= 9'b0;
            mul_a_1 <= 5'b0;
            mul_b_1 <= 5'b0;
            mul_out_H <= 1'b0;
            mul_out_H0 <= 1'b0;
            mul_out_H1 <= 1'b0;
            mul_out_H2 <= 1'b0;
            mul_out_H3 <= 1'b0;
            stored0 <= 8'b0;
            stored1 <= 8'b0;
            stored2 <= 8'b0;
            stored3 <= 8'b0;
            add0 <= 8'b0;
            add1 <= 8'b0;
            add2 <= 8'b0;
        end
        else begin
            mul_out_H0 <= mul_a[4] ^ mul_b[4];
            mul_out_H1 <= mul_out_H0;
            mul_out_H2 <= mul_out_H1;
            mul_out_H <= mul_out_H2;//对符号位进行延时,满足与数据位的时序要求
          
            
            mul_a_1 <= (mul_a[4]==1'b0)?mul_a:({mul_a[4],~mul_a[3:0]+1'b1});
            mul_b_1 <= (mul_b[4]==1'b0)?mul_b:({mul_b[4],~mul_b[3:0]+1'b1});

            stored0 <= ((mul_b_1[0]==1'b1)?{4'b0,mul_a_1[3:0]}:8'b0);
            stored1 <= ((mul_b_1[1]==1'b1)?{3'b0,mul_a_1[3:0],1'b0}:8'b0);
            stored2 <= ((mul_b_1[2]==1'b1)?{2'b0,mul_a_1[3:0],2'b0}:8'b0);
            stored3 <= ((mul_b_1[3]==1'b1)?{1'b0,mul_a_1[3:0],3'b0}:8'b0);

            add0 <= stored0 + stored1;
            add1 <= stored2 + stored3;
            
            add2 <= add1 + add0;

            mul_out <= (mul_out_H==1'b0)?({mul_out_H,add2}):({mul_out_H,~add2+1'b1});

        end
    end

endmodule

tb文件:

`timescale 1ns/1ps
module sign_pipline_muli_tb;
    
    reg clk;
    reg rst;
    reg [4:0]mul_a;
    reg [4:0]mul_b;
    wire [8:0]mul_out;

    sign_pipline_muli u1(
        .clk(clk),
        .rst(rst),
        .mul_a(mul_a),
        .mul_b(mul_b),
        .mul_out(mul_out)
    );

    initial begin
        clk = 1'b1;
        rst = 1'b0;
        #10;
        rst = 1'b1;
    end

    always #5 clk = ~clk;

    initial begin
        mul_a = 5'b11011;
        mul_b = 5'b10011;
        #50;
        mul_a = 5'b01101;
        mul_b = 5'b01001;
        #50;
        mul_a = 5'b10011;
        mul_b = 5'b00101;
        #50;
        mul_a = 5'b01111;
        mul_b = 5'b10101;
        #50;
        mul_a = 5'b00000;
        mul_b = 5'b11000;
        #50;
        mul_a = 5'b10111;
        mul_b = 5'b01101;
        #50;
        mul_a = 5'b00000;
        mul_b = 5'b01000;
        #50;
        mul_a = 5'b11011;
        mul_b = 5'b11001;
        #100;
        $stop();
    end
endmodule

仿真结果:

 

 

小结:

  1,符号位如果不添加延时,会存在与数据位的时序不符情况,导致结果出错。

  2,输出结果,正则为本身,负则以补码的形式输出。

  3,这个程序只使用了一个always语句进行处理,也可以使用多个always语句。

  4,此程序以流水线方式实现乘法器,但也可通过移位相加实现乘法器(后续会更新)。

  5,乘法器的输出位宽为输入的两倍(数据位)。

 

posted @ 2020-07-23 20:58  影-fish  阅读(1326)  评论(1编辑  收藏  举报