gtkwave 中奇怪的测试台行为
Strange testbench behavior in gtkwave
我正在尝试使用 SystemVerilog 设计电梯控制器。代码编译得很好,但是当我把它放在 gtkwave 中时,测试台是完全不同的。
控制器接收 3 个不同的输入(3 个楼层各一个,就像电梯的按钮一样)并将其输出传递给电梯引擎,电梯引擎可以停留在同一楼层,上行或下行一层或两层。
这是模块的代码:
enum logic [4:0] {fermo, sale, sale2, scende, scende2} motore;
module ascx (input logic x0, x1, x2, clk, reset,
output logic [4:0] y);
enum logic [1:0] {pianoterra, primopiano, secondopiano} piani;
logic [1:0] pianoatt, pianoprox;
always_ff@(posedge clk, posedge reset)
if(reset) pianoatt <= pianoterra;
else pianoatt <= pianoprox;
always_comb begin
if(x1) pianoprox = primopiano;
else if(x0) pianoprox = pianoterra;
else if(x2) pianoprox = secondopiano;
end
always @(*) begin
case(pianoatt)
pianoterra: begin
if(x0) assign y = fermo; /*assign y = 5'b00001;*/
if(x1) assign y = sale; /*assign y = 5'b00010;*/
if(x2) assign y = sale2; /*assign y = 5'b00100;*/
end
primopiano: begin
if(x0) assign y = scende; /*assign y = 5'b01000;*/
if(x1) assign y = fermo; /*assign y = 5'b00001;*/
if(x2) assign y = sale; /*assign y = 5'b00010;*/
end
secondopiano: begin
if(x0) assign y = scende2; /*assign y = 5'b10000;*/
if(x1) assign y = scende; /*assign y = 5'b01000;*/
if(x2) assign y = fermo; /*assign y = 5'b00001;*/
end
default assign y = fermo;
endcase
end
endmodule
这是测试台:
module tst_ascx();
logic clk, reset, x0, x1, x2;
logic [4:0] y;
ascx dut(clk, reset, x0, x1, x2, y);
always begin
clk=0; #10;
clk=1; #10;
end
initial begin
$dumpfile("ascx.vcd");
$dumpvars;
reset=1; x0=0; x1=0; x2=0; #10;
reset=0; x0=1; x1=0; x2=0; #10;
x0=0; x1=1; #10;
x1=0; x2=1; #10;
x0=1; x2=0; #10;
x0=0; x2=1; #10;
x1=1; x2=0; #10;
x0=1; x0=0; #10;
end
endmodule
这里是 gtkwave 显示:
图中所示的时钟不正确。
输入 x0 不应该是周期性的,它只是代表某个时间按下的按钮。
由于这两个问题,我不能说模块其余部分是否正常工作。
您将信号连接到 dut
不正确。 dut
实例中的第一个信号 (clk
) 连接到模块声明中的第一个端口 (x0
),等等
为避免此类常见错误,请使用按名称连接而不是按位置连接。请参阅 IEEE Std 1800-2017,第 23.3.2.2 节 按名称连接模块实例端口。
变化:
ascx dut(clk, reset, x0, x1, x2, y);
至:
ascx dut (
.clk (clk),
.reset (reset),
.x0 (x0),
.x1 (x1),
.x2 (x2),
.y (y)
);
与您的问题无关:您不应在 always
块中使用 assign
关键字。
我正在尝试使用 SystemVerilog 设计电梯控制器。代码编译得很好,但是当我把它放在 gtkwave 中时,测试台是完全不同的。 控制器接收 3 个不同的输入(3 个楼层各一个,就像电梯的按钮一样)并将其输出传递给电梯引擎,电梯引擎可以停留在同一楼层,上行或下行一层或两层。
这是模块的代码:
enum logic [4:0] {fermo, sale, sale2, scende, scende2} motore;
module ascx (input logic x0, x1, x2, clk, reset,
output logic [4:0] y);
enum logic [1:0] {pianoterra, primopiano, secondopiano} piani;
logic [1:0] pianoatt, pianoprox;
always_ff@(posedge clk, posedge reset)
if(reset) pianoatt <= pianoterra;
else pianoatt <= pianoprox;
always_comb begin
if(x1) pianoprox = primopiano;
else if(x0) pianoprox = pianoterra;
else if(x2) pianoprox = secondopiano;
end
always @(*) begin
case(pianoatt)
pianoterra: begin
if(x0) assign y = fermo; /*assign y = 5'b00001;*/
if(x1) assign y = sale; /*assign y = 5'b00010;*/
if(x2) assign y = sale2; /*assign y = 5'b00100;*/
end
primopiano: begin
if(x0) assign y = scende; /*assign y = 5'b01000;*/
if(x1) assign y = fermo; /*assign y = 5'b00001;*/
if(x2) assign y = sale; /*assign y = 5'b00010;*/
end
secondopiano: begin
if(x0) assign y = scende2; /*assign y = 5'b10000;*/
if(x1) assign y = scende; /*assign y = 5'b01000;*/
if(x2) assign y = fermo; /*assign y = 5'b00001;*/
end
default assign y = fermo;
endcase
end
endmodule
这是测试台:
module tst_ascx();
logic clk, reset, x0, x1, x2;
logic [4:0] y;
ascx dut(clk, reset, x0, x1, x2, y);
always begin
clk=0; #10;
clk=1; #10;
end
initial begin
$dumpfile("ascx.vcd");
$dumpvars;
reset=1; x0=0; x1=0; x2=0; #10;
reset=0; x0=1; x1=0; x2=0; #10;
x0=0; x1=1; #10;
x1=0; x2=1; #10;
x0=1; x2=0; #10;
x0=0; x2=1; #10;
x1=1; x2=0; #10;
x0=1; x0=0; #10;
end
endmodule
这里是 gtkwave 显示:
图中所示的时钟不正确。
输入 x0 不应该是周期性的,它只是代表某个时间按下的按钮。
由于这两个问题,我不能说模块其余部分是否正常工作。
您将信号连接到 dut
不正确。 dut
实例中的第一个信号 (clk
) 连接到模块声明中的第一个端口 (x0
),等等
为避免此类常见错误,请使用按名称连接而不是按位置连接。请参阅 IEEE Std 1800-2017,第 23.3.2.2 节 按名称连接模块实例端口。
变化:
ascx dut(clk, reset, x0, x1, x2, y);
至:
ascx dut (
.clk (clk),
.reset (reset),
.x0 (x0),
.x1 (x1),
.x2 (x2),
.y (y)
);
与您的问题无关:您不应在 always
块中使用 assign
关键字。