UART验证之uart_monitor
这篇文章提供一个uart_monitor的写法思路
1.monitor书写思路
首先是monitor中可能用到的信号
`ifndef UART_MONITOR_SV
`define UART_MONITOR_SV
class uart_monitor extends uvm_monitor;
//注册工厂机制
`uvm_component_utils(uart_monitor)
//使用uart interface中的信号
virtual uart_if vif;
//采样数据时需要使用到配置信息
uart_config cfg;
//定义一个TLM fifo用于向scoreboard发数据
uvm_analysis_port #(uart_frame) frame_collected_port;
//采样时钟,它是基于系统时钟和波特率换算出的用于采用的时钟信号
//在driver中要依据该时钟按bit发送数据,monitor中要依据该时钟按bit采样数据
//这样才能保证数据的收发双方的步调一致
bit sample_clk;
//这是生成采样时钟时所需要使用到的计数器,当count = ratio = pclk / baud_rate时,采样时钟翻转
bit [15:0] count;
//统计收集到的数据流数量
int num_frames;
//延迟信号,在采样的时候需要采集这个延迟信号的长度,
//赋值到uart_frame.transmit_delay中
int transmit_delay;
//这个信号用于指示是否检测到起始位,
//set 1表示起始位到了可以开始采样数据
bit sop_detected;
bit serial_d1; // UART数据线1
//这个信号用于存放从vif.txd和vif.rxd上传输的数据,
//在monitor中收集的就是这个数据
bit serial_b;
//收集到的数据流打包放到这个transaction中
uart_frame cur_frame;
uvm_event mon_done; // 监视器完成事件
uvm_event_pool event_pool; // 事件池
然后是monitor中需要实现的具体功能(略去build这种)
//复位方法,对需要复位的信号进行复位,以及实现工作中的复位
task reset();
endtask
//概括主函数的任务就是:生成采样时钟,从接口上的rxd端和txd端收集数据,
//并把数据打包成transaction通过TLM fifo发送到scoreboard中
task run_phase(uvm_phase phase);
while(1) begin//定义一个死循环,不断采样数据,
//这个循环的结束由sequence中的objection控制
//进来先复位一下
reset();
fork : FORK//主程序要用fork join_any块包住才能实现工作的复位
begin//阻塞一个下降沿进程,
//如果工作中复位了这个进程就能结束,触发fork join_any
@(negedge vif.rst_n);
`uvm_info(get_type_name(),"Detected Reset Done",UVM_LOW)
end
//第一个任务是产生用于采样的sample clk
gen_sample_rate();
//第二个任务是从vif.txd和vif.rxd上把数据赋值到serial_b信号上;
start_synchronizer();
//第三个任务是把serial_b上的数据按sample clk打包到cur_frame中
sample_and_store();
join_any
end
endtask
task uart_monitor::gen_sample_rate();
forever begin//时钟信号必须是一直产生的,由于在run_phase中运行,
//所以也由sequence中的objection机制控制其结束
@(posedge vif.clock);
if((!vif.rst_n) || (sop_detected)) begin//先复位
`uvm_info(get_type_name(), "sample_clk-resetting count", UVM_HIGH)
count = 0;
sample_clk = 0;
sop_detected = 0;
end
else begin
//产生采样时钟逻辑是当计数器count == ratio(假如为16)时就拉高sample_clk,
//然后复位count,这个高信号只保持1个系统时钟周期,采样发生在这一个cycle
//当count