Jump to content

RAL Read Method

Recommended Posts

Hello Everyone.

My question is I can write a register value, but cannot read the same value back.


I can get the written value from register by get() method, but when i read the same value, i receive 0, "ZERO".



Any solution for this one ?

my register sequence is as follows.


virtual task body();
uvm_status_e status;
uvm_reg_data_t data;
$display("\n\n\nTRANSACTION SEQ1 Starting.....");
desired_value = block_obj.reg2.get();
$display($time,"(1)desired_value is %0h",desired_value);
$display ($time,"\n\nSEQ READ START");
$display ($time,"READ SEQ final data %h\n\n\n",data);
desired_value = block_obj.reg2.get();
$display($time,"(2)desired_value is %0h",desired_value);
endtask: body
Link to comment
Share on other sites

My Register Class: 

My registers are of RW access policy.



class my_register extends uvm_reg;
rand uvm_reg_field pid;
rand uvm_reg_field token;
uvm_reg_field reserved;
function new (string name = "my_register");
super.new (name, 8, UVM_NO_COVERAGE);
endfunction: new
virtual function void build();
pid = uvm_reg_field::type_id::create("pid");
token = uvm_reg_field::type_id::create("token");
reserved = uvm_reg_field::type_id::create("reserved");
endfunction: build
endclass: my_register
Link to comment
Share on other sites

Thankyou sir,
But i have defined the registers as RW only.
Still facing the problem.
The issue i observed is that when i do write-read method.
During read method, the bus2reg function is called twice, which overwrites my data.
The last third line of below transcript provides me correct address and data.
But the second call to bus2reg, overwrites my data and address.
And when i use get() method to recheck the data, it will return the correct data stored in my register.
                0REG2BUS    rw,data = 9 at rw,addr = 20 // write sequence started. reg2bus called.
#                   10value of read_en is 0 // Driver driving the signals on the interface
#                   10value of write_en is 1 // Driver driving the signals on the interface
#                   10value of ADD is 20 // Driver driving the signals on the interface
#                   10value of write_data is 9 // Driver driving the signals on the interface
#                   10DUT - WR 09 @ 20 // Transaction executed on DUT
#                   15 mo - read_data is 00 // Monitor gets the previous value of DUT.
#                   15PRED - in write data 0000000000000000 | mypl data00 // Bus2Reg called once in write condition.
#                   19PRED - in write data 0000000000000000 | mypl data00 // Bus2Reg called 2nd time in write condition.
#                   20DUT - WR 09 @ 20 // As i have placed a #10 delay between write and read, the write will executed once again.
#                   25 mo - read_data is 00
#                   25PRED - in write data 0000000000000000 | mypl data00
#                   29
# SEQ READ START // Read Sequence started
#                   29REG2BUS    rw,data = 0 at rw,addr = 20
#                   30value of read_en is 1
#                   30value of write_en is 0
#                   30value of ADD is 20
#                   30value of write_data is 0
#                   30DUT - RD 09 @ 20
#                   35 mo - read_data is 09
#                   35PRED - in read data 0000000000000009 | mypl data09
#                   39PRED - in read data 0000000000000000 | mypl data00
#                   39READ SEQ final data 0000000000000000
:::Register Block Class:::
virtual function void build();
reg1 = my_register::type_id::create("reg1");
reg2 = my_register::type_id::create("reg2");
my_reg_map = create_map (.name("my_reg_map"),
$display("REG_BLOCK -- REG1 CREATED");
$display("REG_BLOCK -- REG2 CREATED");
endfunction: build
Link to comment
Share on other sites



#1. when you call the UVM_REG.write, the bus2reg happens twice. It's correct.

1st happens on uvm_reg_map::do_bus_write (adapter.bus2reg(bus_rsp/req,rw_access);)

2nd happens on uvm_reg_predictor::write( adapter.bus2reg(tr,rw);)  ---- when bus monitor broadcasts the bus transaction (write or read) to uvm_reg_predictor.bus_in, this function will be called and will update the RAL model.


#2. Make sure your bus monitor connects to the uvm_reg_predictor.bus_in uvm_analysis_imp well. 


please also check if the read data is 0 or correct value on the bus of DUT.


Try block_obj.reg2.get_mirrored_value(); to check the mirror value.

Link to comment
Share on other sites

Yes, sir. But you can see from transcript output, i have replied in previous post.

The bus2reg called by monitor broadcast executes first. And it returns correct data. (Checked by placing display).

Where as when bus2reg called by uvm_reg_map, executes last, and that does not provides correct data.



The transcript output at time "35".

                     35 mo - read_data is 09 // Monitor Snoops the data and broadcast it.
#                   35PRED - in read data 0000000000000009 | mypl data09 // BUS2REG called by uvm_reg_predictor class, which return 09 value.
#                   39PRED - in read data 0000000000000000 | mypl data00 // BUS2REG called by uvm_reg_map, which DOES NOT RETURN ACTUAL (09) VALUE. :(
#                   39READ SEQ final data 0000000000000000 // Displaying actual data.
The connections in environment class are as follows:
function void connect_phase(uvm_phase phase);
block_obj.my_reg_map.set_sequencer(agt_obj.seqr_obj, adpt_obj); // block_obj -> register Block instance, my_reg_map -> register map instance.
agt_obj.mon_obj.mon_ap.connect(predictor_obj.bus_in); // agt_obj -> agent class instance, mon_obj -> monitor class instance, mon_ap -> monitor analysis port.
predictor_obj.map = block_obj.my_reg_map;
predictor_obj.adapter = adpt_obj;
endfunction: connect_phase
Link to comment
Share on other sites

What I found problematic was that he said he did set_auto_predict(0) and he still needed to update the item coming from the driver, because its value was used to update the register model. This might be interesting to debug by some UVM developer, maybe there's an issue in UVM behind it.

Link to comment
Share on other sites



i think the answer is "simple"


1. the active path reg.read()->seqr->adapter->driver->adapter->seqr->reg.read()-end always needs that the driver supplies the final data and the adapter translates it. if your driver finishes the transaction before the transfer is complete (posted transactions, out of order, pipelined transactions, etc) OR doesnt provide the correct data then the result of the read() does not reflect the right value. there is no other way to return data to the caller than via this path.


2. the difference auto_predict() makes is that with auto_predict(1) the active path will update the shadow register while with auto_predict(0) some other instance needs to take care of that (monitor->predictor).in other words - auto-predict() has no influence of what data is being returned to the caller of a reg.read() call.


3. the adapters bus2reg and reg2bus  should be kind of "inverse" - if they are not its likely that wrong data is provided, the wrong register updated with wrong data etc.



Link to comment
Share on other sites

Exactly you are right uwes.


But my point of confusion was that, dont we have any other method to update the transaction packet ?

I mean, INITIALLY my driver class contained a single task, which simple recieves the transaction and send it on iterface.

I was not taking response from DUT.


But as TIMI suggested, i added a logic which gets back the response from DUT.



virtual task drive_sig(my_packet drv_pkt);     //Driving the signals on the interface.
drv_intf.read_en <= drv_pkt.read_rq;
drv_intf.write_en <= drv_pkt.write_rq;
drv_intf.ip_add <= drv_pkt.add;
drv_intf.write_data <= drv_pkt.write_data;
receive_data();          // Recieving transaction generated by DUT.
endtask: drive_sig 
task receive_data();
if (drv_intf.read_en == 1) begin
drv_pkt.read_data = drv_intf.read_data;
end else drv_pkt.read_data = 'hff;
endtask: receive_data



So this do imply that, i have implemented MONITOR CLASS functionality in my DRIVER CLASS.

For a single RAM DUT, it is OK to have such logic.


But for a big design, do i have to implement whole Monitoring Logic (i.e. DUT's Output).



uwes any words on above confusion ?

Link to comment
Share on other sites

  • 6 years later...
On 8/11/2014 at 10:06 PM, hvgbl said:



 In my driver, i had update the data field after a read transaction.

Which reflects the BUS2REG.


Thank you everyone, for your precious inputs.



what do you mean? how is the data sent to the adapter's bus2reg function?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...