AHB-to-APB Bridge——06testbench、env、base_test、scb

news2024/11/24 10:05:17

框架:

testbench:

HCLK_PCLK_RATIO:随机定义hclk pclk比率;各个接口clk、rst连接;生成满足相应比率的pclk;与DUT的连接;将vif set到agt中去;agt在set到底层 

关于rest_if:直接在tb中写rest task,uvm侧是识别不到的,因为uvm用pkg包裹了起来。所以定义了rest_if在其中设置task,再通过config_db到uvm环境中;

`include "uvm_macros.svh"
//import uvm_pkg::*;
import ahbl_mst_pkg::*;
import apb_slv_pkg::*;

module ahb2apb_tb();

parameter HCLK_PERIOD = 100ns;//10MHz 定义周期
bit[1:0] tmp_var;
int HCLK_PCLK_RATIO;//随机定义hclk pclk比值
initial begin
  tmp_var = $urandom_range(0,3);
  case(tmp_var)
    0:HCLK_PCLK_RATIO = 1;
    1:HCLK_PCLK_RATIO = 2;
    2:HCLK_PCLK_RATIO = 4;
    3:HCLK_PCLK_RATIO = 8;
  endcase
end

reg       hclk;
wire      hresetn;

wire      pclk;
wire      presetn;
reg [3:0] hclk_cnt;
reg       pclken;
wire      apbactive;

ahbl_if   ahbl_if_i(hclk,hresetn);//接口的clk、rst连接
apb_if    apb_if_i(pclk,presetn);
reset_if  reset_if_i(hclk);

initial begin
  hclk = 1'b0;

  forever begin
    #(HCLK_PERIOD/2);//每过1/2周期翻转一次
    hclk = !hclk;
  end
end

assign hresetn = !reset_if_i.reset;

always @(posedge hclk or negedge hresetn)//实现满足相应比率的pclk
  if(!hresetn)
    hclk_cnt <= 4'd0;
  else if(hclk_cnt == (HCLK_PCLK_RATIO - 1'b1))
    hclk_cnt <= 4'd0;
  else
    hclk_cnt <= hclk_cnt + 1'd1;

always @(negedge hclk or negedge hresetn)
  if(!hresetn)
    pclken  <= 1'b0;
  else if(hclk_cnt == (HCLK_PCLK_RATIO - 1'b1))
    pclken  <= 1'b1;
  else
    pclken  <= 1'b0;

reg pclken_r;
always @(*)begin
  #1ns;
  pclken_r = pclken;
end

assign pclk    = pclken_r & hclk;//&操作 满足比率下只在hclk为高pclk才高
assign presetn = hresetn;

cmsdk_ahb_to_apb #(
    .ADDRWIDTH      (16),
    .REGISTER_RDATA (1),
    .REGISTER_WDATA (0)) dut(
    .HCLK           (hclk),
    .HRESETn        (hresetn),
    .PCLKEN         (pclken),

    .HSEL           (ahbl_if_i.hsel),
    .HADDR          (ahbl_if_i.haddr[15:0]),
    .HTRANS         (ahbl_if_i.htrans),
    .HSIZE          (ahbl_if_i.hsize),
    .HPROT          (ahbl_if_i.hprot),
    .HWRITE         (ahbl_if_i.hwrite),
    .HREADY         (ahbl_if_i.hready),
    .HWDATA         (ahbl_if_i.hwdata),

    .HREADYOUT      (ahbl_if_i.hready),
    .HRDATA         (ahbl_if_i.hrdata),
    .HRESP          (ahbl_if_i.hresp),

    .PADDR          (apb_if_i.paddr[15:0]),
    .PENABLE        (apb_if_i.penable),
    .PWRITE         (apb_if_i.pwrite),
    .PSTRB          (apb_if_i.pstrb),
    .PPROT          (apb_if_i.pprot),
    .PWDATA         (apb_if_i.pwdata),
    .PSEL           (apb_if_i.psel),
    .PRDATA         (apb_if_i.prdata),
    .PREADY         (apb_if_i.pready),
    .PSLVERR        (apb_if_i.pslverr),

    .APBACTIVE      (apbactive)
    );

  assign apb_if_i.paddr[31:16] = 16'd0;

  initial begin//vif set到agt中去
    uvm_config_db#(virtual apb_if)::set(null,"uvm_test_top.env_i.apb_slv_agt_i","vif",apb_if_i);
    uvm_config_db#(virtual ahbl_if)::set(null,"uvm_test_top.env_i.ahbl_mst_agt_i","vif",ahbl_if_i);
    uvm_config_db#(virtual reset_if)::set(null,"uvm_test_top","vif",reset_if_i);
    run_test();
  end 

env:

例化各个agt、scb并build;连接mon与scb中ahbFIFO和apbFIFO的TLM;drv和sqrTLM在agt连接

class ahb2apb_env extends uvm_env;
  `uvm_component_utils(ahb2apb_env)

  apb_slv_agt   apb_slv_agt_i;
  ahbl_mst_agt  ahbl_mst_agt_i;

  ahb2apb_scb   ahb2apb_scb_i;

  function new(string name,uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
    apb_slv_agt_i = apb_slv_agt::type_id::create("apb_slv_agt_i",this);
    ahbl_mst_agt_i = ahbl_mst_agt::type_id::create("ahbl_mst_agt_i",this);
    ahb2apb_scb_i = ahb2apb_scb::type_id::create("ahb2apb_scb_i",this);
  endfunction

  virtual function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    apb_slv_agt_i.mon_i.ap.connect(ahb2apb_scb_i.apb_fifo.analysis_export);
    ahbl_mst_agt_i.mon_i.ap.connect(ahb2apb_scb_i.ahb_fifo.analysis_export);
  endfunction

endclass

base_test:

virtual reset接口、例化env;set is_active到agt,get reset_if;

 uvm_top.print_topology() 仿真一启动打印出uvm的hierarchy(层次结构)

report_phase中收集整个仿真过程中uvm_error,为0成功 有error失败;

import ahb2apb_pkg::*;

class ahb2apb_base_test extends uvm_test;
  `uvm_component_utils(ahb2apb_base_test)

  virtual reset_if reset_if_i;//例化reset接口和env
  ahb2apb_env env_i;

  function new(string name,uvm_component parent=null);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env_i=ahb2apb_env::type_id::create("env_i",this);

    uvm_config_db#(uvm_active_passive_enum)::set(this,"env_i.ahbl_mst_agt_i","is_active",UVM_ACTIVE);
    if(!uvm_config_db#(virtual reset_if)::get(this,"","vif",reset_if_i))
      `uvm_fatal("No reset_if","reset_if_i is not set!")
  endfunction

  virtual function void start_of_simulation_phase(uvm_phase phase);
    super.start_of_simulation_phase(phase);

    uvm_top.print_topology();//仿真一启动打印出uvm的hierarchy(层次结构)
  endfunction

  virtual task run_phase(uvm_phase phase);
    super.run_phase(phase);
    reset_if_i.reset_dut;//reset信号 0 1 0

    phase.phase_done.set_drain_time(this,5us);//仿真延迟时间
  endtask

  function void report_phase(uvm_phase phase);//收集整个仿真过程中uvm_error,为0成功 有error失败
    super.report_phase(phase);
    if(num_uvm_errors==0)begin
      `uvm_info(get_type_name(),"Simulation PASSED!",UVM_NONE)
    end
    else begin
      `uvm_info(get_type_name(),"SImulation FAILED!",UVM_NONE)
    end
  endfunction
 
  function int num_uvm_errors();
    uvm_report_server server;
    if(server==null) server = get_report_server();
    return server.get_severity_count(UVM_ERROR);
  endfunction
endclass

scb:

两个fifo两个port,使用FIFO缓存数据,可以选择ahb、apb端都单个比较,或者ahb端打包发一整个pkt,apbfifo端获得同等数量后同时发出比较;

在env中mon连接到了fifo的export;需要在scb中把fifo的export连到scb的port中;

run_phase中check_pkt中用port.get到apb、ahbl的tran后,将其中信号进行对比,有误报错并err_flag+1;

  在进行prot对比时需要注意:apb_pkt.prot[0]对应于ahb_pkt.hprot[1];Privileged access访问权限

                                                apb_pkt.prot[2]为1对应于ahb_pkt.hprot[0]为0,所以在相等的时候有错误;Bufferable

class ahb2apb_scb extends uvm_scoreboard;
//两个fifo两个port,使用FIFO缓存数据,可以选择ahb、apb端都单个比较,或者ahb端打包发一整个pkt,apbfifo端获得同等数量后同时发出比较;
  uvm_tlm_analysis_fifo #(apb_tran) apb_fifo;
  uvm_blocking_get_port #(apb_tran) apb_port;

  uvm_tlm_analysis_fifo #(ahbl_tran) ahb_fifo;
  uvm_blocking_get_port #(ahbl_tran) ahb_port;

  func_cov  fcov;
  `uvm_component_utils(ahb2apb_scb)

  function new(string name,uvm_component parent);
    super.new(name,parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    apb_fifo = new("apb_fifo",this);
    apb_port = new("apb_port",this);
    ahb_fifo = new("ahb_fifo",this);
    ahb_port = new("ahb_port",this);
    fcov     = new("fcov");
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
	//在env中mon连接到了fifo的export;需要在scb中把fifo的export连到scb的port中;
    apb_port.connect(apb_fifo.blocking_get_export);
    ahb_port.connect(ahb_fifo.blocking_get_export);
  endfunction

  virtual task run_phase(uvm_phase phase);
    check_pkt();
  endtask

  virtual task check_pkt();
    apb_tran  apb_pkt;
    ahbl_tran ahb_pkt;
    bit       err_flag;

    while(1)begin
      err_flag = 0;
      ahb_port.get(ahb_pkt);
      apb_port.get(apb_pkt);

      fcov.cg.sample(ahb_pkt,apb_pkt);
//run_phase中check_pkt中用port.get到apb、ahbl的tran后,将其中信号进行对比,有误报错并err_flag+1;
      if(ahb_pkt.haddr[15:2] != apb_pkt.addr[15:2])begin
        `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet address mismatch! ahb-addr[15:2][%0h],apb-addr[15:2][0%h]",ahb_pkt.haddr[15:2],apb_pkt.addr[15:2]))
        err_flag = 1;
      end

      if(ahb_pkt.hrwdata != apb_pkt.data)begin
        `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet rw-data mismatch! ahb-data[%0h],apb-data[0%h]",ahb_pkt.hrwdata,apb_pkt.data))
        err_flag = 1;
      end

      if(ahb_pkt.hwrite & (apb_pkt.kind == apb_slv_pkg::READ ))begin
        `uvm_error(get_type_name(),"AHB-packet and APB-packet read/write mismatch! ahb-'write',apb-'read'")
        err_flag = 1;
      end
      if(!ahb_pkt.hwrite & (apb_pkt.kind == apb_slv_pkg::WRITE ))begin
        `uvm_error(get_type_name(),"AHB-packet and APB-packet read/write mismatch! ahb-'read',apb-'write'")
        err_flag = 1;
      end

      if(apb_pkt.prot[0] != ahb_pkt.hprot[1])begin
        `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet 'hprot[1]/prot[0]' mismatch! ahb:[%0d],apb:[%0d]",ahb_pkt.hprot[1],apb_pkt.prot[0]))
        err_flag = 1;
      end

      if(apb_pkt.prot[2] == ahb_pkt.hprot[0])begin
        `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet 'hport[0]/prot[2]' mismatch! ahb:[%0d],apb:[%0d]",ahb_pkt.hprot[0],apb_pkt.prot[2]))
        err_flag = 1;
      end

      if(ahb_pkt.hwrite)begin
        if((ahb_pkt.hsize==WORD) & (apb_pkt.strb != 4'b1111))begin
          `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet hsize/haddr/pstrb mismatch! ahb-hsize:WORD,apb-pstrb:%4b.",apb_pkt.strb))
          err_flag = 1;
        end
        if(((ahb_pkt.hsize==HWORD) & !ahb_pkt.haddr[1] & (apb_pkt.strb!=4'b0011)) | ((ahb_pkt.hsize==HWORD) & ahb_pkt.haddr[1] &(apb_pkt.strb != 4'b1100)))begin
           `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet hsize/haddr/pstrb mismatch! ahb-hsize:HWORD,ahb-haddr[1]:%d,apb-pstrb:%4b.",ahb_pkt.haddr[1],apb_pkt.strb))
          err_flag = 1;
        end
        if(((ahb_pkt.hsize==BYTE) & (ahb_pkt.haddr[1:0]==2'b00) &(apb_pkt.strb != 4'b0001)) | ((ahb_pkt.hsize==BYTE) & (ahb_pkt.haddr[1:0]==2'b01) &(apb_pkt.strb != 4'b0010)) | ((ahb_pkt.hsize==BYTE) & (ahb_pkt.haddr[1:0]==2'b10) &(apb_pkt.strb != 4'b0100)) | ((ahb_pkt.hsize==BYTE) & (ahb_pkt.haddr[1:0]==2'b11) &(apb_pkt.strb != 4'b1000)))begin
          `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet hsize/haddr/pstrb mismatch! ahb-hsize:BYTE,ahb-haddr[1:0]:%2b,apb-pstrb:%4b.",ahb_pkt.haddr[1:0],apb_pkt.strb))
          err_flag = 1;
        end
      end
      
      if(ahb_pkt.hresp != apb_pkt.slverr)begin
        `uvm_error(get_type_name(),$sformatf("AHB-packet and APB-packet hresp/pslverr mismatch! ahb:[%0d],apb:[%0d].",ahb_pkt.hresp,apb_pkt.slverr))
         err_flag = 1;
      end

      if(err_flag)begin
        `uvm_error(get_type_name(),"Pkt comparing FAILED!")
      end
      else begin
        `uvm_info(get_type_name(),"Pkt comparing correct!",UVM_LOW)
      end
      # 20ns;
    end
  endtask

endclass

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/589191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何保证三个线程按顺序执行?不会我教你

&#x1f468;‍&#x1f393;作者&#xff1a;bug菌 ✏️博客&#xff1a;CSDN、掘金、infoQ、51CTO等 &#x1f389;简介&#xff1a;CSDN|阿里云|华为云|51CTO等社区博客专家&#xff0c;历届博客之星Top30&#xff0c;掘金年度人气作者Top40&#xff0c;51CTO年度博主Top12…

仪表板展示 | DataEase看世界:数据呈现世界油价变化

背景介绍 最近几个月&#xff0c;全球能源市场一直处于动荡不安的状态&#xff0c;与石油相关的新闻也非常频繁。2023年2月10日&#xff0c;面对西方多轮限价举措&#xff0c;俄罗斯副总理亚历山大诺瓦克宣布&#xff0c;俄罗斯将在3月把每日原油产量下调50万桶。目前&#xf…

FOFA-攻防挑战

记录一下中途短暂的辉煌时刻 辉煌一刻谁都有,别拿一刻当永久 在昨天初尝战果之后&#xff0c;今天又习惯性的打开 https://vulfocus.cn/ 发现今天还有挑战赛&#xff0c;按捺不住躁动的心&#xff0c;又开始了学习。今天主要拿下的是这四个镜像&#xff0c;同时我也会对我了解…

前端SKU一站式解决方案 - Geek-SKU

因为业务需要且市场上的UI框架与插件市场内没有简易的用法并且不够全面萌生便了自己写一个SKU组件的想法&#xff0c;于是Geek-SKU便应运而生。 现在的SKU组件已支持vue、uniapp&#xff0c;支持带图SKU、主题色设置、自动选择低价SKU、自动展示价格区间等&#xff0c;让您更便…

浏览器自动填充但是数据为空的问题

问题背景 公司项目中登录页为了方便&#xff0c;需要允许浏览器自动填充账号密码。这个在很多项目都很常见&#xff0c;但是测试中出现了这样一个问题&#xff1a;视觉上已经自动填充账号密码&#xff0c; 但是当点击密码的小眼睛或者点击登录时&#xff0c;会清空掉填充的数据…

火爆全网,性能测试-全链路压测实战总结,从需求到实战...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 流程导图 梳理阶段…

SpringBoot+Vue 的家政服务管理平台+数据库(附源码)

文章目录 1. 背景2.主要技术3. 可行性分析4.系统设计5系统的详细设计与实现5.1前台模块设计5.2后台功能模块 源码下载地址 1. 背景 本系统主要是设计出家政服务管理平台&#xff0c;基于B/S构架&#xff0c;后台数据库采用了Mysql&#xff0c;可以使数据的查询和存储变得更加有…

Linux函数库管理

文章目录 Linux函数库管理动态与静态函数库静态函数库动态函数库 ldconfig与 /etc/ld.so.confldconfig使用案例 程序的动态函数库解析&#xff1a;lddldd使用案例 校验软件的正确性常见的校验软件有哪些&#xff1f;使用案例 Linux函数库管理 在 Linux 操作系统中&#xff0c;…

【算法竞赛进阶指南】141.周期 题解 KMP 最小循环节

题目描述 一个字符串的前缀是从第一个字符开始的连续若干个字符&#xff0c;例如 abaab 共有 5 5 5 个前缀&#xff0c;分别是 a&#xff0c;ab&#xff0c;aba&#xff0c;abaa&#xff0c;abaab。 我们希望知道一个 N N N 位字符串 S S S 的前缀是否具有循环节。 换言之…

7.Ansible Modules介绍

什么是Ansible Modules? Ansible模块根据其功能分为不同的组&#xff0c;每个模块提供了一些功能&#xff0c;可以直接使用。 模块官方文档: https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html 系统模块是要在系统级别执行的操作,例如修改系统上的用户…

Springboot +spring security,认证方式---Form表单认证的实现(三)

一.简介 这篇文章来学习下security的认证方式其中的Form表单认证 二.Spring Security的认证方式 2.1什么是认证 认证: 就是用来判断系统中是否存在某用户&#xff0c;并判断该用户的身份是否合法的过程&#xff0c;解决的其实是用户登录的问题。认证的存在&#xff0c;是为…

Spring Boot 如何实现异步消息处理

Spring Boot异步消息处理 在现代应用程序中&#xff0c;异步消息处理是一项至关重要的任务。它可以提高应用程序的性能、可伸缩性和可靠性&#xff0c;同时也可以提供更好的用户体验。Spring Boot提供了多种方式来实现异步消息处理&#xff0c;包括使用Spring AMQP、Spring Ka…

【斯歌X捷普】优秀体验官活动:全民开发的样板企业是这样炼成的

3月22日&#xff0c;上海斯歌与捷普共同举办了一场别出心裁的活动——“产品优秀体验官”颁奖典礼&#xff0c;以表彰对业务流程开发做出突出贡献的捷普员工。值得注意的是&#xff0c;获奖的14名流程开发人员中&#xff0c;有7人并非是专业的IT人员&#xff0c;而是来自业务岗…

搜索引擎变天了!谷歌宣布开放「生成式搜索平台」!AI 大模型颠覆搜索体验

作者 | 小戏、兔子酱 搜索引擎&#xff0c;可能真的要变天了&#xff01; Google 终于要迎来它 25 年来最大的改变&#xff0c;谷歌宣布了开始内测开放【生成式搜索平台&#xff08;Search Generative Experience&#xff0c;SGE&#xff09;】&#xff0c;并逐步舍弃那些甚至是…

Linux中与中断相关的内核数据结构

【摘要】本文树妖详细讲解了Linux中与中断相关的内核数据结构及其内部联系。 八、中断相关的数据结构 8.1 irq_desc 用于表示IRQ描述符的结构定义如下&#xff1a;\linux-2.6.32.63\include\linux\irq.h struct irq_desc {unsigned int irq; //中断号unsigned int …

ipad可以使用其他品牌的手写笔吗?2023年电容笔推荐

现在&#xff0c;人们的生活越来越智能化&#xff0c;有些人已经用平板电脑取代了传统的笔记本。我发现用ipad不管是用来画画还是做笔记非常方便&#xff0c;但是苹果Pencil对于大多数人来说都是昂贵的。据我所知&#xff0c;如果仅仅是为了记录&#xff0c;而不是为了画画的话…

他是98年的卷王,我真的玩不过他····

现在的小年轻真的卷得过分了。前段时间我们公司来了个98年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天&#xff0c;原来这位小老弟家里…

PKI 基础知识

摘要 本白皮书介绍了加密和公钥基本结构(PKI)的概念和使用 Microsoft Windows 2000 Server 操作系统中的证书服务的基础知识。如果您还不熟悉加密和公钥技术&#xff0c;先阅读本白皮书将有助于理解 Windows 2000 Web 站点上有关这些主题的其它技术白皮书。 引言 Microsoft …

玩转VLAN间路由,教你3个好方法

我的网工朋友大家好啊 在现实网络中&#xff0c;经常会遇到需要跨VLAN相互访问的情况。 很多网工通常会选择一些方法&#xff0c;来实现不同VLAN间主机的相互访问&#xff0c;例如单臂路由。 但是&#xff0c;单臂路由技术中由于存在一些局限性&#xff0c;比如带宽、转发效…

NodeJS基础到入门EXPS⑥

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言Express框架 Router路由NEST 方法路由端点使用回调函数数组处理路由使用混合使用函数和函数数组处理路由中间件的分类及用法 1、应用级中间件 2、路…