⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apb_slave.sv

📁 VMM 文档加源码, synopsys公司很好的验证资料
💻 SV
字号:
// // -------------------------------------------------------------//    Copyright 2004-2008 Synopsys, Inc.//    All Rights Reserved Worldwide// //    Licensed under the Apache License, Version 2.0 (the//    "License"); you may not use this file except in//    compliance with the License.  You may obtain a copy of//    the License at// //        http://www.apache.org/licenses/LICENSE-2.0// //    Unless required by applicable law or agreed to in//    writing, software distributed under the License is//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR//    CONDITIONS OF ANY KIND, either express or implied.  See//    the License for the specific language governing//    permissions and limitations under the License.// -------------------------------------------------------------// `ifndef APB_SLAVE__SV`define APB_SLAVE__SV`include "apb_if.sv"`include "apb_rw.sv"class apb_slave_cfg;   rand bit [31:0] start_addr = 32'h0000_0000;   rand bit [31:0] end_addr   = 32'hFFFF_FFFF;   constraint apb_slave_cfg_valid {                                   end_addr >= start_addr;   }   virtual function string psdisplay(string prefix = "");      $sformat(psdisplay, "%sAPB Slave Config: ['h%h-'h%h]",               prefix, this.start_addr, this.end_addr);   endfunction: psdisplayendclass: apb_slave_cfgtypedef class apb_slave;class apb_slave_cbs extends vmm_xactor_callbacks;   virtual function void pre_response(apb_slave xact,                                      apb_rw    cycle);   endfunction: pre_response   virtual function void post_response(apb_slave xactor,                                       apb_rw    cycle);   endfunction: post_response     endclass: apb_slave_cbsclass apb_slave extends vmm_xactor;   virtual apb_if.slave sigs;   local apb_slave_cfg cfg;   apb_rw_channel resp_chan;   typedef enum {RESPONSE} notifications_e;   apb_rw tr_factory;   local bit [31:0] ram[*];   function new(string               name,                int unsigned         stream_id,                virtual apb_if.slave sigs,                apb_slave_cfg        cfg = null,                apb_rw_channel       resp_chan = null,                apb_rw               tr_factory = null);      super.new("APB Slave", name, stream_id);      this.sigs = sigs;      if (cfg == null) cfg = new;      this.cfg = cfg;      this.resp_chan = resp_chan;      if (tr_factory == null) tr_factory = new;      this.tr_factory = tr_factory;      this.notify.configure(RESPONSE);   endfunction: new   virtual function void reconfigure(apb_slave_cfg cfg);      this.cfg = cfg;   endfunction: reconfigure   virtual function void poke(bit [31:0] addr,                              bit [31:0] data);      if (addr < this.cfg.start_addr ||          addr > this.cfg.end_addr) begin         `vmm_error(this.log, "Out-of-range poke");         return;      end      this.ram[addr] = data;endfunction: poke   virtual function bit [31:0] peek(bit [31:0] addr);      if (addr < this.cfg.start_addr ||          addr > this.cfg.end_addr) begin         `vmm_error(this.log, "Out-of-range peek");         return 'x;      end      return (this.ram.exists(addr)) ? this.ram[addr] : 'x;endfunction: peek   virtual function void reset_xactor(reset_e rst_typ = SOFT_RST);      super.reset_xactor(rst_typ);      this.resp_chan.flush();      this.sigs.sck.prdata <= 'z;   endfunction: reset_xactor   virtual protected task main();      super.main();      forever begin         apb_rw tr;         this.sigs.sck.prdata <= 'z;         this.wait_if_stopped();         `vmm_trace(log, "Waiting for start of transaction...");         // Wait for a SETUP cycle         do @ (this.sigs.sck);         while (this.sigs.sck.psel !== 1'b1 ||                this.sigs.sck.penable !== 1'b0 ||                this.sigs.sck.paddr < this.cfg.start_addr ||                this.sigs.sck.paddr > this.cfg.end_addr);         $cast(tr, this.tr_factory.allocate());         tr.notify.indicate(vmm_data::STARTED);         tr.kind = (this.sigs.sck.pwrite) ?                      apb_rw::WRITE : apb_rw::READ;         tr.addr = this.sigs.sck.paddr;         `vmm_trace(log, {"Responding to transaction...\n",                          tr.psdisplay("   ")});         if (tr.kind == apb_rw::READ) begin            if (this.resp_chan == null) begin               if (!this.ram.exists(tr.addr)) tr.data = 'x;               else tr.data = this.ram[tr.addr];            end            else begin               bit abort = 0;               fork                  begin                     fork                       begin                          @ (this.sigs.sck);                          `vmm_error(this.log, "No response in time");                          abort = 1;                       end                       this.resp_chan.put(tr);                     join_any                     disable fork;                  end               join               if (abort) continue;            end            `vmm_callback(apb_slave_cbs, pre_response(this, tr));            this.sigs.sck.prdata <= tr.data;            @ (this.sigs.sck);         end         else begin            @ (this.sigs.sck);            tr.data = this.sigs.sck.pwdata;            `vmm_callback(apb_slave_cbs, pre_response(this, tr));            if (this.resp_chan == null)               this.ram[tr.addr] = tr.data;            else this.resp_chan.sneak(tr);         end         if (this.sigs.sck.penable !== 1'b1) begin            `vmm_error(this.log, "APB protocol violation: SETUP cycle not followed by ENABLE cycle");         end         tr.notify.indicate(vmm_data::ENDED);         `vmm_callback(apb_slave_cbs, post_response(this, tr));         `vmm_trace(log, {"Responded to transaction...\n",                          tr.psdisplay("   ")});         this.notify.indicate(RESPONSE, tr);      end   endtask: mainendclass: apb_slave`endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -