赞
踩
今早写了从gmii接收到字节,去掉前导字节和起始字节,以及校验得到mac层数据流,并校验crc输出指示此帧是否有错。
实现代码如下:
-
-
- /*
- ether_rx ether_rx (
- .clk( ) ,
- .rst( ) ,
- .phy_din( ) ,
- .phy_dv( ),
- .sof( ),
- .eof( ),
- .crc_err( ),
- .valid( ),
- .dout( )
- );
-
- */
-
-
- module ether_rx (
- input clk , rst ,
- input [7:0] phy_din ,
- input phy_dv ,
- output reg sof,eof,crc_err,valid,
- output reg [7:0] dout
- );
-
- reg sof_r,eof_r,valid_r;
-
- always@(posedge clk) {sof,eof,valid} <= {sof_r,eof_r,valid_r} ;
- reg [4:0] dv ;
- always @ (posedge clk) if (rst) dv[3:0]<=0;else dv[3:0] <= {dv[2:0],phy_dv} ;
- always @ (posedge clk) if (rst) dv[4]<=0;else dv[4] <= dv[3] ;
-
- reg [7:0]regs0,regs1,regs2,regs3,regs4,regs5;
- wire [31:0] last_4_bytes = {regs3,regs2,regs1,regs0};
- always @ (posedge clk) if (phy_dv)begin regs3<=regs2;regs2<=regs1;regs1<=regs0;regs0<=phy_din;end
- always @ (posedge clk) begin regs4<=regs3;regs5<=regs4 ;dout <= regs5 ;end
-
-
- wire [31:0] crc_result , crc_next_result,crc_next_result_final,crc_result_final ;
- crc_final crc_final ( .din (crc_result) , .dout ( crc_result_final) );
-
- always@(posedge clk ) crc_err <= ( crc_result_final == last_4_bytes ) ?0:1;
-
- reg [7:0] st; always @(posedge clk) if(rst){valid_r,eof,sof_r,st}<=0; else case (st)
- 0:st<=10;
- 10,11,12,13,14,15: begin {valid_r,eof_r,sof_r}<=0; if ( regs4==8'h55 &&dv[4] ) st<=st+1;else st<=10; end
- 16:if ( regs4==8'h55 && dv[4] ) st<=20;else st<=10;
- 20:if ( regs4==8'hd5 && dv[4] )st<=25; else if ( regs4==8'h55 && dv[4] ) st<=20;else st<=10;
- 25:begin {valid_r,sof_r,eof_r } <=3'b110 ; st<=30;end
- 30:if ( dv[4]==0 ) begin {valid_r,sof_r,eof_r} <=3'b101; st<=40;end else begin {valid_r,sof_r,eof_r} <=3'b100;end
- 40:begin {valid_r,eof_r,sof_r}<=0; st<=50 ; end
- 50:st<=10;
- default st<=0;
- endcase
- reg [7:0] crc_din ;
- reg crc_en ,crc_clr;
- always @ (posedge clk) if (rst) { crc_din ,crc_en,crc_clr }<=10'h1; else case (st)
- 20:{ crc_en,crc_clr } <= 2'b01;
- 25: begin crc_din<= regs4; { crc_en,crc_clr } <= 2'b10; end
- 30: begin crc_din<= (dv[0])?regs4:0; { crc_en,crc_clr } <= {dv[0],1'b0}; end
- default { crc_din ,crc_en,crc_clr }<=10'h0;
- endcase
-
- crc crc ( .Clk(clk), .Reset(crc_clr), .Data_in(crc_din), .Enable( crc_en ), .Crc(crc_result), .CrcNext(crc_next_result) );
-
- endmodule

在以太网数据包里面我们看不到无法从数据包里面得到帧长度,不能预知哪四个字节是最后的FCS,但是我们知道一个包的传递是连续的,也就说从phy芯片给fpga的rx_dv信号在一个帧内是不会间断的,而帧之间必然间断(记得有文档说过必须大于9.6uS),我们利用这点判断一包的结束,以及确定最后的四个字节就是crc校验字。
关于接口说明:
ether_rx ether_rx (
.clk( ) , //系统时钟
.rst( ) ,//系统复位
.phy_din( ) , //GMII接口的RX_DATA
.phy_dv( ), //GMII接口的DV
.sof( ),//伴随着valid信号 指示此字节是start of frame
.eof( ),//伴随着valid信号 指示此字节是end of frame (相当于axis协议的tlast)
.crc_err( ),//伴随着valid和eof,指示此数据帧是否crc校验有错,1=有错
.valid( ),//dout输出有效
.dout( ) //给mac层的字节数据输出
);
{{aAxvOXMOIvVUoXMxvoxiowMwWV8xxWTxoxOIOVIUUOvwVOUiIoUvvTMMVMwovWHWX8vOUOvUUmiIwvTxwiTwVMwwmVMmWvIwTXTTOooxIUVTHTU8IHMoiHIoVU8VvmvIWXTvvOvv8xvMovOWivmIUIMo8UmooOTvvwUIoTwvmWUoiTw8VmvoHWwMIUWOixiowiUoiXwiwwMMIiIXHwUmOWUVmXXwV8iHWOTUiwTU8xwOoV8HVmTWZz}}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。