数据接收模块负责接收数据的整个过程。外部 PHY 从物理层(具体指双绞线等电缆)接收串行的数据,将其还原成四位字节形式然后发送到数据接收模块。数据接收模块将接收到的 4位字节形式的数据合并成 8 位字节形式的数据,随后通过主机接口发送到上层协议。数据接收模块在接收数据的过程中完成去除报头和 CRC 校验序列的工作。
数据接收模块的结构如图 10-11 所示。
数据接收模块由 4 部分组成。
• 数据接收状态机:完成数据接收的整体控制。
• 计数器模块:包括数据接收中所有需要的计数器。
• CRC 校验模块:根据接收到的数据产生 32 位的 CRC 校验序列,并与接收到的 CRC 校验数据比较,从而得到数据是否被破坏。
• 地址检查模块:确认接收到的数据地址是否与实际地址相符。
数据发送模块的顶层程序完成 4 个部分的连接和控制,主要代码如下。
- `include "timescale.v"
- module eth_rxethmac (MRxClk, MRxDV, MRxD, Reset, Transmitting, MaxFL, r_IFG, HugEn, DlyCrcEn,
- RxData, RxValid, RxStartFrm, RxEndFrm, ByteCnt, ByteCntEq0, ByteCntGreat2, ByteCntMaxFrame,
- CrcError, StateIdle, StatePreamble, StateSFD, StateData, MAC, r_Pro, r_Bro,r_HASH0, r_HASH1,
- RxAbort,
- AddressMiss, PassAll, ControlFrmAddressOK );
- parameter Tp = 1;
- //输入输出信号
- input MRxClk;
- input MRxDV;
- …..
- input [47:0] MAC; // 地址
- input [31:0] r_HASH0; // 低四位哈希表
- input [31:0] r_HASH1; // 高四位哈希表
- input PassAll;
- ….
- //寄存器与连线
- reg [7:0] RxData;
- reg RxValid;
- ….
- //连接接收数据状态机
- eth_rxstatem rxstatem1
- (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .ByteCntEq0(ByteCntEq0),
- .ByteCntGreat2(ByteCntGreat2), .Transmitting(Transmitting), .MRxDEq5(MRxDEq5),
- .MRxDEqD(MRxDEqD), .IFGCounterEq24(IFGCounterEq24), .ByteCntMaxFrame(ByteCntMaxFrame),
- .StateData(StateData), .StateIdle(StateIdle), .StatePreamble(StatePreamble),.StateSFD(Sta
- teSFD),
- .StateDrop(StateDrop));
- // 连接接收数据计数器模块
- eth_rxcounters rxcounters1
- (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .StateIdle(StateIdle),
- .StateSFD(StateSFD), .StateData(StateData), .StateDrop(StateDrop),.StatePreamble(StatePre
- amble),
- .MRxDEqD(MRxDEqD), .DlyCrcEn(DlyCrcEn),.DlyCrcCnt(DlyCrcCnt), .Transmitting(Transmitting
- ),
- .MaxFL(MaxFL), .r_IFG(r_IFG),.HugEn(HugEn), .IFGCounterEq24(IFGCounterEq24),
- .ByteCntEq0(ByteCntEq0),.ByteCntEq1(ByteCntEq1), .ByteCntEq2(ByteCntEq2),
- .ByteCntEq3(ByteCntEq3),.ByteCntEq4(ByteCntEq4), .ByteCntEq5(ByteCntEq5),
- .ByteCntEq6(ByteCntEq6),.ByteCntEq7(ByteCntEq7), .ByteCntGreat2(ByteCntGreat2),
- .ByteCntSmall7(ByteCntSmall7), .ByteCntMaxFrame(ByteCntMaxFrame),.ByteCnt(ByteCnt));
- // 连接地址检查模块
- eth_rxaddrcheck rxaddrcheck1 (.MRxClk(MRxClk),.Reset(Reset),.RxData(RxData),
- .Broadcast (Broadcast),.r_Bro
- (r_Bro),.r_Pro(r_Pro),.ByteCntEq6(ByteCntEq6),.ByteCntEq7(ByteCntEq7),
- .ByteCntEq2(ByteCntEq2),.ByteCntEq3(ByteCntEq3),.ByteCntEq4(ByteCntEq4),.ByteCntEq5(ByteC
- ntEq5),
- .HASH0(r_HASH0),.HASH1(r_HASH1),.CrcHash(CrcHash[5:0]), .CrcHashGood(CrcHashGood),
- .StateData(StateData),.Multicast(Multicast),.MAC(MAC),.RxAbort(RxAbort),.RxEndFrm(RxEndF
- rm),
- .AddressMiss(AddressMiss),.PassAll(PassAll),.ControlFrmAddressOK(ControlFrmAddressOK));
- //设置产生并初始化 CRC 序列
- assign Enable_Crc = MRxDV & (|StateData & ~ByteCntMaxFrame);
- assign Initialize_Crc = StateSFD | DlyCrcEn & (|DlyCrcCnt[3:0]) & DlyCrcCnt[3:0] < 4'h9;
- assign Data_Crc[0] = MRxD[3];
- assign Data_Crc[1] = MRxD[2];
- assign Data_Crc[2] = MRxD[1];
- assign Data_Crc[3] = MRxD[0];
- //连接 Crc 校验模块
- eth_crc crcrx
- (.Clk(MRxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc),
- .Crc(Crc), .CrcError(CrcError)
- );
- //锁存 CRC 序列并用在哈希表中
- always @ (posedge MRxClk)
- begin
- CrcHashGood <= #Tp StateData[0] & ByteCntEq6;
- end
- always @ (posedge MRxClk)
- begin
- if(Reset | StateIdle)
- CrcHash[8:0] <= #Tp 9'h0;
- else
- if(StateData[0] & ByteCntEq6)
- CrcHash[8:0] <= #Tp Crc[31:23];
- end
- // 输出按字节保存的数据到上层协议
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- begin
- RxData_d[7:0] <= #Tp 8'h0;
- DelayData <= #Tp 1'b0;
- LatchedNibble[3:0] <= #Tp 4'h0;
- LatchedByte[7:0] <= #Tp 8'h0;
- RxData[7:0] <= #Tp 8'h0;
- end
- else
- begin
- LatchedNibble[3:0] <= #Tp MRxD[3:0]; // 锁存四位字节数据
- LatchedByte[7:0] <= #Tp {MRxD[3:0], LatchedNibble[3:0]}; // 锁存八位字节数据
- DelayData <= #Tp StateData[0];
- if(GenerateRxValid)
- RxData_d[7:0] <= #Tp LatchedByte[7:0] & {8{|StateData}};
- else
- if(~DelayData)
- RxData_d[7:0] <= #Tp 8'h0; // 延迟数据
- RxData[7:0] <= #Tp RxData_d[7:0]; // 输出按字节保存的数据
- end
- end
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- Broadcast <= #Tp 1'b0;
- else
- begin
- if(StateData[0] & ~(&LatchedByte[7:0]) & ByteCntSmall7)
- Broadcast <= #Tp 1'b0;
- else
- if(StateData[0] & (&LatchedByte[7:0]) & ByteCntEq1)
- Broadcast <= #Tp 1'b1;
- else
- if(RxAbort | RxEndFrm)
- Broadcast <= #Tp 1'b0;
- end
- end
- //多点传送
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- Multicast <= #Tp 1'b0;
- else
- begin
- if(Reset)
- Multicast <= #Tp 1'b0;
- else
- if(StateData[0] & ByteCntEq1 & LatchedByte == 8'h01)
- Multicast <= #Tp 1'b1;
- else if(RxAbort | RxEndFrm)
- Multicast <= #Tp 1'b0;
- end
- end
- assign GenerateRxValid = StateData[0] & (~ByteCntEq0 | DlyCrcCnt >= 4'h3);
- //数据有效
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- begin
- RxValid_d <= #Tp 1'b0;
- RxValid <= #Tp 1'b0;
- end
- else
- begin
- RxValid_d <= #Tp GenerateRxValid;
- RxValid <= #Tp RxValid_d;
- end
- end
- assign GenerateRxStartFrm = StateData[0] & (ByteCntEq1 & ~DlyCrcEn | DlyCrcCnt == 4'h3 &
- DlyCrcEn);
- //产生帧起始信号
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- begin
- RxStartFrm_d <= #Tp 1'b0;
- RxStartFrm <= #Tp 1'b0;
- end
- else
- begin
- RxStartFrm_d <= #Tp GenerateRxStartFrm;
- RxStartFrm <= #Tp RxStartFrm_d;
- end
- end
- assign GenerateRxEndFrm = StateData[0] & (~MRxDV & ByteCntGreat2 | ByteCntMaxFrame);
- assign DribbleRxEndFrm = StateData[1] & ~MRxDV & ByteCntGreat2;
- //产生帧尾信号
- always @ (posedge MRxClk or posedge Reset)
- begin
- if(Reset)
- begin
- RxEndFrm_d <= #Tp 1'b0;
- RxEndFrm <= #Tp 1'b0;
- end
- else
- begin
- RxEndFrm_d <= #Tp GenerateRxEndFrm;
- RxEndFrm <= #Tp RxEndFrm_d | DribbleRxEndFrm;
- end
- end
- endmodule