AHB-to-APB Bridge——05ahbl_tran、ahlb_drv

这篇具有很好参考价值的文章主要介绍了AHB-to-APB Bridge——05ahbl_tran、ahlb_drv。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ahbl_tran:

        声明protected是保证只有当前的class以及子类可以访问这个变量,外部调用没法改变变量值

        声明locol 子类也没法改变

`ifndef AHBL_TRAN_SV
`define AHBL_TRAN_SV
class ahbl_tran extends uvm_sequence_item;
	rand logic [31:0]			haddr		=	32'h0;
	rand logic [31:0]			hdata		=	32'h0;
	rand logic htrans_t			htran		=	NSEQ;
	rand logic hburst_t			hburst		=	SINGLE;
	rand logic hsize_t			hsize		=	BYTE;
	rand logic [3:0]			hprot		=	4'b0;
	rand logic					hsel		=	1'b0;
	rand logic 					hreadyout	=	1'b1;
	rand logic					hwrite		=	1'b0;
	rand logic					hresp		=	1'b0;

	protected rand int unsigned bst_beats;//一组传输需要的传输次数
	protected rand logic [5:0] 	haddr_q[$];	//一组传输中的地址队列集合
	protected rand logic [31:0] hrwdata_q[$];//数据集合
	protected rand htrans_t     htrans_q[$];//传输状态集合

	protected int unsigned haddr_idx   = 0;//用于driver调用函数的计数
	protected int unsigned hrwdata_idx = 0;
	protected int unsigned htrans_idx  = 0;

	`uvm_object_utils_begin(ahbl_tran)
		`uvm_field_int        (hsel,              UVM_DEFAULT)
		`uvm_field_int        (haddr,             UVM_DEFAULT)
		`uvm_field_enum       (htrans_t,htrans,   UVM_DEFAULT)
		`uvm_field_enum       (hsize_t,hsize,     UVM_DEFAULT)
		`uvm_field_enum       (hburst_t,hburst,   UVM_DEFAULT)
		`uvm_field_int        (hprot,             UVM_DEFAULT)
		`uvm_field_int        (hwrite,            UVM_DEFAULT)
		`uvm_field_int        (hrwdata,           UVM_DEFAULT)
		`uvm_field_int        (hresp,             UVM_DEFAULT)
		`uvm_field_int        (hreadyout,         UVM_DEFAULT)

		`uvm_field_int        (bst_beats,         UVM_DEFAULT)
		`uvm_field_queue_int  (haddr_q,           UVM_DEFAULT)
		`uvm_field_queue_int  (hrwdata_q,         UVM_DEFAULT)
		`uvm_field_queue_enum (htrans_t,htrans_q, UVM_DEFAULT)
		
		`uvm_field_int        (haddr_idx,         UVM_DEFAULT)
		`uvm_field_int        (hrwdata_idx,       UVM_DEFAULT)
		`uvm_field_int        (htrans_idx,        UVM_DEFAULT)
	`uvm_object_utils_end

	constraint haddr_constr{
		{hsize == HWORD} -> {haddr[0] 	== 1'b0};
		{hsize ==  WORD} -> {haddr[1:0] == 2'b0};
		solve hsize before haddr;
	}
	
	constraint htrans_constr{
		{htrans == IDLE} -> {hburst 	== SINGLE};
		solve htrans before haddr;
	}
	
	constraint hburst_constr{
		(hburst == SINGLE)  -> (bst_beats == 1);
		(hburst == WRAP4)   -> (bst_beats == 4);
		(hburst == WRAP8)   -> (bst_beats == 8);
		(hburst == WRAP16)  -> (bst_beats == 16);
		(hburst == INCR4)   -> (bst_beats == 4);
		(hburst == INCR8)   -> (bst_beats == 8);
		(hburst == INCR16)  -> (bst_beats == 16);
		solve hburst before bst_beats;
	}

	constraint queue_constr{
		haddr_q.size()   == bst_beats;//传输的次数作为三个队列的大小
		hrwdata_q.size() == bst_beats;
		htrans_q.size()  == bst_beats;
		solve bst_beats before haddr_q;
		solve bst_beats before hrwdata_q;
		solve bst_beats before htrans_q;
	}

	function new(string name = "ahbl_tran");
		super.new(name);
		hsel        = 1'b0;
		haddr       = 32'h0;
		htrans      = NSEQ;
		hsize       = BYTE;
		hburst      = SINGLE;
		hprot       = 4'h0;
		hwrite      = 32'h0;
		hresp       = 1'b0;
		hreadyout   = 1'b1;

		haddr_idx   = 0;
		hrwdata_idx = 0;
		htrans_idx  = 0;
	endfunction	
	
	function void post_randomize();//在randomize之后自动运行
		int i;
		haddr_q[0]   = haddr;//刚randomize的数据作为第一个数据
		htrans_q[0]  = NSEQ;//第一个数据为NSEQ
		hrwdata_q[0] = hrwdata;
		for(i=1;i<bst_beats;i++)begin
			//根据每次传输的size进行地址位移 
			//1byte8位地址加1 2byte16位地址加2 4byte32位地址加4 
		  haddr_q[i] = haddr_q[i-1] + (2**hsize);
		  htrans_q[i]= SEQ;//后续数据为SEQ
    end
  endfunction
  
    virtual function logic [31:0] nxt_haddr();//定义的函数driver使用
		haddr_idx++;
		return haddr_q[haddr_idx-1];
	endfunction

	virtual function logic [31:0] nxt_hrwdata();
		hrwdata_idx++;
		return hrwdata_q[hrwdata_idx-1];
	endfunction

	virtual function logic [31:0] nxt_htrans();
		htrans_idx++;
		return htrans_q[htrans_idx-1];
	endfunction
  
	virtual function bit last_beat();
		return (htrans_idx == htrans_q.size());
	endfunction

	virtual function int get_bst_beats();
		return (bst_beats);
	endfunction

endclass	

`endif//AHBL_TRAN_SV

ahbl_drv:

        定义两个空的pkt_dataphase、pkt_addrphase;

        在没有rst情况下,第一次判断dataphase为空,不发送data,然后判断addrphase也为空不发送addr;

        addrphase:try_next_item 如果没得到设置初始值重新循环,如果得到addr就发送到总线,并将指针给到dataphase;

        则第二次循环判断data不为空,根据hwrite发送数据;然后判断是不是传输结束(hready为0 & SINGLE传输|最后一个数据传输);如果结束item_done、两个pkt置空;如果在burst中间,则继续传输;(相当于对trans中的burst传输数据整体发送)

        实现了当前地址和数据相差一拍,以及和下一个地址的交叠操作;

class ahbl_mst_drv extends uvm_driver #(ahbl_tran);
  `uvm_component_utils(ahbl_mst_drv)

  virtual ahbl_if vif;

  protected ahbl_tran pkt_dpha = null;//最开始data phase和adds phase为空
  protected ahbl_tran pkt_apha = null;

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(virtual ahbl_if)::get(this,"","vif",vif))
      `uvm_fatal("No vif","vif is not set")
  endfunction
  
  task run_phase(uvm_phase phase);
    while(1) begin
      @(vif.mst_cb);
      if(!vif.mst_cb.hresetn)begin//如果reset给初始值
        vif.mst_cb.hsel   <= 1'b0;
        vif.mst_cb.haddr  <= 32'b0;
        vif.mst_cb.htrans <= 2'b0;
        vif.mst_cb.hsize  <= 3'b0;
        vif.mst_cb.hburst <= 3'b0;
        vif.mst_cb.hprot  <= 4'b0;
        vif.mst_cb.hwrite <= 1'b0;
        vif.mst_cb.hwdata <= 32'b0;
      end
      else begin
        if(pkt_dpha != null)begin//不rst 第一次进入dpha为空 不进入   发完第一个addr后进入
          drive_1cyc_pkt_dpha(pkt_dpha);
          if(vif.mst_cb.hready & ((pkt_dpha.hburst == SINGLE) | pkt_dpha.last_beat()))begin
		  //判断是不是传输结束(hready为0 & SINGLE传输|最后一个数据传输)
            seq_item_port.item_done();
            pkt_apha = null;
            pkt_dpha = null;
          end
        end
        
        if(pkt_apha != null)begin//第一次进入apha也为空
          drive_1cyc_pkt_apha(pkt_apha);
        end
        else begin
          seq_item_port.try_next_item(pkt_apha);//try 得没得到都返回 get不得到不返回
          if(pkt_apha != null)begin//如果得到addr 发一个addr到总线
            drive_1cyc_pkt_apha(pkt_apha);
            pkt_apha.print();
          end
          else begin
            drive_1cyc_idle();
          end
        end
      end
    end
  endtask

  task drive_1cyc_pkt_dpha(ref ahbl_tran t);
    if(vif.mst_cb.hready)begin
      vif.mst_cb.hwdata <= t.hwrite ? t.nxt_hrwdata():32'd0;
    end
  endtask

  task drive_1cyc_pkt_apha(ref ahbl_tran t);//传递地址以及控制信号
    if(vif.mst_cb.hready)begin
      vif.mst_cb.hsel   <= t.hsel;
      vif.mst_cb.haddr  <= ((t.htrans != IDLE) & (t.htrans != BUSY))?t.nxt_haddr() : vif.haddr;
      vif.mst_cb.htrans <= t.nxt_htrans();
      vif.mst_cb.hsize  <= t.hsize;
      vif.mst_cb.hburst <= t.hburst; 
      vif.mst_cb.hprot  <= t.hprot; 
      vif.mst_cb.hwrite <= t.hwrite;
      this.pkt_dpha = this.pkt_apha; //发出去一个addr后将t给到pkt_dpha
    end
  endtask

  task drive_1cyc_idle();
    vif.mst_cb.hsel   <= 1'b0;
    vif.mst_cb.haddr  <= 32'd0;
    vif.mst_cb.htrans <= IDLE;
    vif.mst_cb.hsize  <= BYTE;
    vif.mst_cb.hburst <= SINGLE;
    vif.mst_cb.hprot  <= 4'h0;
    vif.mst_cb.hwrite <= 1'b0;
  endtask

endclass

ahbl_mon:

                 定义一个 pkt;如果rst则pkt置空;

                判断slv来的ready,只有ready为高才表示信号真正有效 如果无效重新while循环判断;

                如果ready为高,判断如果pkt里不是空的就把总线上的data送出去,并将pkt置空。(本质就是判断apha有没有接收到信号)

                然后如果  hsel 为高说明选中了这个模块 & htrans[1]为1 即NONSEQ=2'b10 SEQ=2'b11传输状态时,就把addr phase的各个信号采样到pkt里。

                则第二次循环 pkt 不为空,就判断读写 在data phase中把数据送到scb;

(与drv区别:drv将burst传输看作整体发送,需要判断SINGLE以及是否是最后一位传输;

                       mon将burst传输过来的数据拆分一个一个传递到scb中,方便之后的比较,因为apb

                        只支持单个传输。)

class ahbl_mst_mon extends uvm_monitor;
  `uvm_component_utils(ahbl_mst_mon)

  virtual ahbl_if vif;

  uvm_analysis_port #(ahbl_tran) ap;
  ahbl_tran                      pkt;

  function new(string name,uvm_component parent);
    super.new(name,parent);
    ap = new("ap",this);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(virtual ahbl_if)::get(this,"","vif",vif))
      `uvm_fatal("No vif","vif is not set!")
  endfunction

  virtual task run_phase(uvm_phase phase);
    while(1)begin
      @(vif.mon_cb)
      if(!vif.mon_cb.hresetn)begin  
        pkt = null;
      end
      else begin
	  //只有ready为高才表示信号真正有效 如果无效重新while循环
        if(vif.mon_cb.hready)begin
		//ready为高,如果pkt里不是空的把总线上的data送出去,并pkt置空
		//本质就是判断apha有没有接收到
          if(pkt != null)begin
            samp_dpha(pkt);
            ap.write(pkt);
            pkt = null;
          end

          if(vif.mon_cb.hsel & vif.mon_cb.htrans[1])begin
		  //hsel为高选中了这个模块 & htrans[1]为1 即NONSEQ=2'b10 SEQ=2'b11状态时
            samp_apha(pkt);//就把addr phase采样到pkt里
          end
        end
      end
    end
  endtask

  virtual task samp_dpha(ref ahbl_tran pkt);
    pkt.hrwdata = pkt.hwrite ? vif.mon_cb.hwdata : vif.mon_cb.hrdata;
    pkt.hresp = vif.mon_cb.hresp;
  endtask

  virtual task samp_apha(ref ahbl_tran pkt);
    pkt = ahbl_tran::type_id::create("pkt");

    pkt.hsel    = vif.mon_cb.hsel;
    pkt.haddr   = vif.mon_cb.haddr;
    pkt.htrans  = htrans_t'(vif.mon_cb.htrans);//强制类型转换成枚举类型
    pkt.hsize   = hsize_t'(vif.mon_cb.hsize);
    pkt.hburst  = hburst_t'(vif.mon_cb.hburst);
    pkt.hprot   = vif.mon_cb.hprot;
    pkt.hwrite  = vif.mon_cb.hwrite;

  endtask
endclass

mst_agt:文章来源地址https://www.toymoban.com/news/detail-453826.html

class ahbl_mst_agt extends uvm_agent;
  `uvm_component_utils(ahbl_mst_agt)

  ahbl_mst_drv  drv_i;
  ahbl_mst_sqr  sqr_i;
  ahbl_mst_mon  mon_i;

  virtual ahbl_if vif;

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    if(!uvm_config_db#(virtual ahbl_if)::get(this,"","vif",vif))
      `uvm_fatal("No vif","vif is not set!")

    mon_i = ahbl_mst_mon::type_id::create("mon_i",this);
    uvm_config_db#(virtual ahbl_if)::set(this,"mon_i","vif",vif);

    if(!(uvm_config_db#(uvm_active_passive_enum)::get(this,"","is_active",is_active)))
      `uvm_fatal("is_active","is_active is not set!")

    if(is_active == UVM_ACTIVE)begin
      sqr_i = ahbl_mst_sqr::type_id::create("sqr_i",this);
      drv_i = ahbl_mst_drv::type_id::create("drv_i",this);
      uvm_config_db#(virtual ahbl_if)::set(this,"drv_i","vif",vif);
    end
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(is_active == UVM_ACTIVE)begin
      drv_i.seq_item_port.connect(sqr_i.seq_item_export);
    end
  endfunction
endclass

到了这里,关于AHB-to-APB Bridge——05ahbl_tran、ahlb_drv的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA-AMBA协议、APB协议、AHB规范、AXI4协议规范概述及它们之间的关系

    笔记记录,AMBA协议、APB协议、AHB规范、AXI4协议规范概述,只是概述描述,具体详细的协议地址传输、数据传输等内容将在下一章节详细说明。 AMBA(Advanced Microcontroller Bus Architecture)是一种由ARM公司提出的处理器总线架构,它定义了处理器、内存和外设之间的通信标准 。

    2024年02月04日
    浏览(35)
  • CP2102N USB to UART Bridge Controller 驱动程序无法使用

    解决办法来源   原本想通过vitis自带的终端terminal来连接串口进行fpga和电脑通信的时候,发现fpga的UART端口连接不到电脑,故通过设备管理费排查发现端口驱动未安装。 步骤一. 上驱动官网下载驱动 官网链接 步骤二. 选择合适的驱动进行下载,我下载的是CP210x Windows Driver

    2024年02月04日
    浏览(46)
  • 【文献分享】Big data and benchmarking initiatives to bridge the gap from AlphaFold to drug design

    今天来精读一篇发在《Nature Chemical Biology》上的最新评论,题目为: Big data and benchmarking initiatives to bridge the gap from AlphaFold to drug design  原文链接如下: Big data and benchmarking initiatives to bridge the gap from AlphaFold to drug design | Nature Chemical Biology https://www.nature.com/articles/s41589-024-01570

    2024年03月28日
    浏览(47)
  • failed to start daemon: Error initializing network controller: Error creating default “bridge“ netw

    failed to start daemon: Error initializing network controller: Error creating default \\\"bridge\\\" network: Failed to program NAT chain: INVALID_ZONE: docker linux 重启防火墙 输入此命令重启防火墙 systemctl enable firewalld  重新启动docker即可 systemctl start docker

    2024年02月04日
    浏览(62)
  • 笔记本电脑连上开发板后提示CP2104 USB to UART Bridge Controller解决方法

    新型笔记本电脑主板没有串口,需要安装usb转com口驱动。 驱动下载官网: CP210x USB to UART Bridge VCP Drivers - Silicon Labs The CP210x USB to UART Bridge Virtual COM Port (VCP) drivers are required for device operation as a Virtual COM Port to facilitate host communication with CP210x products. These devices can also interface to a

    2024年02月16日
    浏览(91)
  • 浅谈affine_trans_point_2d与affine_trans_pixel

    先看下两个坐标图谱: 变换前: 变换后:   我们根据1号点和9号点前后的关系,计算变换后其他点的坐标:这其实就是 根据MARK点进行定位 的原理  halcon代码:    执行结果:   我们发现,两种变换方式差别在于 : affine_trans_pixel 在变换前先减去0.5,变换后又加上0.5这样才

    2024年02月16日
    浏览(41)
  • CHI read trans flow

    =================Read transactions with DMT and without snoops================ 对于不产生snoop的read trans,建议使用DMT功能,如下图所示: 注意点: a. SNF并不需要给HNF回响应,因为RN发送的compack可以释放HNF处记录的请求; ================Read transaction with DMT and with snoops===================== 对于带snoop的

    2024年02月13日
    浏览(37)
  • UPF learing3:TRANS-11

    在对power aware block 进行综合的过程中,当执行compile_ultra cmd 的过程中,会遇到 TRANS-11 这个warning,导致compile 不能进行下去,最终compile fail。 这个问题是说在target library 中没有可替换的isolation cell或者是 cell 是带有dont_touch 和dont_use 属性的 ,无法完成转化,在netlist 中看到的

    2024年02月03日
    浏览(34)
  • APB协议及APB_Slave设计

    原文: 翻译: APB协议是一个 低成本 的接口,经过了优化, 降低了功耗和接口复杂性 。APB接口是 简单 , 同步 , 无流水线 的协议。 每次传输花费至少两个周期完成。 APB接口设计是为了访问外围设备中的可编程控制寄存器。APB外设通常使用APB桥连接到内存系统。例如,A

    2024年02月05日
    浏览(39)
  • 数据翻译——Easy_Trans的简单使用

    目录 Easy Trans 1、适用场景 2、easy trans 支持的五种类型 3、环境搭建 4、简单翻译(TransType.SIMPLE) 5、字典翻译(TransType.DICTIONARY) 6、跨微服务翻译(TransType.RPC) 7、自定义数据源翻译(TransType.AUTO_Trance) 1 我有一个id,但是我需要给客户展示他的title/name 但是我又不想自己手

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包