我是靠谱客的博主 还单身背包,最近开发中收集的这篇文章主要介绍UVM-FLM-FIFO,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

UVM-FLM-FIFO

在基本TLM通信put示例中,producer和consumer在同一个进程当中,consumer仅在put()方法调用时才处于活动状态。

在许多情况下,可能需要不同速率的组件(components)独立运行,UVM提供了uvm_tlm_fifo通道以支持此类通信。
在这里插入图片描述

uvm_tlm_fifo,顾名思义就是具有所有TLM接口方法的FIFO,producer可以将transaction放入uvm_tlm_fifo,consumer独立地从fifo获取transaction

在上图中componentA将一个transaction放到fifo中(put操作,如果fifo满会被block),componentB从fifo中获取一个transaction(get操作,如果fifo空会被block)。

两次连续的get()操作会获得不同的transaction,而两次连续的peek()操作会获得相同的transaction,因为peek()操作只是复制fifo中的transaction,并不会移除从fifo中移除。

下面是一个uvm_tlm_fifo的实例

Packet (transaction)继承自uvm_object,其在组件之间传输

class Packet extends uvm_object;  
	randbit[7:0] addr;  
	randbit[7:0] data;  

	`uvm_object_utils_begin(Packet)   
	`uvm_field_int(addr, UVM_ALL_ON)   
	`uvm_field_int(data, UVM_ALL_ON)  
	`uvm_object_utils_end  
	
	function new(string name = "Packet");   
		super.new(name);  
	endfunction
	
endclass

然后创建componentA,定义put_port,实现transaction的生成、约束和发送

class componentA extends uvm_component;  
	`uvm_component_utils (componentA) 

	uvm_blocking_put_port #(Packet) m_put_port;  

	int m_num_tx = 2;  

	function new (string name = "componentA", uvm_component parent= null);     
		super.new (name, parent);  
	endfunction  
	
	virtual function void build_phase(uvm_phase phase);     
		super.build_phase(phase);    
		m_put_port = new ("m_put_port", this);  
	endfunction  

	virtual task run_phase(uvm_phase phase);    
		phase.raise_objection(this);    
			repeat (m_num_tx) begin        
				Packet pkt = Packet::type_id::create ("pkt");        
				assert(pkt.randomize ());  
	  
				#50;         
				
				//Print the packet to be displayed in log        
				`uvm_info ("COMPA", "Packetsent to CompB", UVM_LOW)        
				pkt.print (uvm_default_line_printer);        
				//Call the TLM put() method of put_port class and pass packet as argument        
				m_put_port.put(pkt);     
			end     
		phase.drop_objection(this);  
	endtask
endclass

然后创建componentB,定义get_port,实现transaction的接收。可以看出,uvm_tlm_fifo的两端都是export,都是put()和get()的实现端,而不是发起端。

class componentB extend suvm_component;  
	`uvm_component_utils (componentB)  
	//Create a get_port to request for data from componentA  
	uvm_blocking_get_port #(Packet) m_get_port;  

	int m_num_tx = 2;  

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

	virtual function void build_phase(uvm_phase phase);     
		super.build_phase(phase);     
		m_get_port = new ("m_get_port", this);  
	endfunction  

	virtual task run_phase(uvm_phase phase);     
		Packet pkt;    
		phase.raise_objection(this);    
			repeat (m_num_tx) begin      
				#100;        
				m_get_port.get(pkt);        
				`uvm_info ("COMPB", "ComponentAjust gave me the packet", UVM_LOW)       
				pkt.print (uvm_default_line_printer);     
			end    
		phase.drop_objection(this);  
	endtask
endclass

最后在更高的测试平台层次中定义uvm_tlm_fifo,连接compA的put_port和tlm_fifo的put_export,以及compB的get_port和tlm_fifo的get_export

在这里插入图片描述

class my_test extendsuvm_env;  
	`uvm_component_utils (my_test)  

	componentA compA;  
	componentB compB;  

	int m_num_tx;  

	//Create the UVM TLM Fifo that can accept simple_packet  
	uvm_tlm_fifo #(Packet)   m_tlm_fifo;  

	functionnew (string name = "my_test", uvm_component parent = null);     
		super.new (name, parent);  
	endfunction  

	virtual function void build_phase(uvm_phase phase);     
		super.build_phase(phase);     
		//Create an object of both components     
		compA = componentA::type_id::create ("compA", this);     
		compB = componentB::type_id::create ("compB", this);    
		std::randomize(m_num_tx) with {m_num_tx inside {[4:10]}; };    
		compA.m_num_tx = m_num_tx;    
		compB.m_num_tx = m_num_tx;     

		//Create a FIFO with depth 2     
		m_tlm_fifo = new ("uvm_tlm_fifo", this, 2);  
	endfunction  

	//Connect the ports to the export of FIFO.  
	virtualfunctionvoid connect_phase(uvm_phase phase);    
		compA.m_put_port.connect(m_tlm_fifo.put_export);    
		compB.m_get_port.connect(m_tlm_fifo.get_export);  
	endfunction  

	//Display a message when the FIFO is full  
	virtualtask run_phase(uvm_phase phase);     
		forever begin       
		#10;       
		if(m_tlm_fifo.is_full ())         
			`uvm_info ("UVM_TLM_FIFO", "Fifo isnow FULL !", UVM_MEDIUM)              
		end  
	endtask
endclass

仿真结果

# UVM_INFO tb_classes/componentA.sv(33) @50: uvm_test_top.compA [COMPA] Packet sent to CompB
# pkt: (Packet@543) { addr: 'h10  data: 'hcc }
# UVM_INFO tb_classes/componentB.sv(26) @100: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
# pkt: (Packet@543) { addr: 'h10  data: 'hcc }
# UVM_INFO tb_classes/componentA.sv(33) @100: uvm_test_top.compA [COMPA] Packet sent to CompB
# pkt: (Packet@544) { addr: 'h3e  data: 'h92 }
# UVM_INFO tb_classes/componentA.sv(33) @150: uvm_test_top.compA [COMPA] Packet sent to CompB
# pkt: (Packet@545) { addr: 'hde  data: 'h65 }
# UVM_INFO tb_classes/my_test.sv(40) @ 150:uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
# UVM_INFO tb_classes/my_test.sv(40) @ 160:uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
# UVM_INFO tb_classes/my_test.sv(40) @ 170:uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
# UVM_INFO tb_classes/my_test.sv(40) @ 180:uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
# UVM_INFO tb_classes/my_test.sv(40) @ 190:uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
# UVM_INFO tb_classes/componentB.sv(26) @200: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
# pkt: (Packet@544) { addr: 'h3e  data: 'h92 }

componentA每隔50ns往tlm_fifo写入一个transaction,componentB每隔100ns从tlm_fifo读出一个transaction。

转自微信公众号:数字芯片实验室

最后

以上就是还单身背包为你收集整理的UVM-FLM-FIFO的全部内容,希望文章能够帮你解决UVM-FLM-FIFO所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部