Implementing Read on Clear (RC) register

Hi Forum,
I wanted to model a RC register for my Tb, however I am confused on the following ::
(1) If user tries to read the register,
(a) Would they observe Rdata as zero [ or ]
(b) The prior value which RTL has written to it.RTL clears it on same clock such that a 2nd read to the RC register would result in zero value being read by user.

(2) When should the RTL clear the register ? i.e is it done on the same clock that user tries to read it.

My existing code looks like this

module traffic (  input          pclk,
                  input          presetn,
                  input [31:0]   paddr,
                  input [31:0]   pwdata,
                  input          psel,
                  input          pwrite,
                  input          penable,
 
                  // Outputs
                  output [31:0]  prdata);
 
  reg [31:0]     state_reg;    //  Lower 10-bits are "RC" register mapped to Addr:'hC. Upper bits are reserved
  // other register definition

   // Set all registers to default values
   always @ (posedge pclk or negedge preset_n) begin
      if (!preset_n) begin         
         state_reg <= 0; 
         .....
      end
     else begin
       state_reg <= ( (paddr=='hC) & psel & penable & !pwrite ) ? 0 : ($urandom % 1024); // Can't be written by FW. RTL writes based on internal logic
       //  Additional Sequential writes 
     end 
   end
 
   // Provide read data
   always_comb begin
     if (psel & !pwrite & penable) 
         case (paddr)
            ............
            'hc : rdata_tmp = { 22'b0 , 10'b0 }; // "RC" field in state_reg[9:0];
         endcase
   end
 
   assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz;
 
endmodule

Any suggestions are welcome.

Thanks in Advance,
Arshi

If your testbench is implemented using UVM, then the recommended way is to use UVM register model and “RC” access policy is supported by default. If you need to read more about that, you can take a look at this section from UVM cookbook
Register Abstraction Layer
There are some examples in this section that illustrate how to create a register model.

Answering your questions, if we consider the following two statements from uvm class reference documentation:

  • ”RC” W: no effect, R: clears all bits
  • “The effect of a read operation are applied after the current value of the field is sampled. The read operation will return the current value, not the value affected by the read operation (if any).”

Then that means the first read should return the current value and the second read should return zero.

Hope that helps :)

Thanks @Ahmed_Kelany ,
So in my DUT the only change I would need to do is ::

// Provide read data
   always_comb begin
     if (psel & !pwrite & penable) 
         case (paddr)
            ............
            'hc : rdata_tmp = { 22'b0 , state_reg }; // "RC" field in state_reg[9:0];
         endcase
   end

My first answer was based on the transaction level (conceptually), which was not timely accurate. It’s a bit hard for me to answer without knowing :

  • DUT specs i.e. what are the conditions that trigger a change to the internal value of the register? aside from external reading of course
  • Which protocol is used to read the register? From the signal names I reckon it’s apb, but is it the standard one or a modified version, do you support b2b reads?
  • Do you like to create a synthesizable model for this RC register or not?

I recommend you follow the RC description mentioned in the first answer and try to adjust that to your timing/protocol requirements.

My apologies I should have been clear with my intention.
I am simply using the above code as a sample DUT code for my Tb ( hence I am using $urandom )