I am trying to build an AHB vip, just to get hold of the basics of UVM.
I am finding difficulty in randomizing the various AHB protocol signals. For e.g, I can randomize HBURST type , HSIZE type and the starting address. But how do i randomize or create the HTRANS, HADDR for the same burst type (number of HADDR, HTRANS is going to chnage based on the randomized HBURST type). Also, my HADDR values will change, either incremented by 4 or 8 or etc, base on burst type and HSIZE; similarly the HTRANS values can be BUSY and SEQ for burst transfers whereas NSEQ and IDLE for single transfers.
I am presently handling such things in the driver by generating a loop for the number of beat transfer as dictated by HBURST, HSIZE type. But i am not sure whether that is the right way. What will be the best way to handle this?
Here is an example below. You can see how parity is generated in the post_randomize function. Your concerns on HADDR in your situation is the same, I think.
// Parity Type Control knob
typedef enum bit {GOOD_PARITY, BAD_PARITY} parity_e;
class uart_frame extends uvm_sequence_item; //lab1_note1
// UART Frame
rand bit start_bit;
rand bit [7:0] payload;
bit parity;
rand bit [1:0] stop_bits;
rand bit [3:0] error_bits;
// Control Knobs
rand parity_e parity_type;
rand int transmit_delay;
// Parity is calculated in the post_randomize() method //lab1_note5
function void post_randomize();
parity = calc_parity();
endfunction : post_randomize
Hi,
Thanks for sharing the code. I understand the code and how parity is calculated based on the randomized payload.
But my question is different. Let me give you a snippet of my code that i have written so far for the AHB master:
class driver extends uvm_driver…
…
task run_phase();
…
while(1) begin
seq_item_port.get_next_item(req);
req.print();
if($cast(pkt,req)) begin
for(i=0;i<pkt.beats;) begin
if(ahb_if.cb_master.HREADY) begin
ahb_if.HWRITE = pkt.HWRITE;
ahb_if.HBURST = pkt.HBURST;
ahb_if.HSIZE = pkt.HSIZE;
ahb_if.HPROT = pkt.HPROT;
ahb_if.HTRANS = pkt.HTRANS[i];
ahb_if.HWDATA = $random;
i=i+1;
end
@(posedge ahb_if.HCLKM);
end
end
else begin
`uvm_fatal(“CASTERR”, $sformatf(“AHB packet couldn’t be cast”));
end
seq_item_port.item_done();
end
…
endtask
endclass
In the above example, i cannot directly randomize my HTRANS because set of values and the number of values is completely dependent on HBURST. Example, if HBURST = INCR4, HTRANS should have values (NSEQ, SEQ,BUSY) and the number of such values should be 4. For HBURST = INCR8, HTRANS set should have 8 values. If HBURST=SINGLE, HTRANS can be {IDLE, NSEQ} and number of values in the set is 1. What i am trying to say is the number of values to be gathered for a particular variable is not fixed, hence i cannot randomize. Similar is the case for HWDATA (hence i am handling that in the driver). I can still handle HADDR by randomizing the starting address and using addr_incr to increment the address based on the HSIZE.
My question is what is the best way to do that. Also, how to handle weights while randomizing? Like I want HBURST tobe 40% of type INCR4 and remaining 60% of type INCR8.
Please ignore my answer. I read the AHB protol just now. I see that HTRANS[1:0] and HWDATA[31:0] are tightly related to the timing of operation. I will put them in driver like the way you did. Expecting another solution.
The way to handle weights while randomizing I see in book ‘systemverilog for verification’. Is this what your need?