📄 eth_wishbone.v
字号:
// 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 + -