-1

在尝试编译和模拟 Verilog 模块和激励时,我收到了一些奇怪的结果。如果我在 Silos 中模拟它,代码会按预期运行。如果我在 Icarus(iverlog 和 vvp)中模拟它,则时间与 Silos 不同(从 0 而不是 200 开始,我并不关心 Silos 有 235 -> 255 而 Icarus 有 235 -> 265)。Silos 重复功能按我的预期工作,但是当使用 Icarus 时,我似乎无法弄清楚他们是如何得到这个结果的。此外,当将重复 R2GDELAY 更改为 3 时,Icarus 似乎也没有按预期执行。使用 Icarus 时我是否遗漏了一些东西,例如我必须手动将开始时间设置为 0,以便稍后在模拟中获得准确的结果,还是筒仓自动初始化我必须在 Icarus 中手动执行的变量?此代码取自 Verilog HDL 书籍,可在此处找到http://authors.phptr.com/palnitkar/

这是代码:

`define TRUE    1'b1
`define FALSE   1'b0
`define RED     2'd0
`define YELLOW  2'd1
`define GREEN   2'd2

//State definition   HWY          CNTRY
`define S0  3'd0  //GREEN          RED
`define S1  3'd1  //YELLOW         RED
`define S2  3'd2  //RED            RED
`define S3  3'd3  //RED            GREEN
`define S4  3'd4  //RED            YELLOW

//Delays
`define Y2RDELAY    3   //Yellow to red delay
`define R2GDELAY    2   //Red to Green Delay

module sig_control (hwy, cntry, X, clock, clear);

//I/O ports
output [1:0] hwy, cntry;
            //2 bit output for 3 states of signal
            //GREEN, YELLOW, RED;
reg [1:0] hwy, cntry;
            //declare output signals are registers

input X;
            //if TRUE, indicates that there is car on
          //the country road, otherwise FALSE
input clock, clear;
//Internal state variables
reg [2:0] state;
reg [2:0] next_state;


initial
    begin
        state = `S0;
        next_state = `S0;
        hwy = `GREEN;
        cntry = `RED;
    end

//state changes only at positive edge of clock
always @(posedge clock)
    state = next_state;

//Compute values of main signal and country signal
always @(state)
    begin
        case(state)
            `S0: begin
                    hwy = `GREEN;
                    cntry = `RED;
                end
            `S1: begin
                    hwy = `YELLOW;
                    cntry = `RED;
                end
            `S2: begin
                    hwy = `RED;
                    cntry = `RED;
                end
            `S3: begin
                    hwy = `RED;
                    cntry = `GREEN;
                end
            `S4: begin
                    hwy = `RED;
                    cntry = `YELLOW;
                end
    endcase
end


//State machine using case statements
always @(state or  X)
    begin
        if(clear)
            next_state = `S0;
        else
            case (state)
                `S0: if(X)
                        next_state =  `S1;
                    else
                        next_state =  `S0;
                `S1: begin //delay some positive edges of clock
                        repeat(`Y2RDELAY) @(posedge clock) ;
                        next_state =  `S2;
                    end
                `S2: begin //delay some positive edges of clock
                        //EDIT ADDED SEMICOLON
                        repeat(`R2GDELAY) @(posedge clock);
                        next_state =  `S3;
                    end
                `S3: if( X)
                        next_state =  `S3;
                    else
                        next_state =  `S4;
                `S4: begin //delay some positive edges of clock
                        repeat(`Y2RDELAY) @(posedge clock) ;
                        next_state =  `S0;
                    end
            default: next_state =  `S0;
        endcase
    end
endmodule

//Stimulus Module
module stimulus;

wire [1:0] MAIN_SIG, CNTRY_SIG;
reg CAR_ON_CNTRY_RD;
            //if TRUE, indicates that there is car on
          //the country road
reg CLOCK, CLEAR;

//Instantiate signal controller
sig_control SC(MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD, CLOCK, CLEAR);


//Setup monitor
initial
    $monitor($time, " Main Sig = %b Country Sig = %b Car_on_cntry = %b",
                                            MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD);
//setup clock
initial
    begin
        CLOCK = `FALSE;
        forever #5 CLOCK = ~CLOCK;
    end

//control clear signal
initial
    begin
        CLEAR = `TRUE;
        repeat (5) @(negedge CLOCK);
        CLEAR = `FALSE;
    end

//apply stimulus
initial
    begin
        CAR_ON_CNTRY_RD = `FALSE;

        #200 CAR_ON_CNTRY_RD = `TRUE;
        #100 CAR_ON_CNTRY_RD = `FALSE;

        #200 CAR_ON_CNTRY_RD = `TRUE;
        #100 CAR_ON_CNTRY_RD = `FALSE;

        #200 CAR_ON_CNTRY_RD = `TRUE;
        #100 CAR_ON_CNTRY_RD = `FALSE;

        #100 $finish;
    end
endmodule

这是筒仓的输出:

             200 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             205 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             235 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             255 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             300 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             305 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             335 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
             500 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             505 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             535 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             555 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             600 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             605 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             635 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
             800 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             805 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             835 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             855 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             900 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             905 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             935 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0

这是iverilog的输出:

               0 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
             200 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             205 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             235 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             265 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             300 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             305 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             335 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
             500 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             505 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             535 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             565 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             600 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             605 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             635 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
             800 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
             805 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
             835 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
             865 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
             900 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
             905 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
             935 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0

编辑:添加分号,如上面的代码所示。
谢谢你的帮助!

4

1 回答 1

4

如评论中所述,您的逻辑中有竞争条件,您不应该将时钟用作组合逻辑的输入。

查看以下两个逻辑块:

1. repeat(`R2GDELAY) @(posedge clock)
     next_state =  `S3;

2. always @(posedge clock)
     state = next_state;

当 posedge 时钟发生时,模拟器将首先选择这两个语句中的一个来执行,而没有关于它可能选择的规则。如果它先选择#1,则下一个状态将设置为S3,然后#2 将执行,将状态分配给S3。如果 #2 先执行,state 将被设置为其他值,然后在 state 分配后 next_state 将设置为 S3。

现在,根据模拟器选择首先执行的随机事件,您有不同的行为。

避免这种情况的方法是不要让您的组合块以任何方式查看时钟。时钟应该只用于更新您的寄存器,具有非阻塞分配<=

于 2013-11-28T22:02:34.820 回答