Sunday, October 30, 2016

UVM APB Driver Example.

// APB Bus Interface
interface apb_interface;
 
   logic clk;
   logic rstn;
   logic [31:0] Addr;
   logic [31:0] Write_Data;
   logic RNW;
   logic Valid;
   logic Ready;
   logic [31:0] Read_Data;
   logic Error;
 
endinterface: apb_interface

// APB Bus Sequence Item Class
class apb_seq_item extends uvm_sequence_item;
   `uvm_object_utils(apb_seq_item)
 
   // Request fields
   rand logic [31:0] addr;
   rand logic [31:0] write_data;
   rand bit read_not_write;
   rand int delay;
 
   // Response fields
   bit error;
   logic [31:0] read_data;
 
endclass: apb_seq_item

// APB Bus Driver Class
class apb_bus_driver extends uvm_driver #(apb_seq_item);
   `uvm_component_utils(apb_bus_driver)
 
   apb_seq_item req;
 
   virtual apb_interface apb_if;
 
   function new (string name, uvm_component parent);
      super.new(name, parent);
      endfunction: new
 
   task run_phase (uvm_phase phase);
 
      apb_if.Valid <= 0;
      apb_if.RNW <= 0;
 
      // Out of Reset
      @(posedge apb_if.rstn);
      // Pin Level Transfer
      forever begin
         seq_item_port.get_next_item(req);
         repeat(req.delay) begin
            @(posedge apb_if.clk);
         end
         apb_if.Valid <= 1;
         apb_if.Addr <= req.addr;
         apb_if.RNW <= req.read_not_write;
         if (req.read_not_write == 0) begin
            apb_if.Write_Data <= req.write_data;
         end
         while(apb_if.Ready != 1) begin
            @(posedge apb_if.clk);
         end
         // At the end of pin level bus transaction
         // Copy response data into the req related fields
         if (req.read_not_write == 1) begin
            req.read_data <= apb_if.Read_Data;
         end
         req.error <= apb_if.Error;
         apb_if.Valid <= 0;
         seq_item_port.item_done();
      end
   endtask: run_phase
endclass: apb_bus_driver

// APB Bus Sequence
class apb_bus_seq extends uvm_sequence #(apb_seq_item)
   `uvm_object_utils(apb_bus_seq)
 
   function new(string name);
      super.new(name);
   endfunction: new
 
   // No. of iterations
   rand int iti = 30
 
   apb_seq_item req;
 
   task body();
      req = apb_seq_item::type_id::create("req", this);
      repeat(iti) begin
         start_item(req);
         assert (!req.randomize() 
            with {addr inside {[32`h1000_0000:32`h1000_001C]};}) 
         begin
            `uvm_error("Body", "Randomization Error");
         end 
         finish_item(req);
         `uvm_info ("Response Fields", 
            $sformatf("Read Data = %h", req.read_data), UVM_LOW)
      end
   endtask: body
 
endclass: apb_bus_seq

No comments:

Post a Comment