📄 eth_wishbone.v
字号:
reg ReadTxDataFromFifo_tck;reg BlockingTxStatusWrite;reg BlockingTxBDRead;reg Flop;reg [7:1] TxBDAddress;reg [7:1] RxBDAddress;reg TxRetrySync1;reg TxAbortSync1;reg TxDoneSync1;reg TxAbort_q;reg TxRetry_q;reg TxUsedData_q;reg [31:0] RxDataLatched2;reg [31:8] RxDataLatched1; // Big Endian Byte Orderingreg [1:0] RxValidBytes;reg [1:0] RxByteCnt;reg LastByteIn;reg ShiftWillEnd;reg WriteRxDataToFifo;reg [15:0] LatchedRxLength;reg RxAbortLatched;reg ShiftEnded;reg RxOverrun;reg [3:0] BDWrite; // BD Write Enable for access from WISHBONE sidereg BDRead; // BD Read access from WISHBONE sidewire [31:0] RxBDDataIn; // Rx BD data inwire [31:0] TxBDDataIn; // Tx BD data inreg TxEndFrm_wb;wire TxRetryPulse;wire TxDonePulse;wire TxAbortPulse;wire StartRxBDRead;wire StartTxBDRead;wire TxIRQEn;wire WrapTxStatusBit;wire RxIRQEn;wire WrapRxStatusBit;wire [1:0] TxValidBytes;wire [7:1] TempTxBDAddress;wire [7:1] TempRxBDAddress;wire RxStatusWrite;wire RxBufferFull;wire RxBufferAlmostEmpty;wire RxBufferEmpty;reg WB_ACK_O;wire [8:0] RxStatusIn;reg [8:0] RxStatusInLatched;reg WbEn, WbEn_q;reg RxEn, RxEn_q;reg TxEn, TxEn_q;reg r_TxEn_q;reg r_RxEn_q;wire ram_ce;wire [3:0] ram_we;wire ram_oe;reg [7:0] ram_addr;reg [31:0] ram_di;wire [31:0] ram_do;wire StartTxPointerRead;reg TxPointerRead;reg TxEn_needed;reg RxEn_needed;wire StartRxPointerRead;reg RxPointerRead; `ifdef ETH_WISHBONE_B3assign m_wb_bte_o = 2'b00; // Linear burst`endifassign m_wb_stb_o = m_wb_cyc_o;always @ (posedge WB_CLK_I)begin WB_ACK_O <=#Tp (|BDWrite) & WbEn & WbEn_q | BDRead & WbEn & ~WbEn_q;endassign WB_DAT_O = ram_do;// Generic synchronous single-port RAM interfaceeth_spram_256x32 bd_ram ( .clk(WB_CLK_I), .rst(Reset), .ce(ram_ce), .we(ram_we), .oe(ram_oe), .addr(ram_addr), .di(ram_di), .do(ram_do)`ifdef ETH_BIST , .mbist_si_i (mbist_si_i), .mbist_so_o (mbist_so_o), .mbist_ctrl_i (mbist_ctrl_i)`endif);assign ram_ce = 1'b1;assign ram_we = (BDWrite & {4{(WbEn & WbEn_q)}}) | {4{(TxStatusWrite | RxStatusWrite)}};assign ram_oe = BDRead & WbEn & WbEn_q | TxEn & TxEn_q & (TxBDRead | TxPointerRead) | RxEn & RxEn_q & (RxBDRead | RxPointerRead);always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxEn_needed <=#Tp 1'b0; else if(~TxBDReady & r_TxEn & WbEn & ~WbEn_q) TxEn_needed <=#Tp 1'b1; else if(TxPointerRead & TxEn & TxEn_q) TxEn_needed <=#Tp 1'b0;end// Enabling access to the RAM for three devices.always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) begin WbEn <=#Tp 1'b1; RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b0; ram_addr <=#Tp 8'h0; ram_di <=#Tp 32'h0; BDRead <=#Tp 1'b0; BDWrite <=#Tp 1'b0; end else begin // Switching between three stages depends on enable signals case ({WbEn_q, RxEn_q, TxEn_q, RxEn_needed, TxEn_needed}) // synopsys parallel_case 5'b100_10, 5'b100_11 : begin WbEn <=#Tp 1'b0; RxEn <=#Tp 1'b1; // wb access stage and r_RxEn is enabled TxEn <=#Tp 1'b0; ram_addr <=#Tp {RxBDAddress, RxPointerRead}; ram_di <=#Tp RxBDDataIn; end 5'b100_01 : begin WbEn <=#Tp 1'b0; RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b1; // wb access stage, r_RxEn is disabled but r_TxEn is enabled ram_addr <=#Tp {TxBDAddress, TxPointerRead}; ram_di <=#Tp TxBDDataIn; end 5'b010_00, 5'b010_10 : begin WbEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is disabled RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b0; ram_addr <=#Tp WB_ADR_I[9:2]; ram_di <=#Tp WB_DAT_I; BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; BDRead <=#Tp (|BDCs) & ~WB_WE_I; end 5'b010_01, 5'b010_11 : begin WbEn <=#Tp 1'b0; RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is enabled ram_addr <=#Tp {TxBDAddress, TxPointerRead}; ram_di <=#Tp TxBDDataIn; end 5'b001_00, 5'b001_01, 5'b001_10, 5'b001_11 : begin WbEn <=#Tp 1'b1; // TxEn access stage (we always go to wb access stage) RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b0; ram_addr <=#Tp WB_ADR_I[9:2]; ram_di <=#Tp WB_DAT_I; BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; BDRead <=#Tp (|BDCs) & ~WB_WE_I; end 5'b100_00 : begin WbEn <=#Tp 1'b0; // WbEn access stage and there is no need for other stages. WbEn needs to be switched off for a bit end 5'b000_00 : begin WbEn <=#Tp 1'b1; // Idle state. We go to WbEn access stage. RxEn <=#Tp 1'b0; TxEn <=#Tp 1'b0; ram_addr <=#Tp WB_ADR_I[9:2]; ram_di <=#Tp WB_DAT_I; BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; BDRead <=#Tp (|BDCs) & ~WB_WE_I; end endcase endend// Delayed stage signalsalways @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) begin WbEn_q <=#Tp 1'b0; RxEn_q <=#Tp 1'b0; TxEn_q <=#Tp 1'b0; r_TxEn_q <=#Tp 1'b0; r_RxEn_q <=#Tp 1'b0; end else begin WbEn_q <=#Tp WbEn; RxEn_q <=#Tp RxEn; TxEn_q <=#Tp TxEn; r_TxEn_q <=#Tp r_TxEn; r_RxEn_q <=#Tp r_RxEn; endend// Changes for tx occur every second clock. Flop is used for this manner.always @ (posedge MTxClk or posedge Reset)begin if(Reset) Flop <=#Tp 1'b0; else if(TxDone | TxAbort | TxRetry_q) Flop <=#Tp 1'b0; else if(TxUsedData) Flop <=#Tp ~Flop;endwire ResetTxBDReady;assign ResetTxBDReady = TxDonePulse | TxAbortPulse | TxRetryPulse;// Latching READY status of the Tx buffer descriptoralways @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxBDReady <=#Tp 1'b0; else if(TxEn & TxEn_q & TxBDRead) TxBDReady <=#Tp ram_do[15] & (ram_do[31:16] > 4); // TxBDReady is sampled only once at the beginning. else // Only packets larger then 4 bytes are transmitted. if(ResetTxBDReady) TxBDReady <=#Tp 1'b0;end// Reading the Tx buffer descriptorassign StartTxBDRead = (TxRetryPacket_NotCleared | TxStatusWrite) & ~BlockingTxBDRead & ~TxBDReady;always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxBDRead <=#Tp 1'b1; else if(StartTxBDRead) TxBDRead <=#Tp 1'b1; else if(TxBDReady) TxBDRead <=#Tp 1'b0;end// Reading Tx BD pointerassign StartTxPointerRead = TxBDRead & TxBDReady;// Reading Tx BD Pointeralways @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxPointerRead <=#Tp 1'b0; else if(StartTxPointerRead) TxPointerRead <=#Tp 1'b1; else if(TxEn_q) TxPointerRead <=#Tp 1'b0;end// Writing status back to the Tx buffer descriptorassign TxStatusWrite = (TxDonePacket_NotCleared | TxAbortPacket_NotCleared) & TxEn & TxEn_q & ~BlockingTxStatusWrite;// Status writing must occur only once. Meanwhile it is blocked.always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) BlockingTxStatusWrite <=#Tp 1'b0; else if(~TxDone_wb & ~TxAbort_wb) BlockingTxStatusWrite <=#Tp 1'b0; else if(TxStatusWrite) BlockingTxStatusWrite <=#Tp 1'b1;endreg BlockingTxStatusWrite_sync1;reg BlockingTxStatusWrite_sync2;reg BlockingTxStatusWrite_sync3;// Synchronizing BlockingTxStatusWrite to MTxClkalways @ (posedge MTxClk or posedge Reset)begin if(Reset) BlockingTxStatusWrite_sync1 <=#Tp 1'b0; else BlockingTxStatusWrite_sync1 <=#Tp BlockingTxStatusWrite;end// Synchronizing BlockingTxStatusWrite to MTxClkalways @ (posedge MTxClk or posedge Reset)begin if(Reset) BlockingTxStatusWrite_sync2 <=#Tp 1'b0; else BlockingTxStatusWrite_sync2 <=#Tp BlockingTxStatusWrite_sync1;end// Synchronizing BlockingTxStatusWrite to MTxClkalways @ (posedge MTxClk or posedge Reset)begin if(Reset) BlockingTxStatusWrite_sync3 <=#Tp 1'b0; else BlockingTxStatusWrite_sync3 <=#Tp BlockingTxStatusWrite_sync2;endassign RstDeferLatched = BlockingTxStatusWrite_sync2 & ~BlockingTxStatusWrite_sync3;// TxBDRead state is activated only once. always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) BlockingTxBDRead <=#Tp 1'b0; else if(StartTxBDRead) BlockingTxBDRead <=#Tp 1'b1; else if(~StartTxBDRead & ~TxBDReady) BlockingTxBDRead <=#Tp 1'b0;end// Latching status from the tx buffer descriptor// Data is avaliable one cycle after the access is started (at that time signal TxEn is not active)always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxStatus <=#Tp 4'h0; else if(TxEn & TxEn_q & TxBDRead) TxStatus <=#Tp ram_do[14:11];endreg ReadTxDataFromMemory;wire WriteRxDataToMemory;reg MasterWbTX;reg MasterWbRX;reg [29:0] m_wb_adr_o;reg m_wb_cyc_o;reg [3:0] m_wb_sel_o;reg m_wb_we_o;wire TxLengthEq0;wire TxLengthLt4;reg BlockingIncrementTxPointer;reg [31:2] TxPointerMSB;reg [1:0] TxPointerLSB;reg [1:0] TxPointerLSB_rst;reg [31:2] RxPointerMSB;reg [1:0] RxPointerLSB_rst;wire RxBurstAcc;wire RxWordAcc;wire RxHalfAcc;wire RxByteAcc;//Latching length from the buffer descriptor;always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxLength <=#Tp 16'h0; else if(TxEn & TxEn_q & TxBDRead) TxLength <=#Tp ram_do[31:16]; else if(MasterWbTX & m_wb_ack_i) begin if(TxLengthLt4) TxLength <=#Tp 16'h0; else if(TxPointerLSB_rst==2'h0) TxLength <=#Tp TxLength - 3'h4; // Length is subtracted at the data request else if(TxPointerLSB_rst==2'h1) TxLength <=#Tp TxLength - 3'h3; // Length is subtracted at the data request else if(TxPointerLSB_rst==2'h2) TxLength <=#Tp TxLength - 3'h2; // Length is subtracted at the data request else if(TxPointerLSB_rst==2'h3) TxLength <=#Tp TxLength - 3'h1; // Length is subtracted at the data request endend//Latching length from the buffer descriptor;always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) LatchedTxLength <=#Tp 16'h0; else if(TxEn & TxEn_q & TxBDRead) LatchedTxLength <=#Tp ram_do[31:16];endassign TxLengthEq0 = TxLength == 0;assign TxLengthLt4 = TxLength < 4;reg cyc_cleared;reg IncrTxPointer;// Latching Tx buffer pointer from buffer descriptor. Only 30 MSB bits are latched// because TxPointerMSB is only used for word-aligned accesses.always @ (posedge WB_CLK_I or posedge Reset)begin if(Reset) TxPointerMSB <=#Tp 30'h0; else if(TxEn & TxEn_q & TxPointerRead) TxPointerMSB <=#Tp ram_do[31:2]; else if(IncrTxPointer & ~BlockingIncrementTxPointer) TxPointerMSB <=#Tp TxPointerMSB + 1'b1; // TxPointer is word-alignedend// Latching 2 MSB bits of the buffer descriptor. Since word accesses are performed,// valid data does not necesserly start at byte 0 (could be byte 0, 1, 2 or 3). This
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -