ethermac: reduce interrupt overhead
[nios2ecos.git] / eth_ocm / eth_avalon_rxdma.v
blobf0339f83b9b8fe7596a854c28c169c2100ae4079
1 //////////////////////////////////////////////////////////////////////
2 //// ////
3 //// eth_avalon_rxdma.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 //////////////////////////////////////////////////////////////////////
16 module eth_avalon_rxdma #( parameter FIFO_DEPTH = 4096) (
17 //Commaon signals
18 input clk,
19 input reset,
21 //Descriptor ram interface
22 input [6:0] max_rx_bd, //Highest index RX Descriptor
23 input [31:0] bd_desc, //Descriptor Control data input
24 input [31:0] bd_ptr, //Descriptor pointer input
25 input bd_wait, //Descriptor RAM is busy
27 output bd_write, //write control data to BD RAM
28 output bd_read, //read control and pointer data from BD RAM
29 output reg [6:0] bd_index, //Which descriptor to read
30 output [31:0] bd_writedata, //Control data to be written to descriptor
32 //Memory port interface
33 input av_waitrequest, //Memory port is busy
35 output reg av_write, //Memory port write
36 output reg [31:0] av_address, //Memory port address
37 output reg [31:0] av_writedata, //Memory port writedata
38 output reg [3:0] av_byteenable, //Memory port byteenable
40 //Streaming interface
41 input RxEn, //Receive Enable
42 input rxclk, //Receive clock
43 input [7:0] rx_data, //input data
44 input rx_dv, //qualifies datain, startofpacket, and endofpacket
45 input [8:0] rx_err, //error bits
46 input rx_sop, //start of data packet
47 input rx_eop, //end of data packet
48 input rx_abort, //abort packet
50 //Interrupt outputs
51 output reg RxB_IRQ,
52 output reg RxE_IRQ,
53 output Busy_IRQ
56 `include "eth_avalon_functions.v"
58 //Let's determine the FIFO Depths. We use two FIFOs. One to pass data.
59 //and one to pass error information. The error FIFO does not need to be as
60 //large because it is only written to on an end of packet. We'll make the
61 //assumption that normally packets will be a minimum of 64 bytes long. So
62 //We divide the FIFO depth by 64 to get the Error FIFO depth. To be on the
63 //safe side, we double that number (really divide by 32). If Either one of
64 //these FIFOs overflow, on overrun will occur.
65 localparam MINFD = max(FIFO_DEPTH,128); //Minimum 128 byte FIFO depth
66 localparam RFD = nextPow2(MINFD)>>2; //FIFO depth next power of 2 (and divide by 4)
67 localparam EFD = max((RFD>>3), 4); //Minimum error FIFO depth of 4
69 //Descriptor status bit defines
70 localparam BIT_LEN_H = 31, //Upper bit of length field
71 BIT_LEN_L = 16, //Lower bit of length field
72 //Control bits
73 BIT_EMPTY = 15, //Empty control bit (1=EMPTY Controller can write to it)
74 BIT_IRQ = 14, //Generate an interrupt at end of RX
75 BIT_WRAP = 13, //Wrap to first RX descriptor after this one
76 BIT_RSVD_H = 12, //Upper bit of reserved field
77 BIT_RSVD_L = 11, //Lower bit of reserved field
78 //Status bits
79 BIT_CF = 8, //Control Frame was received
80 BIT_M = 7, //Miss
81 BIT_OR = 6, //FIFO overrun
82 BIT_IS = 5, //Invalid Symbol
83 BIT_DN = 4, //Dribble Nibble
84 BIT_TL = 3, //Frame too long
85 BIT_SF = 2, //Frame short
86 BIT_CRC = 1, //CRC error
87 BIT_LC = 0; //Late Collision
89 //DMA State Machine Bits
90 localparam ST_IDLE = 0,
91 ST_BD_RD = 1,
92 ST_DMA1 = 2,
93 ST_DMA2 = 3,
94 ST_BD_WR = 4;
96 //RX State Machine Bits
97 localparam RX_IDLE = 0,
98 RX_REC = 1,
99 RX_DISC = 2,
100 RX_EOP = 3;
102 //Avalon interface signals
103 wire [31:0] pre_av_writedata;
104 wire [3:0] pre_av_byteenable;
105 wire pre_av_write;
106 wire [31:0] pre_av_address;
108 //Descriptor signals
109 reg [31:0] desc; //Descriptor control word
110 reg [31:0] ptr; //Write pointer (from descriptor)
111 reg [15:0] len; //Length counter
113 //DMA controller signals
114 reg [5:0] state; //One-hot state machine bits
115 wire [1:0] cnt; //Valid byte count (out of FIFO);
116 wire eop; //End of packet flag (out of FIFO)
117 wire abort; //Abort flag (out of FIFO)
118 reg err_r;
120 reg first_write;//First write to memory
121 wire [3:0] lsb_be; //LSB byteenable (First write)
122 wire [12:0] msb_be;
123 reg [2:0] msb_be2;
124 wire [63:0] sdata; //shifted data
125 wire rx_write;
126 wire valid_rx_wr;
128 //FIFO Signals
129 //(DMA side)
130 wire dff_empty; //data FIFO empty
131 wire [35:0] dff_dout; //data FIFO output
132 reg [35:0] dff_dout_r; //registered dff_out
133 wire dff_read; //data FIFO read
135 wire eff_empty; //error FIFO empty
136 wire [8:0] eff_dout; //error FIFO output
137 reg [8:0] eff_dout_r; //registered eff_dout
138 wire eff_read; //error FIFO read
139 //(Streaming Side)
140 wire [35:0] dff_in; // data fifo input data
141 reg [7:0] dff_in_reg[3:0];// registered incoming data word (to make a x4)
142 reg [3:0] dff_stat; // {errors,eop,#valid bytes}
143 wire dff_wr; // write data to FIFO
144 wire dff_full; // data FIFO full
145 wire eff_wr;
146 wire eff_full;
148 //Streaming interface signals
149 reg [3:0] rx_state; // RX state bits
150 reg [1:0] rx_cnt; // # of valid bytes in data word
151 reg rx_wr; // indicates normal write to FIFO
152 wire rx_rdy; // indicates FIFO is ready to receive (not full)
153 reg rx_overrun; // an overrun as occurred
154 reg rx_abort_r; // latch rx_abort flag at end of packet
155 wire [8:0] rx_res; // RX result (errors and status)
157 //*****************************************************************************
158 //************************* Avalon Interface Logic ****************************
159 always @(posedge clk or posedge reset)
160 if(reset) av_write <= 1'b0;
161 else if(~av_waitrequest) av_write <= pre_av_write;
163 always @(posedge clk)
164 if(~av_waitrequest) begin
165 av_writedata <= pre_av_writedata;
166 av_address <= pre_av_address;
167 av_byteenable <= pre_av_byteenable;
169 //*********************** End Avalon Interface Logic **************************
170 //*****************************************************************************
172 //*****************************************************************************
173 //************************** DMA Interface Logic ******************************
175 assign abort = dff_dout_r [35];
176 assign eop = dff_dout [34];
177 assign cnt = dff_dout [33:32];
179 //Avalon Memory Master interface
180 assign pre_av_writedata = sdata[63:32];
181 assign pre_av_byteenable = first_write ? lsb_be:
182 state[ST_DMA2 ] ? {1'b0,msb_be2}:
183 msb_be[9:6];
185 assign pre_av_address = {ptr[31:2],2'b00};
186 assign pre_av_write = rx_write;
188 assign rx_write = (state[ST_DMA1] & ~dff_empty) | (state[ST_DMA2] & ~eff_empty);
189 assign valid_rx_wr = rx_write & ~av_waitrequest;
190 assign dff_read = state[ST_DMA1] & ~dff_empty & ~av_waitrequest;
191 assign eff_read = state[ST_DMA2] & ~eff_empty & ~av_waitrequest;
193 //Shift data for unaligned transfers
194 assign sdata = {dff_dout[31:0], dff_dout_r[31:0]} << {ptr[1:0],3'd0};
195 //Shift byteenable for first unaligned transfer
196 assign lsb_be = 4'b1111 << ptr[1:0];
197 assign msb_be = 13'b0000001111111 << ({1'b0,ptr[1:0]} + {1'b0,cnt});
199 //State machine (one-hot) encoding
200 always @(posedge clk or posedge reset)
201 if(reset) begin state <= 5'd0;
202 state[ST_IDLE] <= 1'b1;
203 end else begin
204 /*default case-->*/ state <= 5'd0;
205 case(1'b1) // synopsys parallel_case
206 state[ST_IDLE ]:
207 if(RxEn) state[ST_BD_RD] <= 1'b1;
208 else state[ST_IDLE ] <= 1'b1;
209 state[ST_BD_RD]:
210 if(~bd_wait & bd_desc[BIT_EMPTY]) state[ST_DMA1 ] <= 1'b1;
211 else state[ST_BD_RD] <= 1'b1;
212 state[ST_DMA1 ]:
213 if(valid_rx_wr & eop) state[ST_DMA2 ] <= 1'b1;
214 else state[ST_DMA1 ] <= 1'b1;
215 state[ST_DMA2 ]:
216 if(valid_rx_wr)
217 state[ST_BD_WR] <= 1'b1;
218 else state[ST_DMA2 ] <= 1'b1;
219 state[ST_BD_WR]:
220 if(~bd_wait) state[ST_IDLE ] <= 1'b1;
221 else state[ST_BD_WR] <= 1'b1;
222 endcase
225 always @(posedge clk) begin
226 if(state[ST_IDLE ]) first_write <= 1'b1;
227 if(state[ST_DMA1 ] & valid_rx_wr) first_write <= 1'b0;
230 //Length decoder
231 always @(posedge clk)
232 if(state[ST_BD_RD]) len <= 16'd0;
233 else if(valid_rx_wr) len <= len + ({&pre_av_byteenable[1:0],^pre_av_byteenable[1:0]} + {&pre_av_byteenable[3:2],^pre_av_byteenable[3:2]});
234 //((av_byteenable[0] + av_byteenable[1]) + (av_byteenable[2] + av_byteenable[3]));
237 always @(posedge clk)
238 if(valid_rx_wr) msb_be2 <= msb_be[12:10];
240 //Latch Data FIFO output whenever a write to memory takes place
241 always @(posedge clk)
242 if(state[ST_DMA1] & valid_rx_wr) dff_dout_r <= dff_dout;
244 //****************************************************************************
245 //********************** Descriptor Interface Logic **************************
246 assign bd_read = state[ST_BD_RD];
247 assign bd_write = state[ST_BD_WR] & ~abort;
248 assign bd_writedata= {len[15:0],1'b0,desc[BIT_IRQ:BIT_WRAP],4'b000,eff_dout_r};
250 //Load pointer and descriptor data in BD Read state
251 always @(posedge clk) begin
252 if(bd_read) {ptr,desc} <= {bd_ptr,bd_desc};
253 if(valid_rx_wr) ptr[31:2] <= ptr[31:2] + 30'd1;
256 always @(posedge clk)
257 if(state[ST_DMA2 ] & valid_rx_wr) begin
258 eff_dout_r <= eff_dout;
259 err_r <= |{eff_dout[8:3],eff_dout[1:0]};
262 //bd_index decoder
263 always @(posedge clk or posedge reset)
264 if(reset) bd_index <= 7'd0;
265 else if(~RxEn) bd_index <= 7'd0;
266 else if(bd_write & ~bd_wait) begin
267 if((bd_index == max_rx_bd) | desc[BIT_WRAP])
268 bd_index <= 7'd0;
269 else
270 bd_index <= bd_index + 7'd1;
273 //IRQ generation to feed back to registers module
274 always @(posedge clk or posedge reset)
275 if(reset) begin RxE_IRQ <= 1'b0;
276 RxB_IRQ <= 1'b0;
277 end else begin
278 RxE_IRQ <= 1'b0;
279 RxB_IRQ <= 1'b0;
280 if(bd_write & ~bd_wait) begin
281 RxE_IRQ <= desc[BIT_IRQ] & err_r;
282 RxB_IRQ <= desc[BIT_IRQ] & ~err_r;
283 end
285 //********************** Descriptor Interface Logic **************************
286 //****************************************************************************
288 //****************************************************************************
289 //****************** Dual-Clock Data and Error FIFOs *************************
291 //Data FIFO
292 eth_avalon_dma_fifo #( .DEPTH(RFD),
293 .WIDTH(36) ) eth_rxdma_datafifo(
294 .aclr (reset ),
295 .wrclk (rxclk ),
296 .wrreq (dff_wr & rx_rdy ),
297 .wrfull (dff_full ),
298 .wrusedw( ),
299 .data (dff_in ),
301 .rdclk (clk ),
302 .rdreq (dff_read ),
303 .rdempty(dff_empty ),
304 .rdusedw( ),
305 .q (dff_dout )
308 //Error FIFO
309 eth_avalon_dma_fifo #( .DEPTH(EFD),
310 .WIDTH(9) ) eth_rxdma_errfifo(
311 .aclr (reset ),
312 .wrclk (rxclk ),
313 .wrreq (eff_wr & rx_rdy ),
314 .wrfull (eff_full ),
315 .wrusedw( ),
316 .data (rx_res ),
318 .rdclk (clk ),
319 .rdreq (eff_read ),
320 .rdempty(eff_empty ),
321 .rdusedw( ),
322 .q (eff_dout )
325 //Set Busy IRQ if a new frame comes in and
326 //we're too busy to receive it.
327 eth_dc_reg tx_start_dc_reg(
328 .d (rx_sop & rx_dv & ~rx_rdy),
329 .inclk (rxclk ),
330 .outclk (clk ),
331 .reset (reset ),
332 .q (Busy_IRQ )
335 //**************** End Dual-Clock Data and Error FIFOs ***********************
336 //****************************************************************************
338 //*****************************************************************************
339 //********************* Streaming Interface Logic *****************************
340 assign rx_rdy = ~dff_full & ~eff_full;
341 assign dff_in = {dff_stat,dff_in_reg[3],dff_in_reg[2],dff_in_reg[1],dff_in_reg[0]};
342 assign dff_wr = (rx_state[RX_REC ] & rx_wr) | rx_state[RX_EOP];
343 assign eff_wr = rx_state[RX_EOP ];
344 assign rx_res = {rx_err[8:7],rx_overrun,rx_err[5:0]};
346 always @(posedge rxclk or posedge reset)
347 if(reset) begin rx_state <= 4'd0;
348 rx_state[RX_IDLE] <= 1'b1;
349 end else begin
350 /*default case-->*/ rx_state <= 4'd0;
351 case(1'b1) // synopsys parallel_case
352 //Wait for start of FRAME
353 //We'll never leave this
354 //state if the FIFO isn't
355 //ready
356 rx_state[RX_IDLE]:
357 if(rx_dv & rx_sop)
358 if(rx_rdy) rx_state[RX_REC ] <= 1'b1;
359 else rx_state[RX_IDLE] <= 1'b1;
360 else rx_state[RX_IDLE] <= 1'b1;
361 //Receiving Frame
362 rx_state[RX_REC ]:
363 if(rx_dv) begin
364 if(rx_eop) rx_state[RX_EOP ] <= 1'b1;
365 else if(~rx_rdy) rx_state[RX_DISC] <= 1'b1;
366 else rx_state[RX_REC ] <= 1'b1;
367 end else rx_state[RX_REC ] <= 1'b1;
368 //Throw away the frame. We
369 //Overran the FIFO in the
370 //middle of the frame. We
371 //discard the rest of the
372 //frame.
373 rx_state[RX_DISC]:
374 if(rx_eop & rx_dv) rx_state[RX_EOP ] <= 1'b1;
375 else rx_state[RX_DISC] <= 1'b1;
376 //Write last word to FIFO.
377 //We will sit here indefintely
378 //until the FIFO is ready
379 rx_state[RX_EOP]:
380 if(rx_rdy) rx_state[RX_IDLE] <= 1'b1;
381 else rx_state[RX_EOP ] <= 1'b1;
382 endcase
385 always @(posedge rxclk or posedge reset)
386 if(reset) rx_overrun <= 1'b0;
387 else if(rx_state[RX_REC]) rx_overrun <= rx_dv & ~rx_rdy;
388 else if(rx_state[RX_EOP] & rx_rdy) rx_overrun <= 1'b0;
390 always @(posedge rxclk)
391 if(rx_state[RX_IDLE]) rx_abort_r <= 1'b0;
392 else if(rx_state[RX_REC] | rx_state[RX_DISC])
393 rx_abort_r <= rx_dv & rx_eop & rx_abort;
395 //We'll allow this to overrun
396 always @(posedge rxclk or posedge reset)
397 if(reset) rx_cnt <= 2'd0;
398 else
399 case(1'b1) // synopsys parallel_case
400 rx_state[RX_IDLE]:
401 if(rx_dv & rx_sop & rx_rdy) rx_cnt <= rx_cnt + 2'd1;
402 else rx_cnt <= 2'd0;
404 rx_state[RX_REC ]:
405 if(rx_dv) rx_cnt <= rx_cnt + 2'd1;
407 rx_state[RX_EOP ]: rx_cnt <= 2'd0;
408 endcase
410 //set the write flag when all 4 bytes are received
411 always @(posedge rxclk or posedge reset)
412 if(reset) rx_wr <= 1'b0;
413 else
414 if(rx_state[RX_REC]) rx_wr <= rx_dv & (&rx_cnt);
415 else rx_wr <= 1'b0;
418 //We'll alow these to overrun
419 always @* begin dff_stat[2] = rx_state[RX_EOP ];
420 if(rx_state[RX_EOP]) dff_stat[3] = rx_abort_r;
421 else dff_stat[3] = 1'b0;
424 always @(posedge rxclk)
425 if(rx_dv) begin dff_in_reg[rx_cnt] <= rx_data;
426 dff_stat[1:0] <= rx_cnt;
430 //******************* End Streaming Interface Logic ***************************
431 //*****************************************************************************
432 endmodule