Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / fpga / opencores / uart_receiver.v
CommitLineData
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
197module 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
474endmodule