-1

Verilog モジュールとスティミュラスをコンパイルおよびシミュレーションしようとすると、奇妙な結果が表示されます。サイロでシミュレートすると、コードは期待どおりに機能します。Icarus (iverlog と vvp) でシミュレートすると、時間は Silos とは異なります (200 ではなく 0 から開始します。Silos の 235 -> 255 と Icarus の 235 -> 265 ほど気にしません)。Silos の繰り返し機能は期待どおりに機能しますが、Icarus を使用すると、どのようにしてその結果が得られたのかがよくわかりません。また、repeat R2GDELAY を 3 に変更すると、Icarus も期待どおりに実行されないようです。シミュレーションの後半で正確な結果を得るには、手動で開始時間を 0 に設定する必要があるなど、Icarus を使用するときに欠けているものはありますか? または 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

サイロからの出力は次のとおりです。

             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

コメントに記載されているように、組み合わせロジックへの入力としてクロックを使用しないでください。

次の 2 つのロジック ブロックを確認します。

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

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

ポーズエッジ クロックが発生すると、シミュレーターはこれら 2 つのステートメントのいずれかを最初に実行するように選択しますが、どちらを選択するかについての規則はありません。最初に #1 を選択すると、次の状態が S3 に設定され、次に #2 が実行され、状態が S3 に割り当てられます。#2 が最初に実行されると、state は別のものに設定され、state が割り当てられた後に next_state が S3 に設定されます。

これで、シミュレーターによって最初に実行するために選択されたランダム イベントに基づいて、異なる動作が得られます。

これを回避する方法は、組み合わせブロックにクロックを監視させないことです。クロックは、ノンブロッキング割り当てを使用して、レジスタを更新するためにのみ使用する必要があります<=

于 2013-11-28T22:02:34.820 に答える