SPI read data

In reply to Rahulkumar Patel:

Hi ,
Please find the code below, In the BFM I can get the read data correctly but in sequence the read data = 0.

class spi_sequence extends uvm_sequence#(spi_trans);

`uvm_object_utils(spi_sequence)

function new(string name = “spi_sequence”);
super.new(name);
endfunction

task body();
spi_trans spi_seq_item;

for(int i=0; i<2; i=i+1)
begin //{
spi_seq_item = spi_trans::type_id::create(“spi_seq_item”);
start_item(spi_seq_item);
case(i)
0 : begin //{
void’(spi_seq_item.randomize() with {pkt_type == WRITE; bit_order == MSB; mode == MODE0; address == 'h01F0; write_data == ‘hAAAA_5555; });
end //}
1 : begin //{
void’(spi_seq_item.randomize() with {pkt_type == READ; bit_order == MSB; mode == MODE0; address == 'h01F0; });
end //}
endcase

        `uvm_info(get_type_name(),$sformatf("SEQ_0: Write and read spi_seq_item.write_data : %0h spi_seq_item.read_data : %0h spi_seq_item.address : %0h", spi_seq_item.write_data, spi_seq_item.read_data, spi_seq_item.address),UVM_LOW)

  finish_item(spi_seq_item);

#10000ns;

    `uvm_info(get_type_name(),$sformatf("SEQ_1: Write and read spi_seq_item.write_data : %0h spi_seq_item.read_data : %0h spi_seq_item.address : %0h", spi_seq_item.write_data, spi_seq_item.read_data, spi_seq_item.address),UVM_LOW)
 end //}

endtask : body

endclass : spi_sequence

class spi_bfm extends uvm_driver #(spi_trans);

`uvm_component_utils(spi_bfm)

spi_trans spi_seq_item;

virtual spi_interface spi_intf;
spi_config spi_cfg;
spi_trans spi_wr_rd_req;
spi_trans spi_wr_rd_data_q[$];
spi_trans data_to_mosi;
bit cmd_assert;

bit [SPI_ADDR_WIDTH-1 : 0] addr; bit [SPI_DATA_WIDTH-1 : 0] data_payload;

extern function new(string name = “spi_bfm”, uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
extern task collect_wr_rd_req(spi_trans wr_rd_request);
extern task set_mode(spi_trans mode_sel);
extern task initialisation();
extern task drive(spi_trans spi_seq_item);
extern task send_addr(input bit [SPI_ADDR_WIDTH-1 : 0] addr); extern task send_data(input bit [SPI_DATA_WIDTH-1 : 0] data_payload);
extern task receive_data(spi_trans spi_seq_item);
extern task receive_dummy(spi_trans spi_seq_item);

endclass : spi_bfm

function spi_bfm::new(string name = “spi_bfm”, uvm_component parent = null);
super.new(name,parent);
endfunction : new

function void spi_bfm::build_phase(uvm_phase phase); // {
super.build_phase(phase);

if(!uvm_config_db #(virtual spi_interface)::get(this, “”, “spi_interface”, spi_intf))
`uvm_fatal(“CONFIG FATAL”,“CAN’T GET THE SPI INTERFACE”)

if(!uvm_config_db #(spi_config)::get(this, “”, “spi_cfg”, spi_cfg))
`uvm_fatal(“CONFIG FATAL”,“CAN’T GET THE SPI CONFIG”)

endfunction : build_phase // }

task spi_bfm::run_phase(uvm_phase phase); // {

`uvm_info(“SPI_BFM”, $sformatf("Entering run_phase "),UVM_LOW);

forever
begin //{
spi_trans spi_seq_item;

seq_item_port.get_next_item(spi_seq_item);

if(spi_seq_item.pkt_type == WRITE || spi_seq_item.pkt_type == READ)
begin //{
`uvm_info(get_type_name(),$sformatf("------ ENTERED PACKET TYPE IS : %s ", spi_seq_item.pkt_type.name),UVM_LOW)
if(spi_seq_item != null)
begin //{
set_mode(spi_seq_item);
initialisation();
fork
collect_wr_rd_req(spi_seq_item);
join
end //}
end //}

 seq_item_port.item_done();

`uvm_info(get_type_name(),$sformatf("------ ENTERED ITEM DONE "),UVM_LOW)
end //}

endtask : run_phase // }

task spi_bfm::collect_wr_rd_req (spi_trans wr_rd_request); // {
@(posedge spi_intf.sample_clk)
spi_wr_rd_req = new wr_rd_request;
spi_wr_rd_data_q.push_back(spi_wr_rd_req);
drive(spi_wr_rd_req);
`uvm_info(get_type_name(),$sformatf("------ CHECK RECEIVE DATA : %h %h ",spi_intf.spi_rd_data,spi_wr_rd_req.read_data),UVM_LOW)
endtask : collect_wr_rd_req // }

task spi_bfm::set_mode(spi_trans mode_sel);
if(mode_sel.mode == 2 || mode_sel.mode == 3)
begin //{
spi_intf.clk_pol = 1’b1;
uvm_info(get_type_name(),$sformatf("------ ENTERED MODE SET : %d , clk_pol : %d ",mode_sel.mode,spi_intf.clk_pol),UVM_LOW) end //} else begin //{ spi_intf.clk_pol = 1'b0; uvm_info(get_type_name(),$sformatf("------ ENTERED MODE SET : %d , clk_pol : %d ",mode_sel.mode,spi_intf.clk_pol),UVM_LOW)
end //}
endtask : set_mode

task spi_bfm::initialisation();
spi_intf.ss = 1’b1;
spi_intf.mosi = 1’b0;

if(spi_intf.clk_pol == 0)
spi_intf.spi_clk <= 1’b0;
else
spi_intf.spi_clk <= 1’b1;

endtask : initialisation

task spi_bfm::drive(spi_trans spi_seq_item);
begin //{
int burst_cnt;

 @(posedge spi_intf.sample_clk)
 if(spi_wr_rd_data_q.size() > 0)
  begin //{
   data_to_mosi           =  spi_wr_rd_data_q.pop_front();

   spi_intf.mode          =  data_to_mosi.mode;
   spi_intf.clk_pol       =  data_to_mosi.clk_pol;
   spi_intf.clk_phase     =  data_to_mosi.clk_phase;
   spi_intf.bit_order     =  data_to_mosi.bit_order;
   spi_intf.pkt_type      =  data_to_mosi.pkt_type;

   addr                   =  data_to_mosi.address; 

   spi_intf.ss           <=  1'b0;
  #(spi_cfg.t_ss_h2l - (spi_cfg.t_clk/2));
   send_addr(addr);

   if(data_to_mosi.pkt_type == WRITE)
     begin //{ 

`uvm_info(get_type_name(),$sformatf("------ ENTERED WRITE : %d ",data_to_mosi.pkt_type),UVM_LOW)
send_data(data_to_mosi.write_data);
#(spi_cfg.t_ss_l2h);
spi_intf.ss <= 1’b1;
#(spi_cfg.t_ss_high);
end //}

   if(data_to_mosi.pkt_type == READ)
     begin //{ 
     //  spi_intf.mosi <= 0;

uvm_info(get_type_name(),$sformatf("------ ENTERED READ : %d ",data_to_mosi.pkt_type),UVM_LOW) receive_data(data_to_mosi); uvm_info(get_type_name(),$sformatf(“------ CHECK RECEIVE DATA : %h %h , %h”,spi_intf.spi_rd_data,spi_seq_item.read_data,data_to_mosi.read_data),UVM_LOW)
#(spi_cfg.t_ss_l2h);
spi_intf.ss <= 1’b1;
#(spi_cfg.t_ss_high);
end //}
end //}

end //}
endtask : drive

task spi_bfm::send_addr(input bit [SPI_ADDR_WIDTH-1 : 0] addr); uvm_info(get_type_name(),$sformatf("------ ENTERED SEND ADDR : %h ",addr),UVM_LOW)
spi_intf.addr_start = 1’b1;
cmd_assert = 1’b1;

for(int i=0; i<(`SPI_ADDR_WIDTH/8); i=i+1) 
 begin //{
  repeat(8)
   begin //{
     if(spi_intf.clk_phase == 0)
       begin //{
           if(spi_intf.bit_order == 0)
            begin //{
             spi_intf.mosi <= addr[`SPI_ADDR_WIDTH-1];
             spi_intf.spi_addr <= addr[`SPI_ADDR_WIDTH-1];
  `uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 0 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
            end //}
           else
            begin //{
             spi_intf.mosi <= addr[0];
             spi_intf.spi_addr <= addr[0];
  `uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 0 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
            end //}
       end //} 

     if(spi_intf.clk_phase == 1)
       begin //{
           if(spi_intf.bit_order == 0)
            begin //{
             spi_intf.mosi <= addr[`SPI_ADDR_WIDTH-1];
             spi_intf.spi_addr <= addr[`SPI_ADDR_WIDTH-1];
`uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 1 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
            end //}
           else
            begin //{
             spi_intf.mosi <= addr[0];
             spi_intf.spi_addr <= addr[0];
`uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 1 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
            end //}
       end //}

       if(spi_intf.bit_order == 0)
        begin //{
         addr <<= 1;
        end //}
       else
        begin //{
         if(cmd_assert == 0)
          addr >>= 1;
        end //}
   end //}
 end //}

endtask : send_addr

task spi_bfm::send_data(input bit [SPI_DATA_WIDTH-1 : 0] data_payload); uvm_info(get_type_name(),$sformatf("------ ENTERED SEND DATA : %h “,data_payload),UVM_LOW)
for(int i=0; i<(SPI_DATA_WIDTH/8); i=i+1) begin //{ repeat(8) begin //{ if(spi_intf.clk_phase == 0) begin //{ if(spi_intf.bit_order == 0) begin //{ spi_intf.mosi <= data_payload[SPI_DATA_WIDTH-1];
uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 0 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW) end //} else begin //{ spi_intf.mosi <= data_payload[0]; uvm_info(get_type_name(),$sformatf(”------ ENTERED SEND TO MOSI PHASE 0 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
end //}
end //}

      if(spi_intf.clk_phase == 1)
        begin //{
         if(spi_intf.bit_order == 0)
          begin //{
           spi_intf.mosi <= data_payload[`SPI_DATA_WIDTH-1];
 `uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 1 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
          end //}
         else
          begin //{
           spi_intf.mosi <= data_payload[0];
 `uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MOSI PHASE 1 spi_intf.mosi : %d ", spi_intf.mosi),UVM_LOW)
          end //}
        end //}

        if(spi_intf.bit_order == 0)
          data_payload <<= 1;
        else
          data_payload >>= 1;

    end //}
  end //}

endtask : send_data

task spi_bfm::receive_data(spi_trans spi_seq_item);

uvm_info(get_type_name(),$sformatf("------ ENTERED RECEIVE DATA "),UVM_LOW) for(int i=0; i<(SPI_DATA_WIDTH/8); i=i+1)
begin //{
repeat(8)
begin //{
if(spi_intf.clk_phase == 0)
begin //{
if(spi_intf.bit_order == 0)
begin //{
spi_intf.spi_rd_data[0] <= spi_intf.miso;
spi_intf.temp_miso <= spi_intf.miso;
uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MISO PHASE 0 spi_intf.miso : %d ", spi_intf.miso),UVM_LOW) end //} else begin //{ spi_intf.spi_rd_data[31] <= spi_intf.miso; spi_intf.temp_miso <= spi_intf.miso; uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MISO PHASE 0 spi_intf.miso : %d ", spi_intf.miso),UVM_LOW)
end //}

         if(spi_intf.bit_order == 0)
           spi_intf.spi_rd_data <<= 1;
         else
           spi_intf.spi_rd_data >>= 1;

        end //} 
  
      if(spi_intf.clk_phase == 1)
        begin //{
         if(spi_intf.bit_order == 0)
          spi_intf.spi_rd_data <<= 1;
         else
          spi_intf.spi_rd_data >>= 1;

         if(spi_intf.bit_order == 0)
          begin //{
             spi_intf.spi_rd_data[0]   =  spi_intf.miso; 
             spi_intf.temp_miso   =  spi_intf.miso; 
`uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MISO PHASE 1 spi_intf.miso : %d ", spi_intf.miso),UVM_LOW)
          end //}
         else
          begin //{
             spi_intf.spi_rd_data[31]  =  spi_intf.miso; 
             spi_intf.temp_miso   =  spi_intf.miso; 
 `uvm_info(get_type_name(),$sformatf("------ ENTERED SEND TO MISO PHASE 1 spi_intf.miso : %d ", spi_intf.miso),UVM_LOW)
          end //}
        end //}
    end //}
 end //}
 spi_seq_item.read_data = spi_intf.spi_rd_data;
`uvm_info(get_type_name(),$sformatf("------ ENTERED RECEIVE DATA : %h  %h",spi_intf.spi_rd_data,spi_seq_item.read_data),UVM_LOW)

endtask : receive_data