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

news/2024/12/4 17:22:41/

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_endconstraint 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;//第一个数据为NSEQhrwdata_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;//后续数据为SEQendendfunctionvirtual function logic [31:0] nxt_haddr();//定义的函数driver使用haddr_idx++;return haddr_q[haddr_idx-1];endfunctionvirtual function logic [31:0] nxt_hrwdata();hrwdata_idx++;return hrwdata_q[hrwdata_idx-1];endfunctionvirtual function logic [31:0] nxt_htrans();htrans_idx++;return htrans_q[htrans_idx-1];endfunctionvirtual function bit last_beat();return (htrans_idx == htrans_q.size());endfunctionvirtual function int get_bst_beats();return (bst_beats);endfunctionendclass	`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);endfunctionfunction 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")endfunctiontask 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;endelse beginif(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;endendif(pkt_apha != null)begin//第一次进入apha也为空drive_1cyc_pkt_apha(pkt_apha);endelse beginseq_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();endelse begindrive_1cyc_idle();endendendendendtasktask drive_1cyc_pkt_dpha(ref ahbl_tran t);if(vif.mst_cb.hready)beginvif.mst_cb.hwdata <= t.hwrite ? t.nxt_hrwdata():32'd0;endendtasktask drive_1cyc_pkt_apha(ref ahbl_tran t);//传递地址以及控制信号if(vif.mst_cb.hready)beginvif.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_dphaendendtasktask 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;endtaskendclass

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);endfunctionfunction 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!")endfunctionvirtual task run_phase(uvm_phase phase);while(1)begin@(vif.mon_cb)if(!vif.mon_cb.hresetn)begin  pkt = null;endelse begin//只有ready为高才表示信号真正有效 如果无效重新while循环if(vif.mon_cb.hready)begin//ready为高,如果pkt里不是空的把总线上的data送出去,并pkt置空//本质就是判断apha有没有接收到if(pkt != null)beginsamp_dpha(pkt);ap.write(pkt);pkt = null;endif(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里endendendendendtaskvirtual 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;endtaskvirtual 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:

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);endfunctionfunction 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)beginsqr_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);endendfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);if(is_active == UVM_ACTIVE)begindrv_i.seq_item_port.connect(sqr_i.seq_item_export);endendfunction
endclass


http://www.ppmy.cn/news/78545.html

相关文章

JVM-Sandbox--测试技术中引流回放的应用

关键点提炼 Sandbox简述原理&#xff1a;利用虚拟化技术创建隔离环境&#xff0c;利用字节码增强将被mock方法添加到隔离环境中&#xff1b;在被调用时Sandbox通过反射机制查找该方法&#xff0c;并使用代理对象将其转发给Sandbox中的虚拟机执行。当Sandbox执行完毕后&#xf…

《LKD3粗读笔记》(15)进程地址空间

进程地址空间&#xff1a;内核除了管理本身的内存外&#xff0c;还必须管理用户空间中进程的内存&#xff0c;这个内存就是进程地址空间&#xff0c;即系统中每个用户空间进程所看到的内存。Linux操作系统采用虚拟内存技术&#xff0c;系统中的所有进程之间以虚拟方式共享内存。…

arm嵌入式系统下,手把手教你移植pppoe拨号客户端,使用pppoe拨号上网

移植pppoe拨号客户端 一、概述二、移植过程1、内核配置2、pppd工具编译3、pppoe工具编译 三、配置pppoe参数四、创建节点信息五、pppoe服务器搭建 一、概述 PPPoE&#xff08;英语&#xff1a;Point-to-Point Protocol Over Ethernet&#xff09;&#xff0c;以太网上的点对点协…

nacos+frp穿透实现局域网调用

简介&#xff1a;首先你要有外网服务器。在外网服务器上安装frp服务端。然后在你想要调用的局域网电脑上安装frp客户端 frp下载链接 Releases fatedier/frp GitHub 外网服务器上我用的是docker安装的。你也可以直接下载并启动。这里我就不描述了。 首先我们先创建某个目录…

全网最牛最前面的浦发银行软件测试面试题精讲分析

面试永远都是软件测试人重点关注的问题&#xff0c;最近也总有很多想去银行面试的小伙伴来问我&#xff0c;有没有什么方法技巧传授一下。 那今天就给大家总结一些浦发银行的面试题&#xff0c;小伙伴们可以看看如果是自己能不能流畅地回答上来这些面试题。 1、说说你们公司测…

[SHOI2008]循环的债务 题解

题目 转换问题&#xff1a;所有人把钱放在桌上&#xff0c;每个人拿走自己所需的钱。 每个人并不需要重复的把相同钞票放在桌子上再拿回来&#xff0c;因此对于第 i i i 种钞票&#xff0c;假设 Alice 初始有 x x x 张&#xff0c;结束有 x ′ x x′ 张&#xff0c;Alice 只…

量化论文学习之《基于 CNN-LSTM 混合模型的股价 预测》

主要原理 CNN-LSTM 混合模型首先使用 CNN 来提取时间序列数据的特征&#xff0c;然 后将特征输入进 LSTM 模型中来进行下一交易日股票收盘价的预测。 数据处理 使用数据 作者发现加入volume,pctChg后效果变差&#xff0c;可能原因是加入了相关性较低的特征后造成了数据冗余…

陕西棒球发展·棒球5号位

陕西省棒球发展现状&#xff1a; 目前&#xff0c;陕西省棒球运动的发展还处于初级阶段&#xff0c;棒球运动的普及程度和水平都相对较低。陕西省内的棒球队伍数量较少&#xff0c;且大多数队伍的水平较为薄弱&#xff0c;缺乏专业的教练和训练设施。此外&#xff0c;陕西省内…