告诉我这段代码有什么问题
Tell me what's wrong with this code
此代码描述此表达式 -> (a+b)(c+d)
。我使用了 2 个求和器,首先对 a 和 b 求和,然后对 c 和 d 求和。然后另一个使结果成倍增加。不幸的是,我真的不擅长 Verilog,所以我无法理解问题所在。
module automate(a,b,c,d,clk,start,result,ready);
parameter n=8;
input [7:0] a,b,c,d;
input start,clk;
output reg[17:0] result;
output reg ready;
reg[7:0] ra;
reg[7:0] rb;
reg[7:0] rc;
reg[7:0] rd;
reg[8:0] sm1;
reg[8:0] sm2;
reg[8:0] acc,q;
always@(posedge start)
begin
ra=a;
rb=b;
rc=c;
rd=d;
sm1=ra+rb;
sm2=rc+rd;
q=sm2;
acc=0;
ready=0;
repeat(9)
begin
@(posedge clk)
if(q[0])
acc=acc+sm1;
else
acc=acc;
q=q>>1;
q[8] = acc[0];
acc=acc>>1;
end
ready=1;
result={acc[8:0],q};
end
endmodule
测试平台:
module test_bench;
reg[7:0] a,b,c,d;
reg clk,start;
wire ready;
wire[17:0] result;
automate res(a,b,c,d,clk,start,result,ready);
initial begin
start = 0;
clk=0;
a=8'd7;
b=8'd5;
c=8'd9;
d=8'd3;
#30 start = 1;
wait(ready);
#20 start = 0;
#500 $finish;
end
always #10 clk=~clk;
endmodule
但这是我得到的:
根据@Matthew Taylor,您的代码工作正常!!,
模拟可能不是 TB,因为它是顶级模块,没有任何东西被驱动到 DUT 所以你的信号是 X
和 Z
。
.....
automate res(a,b,c,d,clk,start,result,ready);
initial begin
$monitor (result, res.sm1, res.sm2); // added monitor system task
start = 0;
.....
然后运行它,你会看到输出如下,
# x x x
# x 12 12
# 144 12 12
尽管如此,我想说,你正在编写 HDL 代码,一个真正的硬件,所以不要使用 repeat
,使用 for循环。
如果您的要求只是(A+B) / (C+D)
,那么就没有使用时钟。
补充,
always@(*)
begin
ra = 0;
rb = 0;
rc = 0;
sm1 = 0;
sm2 = 0;
result = 0;
if(start) begin
ra = a;
rb = b;
rc = c;
rd = d;
sm1 = ra + rb;
sm2 = rc + rd;
result = product(sm1, sm2);
end
end
对于将sm1
和sm2
相乘的函数product
可以是,
function [17:0] product;
input [8:0] multiplier, multiplicand;
integer i;
begin
product = 0;
for(i=0; i<17; i=i+1)
if( multiplier[i] == 1'b1 )
product = product + ( multiplicand << i );
end
endfunction
所以我认为 start 和 ready 会在同一个周期内断言。截至目前,您的代码中没有顺序逻辑。
希望对您有所帮助。
编辑:
对于你的第二个问题,使用以下脚本命令:
vsim -novopt -c -do "add wave -r /*; run -all;" work.test_bench
add wave -r /*
run -all
此代码描述此表达式 -> (a+b)(c+d)
。我使用了 2 个求和器,首先对 a 和 b 求和,然后对 c 和 d 求和。然后另一个使结果成倍增加。不幸的是,我真的不擅长 Verilog,所以我无法理解问题所在。
module automate(a,b,c,d,clk,start,result,ready);
parameter n=8;
input [7:0] a,b,c,d;
input start,clk;
output reg[17:0] result;
output reg ready;
reg[7:0] ra;
reg[7:0] rb;
reg[7:0] rc;
reg[7:0] rd;
reg[8:0] sm1;
reg[8:0] sm2;
reg[8:0] acc,q;
always@(posedge start)
begin
ra=a;
rb=b;
rc=c;
rd=d;
sm1=ra+rb;
sm2=rc+rd;
q=sm2;
acc=0;
ready=0;
repeat(9)
begin
@(posedge clk)
if(q[0])
acc=acc+sm1;
else
acc=acc;
q=q>>1;
q[8] = acc[0];
acc=acc>>1;
end
ready=1;
result={acc[8:0],q};
end
endmodule
测试平台:
module test_bench;
reg[7:0] a,b,c,d;
reg clk,start;
wire ready;
wire[17:0] result;
automate res(a,b,c,d,clk,start,result,ready);
initial begin
start = 0;
clk=0;
a=8'd7;
b=8'd5;
c=8'd9;
d=8'd3;
#30 start = 1;
wait(ready);
#20 start = 0;
#500 $finish;
end
always #10 clk=~clk;
endmodule
但这是我得到的:
根据@Matthew Taylor,您的代码工作正常!!,
模拟可能不是 TB,因为它是顶级模块,没有任何东西被驱动到 DUT 所以你的信号是 X
和 Z
。
.....
automate res(a,b,c,d,clk,start,result,ready);
initial begin
$monitor (result, res.sm1, res.sm2); // added monitor system task
start = 0;
.....
然后运行它,你会看到输出如下,
# x x x
# x 12 12
# 144 12 12
尽管如此,我想说,你正在编写 HDL 代码,一个真正的硬件,所以不要使用 repeat
,使用 for循环。
如果您的要求只是(A+B) / (C+D)
,那么就没有使用时钟。
补充,
always@(*)
begin
ra = 0;
rb = 0;
rc = 0;
sm1 = 0;
sm2 = 0;
result = 0;
if(start) begin
ra = a;
rb = b;
rc = c;
rd = d;
sm1 = ra + rb;
sm2 = rc + rd;
result = product(sm1, sm2);
end
end
对于将sm1
和sm2
相乘的函数product
可以是,
function [17:0] product;
input [8:0] multiplier, multiplicand;
integer i;
begin
product = 0;
for(i=0; i<17; i=i+1)
if( multiplier[i] == 1'b1 )
product = product + ( multiplicand << i );
end
endfunction
所以我认为 start 和 ready 会在同一个周期内断言。截至目前,您的代码中没有顺序逻辑。
希望对您有所帮助。
编辑:
对于你的第二个问题,使用以下脚本命令:
vsim -novopt -c -do "add wave -r /*; run -all;" work.test_bench
add wave -r /*
run -all