TCP/IP Protocol Suite

Transmit Control




eth_transmitcontrol.v
`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
                                   );


        input         MTxClk;
        input         TxReset;
        input         TxUsedDataIn;
        input         TxUsedDataOut;
        input         TxDoneIn;
        input         TxAbortIn;
        input         TxStartFrmIn;
        input         TPauseRq;
        input         TxUsedDataOutDetected;
        input         TxFlow;
        input         DlyCrcEn;
        input  [15:0] TxPauseTV;
        input  [47:0] MAC;

        output        TxCtrlStartFrm;
        output        TxCtrlEndFrm;
        output        SendingCtrlFrm;
        output        CtrlMux;
        output [7:0]  ControlData;
        output        WillSendControlFrame;
        output        BlockTxDone;

        reg           SendingCtrlFrm;
        reg           CtrlMux;
        reg           WillSendControlFrame;
        reg    [3:0]  DlyCrcCnt;
        reg    [5:0]  ByteCnt;
        reg           ControlEnd_q;
        reg    [7:0]  MuxedCtrlData;
        reg           TxCtrlStartFrm;
        reg           TxCtrlStartFrm_q;
        reg           TxCtrlEndFrm;
        reg    [7:0]  ControlData;
        reg           TxUsedDataIn_q;
        reg           BlockTxDone;

        wire          IncrementDlyCrcCnt;
        wire          ResetByteCnt;
        wire          IncrementByteCnt;
        wire          ControlEnd;
        wire          IncrementByteCntBy2;
        wire          EnableCnt;


        // A command for Sending the control frame is active (latched)
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            WillSendControlFrame <=  1'b0;
          else
          if(TxCtrlEndFrm & CtrlMux)
            WillSendControlFrame <=  1'b0;
          else
          if(TPauseRq & TxFlow)
            WillSendControlFrame <=  1'b1;
        end


        // Generation of the transmit control packet start frame
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            TxCtrlStartFrm <=  1'b0;
          else
          if(TxUsedDataIn_q & CtrlMux)
            TxCtrlStartFrm <=  1'b0;
          else
          if(WillSendControlFrame & ~TxUsedDataOut & (TxDoneIn | TxAbortIn | TxStartFrmIn | (~TxUsedDataOutDetected)))
            TxCtrlStartFrm <=  1'b1;
        end



        // Generation of the transmit control packet end frame
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            TxCtrlEndFrm <=  1'b0;
          else
          if(ControlEnd | ControlEnd_q)
            TxCtrlEndFrm <=  1'b1;
          else
            TxCtrlEndFrm <=  1'b0;
        end


        // Generation of the multiplexer signal (controls muxes for switching between
        // normal and control packets)
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            CtrlMux <=  1'b0;
          else
          if(WillSendControlFrame & ~TxUsedDataOut)
            CtrlMux <=  1'b1;
          else
          if(TxDoneIn)
            CtrlMux <=  1'b0;
        end



        // Generation of the Sending Control Frame signal (enables padding and CRC)
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            SendingCtrlFrm <=  1'b0;
          else
          if(WillSendControlFrame & TxCtrlStartFrm)
            SendingCtrlFrm <=  1'b1;
          else
          if(TxDoneIn)
            SendingCtrlFrm <=  1'b0;
        end


        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            TxUsedDataIn_q <=  1'b0;
          else
            TxUsedDataIn_q <=  TxUsedDataIn;
        end



        // Generation of the signal that will block sending the Done signal to the eth_wishbone module
        // While sending the control frame
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            BlockTxDone <=  1'b0;
          else
          if(TxCtrlStartFrm)
            BlockTxDone <=  1'b1;
          else
          if(TxStartFrmIn)
            BlockTxDone <=  1'b0;
        end


        always @ (posedge MTxClk)
        begin
          ControlEnd_q     <=  ControlEnd;
          TxCtrlStartFrm_q <=  TxCtrlStartFrm;
        end


        assign IncrementDlyCrcCnt = CtrlMux & TxUsedDataIn &  ~DlyCrcCnt[2];


        // Delayed CRC counter
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            DlyCrcCnt <=  4'h0;
          else
          if(ResetByteCnt)
            DlyCrcCnt <=  4'h0;
          else
          if(IncrementDlyCrcCnt)
            DlyCrcCnt <=  DlyCrcCnt + 4'd1;
        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]));
        // Byte counter
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            ByteCnt <=  6'h0;
          else
          if(ResetByteCnt)
            ByteCnt <=  6'h0;
          else
          if(IncrementByteCntBy2 & EnableCnt)
            ByteCnt <=  (ByteCnt[5:0] ) + 6'd2;
          else
          if(IncrementByteCnt & EnableCnt)
            ByteCnt <=  (ByteCnt[5:0] ) + 6'd1;
        end


        assign ControlEnd = ByteCnt[5:0] == 6'h22;


        // Control data generation (goes to the TxEthMAC module)
        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;                   // Reserved Multicast Address
                     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


        // Latched Control data
        always @ (posedge MTxClk or posedge TxReset)
        begin
          if(TxReset)
            ControlData[7:0] <=  8'h0;
          else
          if(~ByteCnt[0])
            ControlData[7:0] <=  MuxedCtrlData[7:0];
        end



        endmodule