Equivalent construct in SV for modelling Reference model for Verification

Hi Everyone,

I am trying to model Reference model for verification purposes.
Can anyone point to me how can i model the following code in SV construct as i cannot use always and assign statements for reference model. The design code is below :

always @ ( posedge clk  or negedge rst_n) begin
   if(!rst_n) begin
      count <= 2'b00;
   end
   else begin
      count <= count + 2'b1; 
   end
end

wire dv2_pos = (count == 2'd0) || (count == 2'd2);
wire dv4_pos = (count == 2'd0);

reg fr_pos_en;
always @ ( * ) begin
   case(d_fr_en)
      2'b00: fr_pos_en = 1'b0;
      2'b01: fr_pos_en = dv4_pos;
      2'b10: fr_pos_en = dv2_pos;
      2'b11: fr_pos_en = dv4_pos;
   endcase
end

Thanks in advance !!

In reply to tejasakulu:

Let me preface my answer by saying that I think you are taking the wrong approach in creating a reference model. It’s not supposed to be a duplicate of the RTL model and it does not need a clock. It needs to capture inputs as they arrive to the DUT and output as they exit the DUT. The fact that these occurrences come at clock edges should be irrelevant.

You can model any always block

always code;

becomes


fork 
  forever code;
join_none

and a continuous assignment

assign w = expr;

becomes

fork 
  forever @* w = expr;
join_none

In reply to dave_59:

Thanks Dave for the reply. Suppose I have timer which uses a 32KHZ clk I need a that clock right in the ref model. How do I model that

Thanks
Tejas

In reply to tejasakulu:

Does the clock frequency really matter? Unless you have more than one clock in your design, all that matters is that it counts properly.

In reply to dave_59:
Dave,

I agree with your point. I have 3 clocks in my design. My question in general if i have something like always @(posedge clk) in RTL, how do i model the clk in ref model for scoreboard. i cannot directly use the design clock using hierarchal reference. As of now i am doing forever @(posedge mtb.DUT.clk) which is design’s clock. Let me know if i am missing something.

Thannks,
Tejas

In reply to tejasakulu:

Typically the monitors in your testbench sample the inputs/outputs of your design every clock cycle and send it out as a transaction to your checkers/scoreboards. The clock is implicitly imbedded in your transaction as you know that each transaction is sent on a clock edge. And if you have different clocks, you’ll have different types of transactions. The UVM encapsulates this in terms of agents/interfaces. This may seem overly complicated for just a simple timer, but starts making more sense in increasingly larger designs.

In reply to dave_59:

Thanks for the clarification dave. You mean to say the clock is implicitly embedded in my transaction i agree to that. Let me put it this way, say i have a requirement to write a piece of reference model which counts till 256 and generates a interrupt on the terminal count. For this timer/counter to work i need to have clock in my ref model which runs on it right ? how do i take care of this case? And one more question regarding the coding guidelines suppose i have a design code as follows

always @ ( * ) begin
   case(d_fr_en)
      2'b00: fr_pos_en = 1'b0;
      2'b01: fr_pos_en = dv4_pos;
      2'b10: fr_pos_en = dv2_pos;
      2'b11: fr_pos_en = dv4_pos;
   endcase
end
The equivalent ref model code will look something like this right ?

forever begin
@(d_fr_en or dv4_pos or dv2_pos or dv4_pos);
case(d_fr_en)
      2'b00: fr_pos_en = 1'b0;
      2'b01: fr_pos_en = dv4_pos;
      2'b10: fr_pos_en = dv2_pos;
      2'b11: fr_pos_en = dv4_pos;
   endcase
end

Let me know if this is incorrect.

Thanks,
Tejas