📄 eth_receivecontrol.v
字号:
////////////////////////////////////////////////////////////////////////// //////// eth_receivecontrol.v //////// //////// This file is part of the Ethernet IP core project //////// http://www.opencores.org/projects/ethmac/ //////// //////// Author(s): //////// - Igor Mohor (igorM@opencores.org) //////// //////// All additional information is avaliable in the Readme.txt //////// file. //////// ////////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2001 Authors //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free software; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source is distributed in the hope that it will be //////// useful, but WITHOUT ANY WARRANTY; without even the implied //////// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //////// PURPOSE. See the GNU Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// ////////////////////////////////////////////////////////////////////////////// CVS Revision History//// $Log: eth_receivecontrol.v,v $// Revision 1.1 2005/10/05 01:34:00 jdhar// initial checkin with TSK3000 processor//// Revision 1.1 2005/07/31 05:51:11 jdhar// initial commit for TSK3000 files//// Revision 1.5 2003/01/22 13:49:26 tadejm// When control packets were received, they were ignored in some cases.//// Revision 1.4 2002/11/22 01:57:06 mohor// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort// synchronized.//// Revision 1.3 2002/01/23 10:28:16 mohor// Link in the header changed.//// Revision 1.2 2001/10/19 08:43:51 mohor// eth_timescale.v changed to timescale.v This is done because of the// simulation of the few cores in a one joined project.//// Revision 1.1 2001/08/06 14:44:29 mohor// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).// Include files fixed to contain no path.// File names and module names changed ta have a eth_ prologue in the name.// File eth_timescale.v is used to define timescale// All pin names on the top module are changed to contain _I, _O or _OE at the end.// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O// and Mdo_OE. The bidirectional signal must be created on the top level. This// is done due to the ASIC tools.//// Revision 1.1 2001/07/30 21:23:42 mohor// Directory structure changed. Files checked and joind together.//// Revision 1.1 2001/07/03 12:51:54 mohor// Initial release of the MAC Control module.//////////`include "timescale.v"module eth_receivecontrol (MTxClk, MRxClk, TxReset, RxReset, RxData, RxValid, RxStartFrm, RxEndFrm, RxFlow, ReceiveEnd, MAC, DlyCrcEn, TxDoneIn, TxAbortIn, TxStartFrmOut, ReceivedLengthOK, ReceivedPacketGood, TxUsedDataOutDetected, Pause, ReceivedPauseFrm, AddressOK, RxStatusWriteLatched_sync2, r_PassAll, SetPauseTimer );parameter Tp = 1;input MTxClk;input MRxClk;input TxReset; input RxReset; input [7:0] RxData;input RxValid;input RxStartFrm;input RxEndFrm;input RxFlow;input ReceiveEnd;input [47:0]MAC;input DlyCrcEn;input TxDoneIn;input TxAbortIn;input TxStartFrmOut;input ReceivedLengthOK;input ReceivedPacketGood;input TxUsedDataOutDetected;input RxStatusWriteLatched_sync2;input r_PassAll;output Pause;output ReceivedPauseFrm;output AddressOK;output SetPauseTimer;reg Pause;reg AddressOK; // Multicast or unicast address detectedreg TypeLengthOK; // Type/Length field contains 0x8808reg DetectionWindow; // Detection of the PAUSE frame is possible within this windowreg OpCodeOK; // PAUSE opcode detected (0x0001)reg [2:0] DlyCrcCnt;reg [4:0] ByteCnt;reg [15:0] AssembledTimerValue;reg [15:0] LatchedTimerValue;reg ReceivedPauseFrm;reg ReceivedPauseFrmWAddr;reg PauseTimerEq0_sync1;reg PauseTimerEq0_sync2;reg [15:0] PauseTimer;reg Divider2;reg [5:0] SlotTimer;wire [47:0] ReservedMulticast; // 0x0180C2000001wire [15:0] TypeLength; // 0x8808wire ResetByteCnt; // wire IncrementByteCnt; // wire ByteCntEq0; // ByteCnt = 0wire ByteCntEq1; // ByteCnt = 1wire ByteCntEq2; // ByteCnt = 2wire ByteCntEq3; // ByteCnt = 3wire ByteCntEq4; // ByteCnt = 4wire ByteCntEq5; // ByteCnt = 5wire ByteCntEq12; // ByteCnt = 12wire ByteCntEq13; // ByteCnt = 13wire ByteCntEq14; // ByteCnt = 14wire ByteCntEq15; // ByteCnt = 15wire ByteCntEq16; // ByteCnt = 16wire ByteCntEq17; // ByteCnt = 17wire ByteCntEq18; // ByteCnt = 18wire DecrementPauseTimer; // wire PauseTimerEq0; // wire ResetSlotTimer; // wire IncrementSlotTimer; // wire SlotFinished; // // Reserved multicast address and Type/Length for PAUSE controlassign ReservedMulticast = 48'h0180C2000001;assign TypeLength = 16'h8808;// Address Detection (Multicast or unicast)always @ (posedge MRxClk or posedge RxReset)begin if(RxReset) AddressOK <= #Tp 1'b0; else if(DetectionWindow & ByteCntEq0) AddressOK <= #Tp RxData[7:0] == ReservedMulticast[47:40] | RxData[7:0] == MAC[47:40]; else if(DetectionWindow & ByteCntEq1) AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[39:32] | RxData[7:0] == MAC[39:32]) & AddressOK; else if(DetectionWindow & ByteCntEq2) AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[31:24] | RxData[7:0] == MAC[31:24]) & AddressOK; else if(DetectionWindow & ByteCntEq3) AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[23:16] | RxData[7:0] == MAC[23:16]) & AddressOK; else if(DetectionWindow & ByteCntEq4) AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[15:8] | RxData[7:0] == MAC[15:8]) & AddressOK; else if(DetectionWindow & ByteCntEq5) AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[7:0] | RxData[7:0] == MAC[7:0]) & AddressOK; else if(ReceiveEnd) AddressOK <= #Tp 1'b0;end// TypeLengthOK (Type/Length Control frame detected)always @ (posedge MRxClk or posedge RxReset )begin if(RxReset) TypeLengthOK <= #Tp 1'b0; else if(DetectionWindow & ByteCntEq12) TypeLengthOK <= #Tp ByteCntEq12 & (RxData[7:0] == TypeLength[15:8]); else if(DetectionWindow & ByteCntEq13) TypeLengthOK <= #Tp ByteCntEq13 & (RxData[7:0] == TypeLength[7:0]) & TypeLengthOK; else if(ReceiveEnd) TypeLengthOK <= #Tp 1'b0;end// Latch Control Frame Opcodealways @ (posedge MRxClk or posedge RxReset )begin if(RxReset) OpCodeOK <= #Tp 1'b0; else if(ByteCntEq16) OpCodeOK <= #Tp 1'b0; else begin if(DetectionWindow & ByteCntEq14) OpCodeOK <= #Tp ByteCntEq14 & RxData[7:0] == 8'h00; if(DetectionWindow & ByteCntEq15) OpCodeOK <= #Tp ByteCntEq15 & RxData[7:0] == 8'h01 & OpCodeOK; endend// ReceivedPauseFrmWAddr (+Address Check)always @ (posedge MRxClk or posedge RxReset )begin if(RxReset) ReceivedPauseFrmWAddr <= #Tp 1'b0; else if(ReceiveEnd) ReceivedPauseFrmWAddr <= #Tp 1'b0; else if(ByteCntEq16 & TypeLengthOK & OpCodeOK & AddressOK) ReceivedPauseFrmWAddr <= #Tp 1'b1; end// Assembling 16-bit timer value from two 8-bit dataalways @ (posedge MRxClk or posedge RxReset )begin if(RxReset) AssembledTimerValue[15:0] <= #Tp 16'h0; else if(RxStartFrm) AssembledTimerValue[15:0] <= #Tp 16'h0; else begin if(DetectionWindow & ByteCntEq16) AssembledTimerValue[15:8] <= #Tp RxData[7:0]; if(DetectionWindow & ByteCntEq17) AssembledTimerValue[7:0] <= #Tp RxData[7:0]; endend// Detection window (while PAUSE detection is possible)always @ (posedge MRxClk or posedge RxReset )begin if(RxReset) DetectionWindow <= #Tp 1'b1; else if(ByteCntEq18) DetectionWindow <= #Tp 1'b0; else if(ReceiveEnd) DetectionWindow <= #Tp 1'b1;end// Latching Timer Valuealways @ (posedge MRxClk or posedge RxReset )begin if(RxReset) LatchedTimerValue[15:0] <= #Tp 16'h0; else if(DetectionWindow & ReceivedPauseFrmWAddr & ByteCntEq18) LatchedTimerValue[15:0] <= #Tp AssembledTimerValue[15:0]; else if(ReceiveEnd) LatchedTimerValue[15:0] <= #Tp 16'h0;end// Delayed CEC counteralways @ (posedge MRxClk or posedge RxReset)begin if(RxReset) DlyCrcCnt <= #Tp 3'h0; else if(RxValid & RxEndFrm) DlyCrcCnt <= #Tp 3'h0; else if(RxValid & ~RxEndFrm & ~DlyCrcCnt[2]) DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1;end assign ResetByteCnt = RxEndFrm;assign IncrementByteCnt = RxValid & DetectionWindow & ~ByteCntEq18 & (~DlyCrcEn | DlyCrcEn & DlyCrcCnt[2]);// Byte counteralways @ (posedge MRxClk or posedge RxReset)begin if(RxReset) ByteCnt[4:0] <= #Tp 5'h0; else if(ResetByteCnt) ByteCnt[4:0] <= #Tp 5'h0; else if(IncrementByteCnt) ByteCnt[4:0] <= #Tp ByteCnt[4:0] + 1'b1;endassign ByteCntEq0 = RxValid & ByteCnt[4:0] == 5'h0;assign ByteCntEq1 = RxValid & ByteCnt[4:0] == 5'h1;assign ByteCntEq2 = RxValid & ByteCnt[4:0] == 5'h2;assign ByteCntEq3 = RxValid & ByteCnt[4:0] == 5'h3;assign ByteCntEq4 = RxValid & ByteCnt[4:0] == 5'h4;assign ByteCntEq5 = RxValid & ByteCnt[4:0] == 5'h5;assign ByteCntEq12 = RxValid & ByteCnt[4:0] == 5'h0C;assign ByteCntEq13 = RxValid & ByteCnt[4:0] == 5'h0D;assign ByteCntEq14 = RxValid & ByteCnt[4:0] == 5'h0E;assign ByteCntEq15 = RxValid & ByteCnt[4:0] == 5'h0F;assign ByteCntEq16 = RxValid & ByteCnt[4:0] == 5'h10;assign ByteCntEq17 = RxValid & ByteCnt[4:0] == 5'h11;assign ByteCntEq18 = RxValid & ByteCnt[4:0] == 5'h12 & DetectionWindow;assign SetPauseTimer = ReceiveEnd & ReceivedPauseFrmWAddr & ReceivedPacketGood & ReceivedLengthOK & RxFlow;assign DecrementPauseTimer = SlotFinished & |PauseTimer;// PauseTimer[15:0]always @ (posedge MRxClk or posedge RxReset)begin if(RxReset) PauseTimer[15:0] <= #Tp 16'h0; else if(SetPauseTimer) PauseTimer[15:0] <= #Tp LatchedTimerValue[15:0]; else if(DecrementPauseTimer) PauseTimer[15:0] <= #Tp PauseTimer[15:0] - 1'b1;endassign PauseTimerEq0 = ~(|PauseTimer[15:0]);// Synchronization of the pause timeralways @ (posedge MTxClk or posedge TxReset)begin if(TxReset) begin PauseTimerEq0_sync1 <= #Tp 1'b1; PauseTimerEq0_sync2 <= #Tp 1'b1; end else begin PauseTimerEq0_sync1 <= #Tp PauseTimerEq0; PauseTimerEq0_sync2 <= #Tp PauseTimerEq0_sync1; endend// Pause signal generationalways @ (posedge MTxClk or posedge TxReset)begin if(TxReset) Pause <= #Tp 1'b0; else if((TxDoneIn | TxAbortIn | ~TxUsedDataOutDetected) & ~TxStartFrmOut) Pause <= #Tp RxFlow & ~PauseTimerEq0_sync2;end// Divider2 is used for incrementing the Slot timer every other clockalways @ (posedge MRxClk or posedge RxReset)begin if(RxReset) Divider2 <= #Tp 1'b0; else if(|PauseTimer[15:0] & RxFlow) Divider2 <= #Tp ~Divider2; else Divider2 <= #Tp 1'b0;endassign ResetSlotTimer = RxReset;assign IncrementSlotTimer = Pause & RxFlow & Divider2;// SlotTimeralways @ (posedge MRxClk or posedge RxReset)begin if(RxReset) SlotTimer[5:0] <= #Tp 6'h0; else if(ResetSlotTimer) SlotTimer[5:0] <= #Tp 6'h0; else if(IncrementSlotTimer) SlotTimer[5:0] <= #Tp SlotTimer[5:0] + 1'b1;endassign SlotFinished = &SlotTimer[5:0] & IncrementSlotTimer; // Slot is 512 bits (64 bytes)// Pause Frame receivedalways @ (posedge MRxClk or posedge RxReset)begin if(RxReset) ReceivedPauseFrm <=#Tp 1'b0; else if(RxStatusWriteLatched_sync2 & r_PassAll | ReceivedPauseFrm & (~r_PassAll)) ReceivedPauseFrm <=#Tp 1'b0; else if(ByteCntEq16 & TypeLengthOK & OpCodeOK) ReceivedPauseFrm <=#Tp 1'b1; endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -