当前位置:   article > 正文

以太网PHY->MAC接收代码的实现_以太网mac层代码

以太网mac层代码

今早写了从gmii接收到字节,去掉前导字节和起始字节,以及校验得到mac层数据流,并校验crc输出指示此帧是否有错。

实现代码如下:

  1. /*
  2. ether_rx ether_rx (
  3. .clk( ) ,
  4. .rst( ) ,
  5. .phy_din( ) ,
  6. .phy_dv( ),
  7. .sof( ),
  8. .eof( ),
  9. .crc_err( ),
  10. .valid( ),
  11. .dout( )
  12. );
  13. */
  14. module ether_rx (
  15. input clk , rst ,
  16. input [7:0] phy_din ,
  17. input phy_dv ,
  18. output reg sof,eof,crc_err,valid,
  19. output reg [7:0] dout
  20. );
  21. reg sof_r,eof_r,valid_r;
  22. always@(posedge clk) {sof,eof,valid} <= {sof_r,eof_r,valid_r} ;
  23. reg [4:0] dv ;
  24. always @ (posedge clk) if (rst) dv[3:0]<=0;else dv[3:0] <= {dv[2:0],phy_dv} ;
  25. always @ (posedge clk) if (rst) dv[4]<=0;else dv[4] <= dv[3] ;
  26. reg [7:0]regs0,regs1,regs2,regs3,regs4,regs5;
  27. wire [31:0] last_4_bytes = {regs3,regs2,regs1,regs0};
  28. always @ (posedge clk) if (phy_dv)begin regs3<=regs2;regs2<=regs1;regs1<=regs0;regs0<=phy_din;end
  29. always @ (posedge clk) begin regs4<=regs3;regs5<=regs4 ;dout <= regs5 ;end
  30. wire [31:0] crc_result , crc_next_result,crc_next_result_final,crc_result_final ;
  31. crc_final crc_final ( .din (crc_result) , .dout ( crc_result_final) );
  32. always@(posedge clk ) crc_err <= ( crc_result_final == last_4_bytes ) ?0:1;
  33. reg [7:0] st; always @(posedge clk) if(rst){valid_r,eof,sof_r,st}<=0; else case (st)
  34. 0:st<=10;
  35. 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
  36. 16:if ( regs4==8'h55 && dv[4] ) st<=20;else st<=10;
  37. 20:if ( regs4==8'hd5 && dv[4] )st<=25; else if ( regs4==8'h55 && dv[4] ) st<=20;else st<=10;
  38. 25:begin {valid_r,sof_r,eof_r } <=3'b110 ; st<=30;end
  39. 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. 40:begin {valid_r,eof_r,sof_r}<=0; st<=50 ; end
  41. 50:st<=10;
  42. default st<=0;
  43. endcase
  44. reg [7:0] crc_din ;
  45. reg crc_en ,crc_clr;
  46. always @ (posedge clk) if (rst) { crc_din ,crc_en,crc_clr }<=10'h1; else case (st)
  47. 20:{ crc_en,crc_clr } <= 2'b01;
  48. 25: begin crc_din<= regs4; { crc_en,crc_clr } <= 2'b10; end
  49. 30: begin crc_din<= (dv[0])?regs4:0; { crc_en,crc_clr } <= {dv[0],1'b0}; end
  50. default { crc_din ,crc_en,crc_clr }<=10'h0;
  51. endcase
  52. crc crc ( .Clk(clk), .Reset(crc_clr), .Data_in(crc_din), .Enable( crc_en ), .Crc(crc_result), .CrcNext(crc_next_result) );
  53. 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}}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/972223
推荐阅读
相关标签
  

闽ICP备14008679号