Two Clock in Clocking block

Hi,
I have two different clock frequency 65MHz and 53.16MHz, at interface clocking block (for driver). I wanted to add both the clocks in clocking block sensitivity list.
So how can I approach that scenario ? Your advice and guidance is highly appreciated Thanks.

In reply to Yeptho:

This seems like a very unusual situation.

A SystemVerilog clocking block can only be associated with a single clock. You can either use the output of a multiplexer that selects between the two clocks, or you can create two clocking blocks that drive the same signals.

In reply to Yeptho:

Hi,
I have two different clock frequency 65MHz and 53.16MHz, at interface clocking block (for driver). I wanted to add both the clocks in clocking block sensitivity list.
So how can I approach that scenario ? Your advice and guidance is highly appreciated Thanks.

The key question is if you are using these clocks concurrently or as alternatives.

In reply to chr_sue:

In reply to Yeptho:
The key question is if you are using these clocks concurrently or as alternatives.

Hi chr_sue, I have to use in concurrent manner, If you can please help me with some example code will be really helpful.

In reply to Yeptho:
What you are describing looks like a driver protocol depending on 2 clocks at the same time.
Can you please show some more details.

In reply to Yeptho:

interface my_itf(input clk1,clk2);

  wire signal;
  clocking cb1 @(posedge clk1);
    output signal;
  endclocking
  clocking cb2 @(posedge clk2);
    output signal;
  endclocking
  
endinterface

Assuming you have a virtual interface handle vif, you would drive the signal with either

  vif.cb1.signal <= something; 
  // or 
  vif.cb2.signal <= something;

In reply to chr_sue:

Hi Chr_sue, Here’s my sample code

// my_Sequence
task body(); 
if (pkt_tx.rd_file == 1'b1) begin
 assert(pkt_tx.randomize());
end
 else begin
 #1009.700ns  $readmemh("./image_2_hex.txt", mem_array);
   if(vif.i_reset_n==1'b1) begin   
      for(int i=0;i<2000; i++) begin
      @(posedge vif.i_Pixel_clock);
      pkt_tx.i_pixel_data   <= mem_array[i];
  end
  
   start_item(pkt_tx);
     pkt_tx.signal1   <= 4'h4    ;
     pkt_tx.signal2   <= 4'h5    ; 
    // .
    // .
   finish item(pkt_tx);
 end 
 endtask

// Driver :
//Below drive_pixel and drive_framer task are mine 

  task drive_pixel(packet_trans  pkt_tx); 
      vif.drv_pxl_cb.i_pixel_data    <= pkt_tx.i_pixel_data  ;
      vif.drv_pxl_cb.signal1         <= pkt_tx.signal1  ;
          // .
          // .
      endtask
             
  task drive_framer(packet_trans   pkt_tx);        
      vif.drv_frmr_cb.signal2        <= pkt_tx.signal2;
         //  .
         //  .                
  endtask

//-------------Driver run_phase ------------//
  seq_item_port.get_next_item(pkt_tx);
     wait(vif.i_reset_n == 1'b1) 
      begin
          fork
             @(posedge vif.i_Pixel_clock)drive_pixel(pkt_tx);
             @(posedge vif.i_sys_clock)drive_framer(pkt_tx);
          join
      end
   seq_item_port.item_done();

For the clocking block in the interface, I have implemented as shown by Dave, with respect to two different clock

In reply to Yeptho:

You shoule bever deal with clock and reset in the sequence. This makes your sequences unreusable and slows down the simulation.
Is this really true you are processing the pixel and the frame data concurrently?
How is yor DUT reacting?

1 Like

In reply to chr_sue:

Hi chr_sue, I need to pass the backdoor read image_2_hex.txt value to i_pixel_data with respect to i_Pixel_clock so I’m depending on vif in sequence. If there’s any other way Please suggest.

Well my DUT is responding to the values which are driven from sequence (example : signal1 and signal2) but for i_pixel_data which is pass from sequence, it is not responding by DUT.

In reply to Yeptho:

In the sequencer/sequence only the order of data is relevant. Any timing will be done in the driver.

In reply to dave_59:

Hi Dave, Implemented clocking block by following your example.
I have driven the signals with respect to clocking block from Driver and DUT has responded, except the backdoor read file which is not able to drive from driver to DUT.
So can you please point out where i did gaffe in the code.

In reply to chr_sue:

Hi Chr_sue, like you said timing related to do in driver, So a task is created for reading the text file in the driver class.

//task for reading txt file in driver
 task read_image_2_hex();
      
    #1009.700ns $readmemh("./image_2_hex.txt", this.temp_mem); 
    if(vif.i_pixel_enable==1'b1) begin   
    for(int i=0;i<2000;i++) begin
    @(posedge vif.i_Pixel_clock);
    arinc_818_tx.i_pixel_data   <= this.temp_mem[i];
    $display("read_file_drv --> temp_mem[%0d] = %h",i,this.temp_mem[i]);
    $display("read_file_drv --> i_pixel_data[%0d] = %h",i,arinc_818_tx.i_pixel_data[i]); //not able to take the value from temp_mem to i_pixel_data
     end
    end
   endtask

// driver task run_phase
  wait(vif.i_reset_n == 1'b1) begin :B3
       fork            
            @(posedge vif.i_Pixel_clock) drive_pxl(arinc_818_tx);
             read_image_2_hex();
            @(posedge vif.i_sys_clock) drive_frmr(arinc_818_tx);
        join
      end :B3
   
endclass :driver

//Console Output Report
.
.
read_file_drv → temp_mem[1998] = 67503e
read_file_drv → i_pixel_data[1998] = 0
read_file_drv → temp_mem[1999] = 67513c
read_file_drv → i_pixel_data[1999] = 0
read_file_drv → temp_mem[2000] = 6e5843
read_file_drv → i_pixel_data[2000] = 0

In reply to Yeptho:

This is not enough code to see where your problem is.
Why do you delay the readmemh and you should do this from outside your driver task.

In reply to chr_sue:

Hi Chr_sue, thank you for pointing out the reading file of .txt outside the driver task.
I’m passing the .txt with the help of vif, some data are missed as well as some are captured in the waveforms. BTW thank you and Dave for the valuable inputs.

cheers,

Are there any limitations to using multiple clocking blocks, each using a different clock edge, within a driver or monitor?

No limitations. But that does not mean no problems. Hard to say with such a general question.

I am finding that even if I use a clocking block with the negedge, the transaction data is applied to the DUT on the posedge, which is not expected. So obviously, there is a ghost in the machine.