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

📄 eth_wishbone.v

📁 用Verilog实现的以太网接口
💻 V
📖 第 1 页 / 共 5 页
字号:
    TxBDReady <=#Tp 1'b0;
end


// Reading the Tx buffer descriptor
assign 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 pointer
assign StartTxPointerRead = TxBDRead & TxBDReady;

// Reading Tx BD Pointer
always @ (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 descriptor
assign 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;
end


reg BlockingTxStatusWrite_sync1;
reg BlockingTxStatusWrite_sync2;

// Synchronizing BlockingTxStatusWrite to MTxClk
always @ (posedge MTxClk or posedge Reset)
begin
  if(Reset)
    BlockingTxStatusWrite_sync1 <=#Tp 1'b0;
  else
    BlockingTxStatusWrite_sync1 <=#Tp BlockingTxStatusWrite;
end

// Synchronizing BlockingTxStatusWrite to MTxClk
always @ (posedge MTxClk or posedge Reset)
begin
  if(Reset)
    BlockingTxStatusWrite_sync2 <=#Tp 1'b0;
  else
    BlockingTxStatusWrite_sync2 <=#Tp BlockingTxStatusWrite_sync1;
end


// 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];
end

reg ReadTxDataFromMemory;
wire WriteRxDataToMemory;

reg MasterWbTX;
reg MasterWbRX;

reg [31:0] m_wb_adr_o;
reg        m_wb_cyc_o;
reg        m_wb_stb_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
    end
end



//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];
end

assign 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-aligned
end


// 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
// 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;
end


reg  [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;
end


wire 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;
end

reg 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;
end


assign 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 32'h0;
      m_wb_cyc_o <=#Tp 1'b0;
      m_wb_stb_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_stb_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+1;
            if(tx_burst_cnt==0)
              m_wb_adr_o <=#Tp {TxPointerMSB, 2'h0};
            else
              m_wb_adr_o <=#Tp m_wb_adr_o+3'h4;

            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_stb_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+1;

            if(rx_burst_cnt==0)
              m_wb_adr_o <=#Tp {RxPointerMSB, 2'h0};
            else
              m_wb_adr_o <=#Tp m_wb_adr_o+3'h4;

            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, 2'h0};
            m_wb_cyc_o <=#Tp 1'b1;
            m_wb_stb_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, 2'h0};
            m_wb_cyc_o <=#Tp 1'b1;
            m_wb_stb_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, 2'h0};
            m_wb_cyc_o <=#Tp 1'b1;
            m_wb_stb_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, 2'h0};
            m_wb_cyc_o <=#Tp 1'b1;
            m_wb_stb_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
            m_wb_stb_o <=#Tp 1'b0;
            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;
            m_wb_stb_o <=#Tp 1'b0;
            cyc_cleared<=#Tp 1'b0;
            IncrTxPointer<=#Tp 1'b0;
            rx_burst_cnt<=#Tp 0;

⌨️ 快捷键说明

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