为什么 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,这将清除大部分 zx:

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)