问题描述
我正在使用Verilog设计一个8位有符号顺序乘法器。输入为clk
(时钟),rst
(复位),a
(8位乘数),b
(8位被乘数),输出为{{1 }}(乘积)和p
(就绪信号,表示乘法结束)。对于负输入,我进行了符号扩展并将其保存在15位寄存器变量rdy
和multiplier
中。这是我的代码:
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
后,您可能需要将平移移动到。