基于system verilog开发FPGA struct 、 interface

System Verilog助力FPGA开发

文章

背景:

       在fpga开发项目的时候,尤其是模块比较多的时候,那么信号连接多,需要在多个模块内保持信号连接正确,并且位宽需要保持一致,在这个问题上经常会疏忽出错,近期开发fpga项目时使用了system verilog来进行开发FPGA,在这个过程中发现了一些优点,特此分享,syetem verilog的语法是兼容verilog的,在fpga开发时只会用到部分可综合的语法,恰是这部分语法让fpga开发变得更加方便。

      1、system verilog中的 ** struct ** 在协议组包和参数读取处理等应用上比较方便

      2、system verilog中的 ** interface ** 让模块间的连接变得非常简洁清晰,省区繁杂的连接

一、struct

在system verilog里体的使用结构体可以使逻辑开发的效率提高,并且具有非常高的可读性,下面举例结构体的具体使用的一个场景,我们在用fpga开发以太网时进行协议组包时请问之前是怎么进行操作的?可能不同的人做法不尽相同,可读性可参差不齐,今天我们来介绍下使用结构体来进行组包操作。

1、第一步使用结构体需要先声明一个结构体,和C++里的用法类似,下面一段代码就是对以太网的MAC头进行组包,对IP层的20个Byte进行组包。

typedef struct packed{
logic	[63:0]		 preamble 		  	;
logic	[47:0]		 target_mac		  	;		//arp_tx里的target 在这里看是pc端
logic	[47:0]		 sender_mac		  	;		//arp_tx里的sender 在这里看是板端
logic	[15:0]		 eth_type 		  	;		//0806 代表arp协议 0800代表ip协议
}mac_t;		

typedef struct packed{
logic	[3:0]		 version	 		;		//4    : ipv4
logic	[3:0]		 header_len 		;		//5    : 5*32bit(4字节)=20字节
logic	[7:0]		 tos		 		;		//00   
logic	[15:0]		 total_len 	  		;		//xx   : (ip头+udp首部+数据)/(ip头+icmp首部+数据)
logic	[15:0]		 identification  	;		//xx   :  0000
logic	[15:0]		 flag_offset 	  	;		//xx   :  0000
logic	[7:0]		 time_to_live	  	;		//xx   :  80('d128)
logic	[7:0]		 protocol	   	  	;		//01 : icmp  11 : udp
logic	[15:0]		 checksum	   	  	;		//IP头部的校验和
logic	[31:0]		 sender_ip	  		;		//在这里看是板端
logic	[31:0]		 target_ip	  		; 		//在这里看是PC端
}ip_t;	

2、声明了结构体,就要实例化一下

mac_t			mac			;
ip_t			ip			;

3、上述是进行声明结构体,那么如何使用呢,我们下面看一下如何使用,

这样就可以对结构体的便利进行装载具体的参数,后续只要把结构体进行发送就可以了。

always @(posedge gmii_clk) eth.mac.preamble 	 =  64'h55555555555555d5	;
always @(posedge gmii_clk) eth.mac.target_mac	 =  traget_mac_tx			;
always @(posedge gmii_clk) eth.mac.sender_mac	 =  sender_mac		 		;
always @(posedge gmii_clk) eth.mac.eth_type 	 =  16'h0800			 	; 
												    
always @(posedge gmii_clk) eth.ip.version	 	 =  4'h4			 		; 
always @(posedge gmii_clk) eth.ip.header_len 	 =  4'h5			 		; 
always @(posedge gmii_clk) eth.ip.tos		 	 =  8'h00			 		; 
always @(posedge gmii_clk) eth.ip.total_len 	 =  tx_dlen					; 
always @(posedge gmii_clk) eth.ip.identification =  16'h0000				; 
always @(posedge gmii_clk) eth.ip.flag_offset 	 =  16'h0000				; 
always @(posedge gmii_clk) eth.ip.time_to_live	 =  8'h80			 		; 
always @(posedge gmii_clk) eth.ip.protocol	   	 =  8'h11	  				; 
always @(posedge gmii_clk) eth.ip.checksum	   	 =  16'h0000  				; 
always @(posedge gmii_clk) eth.ip.sender_ip	  	 =  sender_ip				; 
always @(posedge gmii_clk) eth.ip.target_ip	  	 =  traget_ip_tx			;

4、结构体还支持继承的使用,如上已经有了MAC和IP的组包,,那么UDP该怎么使用呢,可以看如下用法:在UDP的结构体中可以直接继承使用前面已有的结构体。

typedef struct packed{
mac_t				mac 				;		
ip_t				ip					;
logic	[15:0]		sender_port	   		;		//udp的发送端端口
logic	[15:0]		target_port	   		;		//udp的目的端端口
logic	[15:0]		total_len	   		;		//udp首部+数据 8+1024
logic	[15:0]		checksum	   		;		//组包时先填0
}udp_tx_t;		

 

 4、上述结构中的eth.xx其实就是使用了system-veriloginterface 使用interface有什么好处呢,在不使用的情况下,模块间的例化模块时会有很多信号接口,还要控制好信号的位宽,信号数量多的话,顶层模块会非常繁杂,那么使用 interface就会简化很多,下面举例使用interface进行例化的模块

RGMII_RX       		RGMII_RX	 	 (.sv(sv)  );	
RGMII_TX       		RGMII_TX	 	 (.sv(sv)  );	
GMII_ASYNC      	GMII_ASYNC 	 	 (.sv(sv)  );	
									 
ETH_Protocol   		ETH_Protocol  	 (.sv(sv) );	
CMD_Analysis   		CMD_Analysis  	 (.sv(sv) );	
Resp_Management		Resp_Management	 (.sv(sv) );	

5、结构体的使用还试用于一些参数的传递,在配合interface使用结构体传递参数也是非常的简单清晰。

欢迎讨论!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值