APB READ_TRANSFER

Hi,

 Presently I'm working on apb protocol, for apb read transfer(PSEL=1,PENABLE=1,PWRITE=0),
   first i write the data into a memory(using apb write_transfer),and i'm trying to do is read the data from memory(using apb read_transfer) 
          
     but there is error in my uvm code for read transfer ,please can you check once

   https://www.edaplayground.com/x/5p5f

Thanks,
Prawin

In reply to PJ:

What type of errors are you facing? There are some obvious compilation errors in that code. Minor errors like “use of = instead of ==” or “missing semi-colon” and many more. What is the source of that code?

In reply to PJ:

Your Problem is here:

penable=rhs_.penable &&

it has to be

penable == rhs_.penable &&

as you did with all the other data fields.

In reply to chr_sue:

Hi,

Please observe the waveform, it is perfect with the write transfer,but error in read transfer

https://www.edaplayground.com/w/x/2KH 

and
Scoreboard not working…

In reply to chr_sue:

can u pls tell in which class this mistake is creating

In reply to vlsique:

It seems you fixed the code in the meantime. Because the old version did not compile.
It was in the seq_item definition.

In reply to PJ:

In reply to chr_sue:
Hi,
Please observe the waveform, it is perfect with the write transfer,but error in read transfer
EPWave Waveform Viewer
and
Scoreboard not working…

Your sequence Body Task looks a Little bit strange.

  task body();
     
     //Create 10 random APB read/write transaction and send to driver
    rw_trans = apb_rw::type_id::create("rw_trans");
      //apb_rw::type_id::create(.name("rw_trans"),.contxt(get_full_name()));
    for(int i=0;i<5;i++) begin
       start_item(rw_trans);
       //assert (rw_trans.randomize());
      assert(rw_trans.randomize() with { addr==32'h6523_1221;data == 32'h1021_2321;apb_cmd == 1'b0;});
       finish_item(rw_trans);
      
      
      start_item(rw_trans);
       //assert (rw_trans.randomize());
      assert(rw_trans.randomize() with { addr==32'h6523_1221;data == 32'h1021_2321;apb_cmd == 1'b1;});
       finish_item(rw_trans);
      
        start_item(rw_trans);
       //assert (rw_trans.randomize());
      assert(rw_trans.randomize() with { addr==32'h6526_1551;data == 32'h5555_0202;apb_cmd == 1'b0;});
       finish_item(rw_trans);
      
        start_item(rw_trans);
       //assert (rw_trans.randomize());
      assert(rw_trans.randomize() with { addr==32'h6526_1551;data == 32'h5555_0202;apb_cmd == 1'b1;});
       finish_item(rw_trans);
      
     end
  endtask

Could you please explain which apb_cmd is RD and which is WR. The RD needs only the command and the address, but no data in the sequence.

In reply to chr_sue:

This is my Driver class… so apb_cmd =1 is RD and,= 0 WR
case (tr.apb_cmd)
1’b1: drive_read(tr.addr, tr.data);
1’b0: drive_write(tr.addr, tr.data);
endcase
////////////////////////////////

i changed little bit of code, but now it is working fine. without scoreboard

In reply to PJ:

In reply to chr_sue:
This is my Driver class… so apb_cmd =1 is RD and,= 0 WR
case (tr.apb_cmd)
1’b1: drive_read(tr.addr, tr.data);
1’b0: drive_write(tr.addr, tr.data);
endcase
////////////////////////////////
i changed little bit of code, but now it is working fine. without scoreboard

can u pls share urs changed code


In reply to vlsique:

before change the code the uvm sequence like below ,i randomize penable,psel,pwrite directly here…
typedef enum {READ, WRITE} kind_e;
rand bit [31:0] addr; //Address
rand logic [31:0] data; //Data - For write or read response
rand logic penable;
rand logic psel;
rand logic pwrite;
rand kind_e apb_cmd;
so the sequence_item was :-
assert(rw_trans.randomize() with { addr==32’h6523_1221;data == 32’h1021_2321;apb_cmd == 1’b0;penable==1’b1;psel==1’b1;pwrite==1’b1});
finish_item(rw_trans);
but now,

i’m directly hard coded the psel,pwrite,penable values in uvm_driver only

case (tr.apb_cmd)
1’b1: drive_read(tr.addr, tr.data);
1’b0: drive_write(tr.addr, tr.data);
endcase
//Handshake DONE back to sequencer
seq_item_port.item_done();
end
endtask: run_phase
virtual protected task drive_write(input bit [31:0] addr,
input bit [31:0] data);

  this.vif.master_cb.paddr   <= addr;             
 @(this.vif.master_cb);
  this.vif.master_cb.pwdata  <= data;
  
 this.vif.master_cb.psel    <= '1;
 this.vif.master_cb.penable <= '0;
 this.vif.master_cb.pwrite  <= '1;  

////////
k…

In reply to PJ:

I don’t understand why you have psel, pwrite and penable in your sequence item. I believe it does not make any sense to have them there. There is no need to randomize these items. They are simple control signals for your bus protocol.

In reply to chr_sue:

yes chr_sue, that’s what i changed the code

In reply to PJ:

Hi,

In waveform transfers of apb protocol working fine,but there is a mistake in scoreboard expected and actual values.

thanks,
pj

In reply to PJ:

In reply to PJ:
Hi,
In waveform transfers of apb protocol working fine,but there is a mistake in scoreboard expected and actual values.
apb_with_sb - EDA Playground
thanks,
pj

why is scoreboard giving error ,i m not getting the solution ,can anyone pls help

In reply to vlsique:

You should publish the EDAplayground page …

In reply to chr_sue:

Hi,

sorry for delay.

you can proceed now.

Thanks,
pj

In reply to PJ:
Your environment looks a little bit like quick & dirty. There are a few weaknesses:

(1) the ADDR_WIDTH is not consistent (8/32 bit)
(2) you are dealing in some components with the clocking block in others not
(3) if you want to compare x-values (undefined) you have to use the case equality (===). Changing this generates only passes.

I did not investigate where the x-values are coming from and if they are correct.

In reply to chr_sue:
Hi,

am getting zero when fifo rd operation,

Thanks,

In reply to PJ:

I had a closer look to your code. You are still doing strange things:
(1) in the driver you have on the left-hand side in the run_task the transaction object.
(2) in the monitor you are assigning the re in the same clock as the value from the vif.d_out to your transaction.

I do not know your protocol, but I believe there is more than 1 clock cycle in between. The d_out in the wave forms is always ‘x’.

In reply to PJ:

I was now looking in more detail.
You are reading from your uninitialized memory. This is really not useful, because it returns only x on your interface.
And I modified your monitor to:

task run_phase(uvm_phase phase);
    sequence_item transaction;
    transaction = sequence_item::type_id::create("transaction");
forever begin
  @ (posedge vif.clk);
  transaction.data_in = vif.din;
  transaction.wr_en = vif.wr_en;
  transaction.rd_en  = vif.rd_en;
  //transaction.data_ram = vif.mem;
  @ (posedge vif.clk);
  transaction.data_out = vif.dout;
  
  //$display("ram=%h",vif.mem);
  item_collected_port.write(transaction);
 `uvm_info("FIFO_MONITOR", $psprintf("Wrote transaction %s",transaction.convert2string()), UVM_LOW);
  end
   
  endtask:run_phase

See the additional clockedge befor vif.dout will be stored.