FPGA 学习小组
直播中

alexdos

6年用户 804经验值
擅长:可编程逻辑 电源/新能源 嵌入式技术 模拟技术
私信 关注

以太网控制器数据发送状态机实现代码

数据发送的整个过程由一个状态机控制完成。数据发送过程主要包括以下状态。

• StateIdle:系统复位后的状态。

• StatePreamble:添加报头。

• StateData0:通知主机接口提供下一个要传输的数据。

• StateData1:发送数据。

• StateFCS:根据要发送的数据产生校验序列。

• StateDefer:延迟。

• StateIPG:帧间隔。

• StatePAD:当发送数据比数据帧最小值(46 字节)小时,补充“0”直到满足帧数据格式的要求。发送数据的整个流程如图 10-10 所示。
7.jpg
(1)系统复位后首先进入 StateIdle 状态;上层协议通过主机接口设置 TxStartFrm 信号要求开始数据传输,并同时提供需要传输的第一个数据,系统进入 StatePreamble 状态。

(2)在 StatePreamble 状态,添加报头,同时通知外部 PHY 芯片传输即将开始;在报头和帧起始分隔符(SFD)传输完成后,系统进入 StateData0 状态,同时设置 TxUsedData 信号通知主机接口提供下一个数据;在数据的低 4 位数据发送完成后,系统进入 StateData1 状态;系统开始传输数据的高 4 位,系统开始在 StateData0 状态和 StateData1 状态之间切换,直到主机接口设置 TxEndFrm 信号通知数据传输结束。

(3)如果发送数据的大小大于帧数据格式要求的最小值,并且设置产生 CRC 校验序列,系统将进入 StateFCS 状态,并产生 CRC 校验序列;然后进入 StateDefer 状态,产生一定的延迟;接下来进入 StateIPG 状态,实现需要的帧间隔时间;最后回到 StateIdle 状态;如果发送数据的大小大于帧数据格式要求的最小值,并且设置不产生 CRC 校验序列,系统将进入StateDefer 状态,产生一定的延迟。

(4)接下来进入 StateIPG 状态,实现需要的帧间隔时间;最后回到 StateIdle 状态;如果发送数据的大小小于帧数据格式要求的最小值,并且设置数据长度满足帧数据格式的最小值要求并产生 CRC 校验序列,系统将进入 StatePAD 状态,补充数据长度直到满足帧数据格式的要求(46 个字节);然后进入 StateFCS 状态,并产生 CRC 校验序列;随后进入 StateDefer 状态,产生一定的延迟;接下来进入 StateIPG 状态,实现需要的帧间隔时间。最后回到 StateIdle状态。

(5)最后回到 StateIdle 状态;如果发送数据的大小小于帧数据格式要求的最小值,并且设置产生 CRC 校验序列但不要求数据长度满足最小值要求,系统将进入 StateFCS 状态,并产生 CRC 校验序列;随后进入 StateDefer 状态,产生一定的延迟;接下来进入 StateIPG 状态,实现需要的帧间隔时间;最后回到 StateIdle 状态;如果发送数据的大小小于帧数据格式要求的最小值,并且设置不产生 CRC 校验序列但不要求数据长度满足最小值要求,系统将进入StateDefer 状态,产生一定的延迟;接下来进入 StateIPG 状态,实现需要的帧间隔时间;最后回到 StateIdle 状态。

发送数据状态机的主要代码如下:

  1. `include "timescale.v"
  2. module eth_txstatem (MTxClk, Reset, ExcessiveDefer, CarrierSense, NibCnt, IPGT, IPGR1,
  3. IPGR2, FullD, TxStartFrm, TxEndFrm, TxUnderRun, Collision, UnderRun, StartTxDone, TooBig,
  4. NibCntEq7, NibCntEq15, MaxFrame, Pad, CrcEn, NibbleMinFl, RandomEq0, ColWindow,
  5. RetryMax, NoBckof, RandomEqByteCnt, StateIdle, StateIPG, StatePreamble, StateData, StatePAD,
  6. StateFCS, StateJam, StateJam_q, StateBackOff, StateDefer, StartFCS, StartJam, StartBackoff,
  7. StartDefer, DeferIndication, StartPreamble, StartData, StartIPG );
  8. parameter Tp = 1;
  9. //输入输出信号
  10. input MTxClk;
  11. input Reset;
  12. output StartIPG;
  13. //连线与寄存器
  14. wire StartIdle; //下一个时钟将进入 Idle 状态
  15. wire StartPAD; // 下一个时钟将进入 PAD 状态
  16. ……
  17. reg Rule1;
  18. //定义下一个状态
  19. assign StartIPG = StateDefer & ~ExcessiveDefer & ~CarrierSense;
  20. assign StartIdle = StateIPG & (Rule1 & NibCnt[6:0] >= IPGT | ~Rule1 & NibCnt[6:0] >= IPGR2);
  21. assign StartPreamble = StateIdle & TxStartFrm & ~CarrierSense;
  22. assign StartData[0] = ~Collision & (StatePreamble & NibCntEq15 | StateData[1] & ~TxEndFrm);
  23. assign StartData[1] = ~Collision & StateData[0] & ~TxUnderRun & ~MaxFrame;
  24. assign StartPAD = ~Collision & StateData[1] & TxEndFrm & Pad & ~NibbleMinFl;
  25. assign StartFCS = ~Collision & StateData[1] & TxEndFrm & (~Pad | Pad & NibbleMinFl) & CrcEn
  26. | ~Collision & StatePAD & NibbleMinFl & CrcEn;
  27. assign StartJam = (Collision | UnderRun) & ((StatePreamble & NibCntEq15) | (|StateData[1:0])
  28. | StatePAD | StateFCS);
  29. assign StartBackoff = StateJam & ~RandomEq0 & ColWindow & ~RetryMax & NibCntEq7 & ~NoBckof;
  30. assign StartDefer = StateIPG & ~Rule1 & CarrierSense & NibCnt[6:0] <= IPGR1 & NibCnt[6:0] !=
  31. IPGR2
  32. | StateIdle & CarrierSense
  33. | StateJam & NibCntEq7 & (NoBckof | RandomEq0 | ~ColWindow | RetryMax)
  34. | StateBackOff & (TxUnderRun | RandomEqByteCnt)
  35. | StartTxDone | TooBig;
  36. assign DeferIndication = StateIdle & CarrierSense;
  37. //发送数据状态机
  38. always @ (posedge MTxClk or posedge Reset)
  39. begin
  40. if(Reset)
  41. begin
  42. StateIPG <= #Tp 1'b0;
  43. StateIdle <= #Tp 1'b0;
  44. StatePreamble <= #Tp 1'b0;
  45. StateData[1:0] <= #Tp 2'b0;
  46. StatePAD <= #Tp 1'b0;
  47. StateFCS <= #Tp 1'b0;
  48. StateJam <= #Tp 1'b0;
  49. StateJam_q <= #Tp 1'b0;
  50. StateBackOff <= #Tp 1'b0;
  51. StateDefer <= #Tp 1'b1;
  52. end
  53. else
  54. begin
  55. StateData[1:0] <= #Tp StartData[1:0];
  56. StateJam_q <= #Tp StateJam;
  57. if(StartDefer | StartIdle)
  58. StateIPG <= #Tp 1'b0;
  59. else
  60. if(StartIPG)
  61. StateIPG <= #Tp 1'b1;
  62. if(StartDefer | StartPreamble)
  63. StateIdle <= #Tp 1'b0;
  64. else
  65. if(StartIdle)
  66. StateIdle <= #Tp 1'b1;
  67. if(StartData[0] | StartJam)
  68. StatePreamble <= #Tp 1'b0;
  69. else
  70. if(StartPreamble)
  71. StatePreamble <= #Tp 1'b1;
  72. if(StartFCS | StartJam)
  73. StatePAD <= #Tp 1'b0;
  74. else
  75. if(StartPAD)
  76. StatePAD <= #Tp 1'b1;
  77. if(StartJam | StartDefer)
  78. StateFCS <= #Tp 1'b0;
  79. else
  80. if(StartFCS)
  81. StateFCS <= #Tp 1'b1;
  82. if(StartBackoff | StartDefer)
  83. StateJam <= #Tp 1'b0;
  84. else
  85. if(StartJam)
  86. StateJam <= #Tp 1'b1;
  87. if(StartDefer)
  88. StateBackOff <= #Tp 1'b0;
  89. else
  90. if(StartBackoff)
  91. StateBackOff <= #Tp 1'b1;
  92. if(StartIPG)
  93. StateDefer <= #Tp 1'b0;
  94. else
  95. if(StartDefer)
  96. StateDefer <= #Tp 1'b1;
  97. end
  98. end
  99. //定义帧间隔
  100. always @ (posedge MTxClk or posedge Reset)
  101. begin
  102. if(Reset)
  103. Rule1 <= #Tp 1'b0;
  104. else
  105. begin
  106. if(StateIdle | StateBackOff)
  107. Rule1 <= #Tp 1'b0;
  108. else
  109. if(StatePreamble | FullD)
  110. Rule1 <= #Tp 1'b1;
  111. end
  112. end
  113. endmodule

更多回帖

发帖
×
20
完善资料,
赚取积分