ethermac: reduce interrupt overhead
[nios2ecos.git] / eth_ocm / eth_avalon.v
blob1bfb13f3131f1229a9976f199ffc98fe4b95fa17
1 //////////////////////////////////////////////////////////////////////
2 //// ////
3 //// eth_avalon.v ////
4 //// ////
5 //// This file is a patch used in conjunction with the ////
6 //// Ethernet IP core project. ////
7 //// http://www.opencores.org/projects/ethmac/ ////
8 //// ////
9 //// Author(s): ////
10 //// - Jakob Jones (jrjonsie@gmail.com) ////
11 //// ////
12 //// All additional information is available in the Readme.txt ////
13 //// file. ////
14 //// ////
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
29 //Avalon Control Port
30 //inputs
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
36 //outputs
37 output [31:0] av_readdata, //Avalon slave readdata
38 output av_waitrequest_n, //Avalon slave waitrequest
40 //Avalon TX memory port
41 //input
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
45 //output
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
50 //inputs
51 input av_rx_waitrequest, //Avalon RX master waitrequest
52 //outputs
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
58 // Rx Status signals
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*/
73 // Tx Status signals
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
81 // Tx
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
94 // Rx
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
103 //Register
104 input r_TxEn, // Transmit enable
105 input r_RxEn, // Receive enable
106 input [7:0] r_TxBDNum, // Receive buffer descriptor number
108 // Interrupts
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
116 // Bist
117 `ifdef ETH_BIST
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
122 `endif
125 //Some useful constant functions
126 `include "eth_avalon_functions.v"
128 localparam Tp = 1;
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
143 //RX BD interface
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
150 //TX BD interface
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
157 //Muxed BD interface
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
178 `ifdef ETH_BIST
179 assign mbist_so_o = mbist_si_i;
180 `endif
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;
217 // Pointer BD RAM
218 eth_avalon_bd_ram #(.DEPTH(RDC) ) ptr_ram(
219 .clock (av_clk ),
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)
226 .wren_b (1'b0 ),
227 .address_b (bd_index ),
228 .data_b (32'd0 ),
229 .q_b (bd_ptr )
232 // Descriptor BD RAM
233 eth_avalon_bd_ram #(.DEPTH(RDC) ) desc_ram(
234 .clock (av_clk ),
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)
241 .wren_b (bd_write ),
242 .address_b (bd_index ),
243 .data_b (bd_writedata ),
244 .q_b (bd_desc )
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;
263 //RX Interface
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
297 //Interrupt outputs
298 .RxB_IRQ (RxB_IRQ ), // Receive success IRQ
299 .RxE_IRQ (RxE_IRQ ), // Receive error IRQ
300 .Busy_IRQ (Busy_IRQ ) // Receive busy IRQ
303 //Register RxStatus
304 always @(posedge MRxClk)
305 if (LoadRxStatus)
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;
321 //TX Interface
322 eth_avalon_txdma #(.FIFO_DEPTH(TX_FIFO_DEPTH)) eth_txdma_inst(
323 //Common signals
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,
355 RetryCntLatched,
356 RetryLimit,
357 LateCollLatched,
358 DeferLatched,
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 ),
368 //Interrupt outputs
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)
382 Flop <= 1'b0;
383 else if(TxUsedData)
384 Flop <= ~Flop;
386 always @(posedge MTxClk or posedge tx_reset)
387 if(tx_reset) TxUnderRun_r <= 1'b0;
388 else begin
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;
400 endmodule