背景技术
以太网帧的封装格式多样,在不同协议层有不同的封装。长度不一,除去7字节前导、1字节定帧、4字节的FCS,范围在60~1514/9600(普通/巨帧),以字节为单位。
封装的字段可能是固定值比如协议类型、版本号、默认保留字等,也可能是可变值比如时戳、MAC地址、IP地址等。各个字段长度不一,从1bit的比如MPLS的栈底标识到连续多个字节的比如MAC地址、IP地址甚至TLV。
由于兼顾硬件的高性能、并行和软件的可编程的特点,FPGA擅长高速、大容量数据包处理,常被用于实现成帧功能,尤其是需要产生处理大容量的协议周期帧的场景。
FPGA内常见的以太网帧的接口信号如表1所示,可能有裁剪比如没有sop甚至eop或没有pdv。
表1.常见的以太网帧接口信号列表
sop |
output |
帧首指示,指示一帧的开始 |
eop |
output |
帧尾指示,指示一帧的结束 |
pdv |
output |
数据有效,高有效,通常开始于sop结束于eop |
ept[ew-1:0] |
output |
帧尾空字节数,帧尾值可能非零,帧首、帧中为0。 |
pda[wid-1:0] |
output |
帧数据 |
帧长度以字节为单位,故wid是8的整数倍,且通常倍数是2的幂。每拍传送的字节数bn=wid/8。
帧尾字节数的位宽ew=log2(wid/8)。若帧数据位宽wid=8时,此时帧数据位宽即1字节,帧尾不会有空字节。
对特定帧,帧图案P={i1,i2,i3,i4,...},其中i1,i2,i3,...是实现帧功能的字段,帧长是len(单位字节)。可知一帧需要的时钟周期数beat=ceiling divide(len*8,wid)。帧尾有效字节数tail=len%bn,而帧尾无效字节数L=bn-tail。
FPGA内以太网帧接口一种常见时序示意图(以wid<=256为例)如图1所示。
帧首指示sop上升沿对齐了帧数据有效pdv的上升沿,帧尾指示eop下降沿对齐了pdv的下降沿,均一拍长度。在pdv有效包络的帧数据才是有效的。在帧数据有效期间(即pdv有效时),帧尾指示有效时ept才有非0值,其余保持零。换句话说,帧中不会有空白字节,只在帧尾有。
FPGA在实现成帧的一种常见结构如图2:
其中帧图案、帧长都是要实现既定帧的、已知的数据信息。用椭圆形表示。直角方框表示代码实现的结构。一个计算成帧节拍的计数器cnt_beat,将帧图案分组后产生的对应不同节拍的n个wid位宽的数据,一个多路复用器。
实现流程是:
CPU或其他处理流程把可变值字段的数值传递给FPGA;
FPGA:
(1)将固定的协议特征值和获取的可变值填充到帧图案的相应字段中;
(2)将帧图案P以帧数据位宽wid为单位,用硬代码显式的分成多组,如图3示例中c0,c1,c2,c3,c4,c5,…图中wid=8.
c0={i1[3:0],i2[7:4]};
c1={i2[3:0],i3[6:3]};
c2={i3[2:0],i4[0:0],i5[3:0]};
c3={i6[5:0],i7[14:13]};
c4={i7[12:5]};
c5={i7[4:0],…}
(3)成帧节拍计数器cnt_beat,当启动成帧时置为初始值,并自增/减1,直到计完至少beat个时钟周期。
当cnt_beat是起始值比如0时:帧首sop置高,并在1拍后置零;pdv置高,ept置零;
当cnt_beat是结束值比如beat-1时:帧尾eop置高,并在1拍后置零;pdv置零,ept=L;
当cnt_beat从起始值到结束值,即cnt_beat=i/beat–1-i时,将ci从帧接口送出。i=0~beat-1。
在现有技术中,当接口改变、带宽变化等造成帧数据接口位宽变化时,P分组成ci产生变化如图5所示(c0,c1,c2…),以往使用ci硬代码组帧结构,会导致P分组要全部重构。当接口位宽变化,8位变成16位时:
c0={i1[3:0],i2[7:0],i3[6:3]};(异)
c1={i3[2:0],i4[0:0],i5[3:0],i6[5:0],i7[14:13]};(异)
c2={i7[12:0],…};(异)
在现有技术中,不分段整帧产生的结构,会导致帧图案若有变化,都会从变化的地方到帧尾的字段全部重构。当帧内容插入删除某字段,增删字段及增删位置之后的ci分组产生变化如图6(增加了i8)、图7(删除了i4)所示,导致变化的部分都要重新实现。
增加了i8的ci分组:
c0={i1[3:0],i8[1:0],i2[7:6]};(异)
c1={i2[5:0],i3[6:5]};(异)
c2={i3[4:0],i4[0:0],i5[3:2]};(异)
c3={i5[1:0],i6[5:0]};(异)
c4={i7[14:7]};(异)
c5={i7[6:0],…}(异)
删除了i4的ci分组:
c0={i1[3:0],i2[7:4]};(同)
c1={i2[3:0],i3[6:3]};(同)
c2={i3[2:0],i5[3:0],i6[5:5]};(异)
c3={i6[4:0],i7[14:12]};(异)
c4={i7[11:4]};(异)
c5={i7[3:0],…}(异)
在现有技术中,同样的PDU使用不同的帧头的场景中,帧头、PDU以字节为单位,不同帧头很可能长度不一,比如根据业务类型不同要适配一层MPLS标签(22字节)和两层的(26字节),PDU的全部字段的实现都要重写。如下图8、图9所示:wid=8,帧头图案h,两层标签的是h[26*8-1:0],一层的是h[22*8-1:0],PDU图案则p[pl*8-1:0].
两层标签帧头的ci分组:
c0=h[26*8-1:18*8];
c1=h[18*8-1:10*8];
c2=h[10*8-1:2*8];
c3={h[2*8-1:0],p[pl*8-1:(pl-6)*8]};
c4=p[(pl-6)*8-1:(pl-14)*8];
c5=p[(pl-14)*8-1:(pl-22)*8];
一层标签帧头的ci分组:
c0=h[22*8-1:14*8];(同)
c1=h[14*8-1:6*8];(同)
c2={h[6*8-1:2*8],p[pl*8-1:(pl-2)*8]};(异)
c3=p[(pl-2)*8-1:(pl-10)*8];(异)
c4=p[(pl-10)*8-1:(pl-18)*8];(异)
c5=p[(pl-18)*8-1:(pl-26)*8];(异)
若参考仪表中帧产生器的设计,让CPU将所有帧内容据完全配置给FPGA,由FPGA从缓存中取出后发出。这样虽然在也可以灵活增删字段,PDU适配不同帧头,但因为处理数据包括了固定值数据和可变值数据,数据量增大,会从帧数据的产生和传输两方面给CPU带来额外的、非常大的负担,且需要消耗相当大的缓存资源。另一方面,这个大缓存带来的长延时,以及CPU产生帧的性能可能不能满足部分协议帧的性能要求,缓存带来的大延时抖动对涉及时间信息和时延的协议帧也不可接受。
具体实施方式
为了解决现有技术中存在的问题,下面通过附图以及列举本发明的一些可选实施例的方式,对本发明的技术方案(包括优选技术方案)做进一步的详细描述。显然,所描述的实施例仅仅是本发明的一部分实施例,而不是全部的实施例。基于本发明的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
参见图9所示,本发明实施例提供一种以太网成帧方法,该方法包括以下步骤:
S1.将待封装的帧拆分为多段;
在本实施例中,可以将待封装的帧拆分为固定长度字段和/或可变长度字段。
比如,要实现的帧,包括多种可选的帧头、PDU的协议规定的固定字段和PDU中的TLV(type length value)字段。则此时会按照帧头、PDU固定字段和TLV字段进行拆分。
其中,不同种类的帧头要进行多选一处理,用于组帧,PDU的固定字段是固定长度、协议规定必需的,而TLV可能是可变长度,还可能是可选的。
S2.确定锚点段,并基于所述锚点段控制每段的起始位置,使相邻段首尾相接且不交叠。
在本实施例中可以任意选择一段作为锚点段,也可以选择一个固定长度字段作为锚点段。
可以理解的是,本实施例中会确定一个必然存在的数据段为锚点段,特殊情况下待封装的帧可能只有一个数据段,那么此时整个数据段都可以作为一个锚点段。
确定出锚点段之后,以锚点段的起始可以确定一个位置,可以理解的是锚点段的起始用于组帧定位,不一定是帧头位置。
根据锚点段确定的位置及其他各数据段的长度,先后顺序,邻接关系推算出各个数据段的起始位置,使各数据段的段尾的下一拍是下个邻接数据段的段头;
具体的,根据锚点段的起始位置和在它之前的每个数据段需要的拍数,确定各个在它之前的数据段的起始位置。
同时,根据锚点段的起始位置,在它之后的数据段完成组帧需要的拍数,确定在它之后的数据段起始位置。
确定了第一段后,后一段的起始位置是前一段的结束位置的下一拍,即相邻段相接不交叠。
S3.将每段对应的帧图案转换成位宽固定的串行码流。
具体而言,步骤S3中,先将每段所包括的字段依序连接组成帧图案;然后根据帧数据位宽wid以及该段的帧长和启动指示,利用软代码进行并串转换,产生数据段的段首sop、段尾eop、数据有效pdv、段尾空余字节数ept,以及段数据pda。
S4.将各串行码流相或并剔除段尾空余字节后,合并成整帧。
可以理解的是根据拆分段数量的不同,步骤S4具体执行是也存在相应的区别,具体而言:
当要实现的帧所拆解的段数为1时,直接输出整帧;当要实现的帧所拆解的段数不为1,但wid为8时,将所有段相或后输出;当要实现的帧所拆解的段数不为1,且wid不为8时,将相邻的两个段间的段尾空余字节剔除后输出。
其中,当要实现的帧所拆解的段数不为1,且wid不为8时,将相邻的两个段间的段尾空余字节剔除后输出时:首先比较当前段的段尾空余字节数与之前累积的段尾空余字节总数之和与每拍传送的字节数的大小关系;然后根据所述大小关系和当前数据段在整帧中的位置,选择对应的数据拼接函数进行拼接后输出。
值得说明的是,一些实施例中,在进行拼接时还包括利用延迟级数指针idx指示当前段拼接所使用的延迟段数据流水信号的级别,并利用指示信号cnt_fn记录当前拼接的进展程度。
同时,本发明实施例还提供一种以太网成帧装置,其包括计算模块、控制模块、组帧段模块和拼接帧模块。
其中,计算模块用于将待封装的帧拆分为多段;控制模块用于确定锚点段,并基于所述锚点段控制每段的起始位置,使相邻段首尾相接且不交叠;组帧段模块用于将每段对应的帧图案转换成位宽固定的串行码流;拼接帧模块用将各串行码流相或并剔除段尾空余字节后,合并成整帧。
一些实施例中,所述计算模块将待封装的帧拆分为多段,包括:
将待封装的帧拆分为固定长度字段和/或可变长度字段。
一些实施例中,所述控制模块可以任意选择一段作为锚点段,优选地,可以选择一个固定长度字段作为锚点段。
一些实施例中,所述组帧段模块将每段对应的帧图案转换成位宽固定的串行码流,包括:
将每段所包括的字段顺序连接组成帧图案;
根据帧数据位宽wid以及该段的帧长和启动指示,利用软代码将以位为单位的帧图案进行以wid为单位的串并转换,产生数据段的段首sop、段尾eop、数据有效pdv、段尾空余字节数ept及段数据pda。
一些实施例中,所述拼接帧模块将各串行码流相或并剔除段尾空余字节后,合并成整帧,包括:
当待封装的帧所拆解的段数为1时,直接输出整帧;
当待封装的帧所拆解的段数不为1,但wid为8时,将所有数据段相或后输出;
当待封装的帧所拆解的段数不为1,且wid不为8时,将相邻的两个数据段间的段尾空余字节剔除后输出。
参见图10至图13所示,下面通过具体的实施例来做出进一步说明:
将要实现的帧分作以下段,帧头、PDU的固定部分、TLV(PDU的可变部分,有连续若干段)。其中帧头有若干种。
在本实施例中,设定要实现的帧的帧头有三种,图案是ph1,ph2,ph3,长度不一,分别是hl1,hl2,hl3,然后用一个信号head_type选择其中一种,PDU中前边有协议规定的固定字段pp_fix,长度pl_fix,后边有两个TLV,是可变内容,图案是pt1,pt2,是可变长度,长度是tl_var1,tl_var2。从先到后的顺序是帧头、PDU固定字段、TLV。wid<=256,可知此时一拍不会传递2个(包括2个)以上的帧。
全局函数cdiv,ceiling divide功能。被除数in,除数div,cdiv=in/div+(in%div!=0)。
在进行分段之后,接下来在大方向上将会从四个部分来说明如何实现:
首先定时控制输出了组帧段开始组帧的定时信号;然后组帧段接到定时信号,将帧图案并串转换成帧数据段,从帧接口送出;接着组帧段输出的多个帧数据段相接;最后将相接的多个帧数据段的结束位置的空字节气泡挤出来。
具体而言:
A.定时控制
表2.定时控制模块的接口信号
wid_len |
parameter |
帧长(以字节为单位)位宽 |
m |
parameter |
可选、必选数据段的总段数 |
hl1 |
parameter |
第1种帧头的长度 |
hl2 |
parameter |
第2种帧头的长度 |
hl3 |
parameter |
第3种帧头的长度 |
pl_fix |
parameter |
PDU的固定字段的长度 |
rst |
input |
同步复位 |
clk |
input |
系统时钟 |
cnt_beat |
input |
组帧计数器 |
tl_var1 |
input |
TLV1(PDU中可变长度字段1)的长度 |
tl_var2 |
input |
TLV2(PDU中可变长度字段2)的长度 |
start[m-1:0] |
output |
组帧段启动指示,单高脉冲,无效沿输出帧 |
帧头3种,每3选1,PDU固定字段1个,TLV有2个,故帧的数据段分段数M=4,分别是帧头、PDU固定字段、TLV1和TLV2,而所有可选和必选的数据段总段数m=6。
(1)计算特定以字节为单位的帧长需要几拍能完成组帧的函数len2beat(n)=cdiv(n,(wid/8));
(2)确定以PDU中固定字段pp_fix为锚点段,它的起始位置是pdu_start
(3)计算出不同帧头的起始head_start1=pdu_start-len2beat(hl1),head_start2=pdu_start-len2beat(hl2),head_start3=pdu_start-len2beat(hl3);
(4)同理可计算出TLV的起点分别是:
tlv_start1=pdu_start+len2beat(pl_fix),tlv_start2=tlv_start1+len2beat(tl_var1);
(5)在cnt_beat==head_start1,head_start2,head_start3,pdu_start,tlv_start1,tlv_start2时分别驱动相应的启动指示start[0],start[1],start[2],start[3],start[4],start[5]为高,不等时拉低。
其中PDU固定字段和TLV的数据段的启动指示,可简化的由它们邻接的前一段的段尾得到。即PDU固定字段的起始指示start[3]是任意一个帧头数据段的结束指示|eop[2:0],TLV1的启动指示start[4]是PDU固定字段的结束指示eop[3],TLV2的启动指示start[5]是TLV1的结束指示eop[4]。
B.组帧段模块
组帧段模块的接口信号见表3.
表3.组帧段模块的接口信号
组帧段模块的接口时序图见图10:
输入信号frm_len在start有效时必须稳定,帧图案frm_data是可变的。
start下一拍开始输出组帧段。
段首指示sop上升沿对齐了帧数据有效pdv的上升沿,段尾指示eop下降沿对齐了pdv的下降沿,一拍长度。在pdv有效包络的数据才是有效的。在数据有效期间(即pdv有效时),段尾指示有效时ept才有非零值的,其余保持零。换句话说,段中不会有空白字节,只在段尾有。
组帧段模块的实现结构见图11,分为四个部分:串行数据的计数器、段尾空余字节的计算、段图案分组、和段控制信号。段图案分组又分为帧图案构成、并行数据的字对齐(若帧图案对齐低位)和并行数据的数选器。
a)串行数据的计数器cnt:
位宽是wid_cnt=(wid_len>ew)?wid_len-ew:1;
若帧图案对齐低位:
当start有效时,cnt=cdiv(frm_len,bn)-1'b1,否则在它未计到0之前不断递减。
若帧图案对齐高位:
当start有效时,cnt={(wid_len-ew){1’b1}},否则在它未计到0之前不断递减。
b)计算段尾空余字节ept_p:
在start有效时,ept_p=bn-len%bn,否则保持。
c)帧控制信号:
当start有效时sop有效,否则sop无效。
当frm_len<=bn时,pdv在start有效时有效,start无效时无效;否则pdv在{start,eop}是2’b01时为0,是2’b10时为1,其余时间保持前值。
若帧图案对齐低位:
当start&(frm_len<bn),eop有效;否则eop<=cnt==1'b1。
当start有效时,若(frm_len<bn),ept=bn-len%bn,否则为0;当start无效时,若(cnt==1'b1),ept<=ept_p;其余情况为0。
若帧图案对齐高位:
~eop&pdv&(cnt==end_cnt)时eop有效否则无效。
其中end_cnt[wid_cnt-:0]=~thrd_cnt+2,而thrd_cnt[wid_cnt:0]=frm_len[wid_len-1:ew]+(|frm_len[ew-1:0]);
当start有效时,若(frm_len<bn),ept=bn-len%bn,否则为0;当start无效时,若(cnt==end_cnt),ept<=ept_p;其余情况为0。
d)图案分组
图案分组实现包括帧图案构成、并行数据的字对齐、并行数据的数选器三个部分。
图案的构成:按照高位先的顺序组合好所有字段,成为一个位宽很大的一维信号。其位宽最长由wid_len参数限制,若实际未达到2**wid_len,则在高位或低位补零。此参数在编译时可重载。
并行数据的字对齐:将输入的帧图案frm_data[2**wid_len*8-1:0]左移ept_p*8位。(若帧图案对齐低位时需要,对齐高位不需要)
并行数据的数选器(mux):
数选器接口如表4所示。
表4.并行数据的数选器接口信号
由软代码实现,将任意输入的一维数,以width为单位,分成selpar组,成为一个二维数组:
按照低位对低位的排列将二维数组顺序接入数选器的数据端。cnt接入数选器的选择端sel。cnt=sel(帧图案低位对齐),或者sel=selpar-1-cnt(帧图案高位对齐)即段首时选择帧图案的有效最高位输出。
assign dao=daos[sel];
例化不同字段对应的长度参数及对应信号:
帧头1,wid_len=log2(hl1),frm_len=hl1,start=定时模块的start[0],frm_data=ph1.
帧头2,wid_len=log2(hl2),frm_len=hl2,start=定时模块的start[1],frm_data=ph2.
帧头3,wid_len=log2(hl3),frm_len=hl3,start=定时模块的start[2],frm_data=ph3.
PDU固定字段,wid_len=log2(pl_fix),frm_len=pl_fix,start=定时模块的start[3],frm_data=pp_fix.
TLV1,wid_len=log2(tl_var1),frm_len=tl_var1,start=定时模块的start[4],frm_data=pt1.
TLV2,wid_len=log2(tl_var2),frm_len=tl_var2,start=定时模块的start[5],frm_data=pt2.
C.或门
用head_type做一个mux选中一种帧头,将该帧头和PDU固定字段以及两段TLV共M=4段,连接至或门输入端。
将所有输入信号相或:
M个组帧段模块的输出是:sop_p2s[M-1:0],eop_p2s[M-1:0],pdv_p2s[M-1:0],ept_p2s[ew-1:0][M-1:0],pda_p2s[wid-1:0][M-1:0]。
拼接帧输入,即本模块输出是sop_mi,eop_mi,pdv_mi,ept_mi[ew-1:0],pda_mi[wid-1:0];
sopmi=|sop_p2s[M-1:0]
eopmi=|eop_p2s[M-1:0]
pdvmi=|pdv_p2s[M-1:0]
ept_mi[ew-1:0]={ept_p2s[0][ew-1:0]|ept_p2s[1][ew-1:0]|...|ept_p2s[M-1:0][ew-1:0]}
pda_mi[wid-1:0]={pda_p2s[0][wid-1:0]|pda_p2s[1][wid-1:0]|...|pda_p2s[M-1:0][wid-1:0]}
D.拼接帧
拼接帧模块的接口信号见表5:
表5.拼接帧模块的接口信号
拼接帧模块的输入接口时序图见图12,sop_n指示了第一段的段头,也是帧首,第2~num_frm-1段的前一段的结束eop_i之后一拍就是后一段的起始sop_i。数据有效pdv_i起始于第一段段首,结束于第num_frm段的段尾。每次要拼接的帧之间必须有空隙,不能背靠背,即第num_frm-1段的结束的下一拍不能是sop_n有效/第一段的开始。
拼接帧模块的实现框图见图13,由边界气泡控制、帧控制信号处理、帧数据拼接三部分组成。
拼接帧的输入sop_i,eop_i,pdv_i,ept_i[ew-1:0],pda_i[wid-1:0]即或门的输出sop_mi,eop_mi,pdv_mi,ept_mi[ew-1:0],pda_mi[wid-1:0]。sop_n是指定的帧头数据段的段首。num_frm=M=4.
a)边界气泡控制:
气泡指当前帧数据有效包络中中段尾空余字节数非零:bub=dv_r[idx]&(ept_r[idx]!=3'b0)。
ept_hr记录之前累积的空余字节尾总数对bn的除余,ept_hr在帧首清零;
当前段的段尾空字节数ept_r[idx]与之前累加段尾空余字节总数ept_hr的之和>=bn时,提示段尾要相对提前1拍结束的指示有效cut_end=1’b1。
cnt_fn记录当前处理完第几段。
用输入的sop_n,eop_i,dv_i,ept_i,da_i产生num_frm级输入帧接口的延迟流水:sop_r[num_frm-1:0],eop_r[num_frm-1:0],dv_r[num_frm-1:0],ept_r[ew-1:0][num_frm-1:0],da_r[wid-1:0][num_frm-1:0];
延迟级数指针idx,在初始状态复位、上一帧拼接完成和本帧拼接开始时指向最后一级idx=num_frm–1’b1,每当cut_end有效时,递减一级,idx=idx–1’b1。
b)帧控制信号
帧首sop_o:sop_r[num_frm-1]有效即有效,否则无效。
帧尾eop_o:处理完num_frm个帧,且到了当前延迟级数指针指向的最后一段段尾eop_r[idx]或者有截短情况时最后一段帧尾eop_r[idx-1]的前一拍。
数据有效dv_o是帧首有效置高,帧尾有效置零。
帧尾空余字节数ept_o是帧首时置零,帧尾时若需提前即cut_end有效时ept_hr+ept_i,否则ept_hr。
c)帧数据拼接
数据拼接函数:
由以下四个函数实现不同条件下的段数据拼接:
align_bounds1:输入a[wid-1:0],b[wid-1:0],n[ew-1:0]。将a的后n个字节消除为0,将b右移bn-n个字节。两者相或。即{a[(bn*8)-1:n*8],b[(bn*8)-1:(bn-n)*8]}.
align_bounds2:输入a[wid-1:0],b[wid-1:0],n[ew-1:0]。a左移n个字节,b右移bn-n字节,两者相或。即{a[(bn-n)*8-1:0],b[bn*8-1:(bn-n)*8]}
align_bounds3:输入a[wid-1:0],b[wid-1:0],c[wid-1:0],p[ew-1:0],n[ew-1:0]。a左移p字节,b右移n字节,再左移n+p-bn字节,c右移bn-(n+p-bn)字节。三者相或。即{a[(bn-p)*8-1:0],b[bn*8-1:n*8],c[bn*8-1:(2*bn-(n+p))]}.
align_bounds4:输入a[wid-1:0],b[wid-1:0],p[ew-1:0],n[ew-1:0]。a右移n字节,再左移p+n字节,b右移bn-(p+n)字节。两者相或。即a[(bn-p)*8-1:n*8],b[bn*8-1:(bn-(p+n))*8].
最终的结果是只有一个帧,每个数据段产生的表示起始和结束的段头和段尾,是为了方便后级合并时的处理的。每个数据段的产生,等同于帧的产生,是独立的。这样在只有一个数据段时,帧可直接等同于这个数据段输出。
(1)第一帧的段头、段中:
段头指的是数据段的起始,帧数据是da_r[idx]。
(2)第一段段尾:
帧数据跟下一拍的第二段段头(da_r[idx-1])合并,align_bounds1(da_r[idx],da_r[idx-1],ept_r[idx]),即{da_r[idx][(bn*8)-1:ept_r[idx]*8],da_r[idx-1][(bn*8)-1:(bn-ept_r[idx])*8]}。
(3)第2~num_frm-1'b1帧的段头、段中:
帧数据跟下一拍的数据合并,align_bounds2(da_r[idx],da_r[idx-1],ept_hr),即{da_r[idx][(bn-ept_hr)*8-1:0],da_r[idx-1][bn*8-1:(bn-ept_hr)*8]}。
(4)第2~num_frm-1'b1段段尾:
若段尾的空余字节数和之前的累加空余字节末数ept_hr之和是不小于bn=wid/8的:
帧数据是align_bounds3(da_r[idx],da_r[idx-1],da_r[idx-2],ept_hr,ept_r[idx-1])即{da_r[idx][(bn-ept_hr)*8-1:0],da_r[idx-1][bn*8-1:ept_r[idx-1]*8],da_r[idx-2][bn*8-1:(2*bn-(ept_r[idx-1]+ept_hr))]},
否则:
帧数据是align_bounds4(da_r[idx],da_r[idx-1],ept_hr_r,ept_r[idx]),即da_r[idx][(bn-ept_hr_r)*8-1:ept_r[idx]*8],da_r[idx-1][bn*8-1:(bn-(ept_hr_r+ept_r[idx]))*8],其中ept_hr_r是ept_hr的一拍延迟。
(5)第num_frm段头、段中:
帧数据是align_bounds2(da_r[idx],da_r[idx-1],ept_hr),即{da_r[idx][(bn-ept_hr)*8-1:0],da_r[idx-1][bn*8-1:(bn-ept_hr)*8]}。
(5)第num_frm段尾:
若帧尾的空余字节数和之前的累加空余字节末数ept_hr之和是不小于bn=wid/8,需要提前一拍结束的:
帧数据是align_bounds2(da_r[idx],da_r[idx-1],ept_hr),即{da_r[idx][(bn-ept_hr)*8-1:0],da_r[idx-1][bn*8-1:(bn-ept_hr)*8]}。
否则:
帧数据是align_bounds2(da_r[idx],da_r[idx-1],ept_hr_r),即{da_r[idx][(bn-ept_hr_r)*8-1:0],da_r[idx-1][bn*8-1:(bn-ept_hr_r)*8]}。
综上所述,本发明中的以太网成帧方法,基于软代码实现的成帧器结构,无需硬代码实现帧图案分组。针对一段特定的帧图案,适配不同的帧接口位宽时只需调整一个参数;增删字段、更换帧图案时只需调整涉及段的起始位置,修改帧图案和帧长两个端口信号值。从而大大简化了设计。
本发明中的以太网成帧方法通过根据数据段长度特性分段并合理选择锚点段,减少固定字段的时序受前后相连数据段的影响,简化了固定字段的时序控制,从而简化了设计。
此外,本发明中的以太网成帧方法的帧的拼接功能,可实现多个字段、多种帧图案、PDU与不同帧头的灵活连接。例如三个可选帧头、一个PDU固定字段,两个可选TLV的帧图案的成帧实现中,相比现有技术中需要组六个整帧后六选一的方式,本发明则可通过三个帧头数据段三选一,一个PDU数据段,两个TLV数据段二选一,最后合并一个整帧的方式来处理。相比原技术六个数据段均重构了六次,本方法六个数据段均只需重构一次。从而在PDU与不同帧头的结合的场景中,大大减少了数据段的重构次数,节省资源、简化设计、提高了设计灵活度。这种结构只需要修改几个参数或接口信号、模块连接关系,即可实现各种类型的以太网帧的成帧功能,通用性高、适用范围广。
以上仅为本发明实施例的具体实施方式,但本发明实施例的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本发明实施例揭露的技术范围内,可轻易想到各种等效的修改或替换,这些修改或替换都应涵盖在本发明实施例的保护范围之内。因此,本发明实施例的保护范围应以权利要求的保护范围为准。