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