[SV]SystemVerilog多線程採樣的案例分析 ---- 兩個線程相互影響,交替出現漏採樣的情況

                   SystemVerilog多線程採樣的案例分析

                                          ---- 兩個線程相互影響,交替出現漏採樣的情況

 

一、多線程採樣代碼段  ---- 兩個線程相互影響,交替出現漏採樣的情況

  • 在下面的代碼中,在clk第一個pulse的negedge到來時,線程:measure_pulse_width_of_if_ck(以後稱之為Thread1)結束,同時線程:interval_between_teo_if_ck_pulse(以後稱之為Thread2)開始。
  • 第二個pulse的posedge到來時,Thread2結束,同時第二輪循環開始。--> (Thread1看不到第二個pulse的posedge)
  • 進入第二輪循環后,Thread1在等posedge,Thread2在等negedge,此時Thread2先等到第二個pulse的negedge,Thread2先開始執行
  • 第三個pulse到來時,Thread2結束,同時Thread1開始,當negedge到來時,Thread1結束,開始下一輪循環。--> (Thread2看不到第三個pulse的negedge
class if_ck_check_monitor extends uvm_monitor;        

  realtime            keep_time_min = 6.00000ns;
  realtime            keep_time_max = 8.00000ns;
  realtime            half_cycle = 1.0012ns;
  bit [7:0]           clk_keep_cnt;

  extern virtual task clk_keep_time_check();

endclass : if_ck_check_monitor;
 
task if_ck_check_monitor::clk_keep_time_check();
  realtime      t1_posedge;
  realtime      t2_negedge;
  realtime      t4_posedge;
  realtime      t3_negedge;
  realtime      keep_time;
 
  @(posedge sync);
  clk_keep_cnt = 0;
 
  do begin
    fork
      begin : measure_pulse_width_of_if_ck
        @(posedge clk);
        t1_posedge = $realtime();
        @(negedge clk);
        t2_negedge = $realtime();

        if(t1_posedge >= t2_negedge) begin
          keep_time = t1_posedge - t2_negedge;
        end
        eles if(t1_posedge < t2_negedge) begin
          keep_time = t2_negedge - t1_posedge;
        end

        if((keep_time >= keep_time_min) && (keep_time <= keep_time_max)) begin
          clk_keep_cnt += 1;    
        end
        else if((keep_time >= half_cycle + 1ps) && (keep_time <= keep_time_min - 1ps)) begin
          `uvm_error()
        end
        else if(keep_time > keep_time_max) begin
          `uvm_error()
        end
        else begin
          `uvm_info()
        end
      end
 
      begin : interval_between_teo_if_ck_pulse
        @(negedge clk);
        t3_negedge = $realtime();
        @(posedge clk);
        t4_negedge = $realtime();

        if(t4_posedge >= t3_negedge) begin
          keep_time = t4_posedge - t3_negedge;
        end
        eles if(t4_posedge < t3_negedge) begin
          keep_time = t3_negedge - t4_posedge;
        end

        if((keep_time >= keep_time_min) && (keep_time <= keep_time_max)) begin
          clk_keep_cnt += 1;    
        end
        else if((keep_time >= half_cycle + 1ps) && (keep_time <= keep_time_min - 1ps)) begin
          `uvm_error()
        end
        else if(keep_time > keep_time_max) begin
          `uvm_error()
        end
        else begin
          `uvm_info()
        end
      end

    join

  end while(sync === 1'b1);
 
endtask : clk_keep_time_check

 

二、解決方案一

 2.1、再複製一個clk信號:clk_d2,并插入一些Delay時間

  • 再造一個clk信號,Delay 2T @clk_ck + 0.08ns,這樣線程:measure_pulse_width_of_if_ck與interval_between_teo_if_ck_pulse就不會同時進行。
logic             clk_d2;
logic [7:0]       clk_d2_cnt;

always @ (posedge clk_ck or negedge rst_n) begin
  if(!rst_n) 
    clk_d2_cnt <= #0.08 'h0;
  else
    clk_d2_cnt <= #0.08 {clk_d2_cnt[0], clk};
end

assign clk_d2 = clk_d2_cnt[1];

 

三、解決方案二

 2.1、把fork join放到循環體之外

  • 這樣的話兩個循環體各自執行,不會出現互相影響的情況
  • 結論:不要在循環體裡面放置fork ... join塊,
class if_ck_check_monitor extends uvm_monitor;        

  realtime            keep_time_min = 6.00000ns;
  realtime            keep_time_max = 8.00000ns;
  realtime            half_cycle = 1.0012ns;
  bit [7:0]           clk_keep_cnt;

  extern virtual task clk_keep_time_check();

endclass : if_ck_check_monitor;
 
task if_ck_check_monitor::clk_keep_time_check();
  realtime      t1_posedge;
  realtime      t2_negedge;
  realtime      t4_posedge;
  realtime      t3_negedge;
  realtime      keep_time;
 
  @(posedge sync);
  clk_keep_cnt = 0;
 
 fork 
   do begin
     begin : measure_pulse_width_of_if_ck
        @(posedge clk);
        t1_posedge = $realtime();
        @(negedge clk);
        t2_negedge = $realtime();

        if(t1_posedge >= t2_negedge) begin
          keep_time = t1_posedge - t2_negedge;
        end
        eles if(t1_posedge < t2_negedge) begin
          keep_time = t2_negedge - t1_posedge;
        end

        if((keep_time >= keep_time_min) && (keep_time <= keep_time_max)) begin
          clk_keep_cnt += 1;    
        end
        else if((keep_time >= half_cycle + 1ps) && (keep_time <= keep_time_min - 1ps)) begin
          `uvm_error()
        end
        else if(keep_time > keep_time_max) begin
          `uvm_error()
        end
        else begin
          `uvm_info()
        end
      end
    end while(sync === 1'b1); 

    do begin
      begin : interval_between_teo_if_ck_pulse
        @(negedge clk);
        t3_negedge = $realtime();
        @(posedge clk);
        t4_negedge = $realtime();

        if(t4_posedge >= t3_negedge) begin
          keep_time = t4_posedge - t3_negedge;
        end
        eles if(t4_posedge < t3_negedge) begin
          keep_time = t3_negedge - t4_posedge;
        end

        if((keep_time >= keep_time_min) && (keep_time <= keep_time_max)) begin
          clk_keep_cnt += 1;    
        end
        else if((keep_time >= half_cycle + 1ps) && (keep_time <= keep_time_min - 1ps)) begin
          `uvm_error()
        end
        else if(keep_time > keep_time_max) begin
          `uvm_error()
        end
        else begin
          `uvm_info()
        end
      end
    end while(sync === 1'b1);

  join


 
endtask : clk_keep_time_check

 

 

四、SV案例一:2個Event同時發生,用@等待

  • 結論:當兩個@event_a,@event_b串行時,若event_a與event_b同時發生,則只有@event_a會被觸發,此時程序才會往下走,當event_b再次發生時,@event_b才能捕獲到。
program event_test();

  logic    sig_a;
  logic    sig_b;

  initial begin
    #10ns;
    sig_a = 0;
    sig_b = 0;

    repeat(100) begin
      #10ns;
      sig_a = ~sig_a;
      sig_b = ~sig_b;
    end

  end

  initial begin
    repeat(10) begin
      @sig_a;    
      $display("Event sig_a occurred at %0t", $realtime());
      @sig_b;    
      $display("Event sig_b occurred at %0t", $realtime());
    end
  end


endprogram
  • Simulation Output
Event sig_a occurred at 20!
Event sig_b occurred at 30!
Event sig_a occurred at 40!
Event sig_b occurred at 50!
..........

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元直数字电路验证

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值