2013-11-28 90 views
-1

當試圖編譯和模擬Verilog模塊和激勵時,我收到了一些奇怪的結果。如果我在筒倉中模擬它,則代碼按預期運行。如果我在Icarus(iverlog和vvp)中模擬它,時間不同於筒倉(從0開始而不是200,我不關心筒倉有235 - > 255,而伊卡洛斯有235 - > 265)。 Silos重複功能按我的預期工作,但使用Icarus時,我似乎無法弄清楚他們是如何得到這個結果的。另外,將重複R2GDELAY更改爲3時,Icarus似乎也沒有按預期那樣進行預成型。在使用Icarus時,我是否缺少某些東西,例如我必須手動將開始時間設置爲0,以便稍後在模擬中獲得準確結果,或者筒倉自動初始化我必須在Icarus中手動執行的變量?此代碼是採取形式的Verilog HDL語言的書,可以在這裏找到http://authors.phptr.com/palnitkar/Icarus產生與筒倉不同的結果

下面是代碼:

`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 

編輯:如上面代碼中所示添加分號。
感謝您的幫助!

+1

這是使用'repeat @(posedge clock)'編碼狀態機的奇怪方法。通常情況下,你會使用一個合適的順序邏輯塊。 – toolic

回答

3

你的邏輯中有競爭條件,正如評論中提到的,你不應該使用時鐘作爲組合邏輯的輸入。

審查以下兩個邏輯塊:

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

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

當posedge時鐘發生時,模擬器將選擇這兩個語句之一先執行,沒有規則就其所可能選擇。如果它首先選擇#1,則下一個狀態將設置爲S3,然後執行#2,將狀態分配給S3。如果#2首先執行,則狀態將被設置爲其他值,然後在分配狀態後next_state將被設置爲S3。

現在,您已經有了不同的行爲,其基於哪個隨機事件被模擬器首先選擇執行。

避免這種情況的方法不是讓您的組合塊以任何方式查看時鐘。該時鐘只能用於更新您的寄存器,無阻塞任務<=

+0

很好的發現 - 當我第一次讀到Palnitkar時,我標記了錯誤,但我放棄了。太多了。 – EML

+0

感謝您的意見。爲了在避免競爭條件的同時實現預期的行爲,你是否建議我創建其他狀態而不是使用重複?你也知道爲什麼作者使用重複來編寫狀態機,如果這會造成競爭狀態?再次感謝! – dannyn382

+0

您不必創建其他狀態,但可以使用當前狀態進行更多操作。當你進入S1時,你可以讓每個時鐘週期的計數器開始倒計數,直到它達到0,當狀態爲S1並且計數器爲零時,則移動到狀態S2等。@ dannyn382 – Tim

相關問題