• 【Verilog】布斯算法(Booth Algorithm)乘法器的 Verilog 实现


     

    目录

    布斯算法介绍

    计算步骤

    计算流程图

    举个栗子

    Verilog 实现

    设计思想

    Verilog 代码

    TestBench 代码

    仿真波形


     

    布斯算法介绍

    Booth 的算法检查有符号二的补码表示中 'N'位乘数 Y 的相邻位对,包括低于最低有效位 y−1 = 0 的隐式位。对于每个位 yi,对于从 0 到 N − 1 的 i,考虑位 yi 和 yi−1。当这两个位相等时,乘积累加器P保持不变。其中 yi = 0 且 yi−1 = 1,乘以 2i 添加到 P;其中 yi = 1 且 yi−1 = 0,则从 P 中减去乘以 2iP 的最终值为有符号产品。

    未指定乘数和乘积的表示形式;通常,这些也都在二的补码表示中,就像乘数一样,但是任何支持加法和减法的数字系统也可以工作。如此处所述,步骤的顺序尚未确定。通常,它从LSB到MSB,从i = 0开始;然后乘以2i通常被P累加器在步长之间向右的增量移位所取代;低位可以移出,然后可以在P的最高N位上进行后续的加法和减法。

    该算法通常被描述为将乘数中 1 的字符串转换为字符串末端的高阶 +1 和低阶 −1。当字符串通过 MSB 运行时,没有高阶 +1,并且净效应被解释为相应值的负数。

    计算步骤

    使用的寄存器:A,M,Q,Qres(Qres是Q右移后的残余位),n(计数器)
     
    第 1 步: 加载寄存器的初始值。
    A = 0(累加器),Qres = 0,M = 乘法,Q = 乘法器,n是等于乘法器位数的计数值。
    第 2 步:检查 {Q0,Qres} 的值。如果为 00 或 11,请转到步骤 5。如果为01,转到步骤3。如果为 10,转到步骤 4。
    第 3 步:执行 A = A + M,转到步骤 5。       
    第 4 步:执行 A = A - M。
    第 5 步:执行 {A,Q,Qres} 的算术位移和递减计数。
    第 6 步: 检查计数器值 n 是否为零。如果是,请转到下一步。否则转到步骤 2。
    第 7 步:停止计算,输出计算结果。
     

    计算流程图

    以下是布斯计算的流程图,从图中可以清楚的看出计算的过程,简单的来说就是判定乘数的最低位和次低位,如果两位相同则直接执行移位操作,如果两者不同,如为“10”则将原始值减去被乘数,如为“01”则将原始值加上被乘数

    bad7d628bf6b4624a5333b9df6ddbdda.png

    举个栗子

    下面就以被乘数为6,乘数为-4为例,做一个计算过程的举例。

    df001b6900a841f88829bcdd6361b497.jpeg

    1. 将所有寄存器初始化,累加器A初始化为0,乘数加载寄存,最低位移出位设定位0。
    2. 判定最低位和移出位为“00”,不进行加减操作,将结果结果值右移一位。
    3. 判定最低位和移出位为“00”,不进行加减操作,将结果结果值右移一位。
    4. 判定最低位和移出位为“10”,对累加器减去被乘数,并将结果结果值右移一位,注意此时累加器A为负数。
    5. 判定最低位和移出位为“10”,不进行加减操作,将结果结果值右移一位,此时累加器为负数,因此右移最高位补1。
    6. 判定最低位和移出位为“10”,不进行加减操作,将结果结果值右移一位,此时累加器为负数,因此右移最高位补1。
    7. 计数器为0表示计算完成,停止计算并输出计算结果值。

    Verilog 实现

    设计思想

    总的来说和上面提到的计算步骤是一致的,利用三段状态机实现,分别为空闲状态、计算状态和完成状态,其中空闲状态等待开始计算信号的到来,计算状态完成布斯计算步骤,完成状态输出结果数据以及同步的有效标志信号。

    Verilog 代码

    1. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    2. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    3. /* Engineer : Linest-5
    4. /* File : booth_multiple.v
    5. /* Create : 2022-08-27 16:40:34
    6. /* Revise : 2022-08-27 16:40:34
    7. /* Module Name : booth_multiple
    8. /* Description : 基于布斯算法的乘法器设计
    9. /* Editor : sublime text3, tab size (4)
    10. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    11. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    12. module booth_multiple(
    13. input clk,
    14. input rst,
    15. input start,
    16. input signed [3:0] X,
    17. input signed [3:0] Y,
    18. output reg signed [7:0] Z,
    19. output valid
    20. );
    21. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    22. /* 参数和信号申明 */
    23. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    24. parameter IDLE = 3'b001;
    25. parameter CACULATE = 3'b010;
    26. parameter FINISH = 3'b100;
    27. reg [2:0] state;
    28. reg [2:0] next_state;
    29. reg [1:0] q_reg; //右移最后两位寄存
    30. reg [2:0] cnt; //右移次数计数信号
    31. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    32. /* 三段状态机 */
    33. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    34. //状态机第一段,状态初始化,时序逻辑非阻塞赋值
    35. always @(posedge clk or posedge rst) begin
    36. if (rst) begin
    37. state <= IDLE;
    38. end
    39. else begin
    40. state <= next_state;
    41. end
    42. end
    43. //状态机第二段,状态跳转,组合逻辑阻塞赋值
    44. always @(*) begin
    45. next_state = state;
    46. case(state)
    47. IDLE: begin
    48. if (start) begin
    49. next_state = CACULATE;
    50. end
    51. else begin
    52. next_state = IDLE;
    53. end
    54. end
    55. CACULATE: begin
    56. if (cnt == 'd3) begin
    57. next_state = FINISH;
    58. end
    59. else begin
    60. next_state = CACULATE;
    61. end
    62. end
    63. FINISH: begin
    64. next_state = IDLE;
    65. end
    66. endcase
    67. end
    68. //状态机第三段,结果输出,时序逻辑非阻塞赋值
    69. always @(posedge clk or posedge rst) begin
    70. if (rst) begin
    71. cnt <= 'd0;
    72. q_reg <= 'd0;
    73. Z <= 'd0;
    74. end
    75. else begin
    76. case(state)
    77. IDLE: begin
    78. cnt <= 'd0;
    79. q_reg <= {Y[cnt],1'b0};
    80. Z <= {4'b0000,Y};
    81. end
    82. CACULATE: begin
    83. cnt <= cnt + 'd1;
    84. q_reg <= {Y[cnt+1],Y[cnt]};
    85. case(q_reg)
    86. 2'b00,2'b11: begin
    87. Z <= $signed(Z)>>>1;
    88. end
    89. 2'b10: begin
    90. Z <= $signed({Z[7:4]-X,Z[3:0]})>>>1;
    91. end
    92. 2'b01: begin
    93. Z <= $signed({Z[7:4]+X,Z[3:0]})>>>1;
    94. end
    95. endcase
    96. end
    97. FINISH: begin
    98. cnt <= 'd0;
    99. q_reg <= 'd0;
    100. Z <= Z;
    101. end
    102. endcase
    103. end
    104. end
    105. assign valid = (state==FINISH);
    106. endmodule

    TestBench 代码

    1. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    2. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    3. /* Engineer : Linest-5
    4. /* File : tb_booth_multiple.v
    5. /* Create : 2022-08-27 19:22:46
    6. /* Revise : 2022-08-27 20:21:49
    7. /* Module Name : tb_booth_multiple
    8. /* Description : 基于布斯算法的乘法器仿真模块
    9. /* Editor : sublime text3, tab size (4)
    10. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    11. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    12. `timescale 1ns/1ns
    13. module tb_booth_multiple();
    14. reg clk;
    15. reg rst;
    16. reg start;
    17. reg signed [3:0] X;
    18. reg signed [3:0] Y;
    19. wire signed [7:0] Z;
    20. wire valid;
    21. initial begin
    22. clk = 'd0;
    23. rst = 'd1;
    24. #20
    25. rst = 'd0;
    26. end
    27. always #10 clk = ~clk;
    28. initial begin
    29. #20
    30. X = 6;
    31. Y = -4;
    32. start = 'd0;
    33. #50
    34. start = 'd1;
    35. #20
    36. start = 'd0;
    37. #200
    38. X = 7;
    39. Y = -5;
    40. start = 'd1;
    41. #20
    42. start = 'd0;
    43. #200
    44. X = 7;
    45. Y = 5;
    46. start = 'd1;
    47. #20
    48. start = 'd0;
    49. end
    50. booth_multiple inst_booth_multiple (
    51. .clk (clk),
    52. .rst (rst),
    53. .start (start),
    54. .X (X),
    55. .Y (Y),
    56. .Z (Z),
    57. .valid (valid)
    58. );
    59. endmodule

    仿真波形

    分别进行有符号的乘法,6和-4、7和-5、7和5,可以看到仿真波形中,正确的得到了计算结果,并且有效标志信号也同步输出。

    验证成功!

    3a895b8051804f9592de9331e0ef2785.png

     

  • 相关阅读:
    力扣—最长回文子串
    22-08-06 西安 EasyExcel实现字典表导入、导出
    Java Web程序设计基础二(服务器交互篇——四大属性作用域)
    NoSQL之 Redis配置与优化
    大语言模型构建的主要四个阶段(各阶段使用的算法、数据、难点以及实践经验)
    Win软件 - (Net-Framework)已处理证书链,但是在不受信任提供程序信任的根证书中终止
    ZooKeeper 5:集群模式
    Windows系统无NVIDIA卡安装APEX
    DO280OpenShift访问控制--加密和ConfigMap
    基础DML(数据更新)知识点总结及实例讲解
  • 原文地址:https://blog.csdn.net/m0_61298445/article/details/126562315