在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2251|回复: 4

[求助] 求一个apb_montior代码学习

[复制链接]
发表于 2017-12-6 15:00:31 | 显示全部楼层 |阅读模式
50资产
运用UVM方法学,sv语言

最佳答案

查看完整内容

写得一般,但是能用: bit [31:0] mem[*]; bit [31:0] apb_base_addr; bit [31:0] apb_seg_size; `uvm_component_utils_begin(apb_bfm) `uvm_component_utils_end ////////////////////////////////////////////////////////////////////// /// Creates new ntb_gsyncPxl_monitor object. function new(string name = "apb_bfm", uvm_component parent); super.new(name, paren ...
发表于 2017-12-6 15:00:32 | 显示全部楼层
写得一般,但是能用:

    bit [31:0]  mem[*];
    bit [31:0]  apb_base_addr;
    bit [31:0]  apb_seg_size;

    `uvm_component_utils_begin(apb_bfm)
    `uvm_component_utils_end

     //////////////////////////////////////////////////////////////////////
     /// Creates new ntb_gsyncPxl_monitor object.
     function new(string name = "apb_bfm", uvm_component parent);
         super.new(name, parent);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM build phase.
     virtual function void build_phase(uvm_phase phase);
         super.build_phase(phase);
         if (!uvm_config_int::get(this,"","apb_base_addr", apb_base_addr)) begin
             `uvm_fatal("ERROR", "APB base address should be assigned to apb_bfm")
         end
         if (!uvm_config_int::get(this,"","apb_seg_size", apb_seg_size)) begin
             `uvm_fatal("ERROR", "APB segment size should be assigned to apb_bfm")
         end
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM connect phase.
     virtual function void connect_phase(uvm_phase phase);
         super.connect_phase(phase);
         // Hook up the virtual interface here
         if (!uvm_config_db#(virtual nitro_apb_slave_if)::get(this, "", "apb_slv_if", apb_slv_if)) begin
             `uvm_fatal("HDCP/KEY/RAM/IF", "No virtual interface specified for this monitor instance")
         end
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM end of elaboration phase.
     function void end_of_elaboration_phase(uvm_phase phase);
        super.end_of_elaboration_phase(phase);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM start of simulation phase.
     function void start_of_simulation_phase(uvm_phase phase);
         super.start_of_simulation_phase(phase);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM reset phase.
     task reset_phase(uvm_phase phase);
         super.reset_phase(phase);
     endtask

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM configure phase.
     task configure_phase(uvm_phase phase);
         super.configure_phase(phase);
     endtask

     task apb_op_with_random_ready();
         bit [7:0] ready_on;
         bit [7:0] ready_off;

         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 apb_slv_if.prdata <= 'h0;
                 apb_slv_if.pready <= 1'b0;
                 continue;
             end
             else begin
                 std::randomize(ready_on, ready_off) with {ready_on dist {1 :/ 1, [2:16] :/ 1}; ready_off dist {1 :/ 1, [2:128] :/ 3, [128:256] :/ 1};};
                 apb_slv_if.pready <= 1'b1;
                 repeat(ready_on) @(apb_slv_if.sck);
                 apb_slv_if.pready <= 1'b0;
                 repeat(ready_off) @(apb_slv_if.sck);
             end
         end
     endtask

     task apb_access_op();
         bit [20:0] apb_addr;
         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 continue;
             end
             else begin
                 if(apb_slv_if.psel == 1'b1 && apb_slv_if.penable == 1'b1) begin
                     apb_addr = apb_slv_if.paddr[13:0];
                     if(apb_slv_if.pwrite == 1'b1) begin
                         // get pwdata
                         mem[apb_addr] = apb_slv_if.pwdata;
                         `uvm_info(get_name, $psprintf("Ext_APB Write %h to Addr %h", apb_slv_if.pwdata, apb_addr), UVM_INFO)
                     end
                     else begin
                         // send prdata
                         `uvm_info(get_name, $psprintf("Ext_APB Read %h, and return %h", apb_addr, mem[apb_addr]), UVM_INFO)
                         if(mem.exists(apb_addr)) begin
                             apb_slv_if.prdata <= mem[apb_addr];
                         end
                         else begin
                             apb_slv_if.prdata <= 'h0;
                         end
                     end
                 end
             end
         end
     endtask

     task apb_sel_check();
         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 continue;
             end
             else begin
                 if(!(apb_slv_if.paddr >= apb_base_addr && apb_slv_if.paddr < apb_base_addr + apb_seg_size)) begin
                     if(apb_slv_if.psel == 1) begin
                         `uvm_error("ERROR", $psprintf("psel should not be set 1"));
                     end
                 end
             end
         end
     endtask

     task apb_op_with_ready();
         bit [20:0] apb_addr;

         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 apb_slv_if.prdata <= 'h0;
                 apb_slv_if.pready <= 1'b0;
                 continue;
             end
             else begin
                 apb_slv_if.pready <= 1'b1;
             end
         end
     endtask

     //////////////////////////////////////////////////////////////////////
     /// Automatically runs during the UVM run phase.
     task run_phase(uvm_phase phase);
         int apb_ready_random;
         super.run_phase(phase);

         if($value$plusargs("apb_ready_random=%d", apb_ready_random)) begin
             if(apb_ready_random == 1) begin
                 fork
                     apb_op_with_random_ready();
                 join_none
             end
             else begin
                 fork
                     apb_op_with_ready();
                 join_none
             end
         end
         else begin
              fork
                  apb_op_with_ready();
              join_none
         end

         fork
             apb_access_op();
             apb_sel_check();
         join_none
     endtask
发表于 2018-3-24 22:21:22 | 显示全部楼层
写得一般,但是能用。

    bit [31:0]  mem[*];
    bit [31:0]  apb_base_addr;
    bit [31:0]  apb_seg_size;

    `uvm_component_utils_begin(apb_bfm)
    `uvm_component_utils_end

     //////////////////////////////////////////////////////////////////////
     /// Creates new ntb_gsyncPxl_monitor object.
     function new(string name = "apb_bfm", uvm_component parent);
         super.new(name, parent);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM build phase.
     virtual function void build_phase(uvm_phase phase);
         super.build_phase(phase);
         if (!uvm_config_int::get(this,"","apb_base_addr", apb_base_addr)) begin
             `uvm_fatal("ERROR", "APB base address should be assigned to apb_bfm")
         end
         if (!uvm_config_int::get(this,"","apb_seg_size", apb_seg_size)) begin
             `uvm_fatal("ERROR", "APB segment size should be assigned to apb_bfm")
         end
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM connect phase.
     virtual function void connect_phase(uvm_phase phase);
         super.connect_phase(phase);
         // Hook up the virtual interface here
         if (!uvm_config_db#(virtual nitro_apb_slave_if)::get(this, "", "apb_slv_if", apb_slv_if)) begin
             `uvm_fatal("HDCP/KEY/RAM/IF", "No virtual interface specified for this monitor instance")
         end
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM end of elaboration phase.
     function void end_of_elaboration_phase(uvm_phase phase);
        super.end_of_elaboration_phase(phase);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM start of simulation phase.
     function void start_of_simulation_phase(uvm_phase phase);
         super.start_of_simulation_phase(phase);
     endfunction

     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM reset phase.
     task reset_phase(uvm_phase phase);
         super.reset_phase(phase);
     endtask
     
     //////////////////////////////////////////////////////////////////////
     /// Called automatically during UVM configure phase.
     task configure_phase(uvm_phase phase);
         super.configure_phase(phase);
     endtask

     task apb_op_with_random_ready();
         bit [7:0] ready_on;
         bit [7:0] ready_off;

         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 apb_slv_if.prdata <= 'h0;
                 apb_slv_if.pready <= 1'b0;
                 continue;
             end
             else begin
                 std::randomize(ready_on, ready_off) with {ready_on dist {1 :/ 1, [2:16] :/ 1}; ready_off dist {1 :/ 1, [2:128] :/ 3, [128:256] :/ 1};};
                 apb_slv_if.pready <= 1'b1;
                 repeat(ready_on) @(apb_slv_if.sck);
                 apb_slv_if.pready <= 1'b0;
                 repeat(ready_off) @(apb_slv_if.sck);
             end
         end
     endtask

     task apb_access_op();
         bit [20:0] apb_addr;
         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 continue;
             end
             else begin
                 if(apb_slv_if.psel == 1'b1 && apb_slv_if.penable == 1'b1) begin
                     apb_addr = apb_slv_if.paddr[13:0];
                     if(apb_slv_if.pwrite == 1'b1) begin
                         // get pwdata
                         mem[apb_addr] = apb_slv_if.pwdata;
                         `uvm_info(get_name, $psprintf("Ext_APB Write %h to Addr %h", apb_slv_if.pwdata, apb_addr), UVM_INFO)
                     end
                     else begin
                         // send prdata
                         `uvm_info(get_name, $psprintf("Ext_APB Read %h, and return %h", apb_addr, mem[apb_addr]), UVM_INFO)
                         if(mem.exists(apb_addr)) begin
                             apb_slv_if.prdata <= mem[apb_addr];
                         end
                         else begin
                             apb_slv_if.prdata <= 'h0;
                         end
                     end
                 end
             end
         end
     endtask

     task apb_sel_check();
         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 continue;
             end
             else begin
                 if(!(apb_slv_if.paddr >= apb_base_addr && apb_slv_if.paddr < apb_base_addr + apb_seg_size)) begin
                     if(apb_slv_if.psel == 1) begin
                         `uvm_error("ERROR", $psprintf("psel should not be set 1"));
                     end
                 end
             end
         end
     endtask

     task apb_op_with_ready();
         bit [20:0] apb_addr;

         forever begin
             @(apb_slv_if.sck);
             if(apb_slv_if.presetn !== 1) begin
                 apb_slv_if.prdata <= 'h0;
                 apb_slv_if.pready <= 1'b0;
                 continue;
             end
             else begin
                 apb_slv_if.pready <= 1'b1;
             end
         end
     endtask

     //////////////////////////////////////////////////////////////////////
     /// Automatically runs during the UVM run phase.
     task run_phase(uvm_phase phase);
         int apb_ready_random;
         super.run_phase(phase);

         if($value$plusargs("apb_ready_random=%d", apb_ready_random)) begin
             if(apb_ready_random == 1) begin
                 fork
                     apb_op_with_random_ready();
                 join_none
             end
             else begin
                 fork
                     apb_op_with_ready();
                 join_none
             end
         end
         else begin
              fork
                  apb_op_with_ready();
              join_none
         end

         fork
             apb_access_op();
             apb_sel_check();
         join_none
     endtask
发表于 2018-4-4 17:47:10 | 显示全部楼层
写的一般,但是能用
class apb_mon extends uvm_monitor;
31    protected virtual apb_if vif;
32    protected int id;
33

34    uvm_analysis_port #(apb_txn) item_collected_port;
35

36    protected apb_txn txn;
37

38    `uvm_component_utils_begin(apb_mon)
39       `uvm_field_int(id, UVM_DEFAULT)
40    `uvm_component_utils_end
41

42    function new (string name, uvm_component parent);
43       super.new(name, parent);
44       txn = new();
45       item_collected_port = new("item_collected_port", this);
46    endfunction // new
47

48    function void build_phase (uvm_phase phase);
49       super.build_phase(phase);
50       if(!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif))
51         `uvm_fatal("NOVIF",
52                    {"virtual interface must be set for: ",
53                     get_full_name(), ".vif"});
54    endfunction // build_phase
55

56    virtual task run_phase (uvm_phase phase);
57       fork
58          collect_transactions();
59       join
60    endtask // run_phase
61

62    virtual protected task collect_transactions();
63       forever begin
64          txn = new();
65          if (vif.presetn == 'b0) begin
66            @(posedge vif.presetn);
67          end
68          if (vif.psel == 'b1) begin
69             @(posedge vif.pclk);
70             if (vif.penable == 'b1) begin
71                if (vif.pwrite == 'b0) begin
72                   txn.kind = apb_txn::READ;
73                   txn.data = vif.prdata;
74                   txn.addr = vif.paddr;
75                end
76                else begin
77                   txn.kind = apb_txn::WRITE;
78                   txn.data = vif.pwdata;
79                   txn.addr = vif.paddr;
80                end
81                `uvm_info("MON", txn.convert2string(), UVM_LOW)
82                item_collected_port.write(txn);
83                @(posedge vif.pclk);
84             end // if (vif.penable == 'b1)
85             else begin
86                `uvm_warning("MON",  
87                             "APB failed to assert penable after psel cycle")
88             end // else: !if(vif.penable == 'b1)
89          end // if (vif.psel == 'b1)
90          else begin
91             @(posedge vif.pclk);
92          end // else: !if(vif.psel == 'b1)
93       end // forever begin
94    endtask // collect_transactions
95
发表于 2018-4-6 22:39:16 | 显示全部楼层
通不能发个比较全的apb vip,还有是否支持所有协议场景?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-23 17:58 , Processed in 0.018564 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表