分时复用的移位相加乘法器

基本算法

移位相加即是日常我们使用的手算算法,移位相加的描述如下

  • 设置积的初值为0
  • 若乘数的最低位为0,则积不变,否则累加被乘数
  • 若乘数的第一位为0,则积不变,否则累加向左移位一位的被乘数
  • ...
  • 若乘数的第n位(最高位)为0,则积不变,否则累加向左移位n位的被乘数

RTL代码

module serial_shiftadder_multipcation # (
    parameter WIDTH = 4
)(
    input clk,    // Clock
    input rst_n,  // Asynchronous reset active low

    input multiplier_valid,
    input [WIDTH - 1:0]multiplier1,
    input [WIDTH - 1:0]multiplier2,

    output reg product_valid,
    output reg [2 * WIDTH - 1:0]product
);

接口定义部分,采用参数化设计,WIDTH为乘数/被乘数的位宽,multiplier_valid拉高时表示输入有效,并开始计算。product_valid被拉高时表示计算完成,当前的输出是有效的

/*****************buffer and shift*******************/
reg [WIDTH - 1:0]min_mult;
reg [2 * WIDTH - 1:0]max_mult;
always @ (posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        {max_mult,min_mult} <= 'b0;
    end else if(multiplier_valid == 1'b1) begin
        if(multiplier1 > multiplier2) begin
            max_mult <= '{multiplier1};
            min_mult <= multiplier2;
        end else begin
            max_mult <= '{multiplier2};
            min_mult <= multiplier1;
        end
    end else if(min_mult != 'b0) begin
        max_mult <= max_mult << 1;
        min_mult <= min_mult >> 1;
    end else begin
        max_mult <= max_mult;
        min_mult <= min_mult;
    end
end

移位部分,有输入时比较两个输入的大小,使用小的数控制迭代数量,减小时间消耗。若较小的乘数不为0,则将较大的数向左移位,较小的的数向右位移。

/******************adder********************/
always @ (posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        {product_valid,product} <= 'b0;
    end else if(min_mult[0] == 1'b1) begin
        product <= product + max_mult;
        product_valid <= 1'b0;
    end else if(min_mult != 'b0) begin
        product <= product;
        product_valid <= 1'b0;
    end else if(multiplier_valid == 1'b1) begin
        product <= 'b0;
        product_valid <= 1'b0;
    end else begin
        product <= product;
        product_valid <= 1'b1;
    end
end

endmodule

累加部分,若较小的乘数最低位为0,保持积不变,否则累加当前的大乘数,当小乘数为0是,表示运算已经结束,输出有效拉高。

测试

使用自动化测试,使用高层次方法计算积,再与输出比较看是否相等

module mult_tb (
);

parameter WIDTH = 4;

logic clk,rst_n;
logic multiplier_valid;
logic [WIDTH - 1:0]multiplier1;
logic [WIDTH - 1:0]multiplier2;

logic product_valid;
logic [2 * WIDTH - 1:0]product;

serial_shiftadder_multipcation # (
    .WIDTH(WIDTH)
) dut (
    .clk(clk),    // Clock
    .rst_n(rst_n),  // Asynchronous reset active low

    .multiplier_valid(multiplier_valid),
    .multiplier1(multiplier1),
    .multiplier2(multiplier2),

    .product_valid(product_valid),
    .product(product)
);

initial begin
    clk = 1'b0;
    forever begin
        #50 clk = ~clk;
    end
end

initial begin
    rst_n = 1'b1;
    #5 rst_n = 1'b0;
    #10 rst_n = 1'b1;
end

initial begin
    {multiplier_valid,multiplier1,multiplier2} = 'b0;
    forever begin
        @(negedge clk);
        if(product_valid == 1'b1) begin
            multiplier1 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
            multiplier2 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
            multiplier_valid = 1'b1;
        end else begin
            multiplier_valid = 1'b0;
        end
    end
end

logic [2 * WIDTH - 1:0]exp;
initial begin
    forever begin
        @(posedge product_valid);
        exp = multiplier1 * multiplier2;
        if(exp == product) begin
            $display("successfully, mult1=%d mult2=%d product=%d",multiplier1,multiplier2,product);
        end else begin
            $display("failed,mult1=%d mult2=%d product=%d exp=%d",multiplier1,multiplier2,product,exp);
        end
    end
end

endmodule
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,904评论 18 139
  • 一、计算机的发展史 01改变世界:没有计算器的日子怎么过——手动时期的计算工具 所谓计算机,顾名思义,就是用于计...
    文思汇集阅读 2,760评论 1 8
  • 每日打卡。 来评论区记录下今天的收获和成长吧!
    树洞君阅读 112评论 6 1
  • 站在机房的外面,心情已经平静下来,外面下着雨还有舞蹈队排练音乐的声音,只是在这一刻,心突然变得很安静,大概是浮躁之...
    西蜀三三三阅读 1,245评论 2 1
  • 两年计划破产,一年计划实现,世事无常。生命是一条从出生流向死亡的长河,如千万条银丝,每条丝线都是一个人的一生。河里...
    蒙山小道阅读 301评论 0 0