1 //////////////////////////////////////////////////////////////////////
5 //// This file is a patch used in conjunction with the ////
6 //// Ethernet IP core project. ////
7 //// http://www.opencores.org/projects/ethmac/ ////
10 //// - Jakob Jones (jrjonsie@gmail.com) ////
12 //// All additional information is available in the Readme.txt ////
15 //////////////////////////////////////////////////////////////////////
17 `include "eth_defines.v"
18 `include "timescale.v"
20 // Parameter DESC_COUNT is the number of descriptors to use.
21 // Parameter RX_FIFO_DEPTH is the Depth of the Receive FIFO (in bytes)
22 // Parameter TX_FIFO_DEPTH is the Depth of the Transmit FIFO (in bytes)
23 module eth_avalon #
( parameter DESC_COUNT
= 128,
24 parameter RX_FIFO_DEPTH
= 4096,
25 parameter TX_FIFO_DEPTH
= 128 ) (
26 input av_reset
, //Asynchronous reset (Avalon side)
27 input av_clk
, //Avalon clock
31 input av_cs
, //Avalon slave BD chipselect
32 input av_write
, //Avalon slave write
33 input av_read
, //Avalon slave read
34 input [7:0] av_address
, //Avalon slave address
35 input [31:0] av_writedata
, //Avalon slave writedata
37 output [31:0] av_readdata
, //Avalon slave readdata
38 output av_waitrequest_n
, //Avalon slave waitrequest
40 //Avalon TX memory port
42 input av_tx_waitrequest
, //Avalon TX master waitrequest
43 input av_tx_readdatavalid
,//Avalon TX master readdatavalid
44 input [31:0] av_tx_readdata
, //Avalon TX master readdata
46 output [31:0] av_tx_address
, //Avalon TX master address
47 output av_tx_read
, //Avalon TX master read
49 //Avalon RX memory port
51 input av_rx_waitrequest
, //Avalon RX master waitrequest
53 output [31:0] av_rx_address
, //Avalon RX master address
54 output av_rx_write
, //Avalon RX master write
55 output [31:0] av_rx_writedata
, //Avalon RX master writedata
56 output [3:0] av_rx_byteenable
, //Avalon RX master byteenable
59 input InvalidSymbol
, // Invalid symbol was received during reception in 100 Mbps mode
60 input LatchedCrcError
, // CRC error
61 input RxLateCollision
, // Late collision occured while receiving frame
62 input ShortFrame
, // Frame shorter then the minimum size (r_MinFL) was received while small packets are enabled (r_RecSmall)
63 input DribbleNibble
, // Extra nibble received
64 input ReceivedPacketTooBig
,// Received packet is bigger than r_MaxFL
65 input [15:0] RxLength
, // Length of the incoming frame
66 input LoadRxStatus
, // Rx status was loaded
67 input ReceivedPacketGood
, // Received packet's length and CRC are good
68 input AddressMiss
, // When a packet is received AddressMiss status is written to the Rx BD
69 input r_RxFlow
, /*TODO*/
70 input r_PassAll
, /*TODO*/
71 input ReceivedPauseFrm
, /*TODO*/
74 input [3:0] RetryCntLatched
, // Latched Retry Counter
75 input RetryLimit
, // Retry limit reached (Retry Max value + 1 attempts were made)
76 input LateCollLatched
, // Late collision occured
77 input DeferLatched
, // Defer indication (Frame was defered before sucessfully sent)
78 output RstDeferLatched
, // Ack DeferLatched
79 input CarrierSenseLost
, // Carrier Sense was lost during the frame transmission
82 input MTxClk
, // Transmit clock (from PHY)
83 input TxUsedData
, // Transmit packet used data (this is an ack)
84 input TxRetry
, // Transmit packet retry
85 input TxAbort
, // Transmit packet abort
86 input TxDone
, // Transmission ended
87 output TxStartFrm
, // Transmit packet start frame
88 output TxEndFrm
, // Transmit packet end frame
89 output [7:0] TxData
, // Transmit packet data byte
90 output TxUnderRun
, // Transmit packet under-run
91 output PerPacketCrcEn
, // Per packet crc enable
92 output PerPacketPad
, // Per packet pading
95 input MRxClk
, // Receive clock (from PHY)
96 input [7:0] RxData
, // Received data byte
97 input RxValid
, // Receive data valid
98 input RxStartFrm
, // Receive start of frame
99 input RxEndFrm
, // Receive end of frame
100 input RxAbort
, // This signal is set when address doesn't match.
101 output reg RxStatusWriteLatched_sync2
, //indication back
104 input r_TxEn
, // Transmit enable
105 input r_RxEn
, // Receive enable
106 input [7:0] r_TxBDNum
, // Receive buffer descriptor number
109 output TxB_IRQ
, // Transmit successful IRQ
110 output TxE_IRQ
, // Transmit error IRQ
111 output RxB_IRQ
, // Receive successful IRQ
112 output RxE_IRQ
, // Receive error IRQ
113 output Busy_IRQ
// Receive busy IRQ
119 input mbist_si_i
, // bist scan serial in
120 output mbist_so_o
, // bist scan serial out
121 input [`ETH_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control
125 //Some useful constant functions
126 `include "eth_avalon_functions.v"
129 //Determine the number
130 localparam RDC
= min(max(nextPow2(DESC_COUNT
), 2), 128); //Real descriptor count
131 localparam MAX_DESC
= RDC
- 1; //highest index descriptor
133 //Avalon interface signals
134 wire av_waitrequest
; // Avalon slave waitrequest
135 wire av_bd_desc_cs
; // Avalon Descriptor RAM is selected
136 wire [31:0] av_desc_readdata
; // Avalon Descriptor readback data
137 wire av_bd_ptr_cs
; // Avalon Pointer RAM is selected
138 wire [31:0] av_ptr_readdata
; // Avalon Pointer readback data
139 reg av_read_r
; // Avalon read registered
141 //Descriptor interface signals
142 wire [7:0] max_rx_bd
; // Highest RX descriptor index
144 wire rx_bd_wait
; // RX BD wait signal
145 wire rx_bd_write
; // RX BD write signal
146 wire rx_bd_read
; // RX BD read signal
147 reg rx_bd_read_r
; // RX BD read registered (used for wait)
148 wire [6:0] rx_bd_index
; // RX BD descriptor or pointer index
149 wire [31:0] rx_bd_writedata
; // RX BD descriptor writeback data
151 wire tx_bd_wait
; // TX BD wait signal
152 wire tx_bd_write
; // TX BD write signal
153 wire tx_bd_read
; // TX BD read signal
154 reg tx_bd_read_r
; // TX BD read registered (used for wait)
155 wire [6:0] tx_bd_index
; // TX BD descriptor or pointer index
156 wire [31:0] tx_bd_writedata
; // TX BD descriptor writeback data
158 wire [31:0] bd_desc
; // Descriptor data from BD RAM
159 wire [31:0] bd_ptr
; // Pointer data from BD RAM
160 wire bd_write
; // Descriptor data write to BD RAM
161 wire [6:0] bd_index
; // Descriptor/Pointer index to BD RAM
162 wire [31:0] bd_writedata
; // Descriptor writeback data to BD RAM
163 reg rx_txn_sel
; // 1 = MUX RX to BD RAM, 0 = MUX TX
165 //Receive side signals
166 reg rx_reset
; // Reset Receive interface
167 wire [8:0] RxStatus
; // RX Status from MAC core
168 reg [8:0] RxStatus_r
; // RX Status latched
170 //Transmit side signals
171 reg tx_reset
; // Reset Transmit interface
172 reg Flop
; // Follow nomenclature from eth_wishbone
173 // toggles to activate TxUsedData
174 reg TxUnderRun_r
; // Underrun of TX FIFO
175 reg tx_retry
; // TX retry signal
176 wire tx_stat_ack
; // TX status ack
179 assign mbist_so_o
= mbist_si_i
;
182 assign av_waitrequest_n
= ~av_waitrequest
;
184 //***************************************************************************
185 //************************** Descriptor Interface ***************************
186 // Avalon bus is in wait if:
187 // 1 - The BD RAM is not selected
188 // 2 - The Avalon BUS issued a read but data is not available yet
189 assign av_waitrequest
= (~av_cs
) |
(av_read
& ~av_read_r
);
191 // Select pointer RAM or descriptor RAM based on lowest address bit
192 assign av_bd_ptr_cs
= av_address
[0];
193 assign av_bd_desc_cs
= ~av_address
[0];
195 // Mux Pointer or descriptor readback data to Avalon BUS
196 assign av_readdata
= av_bd_ptr_cs? av_ptr_readdata
: av_desc_readdata
;
198 // Mux TX or RX address, data, and control signals
199 assign bd_write
= rx_txn_sel ? rx_bd_write
: tx_bd_write
;
200 assign bd_writedata
= rx_txn_sel ? rx_bd_writedata
: tx_bd_writedata
;
201 assign bd_index
= rx_txn_sel ?
(rx_bd_index
+ r_TxBDNum
) : tx_bd_index
;
203 // Determine BD wait signal back to RX interface
204 assign rx_bd_wait
= ~rx_txn_sel |
(rx_txn_sel
& rx_bd_read
& ~rx_bd_read_r
);
205 // Determine BD wait signal back to TX interface
206 assign tx_bd_wait
= rx_txn_sel |
(~rx_txn_sel
& tx_bd_read
& ~tx_bd_read_r
);
208 // Register BD RAM read signals used to control wait
209 always @(posedge av_clk
) begin
210 av_read_r
<= av_read
;
211 rx_bd_read_r
<= rx_bd_read
& rx_txn_sel
;
212 tx_bd_read_r
<= tx_bd_read
& ~rx_txn_sel
;
213 if((rx_txn_sel
& ~rx_bd_wait
) |
(~rx_txn_sel
& ~tx_bd_wait
))
214 rx_txn_sel
<= ~rx_txn_sel
;
218 eth_avalon_bd_ram #
(.
DEPTH(RDC
) ) ptr_ram(
220 // port A (Avalon interface)
221 .
wren_a (av_write
&av_bd_ptr_cs
),
222 .
address_a (av_address
>>1 ),
223 .
data_a (av_writedata
),
224 .
q_a (av_ptr_readdata
),
225 // port B (DMA interface)
227 .
address_b (bd_index
),
233 eth_avalon_bd_ram #
(.
DEPTH(RDC
) ) desc_ram(
235 // port A (Avalon interface)
236 .
wren_a (av_write
&av_bd_desc_cs
),
237 .
address_a (av_address
>>1 ),
238 .
data_a (av_writedata
),
239 .
q_a (av_desc_readdata
),
240 // port B (DMA interface)
242 .
address_b (bd_index
),
243 .
data_b (bd_writedata
),
246 //************************ End Descriptor Interface *************************
247 //***************************************************************************
249 //***************************************************************************
250 //****************************** RX Interface *******************************
252 // Determine maximum RX descriptor index
253 assign max_rx_bd
= MAX_DESC
- r_TxBDNum
;
254 // Decode RX Status inputs
255 assign RxStatus
= { ReceivedPauseFrm
,
256 AddressMiss
, 1'b0 , InvalidSymbol
, DribbleNibble
,
257 ReceivedPacketTooBig
, ShortFrame
, LatchedCrcError
, RxLateCollision
};
259 //RX Interface is held in reset when not enabled
260 always @(posedge av_clk
)
261 rx_reset
<= av_reset |
~r_RxEn
;
264 eth_avalon_rxdma #
(.
FIFO_DEPTH(RX_FIFO_DEPTH
) ) eth_rxdma_inst(
265 .
clk (av_clk
), // Avalon clock
266 .
reset (rx_reset
), // Avalon reset
268 //Descriptor ram interface
269 .
max_rx_bd (max_rx_bd
), // Highest index RX Descriptor
270 .
bd_desc (bd_desc
), // Descriptor Control data input
271 .
bd_ptr (bd_ptr
), // Descriptor pointer input
272 .
bd_wait (rx_bd_wait
), // Descriptor RAM is busy
274 .
bd_write (rx_bd_write
), // write control data to BD RAM
275 .
bd_read (rx_bd_read
), // read control and pointer data from BD RAM
276 .
bd_index (rx_bd_index
), // Which descriptor to read
277 .
bd_writedata (rx_bd_writedata
), // Control data to be written to descriptor
279 //Memory port interface
280 .
av_waitrequest (av_rx_waitrequest
), // Memory port is busy
282 .
av_write (av_rx_write
), // Memory port write
283 .
av_address (av_rx_address
), // Memory port address
284 .
av_writedata (av_rx_writedata
), // Memory port writedata
285 .
av_byteenable (av_rx_byteenable
), // Memory port byteenable
287 //Streaming interface
288 .
RxEn (r_RxEn
), // Receive enable
289 .
rxclk (MRxClk
), // Receive clock
290 .
rx_data (RxData
), // input data
291 .
rx_dv (RxValid
), // qualifies datain, startofpacket, and endofpacket
292 .
rx_err (RxStatus_r
), // error bits
293 .
rx_sop (RxStartFrm
), // start of data packet
294 .
rx_eop (RxEndFrm | RxAbort
), // end of data packet
295 .
rx_abort (RxAbort
), // abort packet
298 .
RxB_IRQ (RxB_IRQ
), // Receive success IRQ
299 .
RxE_IRQ (RxE_IRQ
), // Receive error IRQ
300 .
Busy_IRQ (Busy_IRQ
) // Receive busy IRQ
304 always @(posedge MRxClk
)
306 RxStatus_r
<= RxStatus
;
308 //We save the data and cross the clock domains in the RX DMA module so
309 //there is no need for synchronization here. We do it to be compliant
310 //with Igor's implementaion
311 always @(posedge MRxClk
)
312 RxStatusWriteLatched_sync2
<= LoadRxStatus
;
314 //***************************************************************************
315 //**************************** TX Interface *********************************
317 // TX interface is held in reset when not enabled
318 always @(posedge av_clk
)
319 tx_reset
<= av_reset |
~r_TxEn
;
322 eth_avalon_txdma #
(.
FIFO_DEPTH(TX_FIFO_DEPTH
)) eth_txdma_inst(
324 .
clk (av_clk
), // Avalon clock
325 .
reset (tx_reset
), // Avalon reset
327 //Descriptor ram interface
328 .
max_tx_bd (r_TxBDNum
- 7'd1 ), // Highest index RX Descriptor
329 .
bd_desc (bd_desc
), // Descriptor Control data input
330 .
bd_ptr (bd_ptr
), // Descriptor pointer input
331 .
bd_wait (tx_bd_wait
), // Descriptor RAM is busy
333 .
bd_write (tx_bd_write
), // write control data to BD RAM
334 .
bd_read (tx_bd_read
), // read control and pointer data from BD RAM
335 .
bd_index (tx_bd_index
), // Which descriptor to read
336 .
bd_writedata (tx_bd_writedata
), // Control data to be written to descriptor
338 //Memory port interface
339 .
av_waitrequest (av_tx_waitrequest
), // Memory port is busy
340 .
av_readdata (av_tx_readdata
), // Memory port readdata
341 .
av_readdatavalid (av_tx_readdatavalid
), // Memory port readdata valid signal
343 .
av_read (av_tx_read
), // Memory port read
344 .
av_address (av_tx_address
), // Memory port address
346 //Streaming interface
347 .
TxEn (r_TxEn
), // Enable transmit
348 .
txclk (MTxClk
), // Transmit clock
349 .
tx_data (TxData
), // output data
350 .
tx_dv ( ), // qualifies dataout, startofpacket, and endofpacket
351 .
tx_sop (TxStartFrm
), // start of data packet
352 .
tx_eop (TxEndFrm
), // end of data packet
353 .
tx_ack (TxUsedData
& Flop
), // Acknowledge TX data
354 .
tx_stat ({TxUnderRun_r
,
359 CarrierSenseLost
}), // Status bits
360 .
tx_stat_valid (TxRetry|TxAbort|TxDone
),// Status is valid
361 .
tx_stat_ack (tx_stat_ack
),
362 .
tx_retry (tx_retry
),
364 .
PerPacketPad (PerPacketPad
),
365 .
PerPacketCrc (PerPacketCrcEn
),
366 .
TxUnderRun (TxUnderRun
),
369 .
TxB_IRQ (TxB_IRQ
), // TX success IRQ
370 .
TxE_IRQ (TxE_IRQ
) // TX error IRQ
373 //Send Reset defered latch back to core
374 assign RstDeferLatched
= (TxRetry|TxAbort|TxDone
);
376 //The Flop signal is used to toggle valid TxUsedData
377 //because the core only uses the data on every other
378 //clock (8 bits local interface vs. 4 bits MII interface)
379 always @(posedge MTxClk
or posedge tx_reset
)
380 if(tx_reset
) Flop
<= 1'b0;
381 else if(TxDone|TxAbort|TxRetry
)
386 always @(posedge MTxClk
or posedge tx_reset
)
387 if(tx_reset
) TxUnderRun_r
<= 1'b0;
389 if(tx_stat_ack
) TxUnderRun_r
<= 1'b0;
390 if(TxUnderRun
) TxUnderRun_r
<= 1'b1;
393 always @(posedge MTxClk
or posedge tx_reset
)
394 if(tx_reset
) tx_retry
<= 1'b0;
395 else if(TxRetry
) tx_retry
<= 1'b1;
396 else if(tx_stat_ack
) tx_retry
<= 1'b0;