Icarus产生的结果与Silos不同

时间:2013-11-28 20:44:17

标签: verilog fpga xilinx hdl icarus

在尝试编译和模拟Verilog模块和激励时,我收到了一些奇怪的结果。如果我在Silos中模拟它,代码将按预期运行。如果我在Icarus(iverlog和vvp)中模拟它的时间与Silos不同(从0开始而不是200,我不关心Silos有235 - > 255并且Icarus有235 - > 265)。 Silos重复功能正如我所料,但是当使用Icarus时,我似乎无法弄清楚他们是如何得到这个结果的。此外,当将重复R2GDELAY更改为3时,Icarus似乎也没有像预期的那样预先形成。在使用Icarus时是否有我遗漏的东西,例如我必须手动将开始时间设置为0以便在模拟后期得到准确的结果,或者Silos自动初始化我必须在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

以下是Silos的输出:

             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

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

1 个答案:

答案 0 :(得分:3)

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

查看以下两个逻辑块:

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

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

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

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

避免这种情况的方法不是让你的组合模块以任何方式看时钟。时钟应仅用于更新寄存器,使用非阻塞分配<=