为什么 Verilog 输出显示 x 和 z 而不是零和 1?
Why does Verilog output show x and z instead of zero and 1?
我正在为一个由三个 D 触发器组成的移位寄存器建模。有 3 个输入(clk、reset、shiftIn)和 1 个输出(shiftOut)。复位为同步高电平有效并复位所有触发器。
设计
module shiftReg(shiftIn,clk,reset,shiftOut);
input shiftIn, clk, reset;
output shiftOut;
reg Q1,Q2,shiftOut;
always @(posedge clk or posedge reset)
begin
if(reset == 1'b1) begin
Q1 <= 1'b0;
Q2 <= 1'b0;
shiftOut <= 1'b0;
end
else begin
Q1 <= shiftIn;
Q2 <= Q1;
shiftOut <= Q2;
end
end
endmodule
测试平台
module tb_shiftReg();
reg shiftin;
reg clk;
reg reset;
wire shiftOut;
shiftReg SR(shiftIn,clk,reset,shiftOut);
initial begin
clk=0;
forever #10 clk = ~clk;
end
initial begin
$monitor("time=",$time, "shiftin=%b reset =%d shiftout =%b",shiftIn,reset,shiftOut);
$dumpfile("test.vcd");
$dumpvars;
reset=0;
shiftin <= 0;
#100;
reset=0;
shiftin <= 1;
#100;
reset =1;
shiftin <= 0;
#100;
reset =1;
shiftin <= 0;
#100 $finish;
end
endmodule
当我使用 iverilog
:
模拟它时,我得到以下输出
vu2swz@PPDP01:~$ iverilog Shiftregister.v
vu2swz@PPDP01:~$ ./a.out
VCD info: dumpfile test.vcd opened for output.
time= 0shiftin=z reset =0 shiftout =x
time= 50shiftin=z reset =0 shiftout =z
time= 200shiftin=z reset =1 shiftout =0
为什么我得到的是 z 和 x 而不是 1 和 0?
Verilog 区分大小写。 shiftin
是与 shiftIn
(大写“I”)不同的信号。在测试台中,您声明了 shiftin
,但没有声明 shiftIn
。默认情况下,Verilog 将未声明的信号视为 wire
类型,并且 wire
的默认值为 z
。这意味着您的设计模块的输入是非驱动的。我使用的模拟器给了我一个警告信息。您还可以在 edaplayground 上的不同模拟器上尝试您的代码以获得更多有用的消息。
将测试台模块中的所有 shiftIn
更改为 shiftin
,这将清除大部分 z
和 x
:
time= 0shiftin=0 reset =0 shiftout =x
time= 50shiftin=0 reset =0 shiftout =0
time= 100shiftin=1 reset =0 shiftout =0
time= 150shiftin=1 reset =0 shiftout =1
time= 200shiftin=0 reset =1 shiftout =0
您在时间 0 时仍会得到 x
,因为在时间 0 时未断言重置;复位在时间 200 断言。通常,您会在时间 0 (reset=1;
) 断言复位,然后在几个时钟周期后取消断言 (reset=0;
),比如在时间 100.
module tb_shiftReg();
reg shiftin;
reg clk;
reg reset;
wire shiftOut;
shiftReg SR(shiftin,clk,reset,shiftOut);
initial begin
clk=0;
forever #10 clk = ~clk;
end
initial begin
$monitor("time=",$time, "shiftin=%b reset =%d shiftout =%b",shiftin,reset,shiftOut);
$dumpfile("test.vcd");
$dumpvars;
reset=1;
shiftin <= 0;
#100;
reset=0;
shiftin <= 1;
#100;
shiftin <= 0;
#100;
shiftin <= 0;
#100 $finish;
end
endmodule
经过以上改动,所有信号都显示0/1:
time= 0shiftin=0 reset =1 shiftout =0
time= 100shiftin=1 reset =0 shiftout =0
time= 150shiftin=1 reset =0 shiftout =1
time= 200shiftin=0 reset =0 shiftout =1
time= 250shiftin=0 reset =0 shiftout =0
注意:您的重置信号是异步,而不是同步,因为您在敏感列表中包含了reset
:
always @(posedge clk or posedge reset)
我正在为一个由三个 D 触发器组成的移位寄存器建模。有 3 个输入(clk、reset、shiftIn)和 1 个输出(shiftOut)。复位为同步高电平有效并复位所有触发器。
设计
module shiftReg(shiftIn,clk,reset,shiftOut);
input shiftIn, clk, reset;
output shiftOut;
reg Q1,Q2,shiftOut;
always @(posedge clk or posedge reset)
begin
if(reset == 1'b1) begin
Q1 <= 1'b0;
Q2 <= 1'b0;
shiftOut <= 1'b0;
end
else begin
Q1 <= shiftIn;
Q2 <= Q1;
shiftOut <= Q2;
end
end
endmodule
测试平台
module tb_shiftReg();
reg shiftin;
reg clk;
reg reset;
wire shiftOut;
shiftReg SR(shiftIn,clk,reset,shiftOut);
initial begin
clk=0;
forever #10 clk = ~clk;
end
initial begin
$monitor("time=",$time, "shiftin=%b reset =%d shiftout =%b",shiftIn,reset,shiftOut);
$dumpfile("test.vcd");
$dumpvars;
reset=0;
shiftin <= 0;
#100;
reset=0;
shiftin <= 1;
#100;
reset =1;
shiftin <= 0;
#100;
reset =1;
shiftin <= 0;
#100 $finish;
end
endmodule
当我使用 iverilog
:
vu2swz@PPDP01:~$ iverilog Shiftregister.v
vu2swz@PPDP01:~$ ./a.out
VCD info: dumpfile test.vcd opened for output.
time= 0shiftin=z reset =0 shiftout =x
time= 50shiftin=z reset =0 shiftout =z
time= 200shiftin=z reset =1 shiftout =0
为什么我得到的是 z 和 x 而不是 1 和 0?
Verilog 区分大小写。 shiftin
是与 shiftIn
(大写“I”)不同的信号。在测试台中,您声明了 shiftin
,但没有声明 shiftIn
。默认情况下,Verilog 将未声明的信号视为 wire
类型,并且 wire
的默认值为 z
。这意味着您的设计模块的输入是非驱动的。我使用的模拟器给了我一个警告信息。您还可以在 edaplayground 上的不同模拟器上尝试您的代码以获得更多有用的消息。
将测试台模块中的所有 shiftIn
更改为 shiftin
,这将清除大部分 z
和 x
:
time= 0shiftin=0 reset =0 shiftout =x
time= 50shiftin=0 reset =0 shiftout =0
time= 100shiftin=1 reset =0 shiftout =0
time= 150shiftin=1 reset =0 shiftout =1
time= 200shiftin=0 reset =1 shiftout =0
您在时间 0 时仍会得到 x
,因为在时间 0 时未断言重置;复位在时间 200 断言。通常,您会在时间 0 (reset=1;
) 断言复位,然后在几个时钟周期后取消断言 (reset=0;
),比如在时间 100.
module tb_shiftReg();
reg shiftin;
reg clk;
reg reset;
wire shiftOut;
shiftReg SR(shiftin,clk,reset,shiftOut);
initial begin
clk=0;
forever #10 clk = ~clk;
end
initial begin
$monitor("time=",$time, "shiftin=%b reset =%d shiftout =%b",shiftin,reset,shiftOut);
$dumpfile("test.vcd");
$dumpvars;
reset=1;
shiftin <= 0;
#100;
reset=0;
shiftin <= 1;
#100;
shiftin <= 0;
#100;
shiftin <= 0;
#100 $finish;
end
endmodule
经过以上改动,所有信号都显示0/1:
time= 0shiftin=0 reset =1 shiftout =0
time= 100shiftin=1 reset =0 shiftout =0
time= 150shiftin=1 reset =0 shiftout =1
time= 200shiftin=0 reset =0 shiftout =1
time= 250shiftin=0 reset =0 shiftout =0
注意:您的重置信号是异步,而不是同步,因为您在敏感列表中包含了reset
:
always @(posedge clk or posedge reset)