数据发送模块负责发送数据,通过主机接口从上层协议获得要发送的数据,同时获得数据帧的起始和结束信号;还要设置信号通知上层协议和外部 PHY 芯片。数据发送模块主要由计数器模块、数据发送状态机、错误处理模块和 CRC 校验模块等 4 部分组成,如图 10-9 所示。
这 4 部分的功能描述如下。
• 数据发送状态机:完成数据发送的整体控制。
• 计数器模块:包括数据发送中所有需要的计数器。
• CRC 校验模块:产生 32 位的 CRC 校验序列,添加在发送数据的后面。
• 错误处理模块:当发送数据冲突后,在重新发送数据前产生一个随机的延迟,从而减少发送数据冲突的次数。
当发生如下情况时,数据发送过程结束。
• 数据发送成功结束,设置 TxDone 信号。
• 数据发送过程需要重复,设置 TxRetry 信号,一般发生在数据冲突后。
• 退出数据发送过程,设置 TxAbort 信号。
数据发送模块的顶层程序完成 4 个部分的连接和控制,主要代码如下:
- `include "timescale.v"
- module eth_txethmac (MTxClk, Reset, TxStartFrm, TxEndFrm, TxUnderRun, TxData, CarrierSense,
- Collision, Pad, CrcEn, FullD, HugEn, DlyCrcEn, MinFL, MaxFL, IPGT, IPGR1, IPGR2, CollValid,
- MaxRet, NoBckof, ExDfrEn, MTxD, MTxEn, MTxErr, TxDone, TxRetry, TxAbort,
- TxUsedData, WillTransmit, ResetCollision, RetryCnt, StartTxDone, StartTxAbort,MaxCollisionOccured,
- LateCollision, DeferIndication, StatePreamble, StateData);
- parameter Tp = 1;
- //输入、输出信号
- input MTxClk; //传输时钟
- input Reset; // 复位
- input TxStartFrm; // 数据包的起始帧
- input TxEndFrm; // 数据包的结束帧
- input TxUnderRun;
- input [7:0] TxData; //数据内容
- …..
- //寄存器
- reg [3:0] MTxD;
- …..
- //各个信号
- assign ResetCollision = ~(StatePreamble | (|StateData) | StatePAD | StateFCS);
- assign ExcessiveDeferOccured = TxStartFrm & StateDefer & ExcessiveDefer &~StopExcessiveDeferOccured;
- assign StartTxDone = ~Collision & (StateFCS & NibCntEq7 | StateData[1] & TxEndFrm & (~Pad |Pad & NibbleMinFl) & ~CrcEn);
- assign UnderRun = StateData[0] & TxUnderRun & ~Collision;
- assign TooBig = ~Collision & MaxFrame & (StateData[0] & ~TxUnderRun | StateFCS);
- assign StartTxRetry = StartJam & (ColWindow & ~RetryMax) & ~UnderRun;
- assign LateCollision = StartJam & ~ColWindow & ~UnderRun;
- assign MaxCollisionOccured = StartJam & ColWindow & RetryMax;
- assign StateSFD = StatePreamble & NibCntEq15;
- assign StartTxAbort = TooBig | UnderRun | ExcessiveDeferOccured | LateCollision |MaxCollisionOccured;
- // 停止额外的延迟
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- StopExcessiveDeferOccured <= #Tp 1'b0;
- else
- begin
- if(~TxStartFrm)
- StopExcessiveDeferOccured <= #Tp 1'b0;
- else
- if(ExcessiveDeferOccured)
- StopExcessiveDeferOccured <= #Tp 1'b1;
- end
- end
- //数据冲突
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- ColWindow <= #Tp 1'b1;
- else
- begin
- if(~Collision & ByteCnt[5:0] == CollValid[5:0] & (StateData[1] | StatePAD & NibCnt[0]| StateFCS & NibCnt[0]))
- ColWindow <= #Tp 1'b0;
- else
- if(StateIdle | StateIPG)
- ColWindow <= #Tp 1'b1;
- end
- end
- // 开始
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- StatusLatch <= #Tp 1'b0;
- else
- begin
- if(~TxStartFrm)
- StatusLatch <= #Tp 1'b0;
- else
- if(ExcessiveDeferOccured | StateIdle)
- StatusLatch <= #Tp 1'b1;
- end
- end
- //发送用过的数据包
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- TxUsedData <= #Tp 1'b0;
- else
- TxUsedData <= #Tp |StartData;
- end
- //发送数据包结束
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- TxDone <= #Tp 1'b0;
- else
- begin
- if(TxStartFrm & ~StatusLatch)
- TxDone <= #Tp 1'b0;
- else
- if(StartTxDone)
- TxDone <= #Tp 1'b1;
- end
- end
- // 重新发送数据包
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- TxRetry <= #Tp 1'b0;
- else
- begin
- if(TxStartFrm & ~StatusLatch)
- TxRetry <= #Tp 1'b0;
- else
- if(StartTxRetry)
- TxRetry <= #Tp 1'b1;
- end
- end
- // 退出数据包发送
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- TxAbort <= #Tp 1'b0;
- else
- begin
- if(TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured)
- TxAbort <= #Tp 1'b0;
- else
- if(StartTxAbort)
- TxAbort <= #Tp 1'b1;
- end
- end
- //重新计数
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- RetryCnt[3:0] <= #Tp 4'h0;
- else
- begin
- if(ExcessiveDeferOccured | UnderRun | TooBig | StartTxDone | TxUnderRun| StateJam & NibCntEq7 & (~ColWindow | RetryMax))
- RetryCnt[3:0] <= #Tp 4'h0;
- else
- if(StateJam & NibCntEq7 & ColWindow & (RandomEq0 | NoBckof) | StateBackOff &RandomEqByteCnt)
- RetryCnt[3:0] <= #Tp RetryCnt[3:0] + 1'b1;
- end
- end
- assign RetryMax = RetryCnt[3:0] == MaxRet[3:0];
- // 同时传输 4 位数据
- always @ (StatePreamble or StateData or StateData or StateFCS or StateJam or StateSFD or TxDataor
- Crc or NibCnt or NibCntEq15)
- begin
- if(StateData[0])
- MTxD_d[3:0] = TxData[3:0]; // 低四位
- else
- if(StateData[1])
- MTxD_d[3:0] = TxData[7:4]; //高四位
- else
- if(StateFCS)
- MTxD_d[3:0] = {~Crc[28], ~Crc[29], ~Crc[30], ~Crc[31]}; // CRC 校验序列
- else
- if(StateJam)
- MTxD_d[3:0] = 4'h9;
- else
- if(StatePreamble)
- if(NibCntEq15)
- MTxD_d[3:0] = 4'hd; // 帧起始分隔符,SFD
- else
- MTxD_d[3:0] = 4'h5; // 报头
- else
- MTxD_d[3:0] = 4'h0;
- end
- // 传输使能
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- MTxEn <= #Tp 1'b0;
- else
- MTxEn <= #Tp StatePreamble | (|StateData) | StatePAD | StateFCS | StateJam;
- end
- // 传输四位字节
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- MTxD[3:0] <= #Tp 4'h0;
- else
- MTxD[3:0] <= #Tp MTxD_d[3:0];
- end
- // 传输错误
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- MTxErr <= #Tp 1'b0;
- else
- MTxErr <= #Tp TooBig | UnderRun;
- end
- // 即将传输
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- WillTransmit <= #Tp 1'b0;
- else
- WillTransmit <= #Tp StartPreamble | StatePreamble | (|StateData) | StatePAD | StateFCS
- | StateJam;
- end
- //数据包完成标志
- assign PacketFinished_d = StartTxDone | TooBig | UnderRun | LateCollision | MaxCollisionOccured
- | ExcessiveDeferOccured;
- // 数据包结束
- always @ (posedge MTxClk or posedge Reset)
- begin
- if(Reset)
- begin
- PacketFinished <= #Tp 1'b0;
- PacketFinished_q <= #Tp 1'b0;
- end
- else
- begin
- PacketFinished <= #Tp PacketFinished_d;
- PacketFinished_q <= #Tp PacketFinished;
- end
- end
- // 连接计数器模块
- eth_txcounters txcounters1
- (.StatePreamble(StatePreamble), .StateIPG(StateIPG), .StateData(StateData),
- .StatePAD(StatePAD), .StateFCS(StateFCS), .StateJam(StateJam), .StateBackOff(StateBackOff),
- .StateDefer(StateDefer), .StateIdle(StateIdle), .StartDefer(StartDefer), .StartIPG(StartIPG),
- .StartFCS(StartFCS), .StartJam(StartJam), .TxStartFrm(TxStartFrm), .MTxClk(MTxClk),
- .Reset(Reset), .MinFL(MinFL), .MaxFL(MaxFL), .HugEn(HugEn), .ExDfrEn(ExDfrEn),
- .PacketFinished_q(PacketFinished_q), .DlyCrcEn(DlyCrcEn), .StartBackoff(StartBackoff),
- .StateSFD(StateSFD), .ByteCnt(ByteCnt), .NibCnt(NibCnt), .ExcessiveDefer(ExcessiveDefer),
- .NibCntEq7(NibCntEq7), .NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .NibbleMinFl(NibbleMinFl),
- .DlyCrcCnt(DlyCrcCnt));
- // 连接状态机模块
- eth_txstatem txstatem1 (.MTxClk(MTxClk), .Reset(Reset), .ExcessiveDefer(ExcessiveDefer),
- .CarrierSense(CarrierSense),.NibCnt(NibCnt[6:0]), .IPGT(IPGT), .IPGR1(IPGR1), .IPGR2(IPGR2), .FullD(FullD), .TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm), .TxUnderRun(TxUnderRun), .Collision(Collision),
- .UnderRun(UnderRun), .StartTxDone(StartTxDone), .TooBig(TooBig), .NibCntEq7(NibCntEq7),
- .NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .Pad(Pad), .CrcEn(CrcEn),.NibbleMinFl(NibbleMinFl),
- .RandomEq0(RandomEq0), .ColWindow(ColWindow), .RetryMax(RetryMax),.NoBckof(NoBckof),
- .RandomEqByteCnt(RandomEqByteCnt), .StateIdle(StateIdle),.StateIPG(StateIPG),
- .StatePreamble(StatePreamble), .StateData(StateData), .StatePAD(StatePAD),.StateFCS(StateFCS),
- .StateJam(StateJam), .StateJam_q(StateJam_q), .StateBackOff(StateBackOff),.StateDefer(StateDefer),
- .StartFCS(StartFCS), .StartJam(StartJam), .StartBackoff(StartBackoff),.StartDefer(StartDefer),
- .DeferIndication(DeferIndication), .StartPreamble(StartPreamble), .StartData(StartData),
- .StartIPG(StartIPG));
- // 连接 CRC 模块
- eth_crc txcrc
- (.Clk(MTxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc),
- .Crc(Crc), .CrcError(CrcError)
- );
- //连接随机延迟模块
- eth_random random1
- (.MTxClk(MTxClk), .Reset(Reset), .StateJam(StateJam), .StateJam_q(StateJam_q), .RetryCnt(RetryCnt),
- .NibCnt(NibCnt), .ByteCnt(ByteCnt[9:0]), .RandomEq0(RandomEq0), .RandomEqByteCnt(RandomEqByteCnt));
- endmodule