使用加法和移位的8位顺序乘法器

问题描述

我正在使用Verilog设计一个8位有符号顺序乘法器。输入为clk(时钟),rst(复位),a(8位乘数),b(8位被乘数),输出为{{1 }}(乘积)和p(就绪信号,表示乘法结束)。对于负输入,我进行了符号扩展并将其保存在15位寄存器变量rdymultiplier中。这是我的代码

multiplicand

这是我的测试台:

module seq_mult (p,rdy,clk,reset,a,b);
   input clk,reset;
   input [7:0] a,b;
   output [15:0] p;
   output rdy;
   
   reg [15:0] p;
   reg [15:0] multiplier;
   reg [15:0] multiplicand;
   reg rdy;
   reg [4:0] ctr;

always @(posedge clk or posedge reset) begin
    if (reset) 
    begin
    rdy     <= 0;
    p   <= 0;
    ctr     <= 0;
    multiplier <= {{8{a[7]}},a};
    multiplicand <= {{8{b[7]}},b};
    end 
    else 
    begin 
      if(ctr < 16) 
          begin
          if(multiplier[ctr]==1)
              begin
              multiplicand = multiplicand<<ctr;
              p <= p + multiplicand;
              end
          ctr <= ctr+1;
          end
       else 
           begin
           rdy <= 1;
           end
    end
  end //End of always block
    
endmodule

我还创建了一个名为`timescale 1ns/1ns `define width 8 `define TESTFILE "test_in.dat" module seq_mult_tb () ; reg signed [`width-1:0] a,b; reg clk,reset; wire signed [2*`width-1:0] p; wire rdy; integer total,err; integer i,s,fp,numtests; // Golden reference - can be automatically generated in this case // otherwise store and read from a file wire signed [2*`width-1:0] ans = a*b; // Device under test - always use named mapping of signals to ports seq_mult dut( .clk(clk),.reset(reset),.a(a),.b(b),.p(p),.rdy(rdy)); // Set up 10ns clock always #5 clk = !clk; // A task to automatically run till the rdy signal comes back from DUT task apply_and_check; input [`width-1:0] ain; input [`width-1:0] bin; begin // Set the inputs a = ain; b = bin; // Reset the DUT for one clock cycle reset = 1; @(posedge clk); // Remove reset #1 reset = 0; // Loop until the DUT indicates 'rdy' while (rdy == 0) begin @(posedge clk); // Wait for one clock cycle end if (p == ans) begin $display($time," Passed %d * %d = %d",b,p); end else begin $display($time," Fail %d * %d: %d instead of %d",p,ans); err = err + 1; end total = total + 1; end endtask // apply_and_check initial begin // Initialize the clock clk = 1; // Counters to track progress total = 0; err = 0; // Get all inputs from file: 1st line has number of inputs fp = $fopen(`TESTFILE,"r"); s = $fscanf(fp,"%d\n",numtests); // Sequences of values pumped through DUT for (i=0; i<numtests; i=i+1) begin s = $fscanf(fp,"%d %d\n",b); apply_and_check(a,b); end if (err > 0) begin $display("FAIL %d out of %d",err,total); end else begin $display("PASS %d tests",total); end $finish; end endmodule // seq_mult_tb 文件,用于存储测试用例(第一行表示测试用例的数量):

test_in.dat

现在的问题是:该代码仅适用于前两个输入和后两个输入。对于其余输入,我得到的数字与预期不同。有人可以指出导致此问题的代码中的任何逻辑错误吗?或者,如果有一种更简单的策略可以做到这一点,也请让我知道。

解决方法

如果 │ db.sqlite3 │ manage.py │ sqlite3.exe │ ├───accounts │ admin.py │ apps.py │ models.py │ serializers.py │ tests.py │ urls.py │ views.py │ __init__.py │ ├───core │ models.py │ serializers.py │ views.py │ __init__.py │ ├───saas_django │ asgi.py │ settings.py │ urls.py │ wsgi.py │ __init__.py │ └───user_messages │ admin.py │ apps.py │ models.py │ serializers.py │ tests.py │ urls.py │ views.py │ __init__.py │ ├───migrations 为1,则每次迭代

multiplicand会向左移动ctr

但是multiplier[ctr]已经包含了先前的移位量,因此您移位得太远了。

您应该在每次迭代中无条件地将ctr移1:

multiplicand

您还应该为multiplicand <= multiplicand << 1; if (multiplier[ctr] == 1) begin p <= p + multiplicand; end ctr <= ctr + 1; 使用非阻塞分配。将平移添加到multiplicand后,您可能需要将平移移动到。