2013-11-28 6 views
-1

Verilog 모듈과 자극을 컴파일하고 시뮬레이션 할 때 이상한 결과를 얻고 있습니다. 사일로에서 시뮬레이션하면 코드가 예상대로 작동합니다. Icarus (iverlog 및 vvp)에서 시뮬레이션 한 경우 Silo와는 시간이 다릅니다 (Silo는 235 -> 255이고 Icarus는 235 -> 265 인만큼 200이 아닌 0부터 시작합니다.) 사일로 반복 기능은 예상대로 작동하지만 이카루스를 사용할 때 실제로 어떻게 결과를 얻었는지 파악할 수는 없습니다. 또한 R2GDELAY 반복을 3으로 변경하면 이카루스도 예상대로 실행되지 않습니다. 시뮬레이션에서 나중에 정확한 결과를 얻기 위해 수동으로 시작 시간을 0으로 설정해야하는 등 Icarus를 사용할 때 누락 된 것이 있습니까? 아니면 Silos가 Icarus에서 수동으로 수행해야하는 변수를 자동으로 초기화합니까? 여기 이카루스는 사일로와 다른 결과를냅니다.

   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 

이의 출력입니다 : 여기
`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 

는 사일로의 출력입니다 :이 코드는 여기 여기

http://authors.phptr.com/palnitkar/을 찾을 수있는의 Verilog HDL 책 형태로 촬영하면 코드 이베로 블로그 :

   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 

EDIT : 위 코드에서와 같이 세미콜론을 추가했습니다.
도움 주셔서 감사합니다.

+1

'repeat @ (posedge clock)'을 사용하여 상태 머신을 코딩하는 이상한 방법입니다. 일반적으로 적절한 순차 논리 블록을 사용합니다. – toolic

답변

3

로직에 경쟁 조건이 있습니다. 주석에서 언급했듯이 조합 논리에 대한 입력으로 시계를 사용해서는 안됩니다.

검토 다음과 같은 두 가지 로직 블록 : posedge 시계가 발생하면

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

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

, 시뮬레이터가 선택할 수있는 등 어떤 규칙을 먼저 실행하려면 다음 두 문장 중 하나를 선택합니다. 우선 # 1을 선택하면 다음 상태가 S3으로 설정되고 # 2가 실행되어 S3에 상태가 할당됩니다. # 2가 먼저 실행되면 상태가 다른 것으로 설정되고 상태가 할당 된 후 next_state가 S3로 설정됩니다.

이제는 임의의 이벤트가 시뮬레이터에서 먼저 실행되도록 선택되는 것을 기준으로 다른 동작을 보입니다.

이 문제를 피하는 방법은 조합 방식으로 시계를 보는 것이 아닙니다. 시계는 레지스터를 업데이트하는 데만 사용해야하며 비 블로킹 지정은 <=입니다.

+0

멋지게 발견 - 내가 처음 읽을 때 Palnitkar에서 오류를 표시했지만 포기했습니다. 너무 많아. – EML

+0

의견을 보내 주셔서 감사합니다. 경쟁 조건을 피하면서 예상되는 동작을 달성하려면 반복을 사용하는 대신 추가 상태를 만드는 것이 좋습니다? 또한 경합 조건을 생성하는 경우 작성자가 반복을 사용하여 상태 시스템을 작성한 이유를 알고 있습니까? 다시 한 번 감사드립니다! – dannyn382

+0

추가 상태를 만들 필요는 없지만 현재 상태로 더 많은 작업을 수행 할 수 있습니다. S1을 입력하면 0에 도달 할 때까지 각 클럭주기를 카운트 다운 시작하고, S1이 0이고 카운터가 0이면 S2 상태로 이동할 수 있습니다. @ dannyn382 – Tim