GOOSE报文分析_详解GOOSE服务

https://www.cnblogs.com/software4y/p/10017602.html

http://blog.sina.com.cn/s/blog_af8298410102wnvm.html

https://www.cnblogs.com/software4y/p/10017930.html

https://wenku.baidu.com/view/d47c10c389eb172ded63b75e.html

以上四篇文章整理如下文。

面向通用对象的变电站事件模型GOOSE

图片出自《浅谈GMRP在变电站中的应用》一文

       在分布式的变电站自动化系统中,IED共同协助完成自动化功能的应用场合越来越多,如间隔层的设备之间的防误闭锁、分布式母线保护等,这些功能得以完成的重要前提条件是IED之间数据通信的可靠性和实时性。基于此,IEC61850中定义了通用变电站事件(Generic Substation Event,GSE)模型,该模型提供了在全系统范围内快速可靠地输入、输出数据值的功能。

      GSE分为两种不同的控制类和报文结构:①面向通用对象的变电站事件(Generic Object Oriented Substation Event,GOOSE),支持由数据集(Data-Set)组织的公共数据交换:②通用变电站状态事件(Generic Substation State Event,GSSE),用于传输状态变位信息(双比特)。如果只从抽象通信服务模型控制块(Control Block)的属性和服务定义两方面比较,GOOSE和GSSE差异不大,但实际上,两者的报文传输内容和实现机制截然不同。GSSE报文传输服务均映射于OSI的7层协议堆栈中,一方面存在协议堆栈传输延时,另一方面,此报文仍基于传统的以太网实现,不支持报文优先级和虚拟局域网、无特定的多播地址等。这使得当网络负荷较重时,难以保证报文传输的实时性。GSSE目前较少使用。下面主要介绍应用最多的GOOSE的服务。

       IEC61850中定义的面向通用对象的变电站事件(GOOSE)以快速的以太网多播报文传输为基础,代替了传统的智能电子设备IED之间的硬接线的通信方式,为逻辑节点间的通信提供了快速且高效可靠的方法。GOOSE服务主要用于传输变电站内保护跳闸、断路器位置、测控联锁等实时性要求的数据,还可以传输如温湿度等模拟量信息,甚至可以传输时间同步信息等。

2 GOOSE发送机制及其特点 

2.1 发送机制

        GOOSE报文的发送采用心跳报文和变位报文快速重发相结合的机制,按图1所示的规律执行。

        其中T0又称心跳时间,在GOOSE数据集中的数据没有变化的情况下,装置平均每隔T0时间发送一次当前状态,即心跳报文,报文中的状态序号stNum(StateNumber用于记录GOOSE数据发生变位的总次数)不变,顺序sqNum(SequenceNumber用于记录稳态情况下报文发出的帧数)递增。

       当装置中有事件发生(如开关状态变位)时,GOOSE数据集中的数据就发生变化,装置立刻发送该数据集的所有数据,然后间隔T1发送第2帧及第3帧,间隔T2、T3发送第4、5帧,T2为2T1,T3为4T1,后续报文以此类推,发送间隔以2倍的规律逐渐增加,直到增加到T0,报文再次成为心跳报文。当数据变位后的第1帧报文中stNum增加1,sqNum从零开始,随后报文中stNum不变,sqNum递增。

       工程应用中,T0设为5s,T1设为2ms。GOOSE状态变位过程共发5帧数据,即以2ms—2ms—4ms—8ms的时间间隔重发GOOSE报文,连续发5帧后便以5s时间间隔变成心跳报文。

       GOOSE接收可以根据报文允许存活时间来检测链路中断,定义报文允许存活时间为2T0,接收方若超过2倍允许存活时间没有收到GOOSE报文即判为中断,发GOOSE断链报警信号。由此,通过GOOSE通信机制也实现了装置间二次回路状态在线监测。

                                                                         图1 GOOSE报文传输时间

 

        T0—稳定条件下,心跳报文传输间隔;(T0)—稳定条件下,心跳报文传输可能被事件打断;T1—事件发生后,最短的重传间隔;T2、T3一直至获得稳定条件的重传间隔。

         GOOSE采用发布者/订阅者通信结构,此通信结构支持多个通信节点之间的对等直接通信。与点对点通信结构和客户/服务器通信结构相比,发布者/订阅者通信结构是一个或多个数据源(即发布者)向多个接收者(即订阅者)发送数据的最佳解决方案,尤其适合数据流量大且实时性要求高的数据通信。发布者/订阅者通信结构符合GOOSE报文传输本质,是事件驱动的。

2.2 报文结构     

   GOOSE报文的传输过程与普通的网络报文不同,它是从应用层经过表示层ASN.1编码后,直接映射到底层的数据链路层和物理层(如图2所示),而不经TCP/IP协议,即不经网络层和传输层。这种映射方式避免了通信堆栈造成的传输延时,从而保证了报文传输的快速性。其中,ASN.1基本编码规则采用的编码结构由标记(Tag)、长度(Length)以及内容(Value)三个部分组成。

       Goose报文在网络上传输时采用的是OSI模型,但只用到OSI网络模型七层中的四层,应用层、表示层、数据链路层和物理层,传输层和网络层为空。应用层定义协议数据单元PDU,经过表示层编码后,不采用TCP/IP协议,而是直接映射到数据链路层和物理层。这种映射方式的目的是避免通信堆栈造成传输延时,从而保证报文传输、处理的快速性。

                                         图2 GOOSE报文结构

3 GOOSE接收机制

3.1 GOOSE单网接收机制

        装置的单网GOOSE接收机制,如图3 所示,装置的GOOSE接收缓冲区接收到新的GOOSE报文,接收方严格检查GOOSE报文的相关参数后,首先比较新接收帧和上一帧GOOSE报文中的StNum(状态号)参数是否相等。若两帧GOOSE报文的StNum相等,继续比较两帧GOOSE报文的SqNum(顺序号)的大小关系,若新接收GOOSE帧的SqNum大于上一帧的SqNum,丢弃此报文,否则更新接收方的数据。若两帧GOOSE报文的StNum不相等,更新接收方的数据。

3.2 GOOSE双网接收机制

        接受方和发送方都采用自动信息处理装置并通过双网相连,两个网络同时工作,装置的GOOSE接收缓冲区接收到新的GOOSE报文,接收方严格检查GOOSE报文的相关参数后,首先比较新接收帧和上一帧GOOSE报文中的StNum。

若StNum大于上一帧报文,则判断为新数据,更新老数据。

若StNum等于上一帧报文,再将SqNum与上一帧进行比较,如果SqNum大于等于上一帧,则判断是重传报文而丢弃,

                                          如果SqNum小于上一帧,则判断发送方是否重启装置,是则更新数据,否则丢弃数据。

若StNum小于上一帧报文,则判断发送方是否重启装置,是则更新数据,否则丢弃报文。在丢弃报文的情况下,判断该网络故障,通过网络切换装置切换到备用网络进行传输。这种方法采用双网同时工作的模式,保证了传输的快速性,由接收方判别是否通信中断并决定是否更新数据,当接收到重传或因某一网络故障而传输的错误信息时,并不会更新数据,从而保证了数据的可靠性。

4 GOOSE报文帧结构

来源见水印

       规定表示层格式,以便通用于不同的数据处理机制。

       根据IEC61850标准,GOOSE报文在数据链路层上采用ISO/IEC 8802-3以太网协议,GOOSE报文由报文头和协议数据单元PDU两部分组成,报文头部分如图5 所示,协议数据单元PDU部分如图6 所示。

      GOOSE报文在MAC层的帧结构包括:源MAC地址、目的地址即组播地址、报文类型、四字节Tag、APPID、报文长度、四字节的保留和APDU。

      ASN.1 BE R 编码形式: 编码规则遵循标记TAG(也有称TYPE)、长度LENGTH、值VALUE的格式,简称TLV。

Tag + Length + Value 的形式:

1)Tag 与数据类型标记的编码一致;     

2)Length 表示后面 Value 的长度;

3)Value 应用 ASCII 码进行编码解析。

ASN.1 allData{   }中数据类型

                                                图5  GOOSE报文头    

Header MAC

MAC目的地址(6字节)

6个字节的目的地址“01 0c cd 01 00 33”。前三个字节固定为“01-0C-CD”,第四个字节为“01”时代表GOOSE。IEC61850规定GOOSE报文目的地址取值范围为01-0C-CD-01-00-00~01-0C-CD-01-01-ff。

MAC源地址(6字节)

6个字节的源地址“00 10 00 00 00 33

Priority tagged

TPID(2字节标记)= 0x8100

TCI(2字节)

“8000”包括三个部分,用户优先级前三个Bit位“100”优先级为4,CFI占第四个Bit位“0”,VLAN ID占最后十二个Bit位全0=0。

(TPID + TCI ) 部分可以不使用,但强烈建议以太网传输的时候加入。

网络数据类型

Ethertype(2字节)=0x88B8

IEC 61850中各种报文的以太网类型已经由IEEE的著作权注册机构进行了注册,GOOSE报文的以太网类型值是0x88B8。

APPID (2字节)=0x0000~0x3FFF

应用标识APPID“00 33”,该值全站唯一。

Length(2字节)= 8+m

0x00B6十进制数为182,表示数据帧从APPID开始到应用协议数据单元APDU结束的部分共有182个字节。

Reserved 1(2字节)=0x0000

Reserved 2(2字节)=0x0000

APDU,详述见下方表格

                                                           

                                          

                                                                图6  GOOSE PDU部分

GOOSE的APDU报文格式见下表

APDU数据T-L

标记61H,长度。

此长度占用可能为1,2,3...字节,具体格式如下方右侧图。ASN.1的字节数都在用此方式。

  

GoCBRef字符串

标记80H,长度≤65(占用字节数不确定,参考),GOOSE控制块索引

由分层模型中的逻辑设备名、逻辑节点名、功能约束和控制块名级联而成。

允许生存时间

标记81H,长度,t

该参数值一般为心跳时间T0值的2倍,如果接收端超过2T0时间内没有收到报文则判断报文丢失,在4T0时间内没有收到下一帧报文即判断为GOOSE通信中断,判出中断后装置会发出GOOSE断链报警。

Datset字符串

标记82H,长度≤65,Datset字符串

即GOOSE控制块所对应的GOOSE数据集引用名,由逻辑设备名、逻辑节点名和数据集名级联而成。报文中Data部分传输的就是该数据集的成员值。

GoID

标记83H,长度≤65

该参数是每个GOOSE报文的唯一性标识,该参数的作用和目的地址、APPID的作用类似。接收方通过对目的地址、APPID和goID等参数进行检查,判断是否是其所订阅的报文。

StNum 时间

标记84H,长度=8,t

即Event TimeStamp,事件时标,其值为GOOSE数据发生变位的时间,即状态号stNum加1的UTC时间

此时间格式共占8个字节,其中的前四个字节是从1970年1月1日0时0秒0分0秒至今流过的秒数,紧跟着的3个字节是秒的小数部分,最后的一个字节是时间的品质和精度 

StNum 值

标记85H,长度≤5,StNum值

即StateNumber,状态序号,用于记录GOOSE数据发生变位的总次数

SqNum

标记86H,长度≤5,SqNum值

即SequenceNumber,顺序号SqNum,用于记录稳态情况下报文重复发出的帧数,装置每发出一帧GOOSE报文,SqNum应加1;当有GOOSE数据变化时,该值归0,从头开始重新计数。

Test位

标记87H,长度=1,test值

布尔型变量,检修标识,用于表示发出该GOOSE报文的装置是否处于检修状态。当检修压板投入时,test标识应为True。

配置版本号

标记88H,长度≤5,ConfRev

配置版本号,Config Revision是一个计数器,代表GOOSE数据集配置被改变的次数。当对GOOSE数据集成员进行重新排序、删除等操作时,GOOSE数据集配置被改变。配置每改变一次,版本号应加1。

未配置好标志

标记89H,长度=1,Needs commissioning

该参数是一个布尔型变量,用于指示GOOSE是否需要进一步配置。

GOOSE的ASN.1编码单元个数

标记8aH,长度≤5,总个数

NumDataSetEntries:即数据集条目数,图中其值为“19”,代表该GOOSE数据集中含有19个成员,相应地报文Data部分含有19个数据条目。(alldata中数据链的个数)

GOOSE数据T-L

标记abH,长度

该部分是GOOSE报文所传输的数据当前值。Data部分各个条目的含义、先后次序和所属的数据类型都是由配置文件中的GOOSE数据集定义的。

GOOSE状态

标记83H,长度=1,stVal

标记84H,长度=2,q

标记91H,长度=8,t

GOOSE整型

标记85H,长度=4,值(4字节)

GOOSE浮点

标记87H,长度=5,08H,浮点(4字节)

……

           

解析注意事项:

1.Length-ASN.1的字节数不确定。假定数据域的字节数为n。按ASN.1的编码规则,当n≤127时Length只有一个字节,值为n;当n>127时,Length有2~127字节,第一个字节的Bit7为1,Bit0~6为Length总字节数减1,第二个字节开始给出n,基于256,高位优先(例子:200用ASN.1表示就是0x81C8)

2.GOOSE数据部分,数据集中具体的数据顺序,需要根据goose配置文件进行解析

5 GOOSE报文分析

5.1 例程1

GOOSE报文在MAC层的帧结构包括:源MAC地址、目的地址即组播地址、报文类型、四字节Tag、APPID、报文长度、四字节的保留和GOOSEPDU。Goose具体报文格式如图0所示。

 

图0 Goose报文格式

Goose举例报文(十六进制):

01 0C CD 01 00 51 00 1E 4F D3 AE 41 81 00 80 42 88 B8 00 33 00 90 00 00 00 00 61 81 85 80 08 67 6F 63 62 52 65 66 31 81 05 00 00 00 27 10 82 07 64 61 74 53 65 74 31 83 05 67 6F 49 44 31 84 08 4E F2 85 E1 F7 CE D9 00 85 05 00 00 00 00 01 86 05 00 00 00 00 01 87 01 00 88 05 00 00 00 00 01 89 01 00 8A 05 00 00 00 00 09 AB 36 83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00 83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00 83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00

分析如下(可结合Ethereal解析):

1、01 0C CD 01 00 51

目的MAC地址

2、00 1E 4F D3 AE 41

源MAC地址

3、81 00 80 42

GOOSE报文支持IEEE 802.1Q/P优先级技术,IEEE 802.1Q为VLAN技术的标准,IEEE 802.1P为报文优先级标准。

这4个字节共同组成goose报文的tag位。Tag是有两个字节的TPID(标签协议标识)和2个字节的TCI(标签控制信息)组成。TPID配置为0x8100表示goose报文加入了优先级标识。TPID和TCI组成如图1所示:

 

图1:PID和TCI组成

TCI中12位VID,1位CFI和3位Priority(优先级)。12位VID可以配置4096个VLAN,CFI一般配置为0,3位Priority可以分为8个优先级:其中只配置了0-4级,5、6、7及保留未来使用。

4、88 B8 

以太网类型值

0x88 B8为goose,0x88 B9为GSE,0x88 BA为采样值。如图3所示

 

图3 以太网类型值分配

5、00 33

APPID

两字节的最高两位对照图3解释。所以此处APPID=51(D)

6、00 90

长度=144(D)

长度字节数包含从APPID开始以太网PDU头和APDU(应用协议数据单元)的长度。长度是8+m,m是APDU的长度,m<1492。

为什么是8+m?这个8个字节分别是APPID 2个字节,长度2个字节,以及后面的保留1、保留2各两个字节。对应到本帧报文的8个字节为:00 33 00 90 00 00 00 00。

7、00 00 00 00

保留1、保留2。为将来的应用扩展使用,缺省值为0。

8、61 81 85

GoosePDU开始(APDU应用协议数据单元)

搞清楚这个,得看ASN.1编码,此处稍作解释。ASN.1的传输基于八位位组的字节序列来进行的,它的编码规则遵循标记TAG(也有称TYPE)、长度LENGTH、值VALUE的格式,简称TLV,如图4所示。

 

图4 ASN.1编码格式

对图4解释:

TAG:

一般占1或者2个字节。TAG的组成如图5所示,

 

图5 TAG编码格式

Bit7 Bit6 :Type of Tag ,如上图。

Bit5:Primitive or Constructed Flag =0表示VALUE为简单结构,即只包含数值内容。

                                                             =1表示VALUE为复合结构,即VALUE还包含了TLV结构,直至TLV结构中Bit5为0.

Bit4~0:由于最高的3位(7、6、5)作为它用,因此TAG(bit4~0)只能表示到11111(b)=31(D)。若想表示>31是,此时TAG就要占2个字节(第1个字节后面的被称为扩展字节)。此时TAG编码格式如图6所示。

 

图6  大于31时TAG编码

对图6解释:

此时字节1中Bit7~5不变,Bit4~0全为1,字节2表示真正的TAG值,可表示0~255。

LENGTH:

紧跟TAG后面的length,它描述后续的VALUE值是由多少个字节数所构成。若VALUE长度≤127,则LENGTH占1个字节,字节最高位为Bit7=0;若VALUE长度>127,则LENGTH第1个字节最高位Bit7=1,Bit6~0表示的是LENGTH本身所占的字节数,从第2个字节开始到最后1个字节表示的是VALUE的长度。如图7所示。

 

图7 LENGTH编码格式

VALUE:

Tag Value 值。实际所要传递的编码内容,具体编码规则,根据不同的标记类型,采用不用的编码规范。

因此,结合上述,对61 81 85解释为:TAG=0x61,APPLICATION应用,复合结构,tag值为1。0x81最高位为1,表示VALUE长度>127,LENGTH本身长度为1,即:0x85。后续VALUE长度为0x85=133(D)个字节。

9、之后的字节排列顺序如图8所示

 

图8 IECGoosePDU报文格式

10、80 08 67 6F 63 62 52 65 66 31

gocbRef字符串

ASN.1编码格式TLV。80为TAG,08为LENGTH,后面的为VALUE, 67 6F 63 62 52 65 66 31转换成字符为gocbRef1。

11、81 05 00 00 00 27 10

timeAllowedtoLive(报文存活时间,单位ms)

ASN.1编码格式TLV。81为TAG,05为LENGTH,后面的为VALUE,00 00 00 27 10转成10进制为10000,即10s。

Goose接收方的中断时间一般定为大于2* timeAllowedtoLive即报Goose中断告警。

由于Goose报文的重要性,即使外部状态不再变换,也应重发。此参数提示订阅者等待下一报文到来的最长时间。当等待事件大于timeAllowedtoLive值仍未收到有效报文时,订阅者认为通信联系失去,采用预先定义的默认值取代。

12、82 07 64 61 74 53 65 74 31

datSet字符串

ASN.1编码格式TLV。82为TAG,07为LENGTH,后面的为VALUE, 64 61 74 53 65 74 31转换成字符为datSet1。

13、83 05 67 6F 49 44 31

goID字符串

ASN.1编码格式TLV。83为TAG,05为LENGTH,后面的为VALUE, 67 6F 49 44 31转换成字符为goID1。

14、84 08 4E F2 85 E1 F7 CE D9 00

t,stnum加1时的时间,精确到毫秒。

Goose报文产生时的时标。通常作为驱动事件的发生时标(若有特殊要求,驱动事件的发生时标可另外包含在数据集中)。

ASN.1编码格式TLV。84为TAG,08为LENGTH,后面的为VALUE。

第8个字节代表品质因数。

15、85 05 00 00 00 00 01 86 05 00 00 00 00 01

stnum值  85 05 00 00 00 00 01

sqnum值 86 05 00 00 00 00 01

装置发送方:后面allData数据跟上一次的allData值不一致时stnum+1,sqnum=0。一致时stnum不变,sqnum+1。上电第1帧时stnum=1,sqnum=1。stnum、sqnum加到最大值时都从1开始。

装置接收方:上电时stnum=sqnum=0。

16、87 01 00

test位

当装置检修压板投入时,装置发送的GOOSE报文中的test应置位。Goose接收装置应将接收的Goose报文中的test位与装置自身的检修压板状态比较,只有两者一致时才将信号作为有效进行处理或动作。

17、88 05 00 00 00 00 01

confRev()

配置版本号(配置次数)。表示Data-Set配置改变的计数器,例如当Data-Set里某个成员被删除或成员重新排序等均会导致confRev数值改变。

18、89 01 00

ndsCom

表示此控制块配置的必要性,当属性dataset值为NULL时,ndsCom值应为TRUE,表示此控制块需进一步配置。

19、8A 05 00 00 00 00 09

numDatSetEntries

表示allData中有多少个数据项,此处表示有9个

20、AB 36

从这开始到结束为allData内容

TAG=0xAB,上下文关联,复合结构,即VALUE也是有TLV组成。

LENGTH=0x36=54(D)

21、83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00

时间t表示最后一次状态变位发生的时间,是格林威治时间,即比当前时间晚了8个小时。时间品质反应最后一次状态变位发生时候的时间品质,而不是当前状态的时间品质。

22、83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00

83 01 00 84 03 03 00 00 91 08 00 00 00 00 00 00 00 00

21

5.2  例程2

  • 32
    点赞
  • 199
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
首先,需要了解Goose报文的结构。Goose报文是基于IEC 61850标准的一种通信协议,主要用于在电力系统中进行广域保护和控制。它采用了Ethernet II帧的格式,但添加了一些特殊的字段,用于传输IEC 61850数据。 以下是Goose报文的基本结构: ![Goose报文结构](https://i.imgur.com/gJ7Vd3b.png) 其中,各字段的含义如下: - Destination MAC Address:目的MAC地址,通常为组播地址。 - Source MAC Address:源MAC地址。 - EtherType:以太网类型,固定为0x88B8。 - VLAN Tag:可选的VLAN标签,如果存在则占4个字节。 - APPID:应用程序标识符,用于标识Goose报文。 - Length:数据长度,包括APPID、数据集和GOOSE Control Block。 - Goose Control Block:Goose控制块,包括时间戳、状态变量和数据变量。 - Dataset:数据集,包括状态变量和数据变量。 下面是一个用Verilog实现的Goose报文解析代码示例: ```verilog module goose_parser ( input wire [7:0] rx_data, input wire rx_clk, input wire rx_valid, input wire rst_n, output reg [7:0] appid, output reg [15:0] length, output reg [31:0] time, output reg [47:0] mac_dest, output reg [47:0] mac_src, output reg [15:0] ethertype, output reg [15:0] vlan_tag, output reg [15:0] goose_appid, output reg [15:0] goose_length, output reg [15:0] goose_protocol, output reg [7:0] goose_pdu[], output reg [7:0] goose_mac[], output reg [15:0] goose_mac_length ); reg [7:0] rx_data_reg [63:0]; reg [5:0] rx_data_count; reg [7:0] appid_reg [1:0]; reg [15:0] length_reg [1:0]; reg [31:0] time_reg [1:0]; reg [47:0] mac_dest_reg [1:0]; reg [47:0] mac_src_reg [1:0]; reg [15:0] ethertype_reg [1:0]; reg [15:0] vlan_tag_reg [1:0]; reg [15:0] goose_appid_reg [1:0]; reg [15:0] goose_length_reg [1:0]; reg [15:0] goose_protocol_reg [1:0]; reg [7:0] goose_pdu_reg [255:0]; reg [7:0] goose_mac_reg [5:0]; reg [15:0] goose_mac_length_reg; reg [1:0] state; parameter IDLE = 2'b00; parameter RX_HEADER = 2'b01; parameter RX_GOOSE_PDU = 2'b10; always @(posedge rx_clk) begin if (!rst_n) begin state <= IDLE; rx_data_count <= 0; appid_reg[0] <= 8'h00; appid_reg[1] <= 8'h00; length_reg[0] <= 16'h0000; length_reg[1] <= 16'h0000; time_reg[0] <= 32'h00000000; time_reg[1] <= 32'h00000000; mac_dest_reg[0] <= 48'h000000000000; mac_dest_reg[1] <= 48'h000000000000; mac_src_reg[0] <= 48'h000000000000; mac_src_reg[1] <= 48'h000000000000; ethertype_reg[0] <= 16'h0000; ethertype_reg[1] <= 16'h0000; vlan_tag_reg[0] <= 16'h0000; vlan_tag_reg[1] <= 16'h0000; goose_appid_reg[0] <= 16'h0000; goose_appid_reg[1] <= 16'h0000; goose_length_reg[0] <= 16'h0000; goose_length_reg[1] <= 16'h0000; goose_protocol_reg[0] <= 16'h0000; goose_protocol_reg[1] <= 16'h0000; goose_mac_length_reg <= 16'h0000; state <= IDLE; end else begin case (state) IDLE: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 6) begin mac_dest_reg[1] <= {rx_data_reg[0], rx_data_reg[1], rx_data_reg[2], rx_data_reg[3], rx_data_reg[4], rx_data_reg[5]}; mac_src_reg[0] <= {rx_data_reg[0], rx_data_reg[1], rx_data_reg[2], rx_data_reg[3], rx_data_reg[4], rx_data_reg[5]}; state <= RX_HEADER; rx_data_count <= 0; end end end RX_HEADER: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 2) begin ethertype_reg[1] <= rx_data_reg[0]; ethertype_reg[0] <= rx_data_reg[1]; state <= RX_GOOSE_PDU; rx_data_count <= 0; end end end RX_GOOSE_PDU: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 8) begin appid_reg[1] <= rx_data_reg[0]; appid_reg[0] <= rx_data_reg[1]; length_reg[1] <= rx_data_reg[2]; length_reg[0] <= rx_data_reg[3]; time_reg[3] <= rx_data_reg[4]; time_reg[2] <= rx_data_reg[5]; time_reg[1] <= rx_data_reg[6]; time_reg[0] <= rx_data_reg[7]; state <= RX_GOOSE_PDU; rx_data_count <= 0; end else if (rx_data_count > 8 && rx_data_count <= 8 + length_reg[1] + length_reg[0]) begin goose_pdu_reg[rx_data_count-9] <= rx_data; if (rx_data_count == 8 + length_reg[1] + length_reg[0]) begin goose_protocol_reg[1] <= goose_pdu_reg[0]; goose_protocol_reg[0] <= goose_pdu_reg[1]; goose_appid_reg[1] <= goose_pdu_reg[2]; goose_appid_reg[0] <= goose_pdu_reg[3]; goose_length_reg[1] <= goose_pdu_reg[4]; goose_length_reg[0] <= goose_pdu_reg[5]; goose_mac_length_reg <= goose_pdu_reg[6] * 256 + goose_pdu_reg[7]; for (int i=0; i<goose_mac_length_reg; i=i+1) begin goose_mac_reg[i] <= goose_pdu_reg[i+8]; end end rx_data_count <= rx_data_count + 1; end end end endcase end end assign appid = appid_reg[1:0]; assign length = length_reg[1:0]; assign time = time_reg[3:0]; assign mac_dest = mac_dest_reg[1:0]; assign mac_src = mac_src_reg[1:0]; assign ethertype = ethertype_reg[1:0]; assign vlan_tag = vlan_tag_reg[1:0]; assign goose_appid = goose_appid_reg[1:0]; assign goose_length = goose_length_reg[1:0]; assign goose_protocol = goose_protocol_reg[1:0]; assign goose_pdu = goose_pdu_reg[255:0]; assign goose_mac = goose_mac_reg[5:0]; assign goose_mac_length = goose_mac_length_reg; endmodule ``` 这个模块将输入的Goose报文解析为各个字段,包括目的MAC地址、源MAC地址、应用程序标识符、数据长度、时间戳、数据集等。它通过有限状态机实现了报文解析的逻辑,一步一步地读取报文中的数据,并将其存储到对应的寄存器中。最后,通过输出端口将各个字段输出。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值