数据传输控制要保证主机接口和外部 PHY 可以同时发送数据给对方,从而实现全双工的要求。数据传输控制的主要代码如下:
- `include "timescale.v"
- module eth_transmitcontrol (MTxClk, TxReset, TxUsedDataIn, TxUsedDataOut, TxDoneIn,
- TxAbortIn,
- TxStartFrmIn, TPauseRq, TxUsedDataOutDetected, TxFlow, DlyCrcEn, TxPauseTV, MAC,
- TxCtrlStartFrm,
- TxCtrlEndFrm, SendingCtrlFrm, CtrlMux, ControlData, WillSendControlFrame, BlockTxDone);
- parameter Tp = 1;
- //输入输出信号
- input MTxClk;
- ……
- //寄存器与连线
- reg SendingCtrlFrm;
- ……
- //发送控制帧数据的命令,高有效
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- WillSendControlFrame <= #Tp 1'b0;
- else
- if(TxCtrlEndFrm & CtrlMux)
- WillSendControlFrame <= #Tp 1'b0;
- else
- if(TPauseRq & TxFlow)
- WillSendControlFrame <= #Tp 1'b1;
- end
- //产生传输控制数据包的开始帧
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- TxCtrlStartFrm <= #Tp 1'b0;
- else
- if(TxUsedDataIn_q & CtrlMux)
- TxCtrlStartFrm <= #Tp 1'b0;
- else
- if(WillSendControlFrame & ~TxUsedDataOut & (TxDoneIn | TxAbortIn | TxStartFrmIn |
- (~TxUsedDataOutDetected)))
- TxCtrlStartFrm <= #Tp 1'b1;
- end
- //产生传输控制数据包的结束帧
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- TxCtrlEndFrm <= #Tp 1'b0;
- else
- if(ControlEnd | ControlEnd_q)
- TxCtrlEndFrm <= #Tp 1'b1;
- else
- TxCtrlEndFrm <= #Tp 1'b0;
- end
- //产生乘信号
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- CtrlMux <= #Tp 1'b0;
- else
- if(WillSendControlFrame & ~TxUsedDataOut)
- CtrlMux <= #Tp 1'b1;
- else
- if(TxDoneIn)
- CtrlMux <= #Tp 1'b0;
- end
- //产生发送控制帧数据,使能 CRC 校验和 PAD
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- SendingCtrlFrm <= #Tp 1'b0;
- else
- if(WillSendControlFrame & TxCtrlStartFrm)
- SendingCtrlFrm <= #Tp 1'b1;
- else
- if(TxDoneIn)
- SendingCtrlFrm <= #Tp 1'b0;
- end
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- TxUsedDataIn_q <= #Tp 1'b0;
- else
- TxUsedDataIn_q <= #Tp TxUsedDataIn;
- end
- //当发送控制帧数据时,产生信号屏蔽发送结束信号到主机接口
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- BlockTxDone <= #Tp 1'b0;
- else
- if(TxCtrlStartFrm)
- BlockTxDone <= #Tp 1'b1;
- else
- if(TxStartFrmIn)
- BlockTxDone <= #Tp 1'b0;
- end
- always @ (posedge MTxClk)
- begin
- ControlEnd_q <= #Tp ControlEnd;
- TxCtrlStartFrm_q <= #Tp TxCtrlStartFrm;
- end
- assign IncrementDlyCrcCnt = CtrlMux & TxUsedDataIn & ~DlyCrcCnt[2];
- // 延迟 CRC 计数器
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- DlyCrcCnt <= #Tp 4'h0;
- else
- if(ResetByteCnt)
- DlyCrcCnt <= #Tp 4'h0;
- else
- if(IncrementDlyCrcCnt)
- DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1;
- end
- assign ResetByteCnt = TxReset | (~TxCtrlStartFrm & (TxDoneIn | TxAbortIn));
- assign IncrementByteCnt = CtrlMux & (TxCtrlStartFrm & ~TxCtrlStartFrm_q & ~TxUsedDataIn |
- TxUsedDataIn & ~ControlEnd);
- assign IncrementByteCntBy2 = CtrlMux & TxCtrlStartFrm & (~TxCtrlStartFrm_q) & TxUsedDataIn;
- // When TxUsedDataIn and CtrlMux are set at the same time
- assign EnableCnt = (~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0]));
- //字节计数器
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- ByteCnt <= #Tp 6'h0;
- else
- if(ResetByteCnt)
- ByteCnt <= #Tp 6'h0;
- else
- if(IncrementByteCntBy2 & EnableCnt)
- ByteCnt <= #Tp (ByteCnt[5:0] ) + 2'h2;
- else
- if(IncrementByteCnt & EnableCnt)
- ByteCnt <= #Tp (ByteCnt[5:0] ) + 1'b1;
- end
- assign ControlEnd = ByteCnt[5:0] == 6'h22;
- // 控制数据产生
- always @ (ByteCnt or DlyCrcEn or MAC or TxPauseTV or DlyCrcCnt)
- begin
- case(ByteCnt)
- 6'h0: if(~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0]))
- MuxedCtrlData[7:0] = 8'h01;
- else
- MuxedCtrlData[7:0] = 8'h0;
- 6'h2: MuxedCtrlData[7:0] = 8'h80;
- 6'h4: MuxedCtrlData[7:0] = 8'hC2;
- 6'h6: MuxedCtrlData[7:0] = 8'h00;
- 6'h8: MuxedCtrlData[7:0] = 8'h00;
- 6'hA: MuxedCtrlData[7:0] = 8'h01;
- 6'hC: MuxedCtrlData[7:0] = MAC[47:40];
- 6'hE: MuxedCtrlData[7:0] = MAC[39:32];
- 6'h10: MuxedCtrlData[7:0] = MAC[31:24];
- 6'h12: MuxedCtrlData[7:0] = MAC[23:16];
- 6'h14: MuxedCtrlData[7:0] = MAC[15:8];
- 6'h16: MuxedCtrlData[7:0] = MAC[7:0];
- 6'h18: MuxedCtrlData[7:0] = 8'h88; // Type/Length
- 6'h1A: MuxedCtrlData[7:0] = 8'h08;
- 6'h1C: MuxedCtrlData[7:0] = 8'h00; // Opcode
- 6'h1E: MuxedCtrlData[7:0] = 8'h01;
- 6'h20: MuxedCtrlData[7:0] = TxPauseTV[15:8]; // Pause timer value
- 6'h22: MuxedCtrlData[7:0] = TxPauseTV[7:0];
- default: MuxedCtrlData[7:0] = 8'h0;
- endcase
- end
- //锁存控制数据
- always @ (posedge MTxClk or posedge TxReset)
- begin
- if(TxReset)
- ControlData[7:0] <= #Tp 8'h0;
- else
- if(~ByteCnt[0])
- ControlData[7:0] <= #Tp MuxedCtrlData[7:0];
- end
- endmodule