2016-06-16 6 views
0

내 작업 재귀를 사용할 때 직면 한 한 가지 문제를 이해하도록 도와주십시오. 따라서 enable 및 ddr_clk 신호를 추적해야하는 작업이 있습니다. 그것들은 비동기 신호이며 enable은 ddr_clk posedge 전에 나타날 수 있습니다. 이 경우 태스크는 enable이 하이 (high)가 될 때까지 기다려야한다. @ (posedge itf.ddr_clk)는 쓰기가 완료 될 때까지 일어난다.작업에서 재귀 사용 문제

task automatic write(); 
    $display ("%t:\tdriver: write function", $time); 
    if (itf.enable == 1) begin 
     $display ("%t:\tdriver-write: ->writing in DUT: assiging wdata and waiting for ddr_clk posedge...", $time); 
     itf.wdata = req.data_wfifo_data; // assign and wait for clk posedge 
     fork 
      begin : wait_clock; 
      @ (posedge itf.ddr_clk) 
       $display ("%t:\tdriver-write: Got ddr_clk posedge, considering write done", $time); 
      end 

      @(itf.enable) // In case when enable goes to low before posedge 
      begin 
       $display ("%t:\tdriver-write: enable changed, re-calling write", $time); 
       disable wait_clock; 
       write; 
      end 
     join_any 
    end else 
    begin 
     $display ("%t:\tdriver-write-enable: waiting for enable...", $time); 
     @(itf.enable) 
      write; 
    end 
    $display ("%t:\tdriver: END write function", $time); 

endtask 

을 그리고 이것은 시뮬레이션 결과가주는 것입니다 : 내가 작업에서 재귀를 사용하고이를 구현하는 작업이 exitting 다음 여러 번 전화를하고있는 같은 시뮬레이션 시간에서

65490750.0 ps: driver: write function 
65490750.0 ps: driver-write: ->writing in DUT: assiging data_wfifo_data and waiting for ddr_clk posedge... 
65490850.0 ps: driver-write: enable changed, re-calling write 
65490850.0 ps: driver: write function 
65490850.0 ps: driver-write-enable: waiting for enable... 
65490850.0 ps: driver-write: enable changed, re-calling write 
65490850.0 ps: driver: write function 
65490850.0 ps: driver-write-enable: waiting for enable... 
65490850.0 ps: driver: END write function 
65490850.0 ps: Driver: END Calling write task to write in DUT 

.

행동에 대한 이해를 돕기 바랍니다. "disable wait_clock"문이 작동하지 않는다는 인상을 받았습니다 ...

+0

불편을 끼쳐 드려 죄송합니다. 아마도 몇 가지 파형을 그릴 수 있습니까? –

답변

1

나는 완전한 활동 기록을 보여주지 않았다고 가정합니다. 이 태스크의 초기 $ display 문이 있어야합니다. 또한 enable이 true 인 동안 데이터가 안정적입니까? enable 낮은 간다, 당신이 매달려 과정 왼쪽됩니다 @(posedge itf.ddr_clk)전에 당신이 얻을 경우

문제는, 당신이 write()를 호출 할 때마다 수 true입니다. 그런 다음 enable이 낮아지면 모두 한 번에 트리거됩니다. join_any 뒤에 disable fork을 넣을 수 있습니다.

여기 재귀를 사용하면 상황이 더욱 복잡해집니다. 나는 루프를 포크에 대신

task write; 
    fork 
    forever begin 
       wait(itf.enable); 
       itf.wdata = req.data_wfifo_data; 
       wait(!itf.enable); // @(itf.enable or req.data_wfifo_data) -- if really level sensitive 
      end 
    @(posedge itf.ddr_clk iff itf.enable); 
    join_any 
    disable fork; 
endtask 
+0

감사합니다. join_any 이후 비활성화 포크를 넣었습니다. 작동하고 있습니다. iff 사용법에 대한 좋은 아이디어는 결코 내 마음에 들지 않았습니다. – haykp

0

을 사용하고는 wait_clock 블록을 사용하지 65490850.0에서 실행됩니다 두 번째 블록 (its.enable)를 차단 join_any 및 호출 (2) 물품.

이렇게하면 두 가지 흐름이 발생합니다.

  1. write (2)는 재귀에서 두 번째 호출됩니다. 두 번째 작업은 나중에 대기하거나 심지어 완료하거나 재귀 적으로 쓰기를 더 호출합니다.

  2. write (1) 인스턴스에서 wait_clock 블록이 비활성화되고 join_any 포크가 이제 실행을 완료합니다. 해당 join_any 사용 불가 블록이 join_any의 완료를 트리거합니다. 코드는 else를 건너 뛰고 "END write function"을 표시하고 드라이버의 기본 호출 기능으로 돌아갑니다.

    그러면 write를 호출 한 main 함수는 "END write write task to write to DUT"라는 표시를 보여줄 것입니다.

하나의 솔루션

추가 수는 재귀 호출 횟수를 볼 수 있습니다. 그것은 또한 디버깅을 돕습니다. 첫 번째 실행 (쓰기)을위한 트리거 대기를 시작하는데도 사용됩니다. wait_clock이 완료 될 때마다 트리거를 생성합니다. 원하는 구조로 트리거를 인스턴스화 할 수 있습니다.

task automatic write(int count); 
    $display ("%t:\tdriver: write function , count %d", $time,count); 
    if (itf.enable == 1) begin 
     $display ("%t:\tdriver-write: ->writing in DUT: assiging wdata and waiting for ddr_clk posedge... count %d", $time,count); 
     itf.wdata = req.data_wfifo_data; // assign and wait for clk posedge 
     fork 
      begin : wait_clock; 
      @ (posedge itf.ddr_clk) 
       $display ("%t:\tdriver-write: Got ddr_clk posedge, considering write done count %d", $time,count); 
       ->itf.done; 
       //disable wait_enable; 
      end 

      //begin : wait_enable 
      @(itf.enable) // In case when enable goes to low before posedge 
      begin 
       $display ("%t:\tdriver-write: enable changed, re-calling write count %d", $time,count); 
       disable wait_clock; 
       write(count+1); 
      end 
      //end 
     join_any 
    end else 
    begin 
     $display ("%t:\tdriver-write-enable: waiting for enable...count %d", $time,count); 
     @(itf.enable) 
      write(count+1); 
    end 
    if (count == 0) wait (itf.done.triggered); 
    $display ("%t:\tdriver: END write function , count %d", $time,count); 

end task 

그러나 재귀 함수는 추적 및 디버그하기가 어렵습니다. 이 경우에는 루프 기반 함수가 제대로 작동합니다. wait_clock 블록을 비활성화하면 모든 재귀 함수의 모든 wait_clock 블록이 비활성화되므로 재귀에는 또 다른 잠재적 문제가 있습니다. 그것이 문제를 일으킬 것이지만, 경계를 유지할 수 있는지는 확실하지 않습니다.

프로토콜의 제한된 데이터/약식에 기반하여 루프 기반 기능이 아래에 제시됩니다. 코드는 위의 코드를 모방하려고 시도했지만 프로토콜 관련 픽스를 위해 더 단순화되거나 쉽게 수정할 수도 있습니다.

task automatic write_non_recursive(); 
int done,got_clock,got_enable ; 
    done = 0 ; 
    $display ("%t:\tdriver: write function , ", $time); 
    while (done == 0) 
    begin 
     if (itf.enable == 1) begin 
      $display ("%t:\tdriver-write: ->writing in DUT: assiging wdata and waiting for ddr_clk posedge... ", $time); 
      itf.wdata = req.data_wfifo_data; // assign and wait for clk posedge 
     end 
     got_clock = 0 ; 
     fork 
      begin //using got clock to check edge 
       @ (posedge itf.ddr_clk) ; got_clock = 1; 
      end 
      @(itf.enable) ; 
     join_any 
     //if (itf.ddr_clk == 1 && itf.enable == 1) - if we were looking onyl into clock 
     if (got_clock == 1 && itf.enable == 1) 
     begin 
       $display ("%t:\tdriver-write: Got ddr_clk posedge, considering write done ", $time); 
       done = 1; 
     end 
     else if (itf.enable == 0) // en = 0 , clk = 1 or en = 0 , clk = 0 ; 
     begin 
       $display ("%t:\tdriver-write: enable changed, re-calling write ", $time); 
       @(itf.enable) ; // wait for the next edge 
     end 
     else // en = 1 , clk = 0 ; 
       $display ("%t:\tdriver-write-enable: waiting for enable...", $time); 
     got_clock = 0; //reset and look for edge again 
    end 
    $display ("%t:\tdriver: END write function , ", $time); 

end task 
+0

반복에 대해 설명해 주셔서 감사합니다. 이제는 이해할 수 있습니다. – haykp