]>
Commit | Line | Data |
---|---|---|
1 | ////////////////////////////////////////////////////////////////////// | |
2 | //// //// | |
3 | //// File name "pci_master32_sm_if.v" //// | |
4 | //// //// | |
5 | //// This file is part of the "PCI bridge" project //// | |
6 | //// http://www.opencores.org/cores/pci/ //// | |
7 | //// //// | |
8 | //// Author(s): //// | |
9 | //// - Miha Dolenc (mihad@opencores.org) //// | |
10 | //// //// | |
11 | //// All additional information is avaliable in the README //// | |
12 | //// file. //// | |
13 | //// //// | |
14 | //// //// | |
15 | ////////////////////////////////////////////////////////////////////// | |
16 | //// //// | |
17 | //// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// | |
18 | //// //// | |
19 | //// This source file may be used and distributed without //// | |
20 | //// restriction provided that this copyright statement is not //// | |
21 | //// removed from the file and that any derivative work contains //// | |
22 | //// the original copyright notice and the associated disclaimer. //// | |
23 | //// //// | |
24 | //// This source file is free software; you can redistribute it //// | |
25 | //// and/or modify it under the terms of the GNU Lesser General //// | |
26 | //// Public License as published by the Free Software Foundation; //// | |
27 | //// either version 2.1 of the License, or (at your option) any //// | |
28 | //// later version. //// | |
29 | //// //// | |
30 | //// This source is distributed in the hope that it will be //// | |
31 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// | |
32 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// | |
33 | //// PURPOSE. See the GNU Lesser General Public License for more //// | |
34 | //// details. //// | |
35 | //// //// | |
36 | //// You should have received a copy of the GNU Lesser General //// | |
37 | //// Public License along with this source; if not, download it //// | |
38 | //// from http://www.opencores.org/lgpl.shtml //// | |
39 | //// //// | |
40 | ////////////////////////////////////////////////////////////////////// | |
41 | // | |
42 | // CVS Revision History | |
43 | // | |
44 | // $Log: pci_master32_sm_if.v,v $ | |
45 | // Revision 1.1 2007-03-20 17:50:56 sithglan | |
46 | // add shit | |
47 | // | |
48 | // Revision 1.7 2004/03/19 16:36:55 mihad | |
49 | // Single PCI Master write fix. | |
50 | // | |
51 | // Revision 1.6 2003/12/19 11:11:30 mihad | |
52 | // Compact PCI Hot Swap support added. | |
53 | // New testcases added. | |
54 | // Specification updated. | |
55 | // Test application changed to support WB B3 cycles. | |
56 | // | |
57 | // Revision 1.5 2003/06/12 10:12:22 mihad | |
58 | // Changed one critical PCI bus signal logic. | |
59 | // | |
60 | // Revision 1.4 2003/01/27 16:49:31 mihad | |
61 | // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. | |
62 | // | |
63 | // Revision 1.3 2002/02/01 15:25:12 mihad | |
64 | // Repaired a few bugs, updated specification, added test bench files and design document | |
65 | // | |
66 | // Revision 1.2 2001/10/05 08:14:29 mihad | |
67 | // Updated all files with inclusion of timescale file for simulation purposes. | |
68 | // | |
69 | // Revision 1.1.1.1 2001/10/02 15:33:46 mihad | |
70 | // New project directory structure | |
71 | // | |
72 | // | |
73 | ||
74 | `include "pci_constants.v" | |
75 | `include "bus_commands.v" | |
76 | ||
77 | // synopsys translate_off | |
78 | `include "timescale.v" | |
79 | // synopsys translate_on | |
80 | ||
81 | /*==================================================================== | |
82 | Module provides interface between PCI bridge internals and PCI master | |
83 | state machine | |
84 | ====================================================================*/ | |
85 | module pci_master32_sm_if | |
86 | ( | |
87 | clk_in, | |
88 | reset_in, | |
89 | ||
90 | // interconnect to pci master state machine | |
91 | address_out, | |
92 | bc_out, | |
93 | data_out, | |
94 | data_in, | |
95 | be_out, | |
96 | req_out, | |
97 | rdy_out, | |
98 | last_out, | |
99 | ||
100 | next_data_out, | |
101 | next_be_out, | |
102 | next_last_out, | |
103 | ||
104 | // status inputs from master SM | |
105 | wait_in, | |
106 | wtransfer_in, | |
107 | rtransfer_in, | |
108 | retry_in, | |
109 | rerror_in, | |
110 | first_in , | |
111 | mabort_in, | |
112 | ||
113 | ||
114 | // WISHBONE WRITE fifo inputs and outputs | |
115 | wbw_renable_out, | |
116 | wbw_fifo_addr_data_in, | |
117 | wbw_fifo_cbe_in, | |
118 | wbw_fifo_control_in, | |
119 | wbw_fifo_empty_in, | |
120 | wbw_fifo_transaction_ready_in, | |
121 | ||
122 | // WISHBONE READ fifo inputs and outputs | |
123 | wbr_fifo_wenable_out, | |
124 | wbr_fifo_data_out, | |
125 | wbr_fifo_be_out, | |
126 | wbr_fifo_control_out, | |
127 | ||
128 | // delayed transaction control logic inputs and outputs | |
129 | del_wdata_in, | |
130 | del_complete_out, | |
131 | del_req_in, | |
132 | del_addr_in, | |
133 | del_bc_in, | |
134 | del_be_in, | |
135 | del_burst_in, | |
136 | del_error_out, | |
137 | del_rty_exp_out, | |
138 | del_we_in, | |
139 | ||
140 | // configuration space interconnect | |
141 | // error reporting | |
142 | err_addr_out, | |
143 | err_bc_out, | |
144 | err_signal_out, | |
145 | err_source_out, | |
146 | err_rty_exp_out, | |
147 | ||
148 | cache_line_size_in, | |
149 | ||
150 | // two signals for pci control and status | |
151 | mabort_received_out, | |
152 | tabort_received_out, | |
153 | ||
154 | posted_write_not_present_out | |
155 | ); | |
156 | ||
157 | // system inputs | |
158 | input clk_in ; | |
159 | input reset_in ; | |
160 | ||
161 | // PCI master state machine interconnect | |
162 | output [31:0] address_out ; // address output | |
163 | ||
164 | output [3:0] bc_out ; // bus command output | |
165 | reg [3:0] bc_out ; | |
166 | ||
167 | output [31:0] data_out ; // data output for writes | |
168 | reg [31:0] data_out ; | |
169 | ||
170 | input [31:0] data_in ; // data input for reads | |
171 | output [3:0] be_out ; // byte enable output | |
172 | reg [3:0] be_out ; | |
173 | ||
174 | output req_out ; // request output | |
175 | ||
176 | output rdy_out ; // ready output | |
177 | reg rdy_out ; | |
178 | ||
179 | output last_out ; // last data indicator output | |
180 | ||
181 | output [31:0] next_data_out ; // next data output | |
182 | output [3:0] next_be_out ; // next byte enable output | |
183 | output next_last_out ; // next transfer last indicator | |
184 | ||
185 | input wait_in, | |
186 | wtransfer_in, | |
187 | rtransfer_in, | |
188 | retry_in, | |
189 | rerror_in, | |
190 | first_in , | |
191 | mabort_in ; | |
192 | ||
193 | // WISHBONE write fifo interconnect | |
194 | output wbw_renable_out ; // WBW_FIFO read enable signal | |
195 | ||
196 | input [31:0] wbw_fifo_addr_data_in ; // WBW_FIFO address/data bus | |
197 | input [3:0] wbw_fifo_cbe_in ; // WBW_FIFO command/byte enable bus | |
198 | input [3:0] wbw_fifo_control_in ; // WBW_FIFO control bus | |
199 | input wbw_fifo_empty_in ; // WBW_FIFO's empty status indicator | |
200 | input wbw_fifo_transaction_ready_in ; // WBW_FIFO transaction ready indicator | |
201 | ||
202 | // WISHBONE read FIFO interconnect | |
203 | output wbr_fifo_wenable_out ; // write enable for WBR_FIFO | |
204 | ||
205 | output [31:0] wbr_fifo_data_out ; // data output to WBR_FIFO | |
206 | ||
207 | output [3:0] wbr_fifo_be_out ; // byte enable output for WBR_FIFO | |
208 | ||
209 | output [3:0] wbr_fifo_control_out ; // WBR_FIFO control output | |
210 | ||
211 | // delayed transaction control logic inputs and outputs | |
212 | input [31:0] del_wdata_in ; // delayed write data input | |
213 | output del_complete_out ; // delayed transaction completed output | |
214 | ||
215 | input del_req_in ; // delayed transaction request | |
216 | input [31:0] del_addr_in ; // delayed transaction address | |
217 | input [3:0] del_bc_in ; // delayed transaction bus command input | |
218 | input [3:0] del_be_in ; // delayed transaction byte enables input | |
219 | input del_burst_in ; // delayed transaction burst req. indicator | |
220 | output del_error_out ; // delayed transation error termination signal | |
221 | ||
222 | output del_rty_exp_out ; // retry expired output for delayed transactions | |
223 | ||
224 | input del_we_in ; // delayed write request indicator | |
225 | ||
226 | output [31:0] err_addr_out ; // erroneous address output | |
227 | output [3:0] err_bc_out ; // erroneous bus command output | |
228 | ||
229 | output err_signal_out ; // error signalization | |
230 | ||
231 | output err_source_out ; // error source indicator | |
232 | ||
233 | input [7:0] cache_line_size_in ; // cache line size value input | |
234 | ||
235 | output err_rty_exp_out ; // retry expired error output | |
236 | ||
237 | output mabort_received_out ; // master abort signaled to status register | |
238 | output tabort_received_out ; // target abort signaled to status register | |
239 | ||
240 | output posted_write_not_present_out ; // used in target state machine - must deny read completions when this signal is 0 | |
241 | ||
242 | ||
243 | assign err_bc_out = bc_out ; | |
244 | ||
245 | // assign read outputs | |
246 | /*================================================================================================================== | |
247 | WISHBONE read FIFO data outputs - just link them to SM data outputs and delayed BE input | |
248 | ==================================================================================================================*/ | |
249 | assign wbr_fifo_data_out = data_in ; | |
250 | assign wbr_fifo_be_out = del_be_in ; | |
251 | ||
252 | // decode if current bus command is configuration command | |
253 | wire conf_cyc_bc = ( bc_out[3:1] == `BC_CONF_RW ) ; | |
254 | ||
255 | // register for indicating that current data is also last in transfer | |
256 | reg current_last ; | |
257 | ||
258 | // register indicating that last data was transfered OK | |
259 | reg last_transfered ; | |
260 | always@(posedge reset_in or posedge clk_in) | |
261 | begin | |
262 | if (reset_in) | |
263 | last_transfered <= #`FF_DELAY 1'b0 ; | |
264 | else | |
265 | last_transfered <= #`FF_DELAY ~wait_in && last_out && wtransfer_in ; | |
266 | end | |
267 | ||
268 | // status signals output assignement | |
269 | assign mabort_received_out = mabort_in ; | |
270 | ||
271 | wire tabort_ff_in = ~wait_in && rerror_in ; | |
272 | ||
273 | reg tabort_received_out ; | |
274 | always@(posedge reset_in or posedge clk_in) | |
275 | begin | |
276 | if ( reset_in ) | |
277 | tabort_received_out <= #`FF_DELAY 1'b0 ; | |
278 | else | |
279 | tabort_received_out <= #`FF_DELAY tabort_ff_in ; | |
280 | end | |
281 | ||
282 | // error recovery indicator | |
283 | reg err_recovery ; | |
284 | ||
285 | // operation is locked until error recovery is in progress or error bit is not cleared in configuration space | |
286 | wire err_lock = err_recovery ; | |
287 | ||
288 | // three requests are possible - posted write, delayed write and delayed read | |
289 | reg del_write_req ; | |
290 | reg posted_write_req ; | |
291 | reg del_read_req ; | |
292 | ||
293 | // assign request output | |
294 | assign req_out = del_write_req || posted_write_req || del_read_req ; | |
295 | ||
296 | // posted write is not present, when WB Write Fifo is empty and posted write transaction is not beeing requested at present time | |
297 | assign posted_write_not_present_out = !posted_write_req && wbw_fifo_empty_in ; | |
298 | ||
299 | // write requests are staged, so data is read from source into current data register and next data register | |
300 | reg write_req_int ; | |
301 | always@(posedge reset_in or posedge clk_in) | |
302 | begin | |
303 | if ( reset_in ) | |
304 | write_req_int <= #`FF_DELAY 1'b0 ; | |
305 | else | |
306 | write_req_int <= #`FF_DELAY posted_write_req || del_write_req ; | |
307 | ||
308 | end | |
309 | ||
310 | // ready output is generated one clock after request for reads and two after for writes | |
311 | always@(posedge reset_in or posedge clk_in) | |
312 | begin | |
313 | if (reset_in) | |
314 | rdy_out <= #`FF_DELAY 1'b0 ; | |
315 | else | |
316 | rdy_out <= #`FF_DELAY del_read_req || ( (posted_write_req || del_write_req) && write_req_int) ; | |
317 | end | |
318 | ||
319 | // wires with logic used as inputs to request FFs | |
320 | wire do_posted_write = ( wbw_fifo_transaction_ready_in && ~wbw_fifo_empty_in && ~err_lock ) ; | |
321 | wire do_del = ( del_req_in && ~err_lock && wbw_fifo_empty_in ) ; | |
322 | wire do_del_write = do_del && del_we_in ; | |
323 | wire do_del_read = do_del && ~del_we_in ; | |
324 | ||
325 | // register for indicating current operation's data source | |
326 | parameter DELAYED_WRITE = 1'b1 ; | |
327 | parameter POSTED_WRITE = 1'b0 ; | |
328 | ||
329 | // new data source - depending on which transaction will be processed next - delayed read is here because source of byte enables must | |
330 | // be specified for delayed reads also - data source is not relevant for delayed reads, so value is don't care anyway | |
331 | wire new_data_source = (do_del_write || do_del_read) ? DELAYED_WRITE : POSTED_WRITE ; // input to data source register | |
332 | wire data_source_change = ~req_out ; // change (enable) for data source register - when no requests are in progress | |
333 | ||
334 | reg data_source ; // data source value | |
335 | always@(posedge reset_in or posedge clk_in) | |
336 | begin | |
337 | if (reset_in) | |
338 | // default value is posted write source - wbw_fifo | |
339 | data_source <= #`FF_DELAY POSTED_WRITE ; | |
340 | else | |
341 | if (data_source_change) | |
342 | // change data source on rising clock edge | |
343 | data_source <= #`FF_DELAY new_data_source ; | |
344 | end | |
345 | ||
346 | // multiplexer for data output to PCI MASTER state machine | |
347 | reg [31:0] source_data ; | |
348 | reg [3:0] source_be ; | |
349 | always@(data_source or wbw_fifo_addr_data_in or wbw_fifo_cbe_in or del_wdata_in or del_be_in or del_burst_in) | |
350 | begin | |
351 | case (data_source) | |
352 | POSTED_WRITE: begin | |
353 | source_data = wbw_fifo_addr_data_in ; | |
354 | source_be = wbw_fifo_cbe_in ; | |
355 | end | |
356 | DELAYED_WRITE: begin | |
357 | source_data = del_wdata_in ; | |
358 | // read all bytes during delayed burst read! | |
359 | source_be = ~( del_be_in | {4{del_burst_in}} ) ; | |
360 | end | |
361 | endcase | |
362 | end | |
363 | ||
364 | wire waddr = wbw_fifo_control_in[`ADDR_CTRL_BIT] ; | |
365 | ||
366 | // address change indicator - address is allowed to be loaded only when no transaction is in progress! | |
367 | wire address_change = ~req_out ; // address change - whenever there is no request in progress | |
368 | ||
369 | // new address - input to register storing address of current request - if posted write request will be next, | |
370 | // load address and bus command from wbw_fifo, else load data from delayed transaction logic | |
371 | wire [31:0] new_address = ( ~req_out && do_posted_write ) ? wbw_fifo_addr_data_in[31:0] : del_addr_in[31:0] ; | |
372 | wire [3:0] new_bc = ( ~req_out && do_posted_write ) ? wbw_fifo_cbe_in : del_bc_in ; | |
373 | ||
374 | // address counter enable - only for posted writes when data is actually transfered | |
375 | wire addr_count_en = !wait_in && posted_write_req && rtransfer_in ; | |
376 | ||
377 | always@(posedge reset_in or posedge clk_in) | |
378 | begin | |
379 | if (reset_in) | |
380 | bc_out <= #`FF_DELAY `BC_RESERVED0 ; | |
381 | else | |
382 | if (address_change) | |
383 | bc_out <= #`FF_DELAY new_bc ; | |
384 | end | |
385 | ||
386 | reg [29:0] current_dword_address ; | |
387 | ||
388 | // DWORD address counter with load | |
389 | always@(posedge reset_in or posedge clk_in) | |
390 | begin | |
391 | if (reset_in) | |
392 | current_dword_address <= #`FF_DELAY 30'h0000_0000 ; | |
393 | else | |
394 | if (address_change) | |
395 | current_dword_address <= #`FF_DELAY new_address[31:2] ; | |
396 | else | |
397 | if (addr_count_en) | |
398 | current_dword_address <= #`FF_DELAY current_dword_address + 1'b1 ; | |
399 | end | |
400 | ||
401 | reg [1:0] current_byte_address ; | |
402 | always@(posedge reset_in or posedge clk_in) | |
403 | begin | |
404 | if (reset_in) | |
405 | current_byte_address <= #`FF_DELAY 2'b00 ; | |
406 | else | |
407 | if (address_change) | |
408 | current_byte_address <= #`FF_DELAY new_address[1:0] ; | |
409 | end | |
410 | ||
411 | // byte address generation logic | |
412 | reg [ 1: 0] generated_byte_adr ; | |
413 | reg [ 1: 0] pci_byte_adr ; | |
414 | ||
415 | always@(be_out) | |
416 | begin | |
417 | casex(be_out) | |
418 | 4'bxxx0:generated_byte_adr = 2'b00 ; | |
419 | 4'bxx01:generated_byte_adr = 2'b01 ; | |
420 | 4'bx011:generated_byte_adr = 2'b10 ; | |
421 | 4'b0111:generated_byte_adr = 2'b11 ; | |
422 | 4'b1111:generated_byte_adr = 2'b00 ; | |
423 | endcase | |
424 | end | |
425 | ||
426 | always@(generated_byte_adr or bc_out or current_byte_address) | |
427 | begin | |
428 | // for memory access commands, set lower 2 address bits to 0 | |
429 | if ((bc_out == `BC_MEM_READ) | (bc_out == `BC_MEM_WRITE) | | |
430 | (bc_out == `BC_MEM_READ_MUL) | (bc_out == `BC_MEM_READ_LN) | | |
431 | (bc_out == `BC_MEM_WRITE_INVAL)) | |
432 | begin | |
433 | pci_byte_adr = 2'b00 ; | |
434 | end | |
435 | else if ((bc_out == `BC_IO_WRITE) | (bc_out == `BC_IO_READ)) | |
436 | begin | |
437 | pci_byte_adr = generated_byte_adr ; | |
438 | end | |
439 | else | |
440 | begin | |
441 | pci_byte_adr = current_byte_address ; | |
442 | end | |
443 | end | |
444 | ||
445 | // address output to PCI master state machine assignment | |
446 | assign address_out = { current_dword_address, pci_byte_adr } ; | |
447 | ||
448 | // the same for erroneous address assignement | |
449 | assign err_addr_out = { current_dword_address, pci_byte_adr } ; | |
450 | ||
451 | // cacheline size counter - for read transaction length control | |
452 | // cache line count is enabled during burst reads when data is actually transfered | |
453 | wire read_count_enable = ~wait_in && del_read_req && del_burst_in && wtransfer_in ; | |
454 | ||
455 | // cache line counter is loaded when del read request is not in progress | |
456 | wire read_count_load = ~del_read_req ; | |
457 | ||
458 | reg [(`WBR_ADDR_LENGTH - 1):0] max_read_count ; | |
459 | always@(cache_line_size_in or del_bc_in) | |
460 | begin | |
461 | if ( (cache_line_size_in >= `WBR_DEPTH) || (~del_bc_in[1] && ~del_bc_in[0]) ) | |
462 | max_read_count = `WBR_DEPTH - 1'b1; | |
463 | else | |
464 | max_read_count = cache_line_size_in ; | |
465 | end | |
466 | ||
467 | reg [(`WBR_ADDR_LENGTH - 1):0] read_count ; | |
468 | ||
469 | // cache line bound indicator - it signals when data for one complete cacheline was read | |
470 | wire read_bound_comb = ~|(read_count[(`WBR_ADDR_LENGTH - 1):2]) ; | |
471 | reg read_bound ; | |
472 | always@(posedge clk_in or posedge reset_in) | |
473 | begin | |
474 | if ( reset_in ) | |
475 | read_bound <= #`FF_DELAY 1'b0 ; | |
476 | else if (read_count_load) | |
477 | read_bound <= #`FF_DELAY 1'b0 ; | |
478 | else if ( read_count_enable ) | |
479 | read_bound <= #`FF_DELAY read_bound_comb ; | |
480 | end | |
481 | ||
482 | wire read_count_change_val = read_count_load | read_count_enable ; | |
483 | ||
484 | wire [(`WBR_ADDR_LENGTH - 1):0] read_count_next = read_count_load ? max_read_count : (read_count - 1'b1) ; | |
485 | ||
486 | // down counter with load | |
487 | always@(posedge reset_in or posedge clk_in) | |
488 | begin | |
489 | if (reset_in) | |
490 | read_count <= #`FF_DELAY 0 ; | |
491 | else | |
492 | /* if (read_count_load) | |
493 | read_count <= #`FF_DELAY max_read_count ; | |
494 | else | |
495 | if (read_count_enable) | |
496 | read_count <= #`FF_DELAY read_count - 1'b1 ; | |
497 | */ if (read_count_change_val) | |
498 | read_count <= #`FF_DELAY read_count_next ; | |
499 | end | |
500 | ||
501 | // flip flop indicating error recovery is in progress | |
502 | reg err_recovery_in ; | |
503 | always@(posedge reset_in or posedge clk_in) | |
504 | begin | |
505 | if (reset_in) | |
506 | err_recovery <= #`FF_DELAY 1'b0 ; | |
507 | else | |
508 | err_recovery <= #`FF_DELAY err_recovery_in ; | |
509 | end | |
510 | ||
511 | /*// retry counter implementation | |
512 | reg [7:0] retry_count ; | |
513 | ||
514 | wire retry_expired = ~|(retry_count[7:1]) ; | |
515 | ||
516 | // loading of retry counter - whenever no request is present or other termination than retry or wait is signalled | |
517 | wire retry_load = ~req_out || (~wait_in && rtransfer_in) ; | |
518 | ||
519 | // retry DOWN counter with load | |
520 | always@(posedge reset_in or posedge clk_in) | |
521 | begin | |
522 | if (reset_in) | |
523 | retry_count <= #`FF_DELAY 8'hFF ; | |
524 | else | |
525 | if ( retry_load ) | |
526 | retry_count <= #`FF_DELAY `PCI_RTY_CNT_MAX ; | |
527 | else | |
528 | if (retry_in) | |
529 | retry_count <= #`FF_DELAY retry_count - 1'b1 ; | |
530 | end*/ | |
531 | ||
532 | /*================================================================================================================== | |
533 | Delayed write requests are always single transfers! | |
534 | Delayed write request starts, when no request is currently beeing processed and it is signaled from other side | |
535 | of the bridge. | |
536 | ==================================================================================================================*/ | |
537 | // delayed write request FF input control | |
538 | reg del_write_req_input ; | |
539 | ||
540 | always@( | |
541 | do_del_write or | |
542 | del_write_req or | |
543 | posted_write_req or | |
544 | del_read_req or | |
545 | wait_in or | |
546 | //retry_in or | |
547 | //retry_expired or | |
548 | rtransfer_in or | |
549 | rerror_in or | |
550 | mabort_in | |
551 | ) | |
552 | begin | |
553 | if (~del_write_req) | |
554 | begin | |
555 | // delayed write is not in progress and is requested | |
556 | // delayed write can be requested when no other request is in progress | |
557 | del_write_req_input = ~posted_write_req && ~del_read_req && do_del_write ; | |
558 | end | |
559 | else | |
560 | begin | |
561 | // delayed write request is in progress - assign input | |
562 | del_write_req_input = wait_in || | |
563 | ( /*~( retry_in && retry_expired) &&*/ | |
564 | ~rtransfer_in && ~rerror_in && ~mabort_in | |
565 | ); | |
566 | end | |
567 | end | |
568 | ||
569 | // delayed write request FLIP-FLOP | |
570 | always@(posedge reset_in or posedge clk_in) | |
571 | begin | |
572 | if (reset_in) | |
573 | del_write_req <= #`FF_DELAY 1'b0 ; | |
574 | else | |
575 | del_write_req <= #`FF_DELAY del_write_req_input ; | |
576 | end | |
577 | ||
578 | /*================================================================================================ | |
579 | Posted write request indicator. | |
580 | Posted write starts whenever no request is in progress and one whole posted write is | |
581 | stored in WBW_FIFO. It ends on error terminations ( master, target abort, retry expired) or | |
582 | data transfer terminations if last data is on top of FIFO. | |
583 | Continues on wait, retry, and disconnect without data. | |
584 | ================================================================================================*/ | |
585 | // posted write request FF input control | |
586 | reg posted_write_req_input ; | |
587 | always@( | |
588 | do_posted_write or | |
589 | del_write_req or | |
590 | posted_write_req or | |
591 | del_read_req or | |
592 | wait_in or | |
593 | //retry_in or | |
594 | rerror_in or | |
595 | mabort_in or | |
596 | //retry_expired or | |
597 | rtransfer_in or | |
598 | last_transfered | |
599 | ) | |
600 | begin | |
601 | if (~posted_write_req) | |
602 | begin | |
603 | // posted write is not in progress | |
604 | posted_write_req_input = ~del_write_req && ~del_read_req && do_posted_write ; | |
605 | end | |
606 | else | |
607 | begin | |
608 | posted_write_req_input = wait_in || | |
609 | (/*~(retry_in && retry_expired && ~rtransfer_in) &&*/ | |
610 | ~rerror_in && ~mabort_in && | |
611 | ~(last_transfered) | |
612 | ) ; | |
613 | ||
614 | end | |
615 | end | |
616 | ||
617 | // posted write request flip flop | |
618 | always@(posedge reset_in or posedge clk_in) | |
619 | begin | |
620 | if (reset_in) | |
621 | posted_write_req <= #`FF_DELAY 1'b0 ; | |
622 | else | |
623 | posted_write_req <= #`FF_DELAY posted_write_req_input ; | |
624 | ||
625 | end | |
626 | ||
627 | /*================================================================================================ | |
628 | Delayed read request indicator. | |
629 | Delayed read starts whenever no request is in progress and delayed read request is signaled from | |
630 | other side of bridge. It ends on error terminations ( master, target abort, retry expired) or | |
631 | data transfer terminations if it is not burst transfer or on cache line bounds on burst transfer. | |
632 | It also ends on disconnects. | |
633 | Continues on wait and retry. | |
634 | ================================================================================================*/ | |
635 | // delayed read FF input control | |
636 | reg del_read_req_input ; | |
637 | always@( | |
638 | do_del_read or | |
639 | del_write_req or | |
640 | posted_write_req or | |
641 | del_read_req or | |
642 | last_transfered or | |
643 | wait_in or | |
644 | retry_in or | |
645 | //retry_expired or | |
646 | mabort_in or | |
647 | rtransfer_in or | |
648 | rerror_in or | |
649 | first_in or | |
650 | del_complete_out | |
651 | ) | |
652 | begin | |
653 | if (~del_read_req) | |
654 | begin | |
655 | del_read_req_input = ~del_write_req && ~posted_write_req && ~del_complete_out && do_del_read ; | |
656 | end | |
657 | else | |
658 | begin | |
659 | del_read_req_input = wait_in || | |
660 | ( ~(retry_in && (~first_in /*|| retry_expired */)) && | |
661 | ~mabort_in && ~rerror_in && | |
662 | ~(last_transfered) | |
663 | ) ; | |
664 | end | |
665 | end | |
666 | ||
667 | // delayed read request FF | |
668 | always@(posedge reset_in or posedge clk_in) | |
669 | begin | |
670 | if (reset_in) | |
671 | del_read_req <= #`FF_DELAY 1'b0 ; | |
672 | else | |
673 | del_read_req <= #`FF_DELAY del_read_req_input ; | |
674 | end | |
675 | ||
676 | // wire indicating last entry of transaction on top of fifo | |
677 | wire wlast = wbw_fifo_control_in[`LAST_CTRL_BIT] ; | |
678 | ||
679 | wire last_int = posted_write_req && wlast || del_write_req ; | |
680 | ||
681 | // intermidiate data, byte enable and last registers | |
682 | reg [31:0] intermediate_data ; | |
683 | reg [3:0] intermediate_be ; | |
684 | reg intermediate_last ; | |
685 | ||
686 | wire intermediate_enable = ( posted_write_req || del_write_req ) && ( ~write_req_int || (( ~rdy_out || ~wait_in && rtransfer_in ) && ~intermediate_last)) ; | |
687 | ||
688 | always@(posedge reset_in or posedge clk_in) | |
689 | begin | |
690 | if ( reset_in ) | |
691 | begin | |
692 | intermediate_data <= #`FF_DELAY 32'h0000_0000 ; | |
693 | intermediate_be <= #`FF_DELAY 4'h0 ; | |
694 | intermediate_last <= #`FF_DELAY 1'b0 ; | |
695 | end | |
696 | else | |
697 | if ( intermediate_enable ) | |
698 | begin | |
699 | intermediate_data <= #`FF_DELAY source_data ; | |
700 | intermediate_be <= #`FF_DELAY source_be ; | |
701 | intermediate_last <= #`FF_DELAY last_int ; | |
702 | end | |
703 | end | |
704 | ||
705 | // multiplexer for next data | |
706 | reg [31:0] next_data_out ; | |
707 | reg [3:0] next_be_out ; | |
708 | reg write_next_last ; | |
709 | reg [3:0] write_next_be ; | |
710 | ||
711 | always@ | |
712 | ( | |
713 | rtransfer_in or | |
714 | intermediate_data or | |
715 | intermediate_be or | |
716 | intermediate_last or | |
717 | wbw_fifo_addr_data_in or | |
718 | wbw_fifo_cbe_in or | |
719 | wlast or | |
720 | wait_in | |
721 | ) | |
722 | begin | |
723 | if( rtransfer_in & ~wait_in ) | |
724 | begin | |
725 | next_data_out = wbw_fifo_addr_data_in ; | |
726 | write_next_last = wlast ; | |
727 | write_next_be = wbw_fifo_cbe_in ; | |
728 | end | |
729 | else | |
730 | begin | |
731 | next_data_out = intermediate_data ; | |
732 | write_next_last = intermediate_last ; | |
733 | write_next_be = intermediate_be ; | |
734 | end | |
735 | end | |
736 | ||
737 | always@(del_read_req or source_be or write_next_be) | |
738 | begin | |
739 | if (del_read_req) | |
740 | next_be_out = source_be ; | |
741 | else | |
742 | next_be_out = write_next_be ; | |
743 | end | |
744 | /*================================================================================================ | |
745 | WBW_FIFO read enable - read from WBW_FIFO is performed on posted writes, when data transfer | |
746 | termination is received - transfer or disconnect with data. Reads are enabled during error | |
747 | recovery also, since erroneous transaction must be pulled out of FIFO! | |
748 | ================================================================================================*/ | |
749 | // wbw_fifo read enable input control | |
750 | ||
751 | assign wbw_renable_out = ~req_out && (do_posted_write || err_recovery) || | |
752 | posted_write_req && ( ~write_req_int || (~rdy_out && ~intermediate_last) || (~wait_in && rtransfer_in && ~intermediate_last)) ; | |
753 | ||
754 | /*================================================================================================ | |
755 | WBR_FIFO write enable control - | |
756 | writes to FIFO are possible only when delayed read request is in progress and data transfer | |
757 | or error termination is signalled. It is not enabled on retry or disconnect without data. | |
758 | ================================================================================================*/ | |
759 | // wbr_fifo write enable control - enabled when transfer is in progress and data is transfered or error is signalled | |
760 | assign wbr_fifo_wenable_out = del_read_req && ~wait_in && ( rtransfer_in || mabort_in || rerror_in ) ; | |
761 | ||
762 | /*================================================================================================ | |
763 | WBR_FIFO control output for identifying data entries. | |
764 | This is necesary because of prefetched reads, which partially succeed. On error, error entry | |
765 | gets in to signal it on WISHBONE bus if WISHBONE master reads up to this entry. | |
766 | ================================================================================================*/ | |
767 | assign wbr_fifo_control_out[`ADDR_CTRL_BIT] = 1'b0 ; | |
768 | assign wbr_fifo_control_out[`LAST_CTRL_BIT] = last_transfered ; | |
769 | assign wbr_fifo_control_out[`DATA_ERROR_CTRL_BIT] = rerror_in || (mabort_in && ~conf_cyc_bc) ; | |
770 | assign wbr_fifo_control_out[`UNUSED_CTRL_BIT] = 1'b0 ; | |
771 | ||
772 | // retry expired error for posted writes control | |
773 | //assign err_rty_exp_out = posted_write_req && ~wait_in && retry_in && retry_expired && ~rtransfer_in; | |
774 | assign err_rty_exp_out = 1'b0 ; | |
775 | ||
776 | // error source and error signal output control logic - only for posted writes | |
777 | assign err_source_out = mabort_in /*|| err_rty_exp_out*/ ; | |
778 | ||
779 | assign err_signal_out = /*err_rty_exp_out || */ posted_write_req && ~wait_in && (mabort_in || rerror_in) ; | |
780 | ||
781 | //assign del_rty_exp_out = (~wait_in && (del_read_req || del_write_req)) && (retry_in && retry_expired && ~rtransfer_in) ; | |
782 | assign del_rty_exp_out = 1'b0 ; | |
783 | ||
784 | assign del_error_out = ~wait_in && (del_write_req || del_read_req) && ( (mabort_in && ~conf_cyc_bc) || rerror_in ) ; | |
785 | ||
786 | wire del_write_complete = del_write_req && ~wait_in && ( rtransfer_in || rerror_in || mabort_in ) ; | |
787 | wire del_read_complete = del_read_req && ~wait_in && ( rerror_in || mabort_in || last_transfered || ( retry_in && ~first_in ) ) ; | |
788 | ||
789 | assign del_complete_out = ~wait_in && ( del_write_complete || del_read_complete ) ; | |
790 | ||
791 | // next last output generation | |
792 | assign next_last_out = del_write_req || del_read_req && ( ~del_burst_in || read_bound ) || posted_write_req && ( write_next_last ) ; | |
793 | /*================================================================================================================== | |
794 | Error recovery FF gets a value of one, when during posted write error occurs. It is cleared when all the data provided | |
795 | for erroneous transaction is pulled out of WBW_FIFO | |
796 | ==================================================================================================================*/ | |
797 | ||
798 | // error recovery flip flop input - used when posted write is terminated with an error | |
799 | always@( | |
800 | err_recovery or | |
801 | last_out or | |
802 | wlast or | |
803 | err_signal_out or | |
804 | intermediate_last | |
805 | ) | |
806 | begin | |
807 | // when error recovery is not set - drive its input so it gets set | |
808 | if ( ~err_recovery ) | |
809 | err_recovery_in = ~last_out && ~intermediate_last && err_signal_out ; | |
810 | else | |
811 | // when error recovery is set, wbw_fifo is enabled - clear err_recovery when last data entry of erroneous transaction is pulled out of fifo | |
812 | err_recovery_in = ~wlast ; | |
813 | end | |
814 | ||
815 | wire data_out_load = (posted_write_req || del_write_req) && ( !rdy_out || ( !wait_in && rtransfer_in ) ) ; | |
816 | ||
817 | wire be_out_load = (req_out && !rdy_out) || ( posted_write_req && !wait_in && rtransfer_in ) ; | |
818 | ||
819 | wire last_load = req_out && ( ~rdy_out || ~wait_in && wtransfer_in ) ; | |
820 | ||
821 | always@(posedge reset_in or posedge clk_in) | |
822 | begin | |
823 | if (reset_in) | |
824 | data_out <= #`FF_DELAY 32'h0000_0000 ; | |
825 | else | |
826 | if ( data_out_load ) | |
827 | data_out <= #`FF_DELAY intermediate_data ; | |
828 | end | |
829 | ||
830 | always@(posedge clk_in or posedge reset_in) | |
831 | begin | |
832 | if ( reset_in ) | |
833 | be_out <= #`FF_DELAY 4'hF ; | |
834 | else | |
835 | if ( be_out_load ) | |
836 | be_out <= #`FF_DELAY posted_write_req ? intermediate_be : source_be ; | |
837 | end | |
838 | ||
839 | always@(posedge reset_in or posedge clk_in) | |
840 | begin | |
841 | if (reset_in) | |
842 | current_last <= #`FF_DELAY 1'b0 ; | |
843 | else | |
844 | if ( last_load ) | |
845 | current_last <= #`FF_DELAY next_last_out ; | |
846 | end | |
847 | ||
848 | assign last_out = current_last ; | |
849 | endmodule |