代码来自于 ,本篇文章只对其中的细节做探讨
首先DUT为加法器,但是舒服不仅是加数和被加数,还有ready和valid,输出也不止是和,还有valid和ready。valid代表数据有效,ready表示已经准备好发送或者接收。
加法器的设计语言中,共有三个状态,INITIAL/WAIT/SEND,rst为1时是复位信号,开始置零和置X,状态转为INITIAL态,下一个状态为WAIT状态,此刻输入信号的ready置一,表示准备好接收输入,下一个状态为SEND,在输入信号valid的情况下,开始赋值输出为输入之和,并输出的valid为1,在输出的ready为1时,进入WAIT,表示开始接收下一轮的数据。
定义了两个transaction组件,第一个为输入的transaction包含了两个rand输入数据A/B,第二个为输出的transaction,为data。transaction 扩展于uvm_sequence_item
在sequence中负责启动transaction,需要在forever之前例化,并在forever中创建事务,采用手动启动的方法:start_item / finish_item,并使用断言,如果tx没有随机化的话就退出仿真。
定义了两个driver,一个是在master_agent中,发送数据(transaction)到DUT,采用了get方法从sequence中获取数据,另一个是在slave_agent,只负责控制output的ready信号,这里是无复位时一直为1。
monitor也有两个,一个是监视输入信号,输入进reference_model,另一个监视输出的data,输入scoreboard,以便这两个信号进行对比。对于第一个监视器来说,是在输入信号有效且ready的情况下通过“write”方法写入到reference_model,这里是通过TLM通信机制进行通信的,之后会将整个UVM平台的TLM机制拉通说一遍。第二个监视器同样也是在输出信号valid并ready时把data(A+B)写入。
一样的,有两个agent,一个在输入位置,另一个在输出位置,一个是master_agent,包含了sequencer、monitor、driver,另一个是slave_agent,与master的区别是没有sequencer,因为他不需要从sequence中获取驱动,只需要对输出的ready进行定向驱动。
scoreboard是一个很重要的组件,负责把输入的数据获取到,并利用C语言进行计算,之后把这个结果与输入进来的DUT输出值进行比较。那么如何获取数据,什么时候比对就是关键。在这里先卖个关子,等下面讲清楚TLM机制后再详细说明
在env中需要定义的组件有两个agent,一个reference model,一个scoreboard,他们在env中进行TLM机制的通信接口连接。
在testcase中需要例化env,因为testcase在env的更外层,并在run_phase中手动启动sequence,使用start方法。
在顶层文件top中include所有组件,事务和DUT,并为其注入信号,并配置interface,采用uvm_root::get()方法获取根节点,并返回指针,这样的好处是底下所有组件都可以获取到。
接下来就开始讲解本UVM平台的TLM通信机制:下图为UVM示意图,红线代表的是TLM通信信道。
①:driver与sequencer之间的通信,是在master_agent中进行连接的,都是uvm组件中自带的接口(driver中的seq_item_port/sequencer中的seq_item_export,这个export本质是import),无需另外定义。
drv.seq_item_port.connect(sqr.seq_item_export)
②:需要横跨组件传输的话,需要在横跨的组件内部定义一个export作为中转站。在monitor中定义了接口 uvm_analysis_port #(packet_in) item_collected_port;在master_agent中定义了一个export中转站 uvm_analysis_port #(packet_in) item_collected_port ;analysis_port一般是一对多,一对一也可以用,使用write方法广播写入。
在connect phase中由内向外连接到agent的analysis port(analysis export是由外向内连接)
UVM基础-TLM机制之analysis端口与FIFO_analysis tlm-CSDN博客
mon.item_collected_port.connect(item_collected_port)
③:在env中定义了一个fifo中转站:uvm_tlm_analysis_fifo #(packet_in) to_refmod
在env中将master_agent连接到此FIFO:(这里的export实际上是imp)mst.item_collected_port.connect(to_refmod.analysis_export)(from mst_agent to fifo)
④:将FIFO连接到rfm:rfm.in.connect(to_refmod.get_export)(from fifot to rfm)
⑤:在 slave_agent中连接monitor与slave_agent中的export:mon.item_collected_port.connect(item_collected_port)
在scoreboard中定义的端口,两个都是imp,一个来自rfm,一个来自monitor_out检测到的DUT的输出
uvm_put_imp #(T, this_type) from_refmod
uvm_analysis_imp #(T, this_type) from_dut
⑥:slv.item_collected_port.connect(comp.from_dut)
⑦:rfm.out.connect(comp.from_refmod)
整个平台的TLM机制就讲完了,最后来讲scoreboard的工作方式:
首先需要注意的是rfm的数据是通过put方法写入,而两个monitor是通过write方法。
在scoreboard中会用到put 和write任务,顺序是先put,再write,之后再compare。rfm一得到数据就put进去。
在@35时,rfm使用put方法放入,在put任务中需要等待一个时钟周期,所以在@45 put任务结束
在@45时,monitor_out使用write方法将DUT的data输入,write任务不消耗仿真时间
monitor_out在write任务之后等待一个时钟周期,并在valid和ready=0时再等待应该周期(周期为10),之后再进行write任务
compare结果如下图
波形如下图
标签:全加器,reference,agent,C语言,item,export,analysis,ready,port From: https://blog.csdn.net/qq_45667135/article/details/139332569