2014-07-25 3 views
0

블로킹 (코드 1) 및 블로킹 (코드 2) 지정이 항상 다음과 같은 코드가 있습니다.블로킹 및 비 블로킹 할당 Verilog

그러나 출력은 두 경우 모두 다릅니다. 왜?

이벤트 대기열 알 수는 있지만 "항상 @ (clk)"문이 이벤트 대기열에 배치되는 위치를 이해할 수 없습니다.

// Code 1 
module osc2 (clk, d); 
    output clk; 
    reg clk; 
    input d; 
    initial 
     begin 
      #10 clk = 0; 
      $monitor ("%d %b", $time, clk); 
     end 
    initial #100 $finish;  
    always @ (clk) #10 clk = ~clk; 
endmodule 

// Output of Code 1 
10 0 
20 1 

// Code 2 
module osc2 (clk, d); 
    output clk; 
    reg clk; 
    input d; 
    initial 
     begin 
      #10 clk = 0; 
      $monitor ("%d %b", $time, clk); 
     end 
    initial #100 $finish;  
    always @ (clk) #10 clk <= ~clk; 
endmodule 

// Output of Code 2 
10 0 
20 1 
30 0 (goes on upto 90) 
90 0 
+1

이 몇 일 전에 질문을 받았다 같은 질문이다. 그렉은 잘 대답했다. http://stackoverflow.com/a/24918187/922723 – Russell

+0

감사합니다 russell, 나는 그것을 읽었지만 여전히 약간의 혼란이 있습니다. 정확히 이벤트가 예정 될 때 ~ clk에서 또는 clk =가 실행될 때 ???? & 항상 @ 이벤트가 어떤 이벤트 대기열에 배치됩니까 ??? –

+0

@KaranShah,'clk <='와'$ monitor'을 제외한 모든 것이 활성 영역에 있습니다. 항상 블록 내의 모든 것은 절차 적입니다. '<='은 업데이트를 연기하지만'~ clk'은'@'로 돌아 가기 전에 평가됩니다. 스케줄러의 작동 방식에 관심이 있다면 http://stackoverflow.com/a/22825856/1959732, http://stackoverflow.com/a/21316975/1959732를 참조하십시오. 다른 많은 온라인 리소스가 있습니다. – Greg

답변

1

설명의 목적으로 처음 두 개의 루프 및 확장 된 구성 요소의 내용을 분석했습니다. 아래 코드가 시뮬레이션됩니다.

initial while (1) // to see the loop, functionally equivalent to 'always' 
    begin   // procedural block 
    begin : loop0_unraveled  
     @(clk);  // suspend continuation of loop until change in clk 
     #10;   // suspend continuation of loop 10 time units 
     clk <= ~clk; /* eval '~clk' now, 
        * update clk after all blocking statements are suspended 
        */ 
    end 
    begin : loop1_unraveled 
     begin   // this block is functionally equivalent to '@(clk)' 
     reg smpl_clk;  // local variable 
     smpl_clk = clk; // sample 
     $display("%t::Pre-Suspend : smpl_clk=%b clk=%b",$time, smpl_clk, clk); 
     wait(clk != smpl_clk); // suspend continuation of loop until true 
      /* 1. no other blocking statements can execute, go to next region 
       * 2. In NBA region update clk 
       * 3. Go back to active region 
       * 4. Eval true, continue 
       */ 
     $display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk); 
     end 
     #10;   // reached 
     clk <= ~clk; 
    end 
end     // Go to top of the loop 

이미 here, 자기 트리거 블록을 언급 한 바와 같이 always @ (clk) #10 clk <= ~clk;

initial while (1) // to see the loop, functionally equivalent to 'always' 
    begin   // procedural block 
    begin : loop0_unraveled 
     @(clk);  // suspend continuation of loop until change in clk 
     #10;   // suspend continuation of loop 10 time units 
     clk = ~clk; /* eval '~clk' now 
        * update clk now 
        */ 
    end 
    begin : loop1_unraveled 
     begin // this block is functionally equivalent to '@(clk)' 
     reg smpl_clk;  // local variable 
     smpl_clk = clk; // sample 
     $display("%t::Pre-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk); 
     wait(clk != smpl_clk); // suspend continuation of loop until 
      /* 1. no other blocking statements can execute, go to next region 
       * 2. All other regions are empty 
       * 3. Remaining events are block 
       * 4. Nothing left to do, exit simulation 
       */ 
     $display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk); 
     end 
     #10;   // unreachable 
     clk = ~clk; 
    end 
end 

always @ (clk) #10 clk = ~clk;

은 실제로 매우 흔한되지 않습니다. 클럭 발생기는 일반적으로 비슷한 이식 :

initial begin 
    #10 clk = 0; 
    forever #10 clk = ~clk; 
end 

또는

always #10 clk = (clk===1'b0);