Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | ////////////////////////////////////////////////////////////////////// |
2 | //// //// | |
3 | //// uart_receiver.v //// | |
4 | //// //// | |
5 | //// //// | |
6 | //// This file is part of the "UART 16550 compatible" project //// | |
7 | //// http://www.opencores.org/cores/uart16550/ //// | |
8 | //// //// | |
9 | //// Documentation related to this project: //// | |
10 | //// - http://www.opencores.org/cores/uart16550/ //// | |
11 | //// //// | |
12 | //// Projects compatibility: //// | |
13 | //// - WISHBONE //// | |
14 | //// RS232 Protocol //// | |
15 | //// 16550D uart (mostly supported) //// | |
16 | //// //// | |
17 | //// Overview (main Features): //// | |
18 | //// UART core receiver logic //// | |
19 | //// //// | |
20 | //// Known problems (limits): //// | |
21 | //// None known //// | |
22 | //// //// | |
23 | //// To Do: //// | |
24 | //// Thourough testing. //// | |
25 | //// //// | |
26 | //// Author(s): //// | |
27 | //// - gorban@opencores.org //// | |
28 | //// - Jacob Gorban //// | |
29 | //// - Igor Mohor (igorm@opencores.org) //// | |
30 | //// //// | |
31 | //// Created: 2001/05/12 //// | |
32 | //// Last Updated: 2001/05/17 //// | |
33 | //// (See log for the revision history) //// | |
34 | //// //// | |
35 | //// //// | |
36 | ////////////////////////////////////////////////////////////////////// | |
37 | //// //// | |
38 | //// Copyright (C) 2000, 2001 Authors //// | |
39 | //// //// | |
40 | //// This source file may be used and distributed without //// | |
41 | //// restriction provided that this copyright statement is not //// | |
42 | //// removed from the file and that any derivative work contains //// | |
43 | //// the original copyright notice and the associated disclaimer. //// | |
44 | //// //// | |
45 | //// This source file is free software; you can redistribute it //// | |
46 | //// and/or modify it under the terms of the GNU Lesser General //// | |
47 | //// Public License as published by the Free Software Foundation; //// | |
48 | //// either version 2.1 of the License, or (at your option) any //// | |
49 | //// later version. //// | |
50 | //// //// | |
51 | //// This source is distributed in the hope that it will be //// | |
52 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// | |
53 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// | |
54 | //// PURPOSE. See the GNU Lesser General Public License for more //// | |
55 | //// details. //// | |
56 | //// //// | |
57 | //// You should have received a copy of the GNU Lesser General //// | |
58 | //// Public License along with this source; if not, download it //// | |
59 | //// from http://www.opencores.org/lgpl.shtml //// | |
60 | //// //// | |
61 | ////////////////////////////////////////////////////////////////////// | |
62 | // | |
63 | // CVS Revision History | |
64 | // | |
65 | // $Log: uart_receiver.v,v $ | |
66 | // Revision 1.31 2004/06/18 14:46:15 tadejm | |
67 | // Brandl Tobias repaired a bug regarding frame error in receiver when brake is received. | |
68 | // | |
69 | // Revision 1.29 2002/07/29 21:16:18 gorban | |
70 | // The uart_defines.v file is included again in sources. | |
71 | // | |
72 | // Revision 1.28 2002/07/22 23:02:23 gorban | |
73 | // Bug Fixes: | |
74 | // * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. | |
75 | // Problem reported by Kenny.Tung. | |
76 | // * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. | |
77 | // | |
78 | // Improvements: | |
79 | // * Made FIFO's as general inferrable memory where possible. | |
80 | // So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). | |
81 | // This saves about 1/3 of the Slice count and reduces P&R and synthesis times. | |
82 | // | |
83 | // * Added optional baudrate output (baud_o). | |
84 | // This is identical to BAUDOUT* signal on 16550 chip. | |
85 | // It outputs 16xbit_clock_rate - the divided clock. | |
86 | // It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. | |
87 | // | |
88 | // Revision 1.27 2001/12/30 20:39:13 mohor | |
89 | // More than one character was stored in case of break. End of the break | |
90 | // was not detected correctly. | |
91 | // | |
92 | // Revision 1.26 2001/12/20 13:28:27 mohor | |
93 | // Missing declaration of rf_push_q fixed. | |
94 | // | |
95 | // Revision 1.25 2001/12/20 13:25:46 mohor | |
96 | // rx push changed to be only one cycle wide. | |
97 | // | |
98 | // Revision 1.24 2001/12/19 08:03:34 mohor | |
99 | // Warnings cleared. | |
100 | // | |
101 | // Revision 1.23 2001/12/19 07:33:54 mohor | |
102 | // Synplicity was having troubles with the comment. | |
103 | // | |
104 | // Revision 1.22 2001/12/17 14:46:48 mohor | |
105 | // overrun signal was moved to separate block because many sequential lsr | |
106 | // reads were preventing data from being written to rx fifo. | |
107 | // underrun signal was not used and was removed from the project. | |
108 | // | |
109 | // Revision 1.21 2001/12/13 10:31:16 mohor | |
110 | // timeout irq must be set regardless of the rda irq (rda irq does not reset the | |
111 | // timeout counter). | |
112 | // | |
113 | // Revision 1.20 2001/12/10 19:52:05 gorban | |
114 | // Igor fixed break condition bugs | |
115 | // | |
116 | // Revision 1.19 2001/12/06 14:51:04 gorban | |
117 | // Bug in LSR[0] is fixed. | |
118 | // All WISHBONE signals are now sampled, so another wait-state is introduced on all transfers. | |
119 | // | |
120 | // Revision 1.18 2001/12/03 21:44:29 gorban | |
121 | // Updated specification documentation. | |
122 | // Added full 32-bit data bus interface, now as default. | |
123 | // Address is 5-bit wide in 32-bit data bus mode. | |
124 | // Added wb_sel_i input to the core. It's used in the 32-bit mode. | |
125 | // Added debug interface with two 32-bit read-only registers in 32-bit mode. | |
126 | // Bits 5 and 6 of LSR are now only cleared on TX FIFO write. | |
127 | // My small test bench is modified to work with 32-bit mode. | |
128 | // | |
129 | // Revision 1.17 2001/11/28 19:36:39 gorban | |
130 | // Fixed: timeout and break didn't pay attention to current data format when counting time | |
131 | // | |
132 | // Revision 1.16 2001/11/27 22:17:09 gorban | |
133 | // Fixed bug that prevented synthesis in uart_receiver.v | |
134 | // | |
135 | // Revision 1.15 2001/11/26 21:38:54 gorban | |
136 | // Lots of fixes: | |
137 | // Break condition wasn't handled correctly at all. | |
138 | // LSR bits could lose their values. | |
139 | // LSR value after reset was wrong. | |
140 | // Timing of THRE interrupt signal corrected. | |
141 | // LSR bit 0 timing corrected. | |
142 | // | |
143 | // Revision 1.14 2001/11/10 12:43:21 gorban | |
144 | // Logic Synthesis bugs fixed. Some other minor changes | |
145 | // | |
146 | // Revision 1.13 2001/11/08 14:54:23 mohor | |
147 | // Comments in Slovene language deleted, few small fixes for better work of | |
148 | // old tools. IRQs need to be fix. | |
149 | // | |
150 | // Revision 1.12 2001/11/07 17:51:52 gorban | |
151 | // Heavily rewritten interrupt and LSR subsystems. | |
152 | // Many bugs hopefully squashed. | |
153 | // | |
154 | // Revision 1.11 2001/10/31 15:19:22 gorban | |
155 | // Fixes to break and timeout conditions | |
156 | // | |
157 | // Revision 1.10 2001/10/20 09:58:40 gorban | |
158 | // Small synopsis fixes | |
159 | // | |
160 | // Revision 1.9 2001/08/24 21:01:12 mohor | |
161 | // Things connected to parity changed. | |
162 | // Clock devider changed. | |
163 | // | |
164 | // Revision 1.8 2001/08/23 16:05:05 mohor | |
165 | // Stop bit bug fixed. | |
166 | // Parity bug fixed. | |
167 | // WISHBONE read cycle bug fixed, | |
168 | // OE indicator (Overrun Error) bug fixed. | |
169 | // PE indicator (Parity Error) bug fixed. | |
170 | // Register read bug fixed. | |
171 | // | |
172 | // Revision 1.6 2001/06/23 11:21:48 gorban | |
173 | // DL made 16-bit long. Fixed transmission/reception bugs. | |
174 | // | |
175 | // Revision 1.5 2001/06/02 14:28:14 gorban | |
176 | // Fixed receiver and transmitter. Major bug fixed. | |
177 | // | |
178 | // Revision 1.4 2001/05/31 20:08:01 gorban | |
179 | // FIFO changes and other corrections. | |
180 | // | |
181 | // Revision 1.3 2001/05/27 17:37:49 gorban | |
182 | // Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. | |
183 | // | |
184 | // Revision 1.2 2001/05/21 19:12:02 gorban | |
185 | // Corrected some Linter messages. | |
186 | // | |
187 | // Revision 1.1 2001/05/17 18:34:18 gorban | |
188 | // First 'stable' release. Should be sythesizable now. Also added new header. | |
189 | // | |
190 | // Revision 1.0 2001-05-17 21:27:11+02 jacob | |
191 | // Initial revision | |
192 | // | |
193 | // | |
194 | ||
195 | `timescale 1 ns / 10 ps | |
196 | ||
197 | module uart_receiver(clk, wb_rst_i, lcr, rf_pop, srx_pad_i, enable, counter_t, | |
198 | rf_count, rf_data_out, rf_error_bit, rf_overrun, rx_reset, lsr_mask, | |
199 | rstate, rf_push_pulse); | |
200 | ||
201 | parameter sr_idle = 4'b0; | |
202 | parameter sr_rec_start = 4'b1; | |
203 | parameter sr_rec_bit = 4'd2; | |
204 | parameter sr_rec_parity = 4'd3; | |
205 | parameter sr_rec_stop = 4'd4; | |
206 | parameter sr_check_parity = 4'd5; | |
207 | parameter sr_rec_prepare = 4'd6; | |
208 | parameter sr_end_bit = 4'd7; | |
209 | parameter sr_ca_lc_parity = 4'd8; | |
210 | parameter sr_wait1 = 4'd9; | |
211 | parameter sr_push = 4'd10; | |
212 | ||
213 | input clk; | |
214 | input wb_rst_i; | |
215 | input [7:0] lcr; | |
216 | input rf_pop; | |
217 | input srx_pad_i; | |
218 | input enable; | |
219 | input rx_reset; | |
220 | input lsr_mask; | |
221 | output [9:0] counter_t; | |
222 | output [(5 - 1):0] rf_count; | |
223 | output [(11 - 1):0] rf_data_out; | |
224 | output rf_overrun; | |
225 | output rf_error_bit; | |
226 | output [3:0] rstate; | |
227 | output rf_push_pulse; | |
228 | ||
229 | reg [3:0] rcounter16; | |
230 | reg [2:0] rbit_counter; | |
231 | reg [7:0] rshift; | |
232 | reg rparity; | |
233 | reg rparity_error; | |
234 | reg rframing_error; | |
235 | reg rbit_in; | |
236 | reg rparity_xor; | |
237 | reg [7:0] counter_b; | |
238 | reg rf_push_q; | |
239 | reg [(11 - 1):0] rf_data_in; | |
240 | reg rf_push; | |
241 | wire break_error = (counter_b == 0); | |
242 | wire rcounter16_eq_7 = (rcounter16 == 4'd7); | |
243 | wire rcounter16_eq_0 = (rcounter16 == 4'b0); | |
244 | wire rcounter16_eq_1 = (rcounter16 == 4'b1); | |
245 | wire [3:0] rcounter16_minus_1 = (rcounter16 - 1'b1); | |
246 | reg [9:0] toc_value; | |
247 | wire [7:0] brc_value; | |
248 | reg [9:0] counter_t; | |
249 | reg [3:0] rstate; | |
250 | ||
251 | assign rf_push_pulse = (rf_push & (~rf_push_q)); | |
252 | assign brc_value = toc_value[9:2]; | |
253 | ||
254 | uart_rfifo #(11) fifo_rx( | |
255 | .clk (clk), | |
256 | .wb_rst_i (wb_rst_i), | |
257 | .data_in (rf_data_in), | |
258 | .data_out (rf_data_out), | |
259 | .push (rf_push_pulse), | |
260 | .pop (rf_pop), | |
261 | .overrun (rf_overrun), | |
262 | .count (rf_count), | |
263 | .error_bit (rf_error_bit), | |
264 | .fifo_reset (rx_reset), | |
265 | .reset_status (lsr_mask)); | |
266 | ||
267 | always @(posedge clk or posedge wb_rst_i) begin | |
268 | if (wb_rst_i) begin | |
269 | rstate <= #(1) sr_idle; | |
270 | rbit_in <= #(1) 1'b0; | |
271 | rcounter16 <= #(1) 0; | |
272 | rbit_counter <= #(1) 0; | |
273 | rparity_xor <= #(1) 1'b0; | |
274 | rframing_error <= #(1) 1'b0; | |
275 | rparity_error <= #(1) 1'b0; | |
276 | rparity <= #(1) 1'b0; | |
277 | rshift <= #(1) 0; | |
278 | rf_push <= #(1) 1'b0; | |
279 | rf_data_in <= #(1) 0; | |
280 | end | |
281 | else if (enable) begin | |
282 | case (rstate) | |
283 | sr_idle: begin | |
284 | rf_push <= #(1) 1'b0; | |
285 | rf_data_in <= #(1) 0; | |
286 | rcounter16 <= #(1) 4'b1110; | |
287 | if ((srx_pad_i == 1'b0) & (~break_error)) begin | |
288 | rstate <= #(1) sr_rec_start; | |
289 | end | |
290 | end | |
291 | sr_rec_start: begin | |
292 | rf_push <= #(1) 1'b0; | |
293 | if (rcounter16_eq_7) begin | |
294 | if (srx_pad_i == 1'b1) begin | |
295 | rstate <= #(1) sr_idle; | |
296 | end | |
297 | else begin | |
298 | rstate <= #(1) sr_rec_prepare; | |
299 | end | |
300 | end | |
301 | rcounter16 <= #(1) rcounter16_minus_1; | |
302 | end | |
303 | sr_rec_prepare: begin | |
304 | case (lcr[1:0]) | |
305 | 2'b0: | |
306 | rbit_counter <= #(1) 3'd4; | |
307 | 2'b1: | |
308 | rbit_counter <= #(1) 3'd5; | |
309 | 2'b10: | |
310 | rbit_counter <= #(1) 3'd6; | |
311 | 2'b11: | |
312 | rbit_counter <= #(1) 3'd7; | |
313 | endcase | |
314 | if (rcounter16_eq_0) begin | |
315 | rstate <= #(1) sr_rec_bit; | |
316 | rcounter16 <= #(1) 4'b1110; | |
317 | rshift <= #(1) 0; | |
318 | end | |
319 | else begin | |
320 | rstate <= #(1) sr_rec_prepare; | |
321 | end | |
322 | rcounter16 <= #(1) rcounter16_minus_1; | |
323 | end | |
324 | sr_rec_bit: begin | |
325 | if (rcounter16_eq_0) begin | |
326 | rstate <= #(1) sr_end_bit; | |
327 | end | |
328 | if (rcounter16_eq_7) begin | |
329 | case (lcr[1:0]) | |
330 | 2'b0: | |
331 | rshift[4:0] <= #(1) {srx_pad_i, rshift[4:1]}; | |
332 | 2'b1: | |
333 | rshift[5:0] <= #(1) {srx_pad_i, rshift[5:1]}; | |
334 | 2'b10: | |
335 | rshift[6:0] <= #(1) {srx_pad_i, rshift[6:1]}; | |
336 | 2'b11: | |
337 | rshift[7:0] <= #(1) {srx_pad_i, rshift[7:1]}; | |
338 | endcase | |
339 | end | |
340 | rcounter16 <= #(1) rcounter16_minus_1; | |
341 | end | |
342 | sr_end_bit: begin | |
343 | if (rbit_counter == 3'b0) begin | |
344 | if (lcr[3]) begin | |
345 | rstate <= #(1) sr_rec_parity; | |
346 | end | |
347 | else | |
348 | begin | |
349 | rstate <= #(1) sr_rec_stop; | |
350 | rparity_error <= #(1) 1'b0; | |
351 | end | |
352 | end | |
353 | else | |
354 | begin | |
355 | rstate <= #(1) sr_rec_bit; | |
356 | rbit_counter <= #(1) (rbit_counter - 1'b1); | |
357 | end | |
358 | rcounter16 <= #(1) 4'b1110; | |
359 | end | |
360 | sr_rec_parity: begin | |
361 | if (rcounter16_eq_7) begin | |
362 | rparity <= #(1) srx_pad_i; | |
363 | rstate <= #(1) sr_ca_lc_parity; | |
364 | end | |
365 | rcounter16 <= #(1) rcounter16_minus_1; | |
366 | end | |
367 | sr_ca_lc_parity: begin | |
368 | rcounter16 <= #(1) rcounter16_minus_1; | |
369 | rparity_xor <= #(1) (^{rshift, rparity}); | |
370 | rstate <= #(1) sr_check_parity; | |
371 | end | |
372 | sr_check_parity: begin | |
373 | case ({lcr[4], lcr[5]}) | |
374 | 2'b0: | |
375 | rparity_error <= #(1) (rparity_xor == 0); | |
376 | 2'b1: | |
377 | rparity_error <= #(1) (~rparity); | |
378 | 2'b10: | |
379 | rparity_error <= #(1) (rparity_xor == 1); | |
380 | 2'b11: | |
381 | rparity_error <= #(1) rparity; | |
382 | endcase | |
383 | rcounter16 <= #(1) rcounter16_minus_1; | |
384 | rstate <= #(1) sr_wait1; | |
385 | end | |
386 | sr_wait1: | |
387 | if (rcounter16_eq_0) begin | |
388 | rstate <= #(1) sr_rec_stop; | |
389 | rcounter16 <= #(1) 4'b1110; | |
390 | end | |
391 | else begin | |
392 | rcounter16 <= #(1) rcounter16_minus_1; | |
393 | end | |
394 | sr_rec_stop: begin | |
395 | if (rcounter16_eq_7) begin | |
396 | rframing_error <= #(1) (!srx_pad_i); | |
397 | rstate <= #(1) sr_push; | |
398 | end | |
399 | rcounter16 <= #(1) rcounter16_minus_1; | |
400 | end | |
401 | sr_push: begin | |
402 | if (srx_pad_i | break_error) begin | |
403 | if (break_error) begin | |
404 | rf_data_in <= #(1) {8'b0, 3'd4}; | |
405 | end | |
406 | else begin | |
407 | rf_data_in <= #(1) {rshift, 1'b0, rparity_error, | |
408 | rframing_error}; | |
409 | end | |
410 | rf_push <= #(1) 1'b1; | |
411 | rstate <= #(1) sr_idle; | |
412 | end | |
413 | else if (~rframing_error) begin | |
414 | rf_data_in <= #(1) {rshift, 1'b0, rparity_error, | |
415 | rframing_error}; | |
416 | rf_push <= #(1) 1'b1; | |
417 | rcounter16 <= #(1) 4'b1110; | |
418 | rstate <= #(1) sr_rec_start; | |
419 | end | |
420 | end | |
421 | default: | |
422 | rstate <= #(1) sr_idle; | |
423 | endcase | |
424 | end | |
425 | end | |
426 | always @(posedge clk or posedge wb_rst_i) begin | |
427 | if (wb_rst_i) begin | |
428 | rf_push_q <= 0; | |
429 | end | |
430 | else begin | |
431 | rf_push_q <= #(1) rf_push; | |
432 | end | |
433 | end | |
434 | always @(lcr) case (lcr[3:0]) | |
435 | 4'b0: | |
436 | toc_value = 447; | |
437 | 4'd4: | |
438 | toc_value = 479; | |
439 | 4'b1, 4'd8: | |
440 | toc_value = 511; | |
441 | 4'b1100: | |
442 | toc_value = 543; | |
443 | 4'd2, 4'd5, 4'd9: | |
444 | toc_value = 575; | |
445 | 4'd3, 4'd6, 4'd10, 4'b1101: | |
446 | toc_value = 639; | |
447 | 4'd7, 4'b1011, 4'b1110: | |
448 | toc_value = 703; | |
449 | 4'b1111: | |
450 | toc_value = 767; | |
451 | endcase | |
452 | always @(posedge clk or posedge wb_rst_i) begin | |
453 | if (wb_rst_i) begin | |
454 | counter_b <= #(1) 8'd159; | |
455 | end | |
456 | else if (srx_pad_i) begin | |
457 | counter_b <= #(1) brc_value; | |
458 | end | |
459 | else if (enable & (counter_b != 8'b0)) begin | |
460 | counter_b <= #(1) (counter_b - 1); | |
461 | end | |
462 | end | |
463 | always @(posedge clk or posedge wb_rst_i) begin | |
464 | if (wb_rst_i) begin | |
465 | counter_t <= #(1) 10'd639; | |
466 | end | |
467 | else if ((rf_push_pulse || rf_pop) || (rf_count == 0)) begin | |
468 | counter_t <= #(1) toc_value; | |
469 | end | |
470 | else if (enable && (counter_t != 10'b0)) begin | |
471 | counter_t <= #(1) (counter_t - 1); | |
472 | end | |
473 | end | |
474 | endmodule |