IC验证学习笔记(AHB-RAM)04 Sequence架构的建立

-------------------------------------建立vip的sequence_lib

base_sequence:

`ifndef LVC_AHB_BASE_SEQUENCE_SV
`define LVC_AHB_BASE_SEQUENCE_SV

class lvc_ahb_base_sequence extends uvm_sequence #(lvc_ahb_transaction);

  `uvm_object_utils(lvc_ahb_base_sequence)    
  function new(string name=""); 
    super.new(name);
  endfunction : new

endclass : lvc_ahb_base_sequence 


`endif

master_single_trans:添加body()发送req 接收rsp

`ifndef LVC_AHB_MASTER_SINGLE_TRANS_SV
`define LVC_AHB_MASTER_SINGLE_TRANS_SV

class lvc_ahb_master_single_trans extends lvc_ahb_base_sequence;
  rand bit [`LVC_AHB_MAX_ADDR_WIDTH-1:0]      addr;//地址和数据
  rand bit [`LVC_AHB_MAX_DATA_WIDTH-1:0]      data;
  rand xact_type_enum  xact;//Read还是Write
  rand burst_size_enum bsize;

  constraint single_trans_cstr {
    xact inside {READ, WRITE};
  }

  `uvm_object_utils(lvc_ahb_master_single_trans)    

  function new(string name=""); 
    super.new(name);
  endfunction : new

  virtual task body();
    `uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)
	  `uvm_do_with(req, {//发送数据
                       addr == local::addr;
                       data.size() == 1;
                       data[0] == local::data;
                       burst_size == bsize;
                       burst_type == SINGLE;
                       xact_type == xact;
                      })
    get_response(rsp);//req rsp预定义了 是lvc_ahb_transaction类型
    if(xact == READ) 
      data = rsp.data[0];//如果是read就从rsp的data[0]拿出数据
    `uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)
  endtask: body

endclass : lvc_ahb_master_single_trans 


`endif

都放入sequence_lib:然后更新ahb_pkg

`ifndef LVC_AHB_SEQUENCE_LIB_SVH
`define LVC_AHB_SEQUENCE_LIB_SVH

`include "lvc_ahb_base_sequence.sv"
`include "lvc_ahb_master_single_trans.sv"


`endif 

---------------------------------------在顶层seq_lib下建立elem_seqs文件夹(搭建激励的架子)

        rkv_ahbram_single_write_seq里面将底层vip的master_single_trans例化其中,通过·uvm_do_on_with通过Virtual seqr(p_sequencer)挂载到vip的master_sqr上!

rkv_ahbram_single_write_seq:

`ifndef RKV_AHBRAM_SINGLE_WRITE_SEQ_SV
`define RKV_AHBRAM_SINGLE_WRITE_SEQ_SV

class rkv_ahbram_single_write_seq extends rkv_ahbram_base_element_sequence;
  rand bit [31:0]      addr;
  rand bit [31:0]      data;
  rand burst_size_enum bsize;
  constraint single_write_cstr {
    soft addr[1:0] == 0;
    soft bsize == BURST_SIZE_32BIT;
  }
  `uvm_object_utils(rkv_ahbram_single_write_seq)
  function new (string name = "rkv_ahbram_single_write_seq");
    super.new(name);
  endfunction
  virtual task body();
    lvc_ahb_master_single_trans ahb_single;
    `uvm_info("body", "Entered...", UVM_LOW)
    `uvm_do_on_with(ahb_single, p_sequencer.ahb_mst_sqr, //p_sequencer已经在base_element_sequence中声明
                    {addr == local::addr; data == local::data; xact == WRITE; bsize == local::bsize;}
                   )
    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

endclass

`endif // RKV_AHBRAM_SINGLE_WRITE_SEQ_SV

rkv_ahbram_single_read_seq:取消body中给入data、加了一个从lvc_ahb_master_single_trans拿出rsp中data的操作

`ifndef RKV_AHBRAM_SINGLE_READ_SEQ_SV
`define RKV_AHBRAM_SINGLE_READ_SEQ_SV

class rkv_ahbram_single_read_seq extends rkv_ahbram_base_element_sequence;
  rand bit [31:0]      addr;
  rand bit [31:0]      data;
  rand burst_size_enum bsize;
  constraint single_read_cstr {
    soft addr[1:0] == 0;
    soft bsize == BURST_SIZE_32BIT;
  }
  `uvm_object_utils(rkv_ahbram_single_read_seq)
  function new (string name = "rkv_ahbram_single_read_seq");
    super.new(name);
  endfunction
  virtual task body();
    lvc_ahb_master_single_trans ahb_single;
    `uvm_info("body", "Entered...", UVM_LOW)
    `uvm_do_on_with(ahb_single, p_sequencer.ahb_mst_sqr, 
                    {addr == local::addr; xact == READ; bsize == local::bsize;}
                   )
    data = ahb_single.data;//从例化的ahb_single里把data拿出来,在其中 data = rsp.data[0]
    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

endclass

`endif // RKV_AHBRAM_SINGLE_read_SEQ_SV

在virtual seq中声明刚才建立的seq:

  // element sequence declartion
  rkv_ahbram_single_write_seq single_write;
  rkv_ahbram_single_read_seq single_read;

然后再smoke_virt_seq里就可以使用:在其中设定了随机数addr和data的限定,和single_write、single_read的操作以及最后的compare_data(wr_val, rd_val)比对;

`ifndef RKV_AHBRAM_SMOKE_VIRT_SEQ_SV
`define RKV_AHBRAM_SMOKE_VIRT_SEQ_SV


class rkv_ahbram_smoke_virt_seq extends rkv_ahbram_base_virtual_sequence;
  `uvm_object_utils(rkv_ahbram_smoke_virt_seq)

  function new (string name = "rkv_ahbram_smoke_virt_seq");
    super.new(name);
  endfunction

  virtual task body();
    bit [31:0] addr, data;
    super.body();
    `uvm_info("body", "Entered...", UVM_LOW)
    for(int i=0; i<10; i++) begin
      std::randomize(addr) with {addr[1:0] == 0; addr inside {['h1000:'h1FFF]};};
      std::randomize(wr_val) with {wr_val == (i << 4) + i;};
      data = wr_val;
      `uvm_do_with(single_write, {addr == local::addr; data == local::data;})
      //`uvm_do_with(single_write, {addr == local::addr; data == 'hff;})
      `uvm_do_with(single_read, {addr == local::addr; })
      rd_val = single_read.data;
      compare_data(wr_val, rd_val);
    end

    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

endclass


`endif 

仿真后发现问题应该在rst结束后再发送激励:在顶层rkv_ahbram_virtual_sequence中添加

    wait_ready_for_stim();
    task wait_cycles(int n = 1);
    repeat(n) @(posedge vif.clk);
  endtask

    task wait_ready_for_stim();
    wait_reset_signal_released();
    wait_cycles(10);
  endtask

debug优化了底层ahb_master_driver:发送数据的同时给定下一个状态(否则多占一拍):

 virtual task do_init_read(REQ t);
    wait_for_bus_grant();
    @(vif.cb_mst);
    vif.cb_mst.htrans <= NSEQ;
    vif.cb_mst.haddr  <= t.addr;
    vif.cb_mst.hburst <= t.burst_type;
    vif.cb_mst.hsize  <= t.burst_size;
    vif.cb_mst.hwrite <= 1'b0;
    @(vif.cb_mst);
    if(t.burst_type == SINGLE) begin
      _do_drive_idle();
    end
    // check ready with delay in current cycle
    forever begin
      @(negedge vif.hclk);
      if(vif.hready === 1'b1) begin
        break;
      end
      else
        @(vif.cb_mst);
    end
    t.data = new[t.current_data_beat_num+1](t.data);
    t.data[0] = vif.hrdata;
    
    // update current trans status
    t.trans_type = NSEQ;
    t.current_data_beat_num = 0; // start beat from 0 to make consistence with data array index
    t.all_beat_response[t.current_data_beat_num] = response_type_enum'(vif.hresp);
  endtask

最后发现在clone操作时由于transaction没有进行域的自动化导致克隆失败:

ahb_transaction:

`uvm_object_utils_begin(lvc_ahb_transaction)
    `uvm_field_array_int(data, UVM_ALL_ON)
    `uvm_field_int(addr, UVM_ALL_ON)
    `uvm_field_enum(burst_size_enum, burst_size, UVM_ALL_ON)
    `uvm_field_enum(burst_type_enum, burst_type, UVM_ALL_ON)
    `uvm_field_enum(xact_type_enum, xact_type, UVM_ALL_ON)
    `uvm_field_enum(response_type_enum, response_type, UVM_ALL_ON)
    `uvm_field_enum(trans_type_enum, trans_type, UVM_ALL_ON)
    `uvm_field_array_enum(response_type_enum, all_beat_response, UVM_ALL_ON)
    `uvm_field_int(current_data_beat_num, UVM_ALL_ON)
    `uvm_field_enum(status_enum, status, UVM_ALL_ON)
  `uvm_object_utils_end

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值