⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eth_wishbone.v

📁 此文档为采用FPGA实现的以太网MAC层
💻 V
📖 第 1 页 / 共 5 页
字号:
// signals are used for proper selection of the start byte (TxData and TxByteCnt) are// set by this two bits.always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxPointerLSB[1:0] <=#Tp 0;  else  if(TxEn & TxEn_q & TxPointerRead)    TxPointerLSB[1:0] <=#Tp ram_do[1:0];end// Latching 2 MSB bits of the buffer descriptor. // After the read access, TxLength needs to be decremented for the number of the valid// bytes (1 to 4 bytes are valid in the first word). After the first read all bytes are // valid so this two bits are reset to zero. always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxPointerLSB_rst[1:0] <=#Tp 0;  else  if(TxEn & TxEn_q & TxPointerRead)    TxPointerLSB_rst[1:0] <=#Tp ram_do[1:0];  else  if(MasterWbTX & m_wb_ack_i)                 // After first access pointer is word alligned    TxPointerLSB_rst[1:0] <=#Tp 0;endreg  [3:0] RxByteSel;wire MasterAccessFinished;always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    BlockingIncrementTxPointer <=#Tp 0;  else  if(MasterAccessFinished)    BlockingIncrementTxPointer <=#Tp 0;  else  if(IncrTxPointer)    BlockingIncrementTxPointer <=#Tp 1'b1;endwire TxBufferAlmostFull;wire TxBufferFull;wire TxBufferEmpty;wire TxBufferAlmostEmpty;wire SetReadTxDataFromMemory;reg BlockReadTxDataFromMemory;assign SetReadTxDataFromMemory = TxEn & TxEn_q & TxPointerRead;always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    ReadTxDataFromMemory <=#Tp 1'b0;  else  if(TxLengthEq0 | TxAbortPulse | TxRetryPulse)    ReadTxDataFromMemory <=#Tp 1'b0;  else  if(SetReadTxDataFromMemory)    ReadTxDataFromMemory <=#Tp 1'b1;endreg tx_burst_en;reg rx_burst_en;wire ReadTxDataFromMemory_2 = ReadTxDataFromMemory & ~BlockReadTxDataFromMemory;wire tx_burst = ReadTxDataFromMemory_2 & tx_burst_en;wire [31:0] TxData_wb;wire ReadTxDataFromFifo_wb;always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    BlockReadTxDataFromMemory <=#Tp 1'b0;  else  if((TxBufferAlmostFull | TxLength <= 4)& MasterWbTX & (~cyc_cleared) & (!(TxAbortPacket_NotCleared | TxRetryPacket_NotCleared)))    BlockReadTxDataFromMemory <=#Tp 1'b1;  else  if(ReadTxDataFromFifo_wb | TxDonePacket | TxAbortPacket | TxRetryPacket)    BlockReadTxDataFromMemory <=#Tp 1'b0;endassign MasterAccessFinished = m_wb_ack_i | m_wb_err_i;wire [`ETH_TX_FIFO_CNT_WIDTH-1:0] txfifo_cnt;wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rxfifo_cnt;reg  [`ETH_BURST_CNT_WIDTH-1:0] tx_burst_cnt;reg  [`ETH_BURST_CNT_WIDTH-1:0] rx_burst_cnt;wire rx_burst;wire enough_data_in_rxfifo_for_burst;wire enough_data_in_rxfifo_for_burst_plus1;// Enabling master wishbone access to the memory for two devices TX and RX.always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    begin      MasterWbTX <=#Tp 1'b0;      MasterWbRX <=#Tp 1'b0;      m_wb_adr_o <=#Tp 30'h0;      m_wb_cyc_o <=#Tp 1'b0;      m_wb_we_o  <=#Tp 1'b0;      m_wb_sel_o <=#Tp 4'h0;      cyc_cleared<=#Tp 1'b0;      tx_burst_cnt<=#Tp 0;      rx_burst_cnt<=#Tp 0;      IncrTxPointer<=#Tp 1'b0;      tx_burst_en<=#Tp 1'b1;      rx_burst_en<=#Tp 1'b0;      `ifdef ETH_WISHBONE_B3        m_wb_cti_o <=#Tp 3'b0;      `endif    end  else    begin      // Switching between two stages depends on enable signals      casex ({MasterWbTX, MasterWbRX, ReadTxDataFromMemory_2, WriteRxDataToMemory, MasterAccessFinished, cyc_cleared, tx_burst, rx_burst})  // synopsys parallel_case        8'b00_10_00_10,             // Idle and MRB needed        8'b10_1x_10_1x,             // MRB continues        8'b10_10_01_10,             // Clear (previously MR) and MRB needed        8'b01_1x_01_1x :            // Clear (previously MW) and MRB needed          begin            MasterWbTX <=#Tp 1'b1;  // tx burst            MasterWbRX <=#Tp 1'b0;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b0;            m_wb_sel_o <=#Tp 4'hf;            cyc_cleared<=#Tp 1'b0;            IncrTxPointer<=#Tp 1'b1;            tx_burst_cnt <=#Tp tx_burst_cnt+3'h1;            if(tx_burst_cnt==0)              m_wb_adr_o <=#Tp TxPointerMSB;            else              m_wb_adr_o <=#Tp m_wb_adr_o+1'b1;            if(tx_burst_cnt==(`ETH_BURST_LENGTH-1))              begin                tx_burst_en<=#Tp 1'b0;              `ifdef ETH_WISHBONE_B3                m_wb_cti_o <=#Tp 3'b111;              `endif              end            else              begin              `ifdef ETH_WISHBONE_B3                m_wb_cti_o <=#Tp 3'b010;              `endif              end          end        8'b00_x1_00_x1,             // Idle and MWB needed        8'b01_x1_10_x1,             // MWB continues        8'b01_01_01_01,             // Clear (previously MW) and MWB needed        8'b10_x1_01_x1 :            // Clear (previously MR) and MWB needed          begin            MasterWbTX <=#Tp 1'b0;  // rx burst            MasterWbRX <=#Tp 1'b1;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b1;            m_wb_sel_o <=#Tp RxByteSel;            IncrTxPointer<=#Tp 1'b0;            cyc_cleared<=#Tp 1'b0;            rx_burst_cnt <=#Tp rx_burst_cnt+3'h1;            if(rx_burst_cnt==0)              m_wb_adr_o <=#Tp RxPointerMSB;            else              m_wb_adr_o <=#Tp m_wb_adr_o+1'b1;            if(rx_burst_cnt==(`ETH_BURST_LENGTH-1))              begin                rx_burst_en<=#Tp 1'b0;              `ifdef ETH_WISHBONE_B3                m_wb_cti_o <=#Tp 3'b111;              `endif              end            else              begin              `ifdef ETH_WISHBONE_B3                m_wb_cti_o <=#Tp 3'b010;              `endif              end          end        8'b00_x1_00_x0 :            // idle and MW is needed (data write to rx buffer)          begin            MasterWbTX <=#Tp 1'b0;            MasterWbRX <=#Tp 1'b1;            m_wb_adr_o <=#Tp RxPointerMSB;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b1;            m_wb_sel_o <=#Tp RxByteSel;            IncrTxPointer<=#Tp 1'b0;          end        8'b00_10_00_00 :            // idle and MR is needed (data read from tx buffer)          begin            MasterWbTX <=#Tp 1'b1;            MasterWbRX <=#Tp 1'b0;            m_wb_adr_o <=#Tp TxPointerMSB;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b0;            m_wb_sel_o <=#Tp 4'hf;            IncrTxPointer<=#Tp 1'b1;          end        8'b10_10_01_00,             // MR and MR is needed (data read from tx buffer)        8'b01_1x_01_0x  :           // MW and MR is needed (data read from tx buffer)          begin            MasterWbTX <=#Tp 1'b1;            MasterWbRX <=#Tp 1'b0;            m_wb_adr_o <=#Tp TxPointerMSB;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b0;            m_wb_sel_o <=#Tp 4'hf;            cyc_cleared<=#Tp 1'b0;            IncrTxPointer<=#Tp 1'b1;          end        8'b01_01_01_00,             // MW and MW needed (data write to rx buffer)        8'b10_x1_01_x0  :           // MR and MW is needed (data write to rx buffer)          begin            MasterWbTX <=#Tp 1'b0;            MasterWbRX <=#Tp 1'b1;            m_wb_adr_o <=#Tp RxPointerMSB;            m_wb_cyc_o <=#Tp 1'b1;            m_wb_we_o  <=#Tp 1'b1;            m_wb_sel_o <=#Tp RxByteSel;            cyc_cleared<=#Tp 1'b0;            IncrTxPointer<=#Tp 1'b0;          end        8'b01_01_10_00,             // MW and MW needed (cycle is cleared between previous and next access)        8'b01_1x_10_x0,             // MW and MW or MR or MRB needed (cycle is cleared between previous and next access)        8'b10_10_10_00,             // MR and MR needed (cycle is cleared between previous and next access)        8'b10_x1_10_0x :            // MR and MR or MW or MWB (cycle is cleared between previous and next access)          begin            m_wb_cyc_o <=#Tp 1'b0;  // whatever and master read or write is needed. We need to clear m_wb_cyc_o before next access is started            cyc_cleared<=#Tp 1'b1;            IncrTxPointer<=#Tp 1'b0;            tx_burst_cnt<=#Tp 0;            tx_burst_en<=#Tp txfifo_cnt<(`ETH_TX_FIFO_DEPTH-`ETH_BURST_LENGTH) & (TxLength>(`ETH_BURST_LENGTH*4+4));            rx_burst_cnt<=#Tp 0;            rx_burst_en<=#Tp MasterWbRX ? enough_data_in_rxfifo_for_burst_plus1 : enough_data_in_rxfifo_for_burst;  // Counter is not decremented, yet, so plus1 is used.            `ifdef ETH_WISHBONE_B3              m_wb_cti_o <=#Tp 3'b0;            `endif          end        8'bxx_00_10_00,             // whatever and no master read or write is needed (ack or err comes finishing previous access)        8'bxx_00_01_00 :            // Between cyc_cleared request was cleared          begin            MasterWbTX <=#Tp 1'b0;            MasterWbRX <=#Tp 1'b0;            m_wb_cyc_o <=#Tp 1'b0;            cyc_cleared<=#Tp 1'b0;            IncrTxPointer<=#Tp 1'b0;            rx_burst_cnt<=#Tp 0;            rx_burst_en<=#Tp MasterWbRX ? enough_data_in_rxfifo_for_burst_plus1 : enough_data_in_rxfifo_for_burst;  // Counter is not decremented, yet, so plus1 is used.            `ifdef ETH_WISHBONE_B3              m_wb_cti_o <=#Tp 3'b0;            `endif          end        8'b00_00_00_00:             // whatever and no master read or write is needed (ack or err comes finishing previous access)          begin            tx_burst_cnt<=#Tp 0;            tx_burst_en<=#Tp txfifo_cnt<(`ETH_TX_FIFO_DEPTH-`ETH_BURST_LENGTH) & (TxLength>(`ETH_BURST_LENGTH*4+4));          end        default:                    // Don't touch          begin            MasterWbTX <=#Tp MasterWbTX;            MasterWbRX <=#Tp MasterWbRX;            m_wb_cyc_o <=#Tp m_wb_cyc_o;            m_wb_sel_o <=#Tp m_wb_sel_o;            IncrTxPointer<=#Tp IncrTxPointer;          end      endcase    endendwire TxFifoClear;assign TxFifoClear = (TxAbortPacket | TxRetryPacket);eth_fifo #(`ETH_TX_FIFO_DATA_WIDTH, `ETH_TX_FIFO_DEPTH, `ETH_TX_FIFO_CNT_WIDTH)tx_fifo ( .data_in(m_wb_dat_i),                             .data_out(TxData_wb),           .clk(WB_CLK_I),                                   .reset(Reset),           .write(MasterWbTX & m_wb_ack_i),                  .read(ReadTxDataFromFifo_wb & ~TxBufferEmpty),          .clear(TxFifoClear),                              .full(TxBufferFull),           .almost_full(TxBufferAlmostFull),                 .almost_empty(TxBufferAlmostEmpty),           .empty(TxBufferEmpty),                            .cnt(txfifo_cnt)        );reg StartOccured;reg TxStartFrm_sync1;reg TxStartFrm_sync2;reg TxStartFrm_syncb1;reg TxStartFrm_syncb2;// Start: Generation of the TxStartFrm_wb which is then synchronized to the MTxClkalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxStartFrm_wb <=#Tp 1'b0;  else  if(TxBDReady & ~StartOccured & (TxBufferFull | TxLengthEq0))    TxStartFrm_wb <=#Tp 1'b1;  else  if(TxStartFrm_syncb2)    TxStartFrm_wb <=#Tp 1'b0;end// StartOccured: TxStartFrm_wb occurs only ones at the beginning. Then it's blocked.always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    StartOccured <=#Tp 1'b0;  else  if(TxStartFrm_wb)    StartOccured <=#Tp 1'b1;  else  if(ResetTxBDReady)    StartOccured <=#Tp 1'b0;end// Synchronizing TxStartFrm_wb to MTxClkalways @ (posedge MTxClk or posedge Reset)begin  if(Reset)    TxStartFrm_sync1 <=#Tp 1'b0;  else    TxStartFrm_sync1 <=#Tp TxStartFrm_wb;endalways @ (posedge MTxClk or posedge Reset)begin  if(Reset)    TxStartFrm_sync2 <=#Tp 1'b0;  else    TxStartFrm_sync2 <=#Tp TxStartFrm_sync1;endalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxStartFrm_syncb1 <=#Tp 1'b0;  else    TxStartFrm_syncb1 <=#Tp TxStartFrm_sync2;endalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxStartFrm_syncb2 <=#Tp 1'b0;  else    TxStartFrm_syncb2 <=#Tp TxStartFrm_syncb1;endalways @ (posedge MTxClk or posedge Reset)begin  if(Reset)    TxStartFrm <=#Tp 1'b0;  else  if(TxStartFrm_sync2)    TxStartFrm <=#Tp 1'b1;  else  if(TxUsedData_q | ~TxStartFrm_sync2 & (TxRetry & (~TxRetry_q) | TxAbort & (~TxAbort_q)))    TxStartFrm <=#Tp 1'b0;end// End: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk// TxEndFrm_wb: indicator of the end of framealways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxEndFrm_wb <=#Tp 1'b0;  else  if(TxLengthEq0 & TxBufferAlmostEmpty & TxUsedData)    TxEndFrm_wb <=#Tp 1'b1;  else  if(TxRetryPulse | TxDonePulse | TxAbortPulse)    TxEndFrm_wb <=#Tp 1'b0;end// Marks which bytes are valid within the word.assign TxValidBytes = TxLengthLt4 ? TxLength[1:0] : 2'b0;reg LatchValidBytes;reg LatchValidBytes_q;always @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    LatchValidBytes <=#Tp 1'b0;  else  if(TxLengthLt4 & TxBDReady)    LatchValidBytes <=#Tp 1'b1;  else    LatchValidBytes <=#Tp 1'b0;endalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    LatchValidBytes_q <=#Tp 1'b0;  else    LatchValidBytes_q <=#Tp LatchValidBytes;end// Latching valid bytesalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxValidBytesLatched <=#Tp 2'h0;  else  if(LatchValidBytes & ~LatchValidBytes_q)    TxValidBytesLatched <=#Tp TxValidBytes;  else  if(TxRetryPulse | TxDonePulse | TxAbortPulse)    TxValidBytesLatched <=#Tp 2'h0;endassign TxIRQEn          = TxStatus[14];assign WrapTxStatusBit  = TxStatus[13];assign PerPacketPad     = TxStatus[12];assign PerPacketCrcEn   = TxStatus[11];assign RxIRQEn         = RxStatus[14];assign WrapRxStatusBit = RxStatus[13];// Temporary Tx and Rx buffer descriptor address assign TempTxBDAddress[7:1] = {7{ TxStatusWrite     & ~WrapTxStatusBit}}   & (TxBDAddress + 1'b1) ; // Tx BD increment or wrap (last BD)assign TempRxBDAddress[7:1] = {7{ WrapRxStatusBit}} & (r_TxBDNum[6:0])     | // Using first Rx BD                              {7{~WrapRxStatusBit}} & (RxBDAddress + 1'b1) ; // Using next Rx BD (incremenrement address)// Latching Tx buffer descriptor addressalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)    TxBDAddress <=#Tp 7'h0;  else if (r_TxEn & (~r_TxEn_q))    TxBDAddress <=#Tp 7'h0;  else if (TxStatusWrite)    TxBDAddress <=#Tp TempTxBDAddress;end// Latching Rx buffer descriptor addressalways @ (posedge WB_CLK_I or posedge Reset)begin  if(Reset)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -