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

框架:

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

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ahb to apb bridge验证项目是一种测试和验证所使用的工程项目,旨在验证ahb总线与apb总线之间的连接和数据交换是否正常和有效。 在ahb to apb bridge验证项目中,需要进行以下步骤: 1. 设计验证环境:首先,需要设计一个适当的验证环境,包括搭建硬件平台和开发验证软件。硬件平台包括ahb总线和apb总线的接口电路以及连接这两个总线的bridge电路。验证软件包括用于控制和监测数据传输的测试程序和驱动程序。 2. 编写测试用例:在验证项目中,需要编写一系列的测试用例来测试ahb to apb bridge的功能。测试用例可以包括不同的数据传输模式(例如读取和写入)和不同的错误场景(例如错误的地址访问和错误的数据传输)。 3. 进行功能验证:通过运行测试用例,验证ahb to apb bridge在不同的数据传输模式下是否能够正确地传输数据,以及对错误场景是否能够正确地做出反应。这可以通过检查传输数据的准确性和比对传输结果与预期结果是否一致来进行验证。 4. 进行性能验证:除了功能验证之外,还需要进行性能验证,以验证ahb to apb bridge在高负载和大数据量情况下的性能表现。性能验证可以通过模拟大量数据传输和进行性能测试来进行。 5. 编写报告:验证项目完成后,需要编写验证报告,总结验证过程、测试结果和验证结论。报告应该清晰地记录验证的步骤、使用的工具和测试用例,以及结果的准确性和性能。 通过进行ahb to apb bridge验证项目,可以确保ahb总线和apb总线之间的连接和数据交换是正确可靠的,从而提高整个系统的性能和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值