(3)GFP帧的同步
GFP帧要实现两项非常重要的功能:捕获GFP帧头以及保持帧同步。帧同步情况分为同步状态、预同步状态和搜索状态。由预同步状态到同步状态所需的有效帧头数目N可以由使用者配置。搜索状态为链路链接初始化或GFP接收器接收失败时的基本状态。接收器使用当前的4字节数据来搜索下一帧,如果计算出的Core HEC值与数据域中的Core HEC值相同,则接收器暂时进入预同步状态,否则,它移到下一字节继续进行搜索。预同步状态时,根据PLI能够确定帧的边界,当连续N个GFP帧被正确检测到,则进入同步状态。同步状态为一个规则的操作状态,它检查PLI值,确定Core HEC值,提取帧的PDU,然后到下一帧,如此循环,各状态之间的转移如图3所示。

图3
FPGA的实现
在本设计中采用了XILINX公司的XCV200E芯片,它是一片拥有30万系统门,高速、可灵活编程的FPGA。
(1)MAC帧到GFP帧包封的实现
包封在FPGA中实现的框图如图4所示。

图4
FPGA通过GMII或MII MAC接口以字节的方式接收一个完整的MAC帧,去除帧前导码后进行MAC帧的缓存,同时对帧长进行计数,并保存在FIFO中,当有一帧缓存结束时,取出该帧的长度值加上净荷头的长度后得到PLI,算出其CRC值形成GFP的Core Header,再加上固定的4字节净荷头(只有Type Header,无Extension Header),此时从缓存区取出MAC帧的内容加在净荷头之后,完成GFP的包封。当没有有效的MAC帧发送时,必须插入完整的4字节空闲帧,两者进行复用后,分别进行Core Header扰码(与十六进制数B6AB31E0异或)和Payload扰码(X^43+1)。扰码完成后直接发送给SDH的虚容器中。
(2)GFP帧到MAC帧解包封的实现
解包封在FPGA中实现的框图如图5所示。
从SDH虚容器中接收到数据后,分别送入GFP帧同步的Delineation模块和Payload解扰码模块中,Delineation模块实现GFP帧的同步捕捉和保持,从由预同步状态到同步状态所需的有效帧头数目N取为1,为避免有效的数据丢失,进入预同步状态后,该帧的payload也是有效的,Delineation模块输出一个payload_valid信号给Payload解扰码模块,指示其对有效的数据进行X^43+1解扰码。对解扰后的GFP帧进行解包封,在解包封时要注意一些错误的处理,如要对Type Header HEC值进行检查,若正确还要对Type Header中的各项值(PTI,PFI,EXI,UPI)进行检查,看接收到的数据是否为所需的MAC帧类型,若有错误则把该帧丢弃,并要进行统计,当PFI为1时,还必须对Payload域进行CRC32的计算,并检查FCS是否正确。解包封完的数据加上前导码后通过GMII或MII MAC接口送出。由于帧的同步是GFP中比较有特点的地方,所以我把帧同步模块Delineation的Verilog语言程序附在了后面作为参考。

图5GFP帧到MAC帧解包封
结束语
由于以太网在企业中非常流行,所以不同区域同一企业间的以太网互联互通将会成为一个问题,GFP作为ITU的国际标准,将会成为今后的主流协议。
附程序:
module delineation ( reset_in, clk, sdh_valid,sdh_data,payload_valid);
input reset_in;
input clk;
input sdh_valid;
input [7:0] sdh_data;
output payload_valid;
reg [1:0] syn_cnt;reg [2:0] state;
reg [23:0] core_shift;
reg [15:0] payload_length;
wire [31:0] descram_core;
wire [15:0] crc_result;
parameter HUNT =3'b001;
parameter PRE_SYN = 3'b010;
parameter SYN = 3'b100;>parameter core_poly = 32'hb6ab31e0;
assign descram_core = {core_shift,sdh_data} ^ core_poly;
assign payload valid = ((state == SYN) | (state ==PRE_ SYN))& ( | payload_length);
assign crc_result = CRC16_D16(descram_core[31:16],16'h0000);
always @(posedge clk or negedge reset_in)
if (~reset_in)
core_shift <=0;
else
if ( ~| payload_length)
begin
if (sdh_valid)
core_shift <= {core_shift[15:0],sdh_data};
end
else
core_shift <= 0;
always @(posedge clk or negedge reset_in)
if (~reset_in)
syn_cnt <= 0;
else
if (sdh_valid)
if ( ~| payload_length)
begin
if (syn_cnt != 2'b11)
syn_cnt <= syn_cnt+1;
else
if (descram_core[15:0] == crc_result)
syn_cnt <= 2'b00;
else
if ((state==PRE_SYN) | (state==SYN))
syn_cnt <= 2'b00;
else
syn_cnt <= 2'b11;
end
else
syn_cnt <= 2'b00;
always @(posedge clk or negedge reset_in)
if (~reset_in)
state <= HUNT;
else
case (state)
HUNT: if ((~| payload_length) & (syn_cnt==2'b11) & sdh_valid)
if (descram_core[15:0] == crc_result)
state <= PRE_SYN;
PRE_SYN:if ((~| payload_length) & (syn_cnt==2'b11) & sdh_valid)
if (descram_core[15:0] == crc_result)
state <= SYN;
else
state <= HUNT;
SYN: if ((~| payload_length) & (syn_cnt==2'b11) & sdh_valid)
if (descram_core[15:0] == crc_result)
state <= SYN;
else
state <= HUNT;
default:state <= HUNT;
endcase
always @(posedge clk or negedge reset_in)
if (~reset_in)
payload_length <= 0;
else
if (sdh_valid)
if (~| payload_length)
begin
if (syn_cnt==2'b11)
if (descram_core[15:0] == crc_result)
payload_length <= descram_core[31:16];
else
payload_length <= 0;
end
else
payload_length <= payload_length-1;
function [15:0] CRC16_D16;
input [15:0] Data;
1.部分资源来自网络,经ET电子归类整理,旨在服务电子爱好者并无商业目的,不保证正确性与完整性.
2.如果您觉得本站资源对您有用,请告知您的好友,用搜索引擎搜"ET电子"即可.

