Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | ////////////////////////////////////////////////////////////////////// |
2 | //// //// | |
3 | //// uart_transmitter.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 transmitter 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_transmitter.v,v $ | |
66 | // Revision 1.19 2002/07/29 21:16:18 gorban | |
67 | // The uart_defines.v file is included again in sources. | |
68 | // | |
69 | // Revision 1.18 2002/07/22 23:02:23 gorban | |
70 | // Bug Fixes: | |
71 | // * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. | |
72 | // Problem reported by Kenny.Tung. | |
73 | // * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. | |
74 | // | |
75 | // Improvements: | |
76 | // * Made FIFO's as general inferrable memory where possible. | |
77 | // So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). | |
78 | // This saves about 1/3 of the Slice count and reduces P&R and synthesis times. | |
79 | // | |
80 | // * Added optional baudrate output (baud_o). | |
81 | // This is identical to BAUDOUT* signal on 16550 chip. | |
82 | // It outputs 16xbit_clock_rate - the divided clock. | |
83 | // It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. | |
84 | // | |
85 | // Revision 1.16 2002/01/08 11:29:40 mohor | |
86 | // tf_pop was too wide. Now it is only 1 clk cycle width. | |
87 | // | |
88 | // Revision 1.15 2001/12/17 14:46:48 mohor | |
89 | // overrun signal was moved to separate block because many sequential lsr | |
90 | // reads were preventing data from being written to rx fifo. | |
91 | // underrun signal was not used and was removed from the project. | |
92 | // | |
93 | // Revision 1.14 2001/12/03 21:44:29 gorban | |
94 | // Updated specification documentation. | |
95 | // Added full 32-bit data bus interface, now as default. | |
96 | // Address is 5-bit wide in 32-bit data bus mode. | |
97 | // Added wb_sel_i input to the core. It's used in the 32-bit mode. | |
98 | // Added debug interface with two 32-bit read-only registers in 32-bit mode. | |
99 | // Bits 5 and 6 of LSR are now only cleared on TX FIFO write. | |
100 | // My small test bench is modified to work with 32-bit mode. | |
101 | // | |
102 | // Revision 1.13 2001/11/08 14:54:23 mohor | |
103 | // Comments in Slovene language deleted, few small fixes for better work of | |
104 | // old tools. IRQs need to be fix. | |
105 | // | |
106 | // Revision 1.12 2001/11/07 17:51:52 gorban | |
107 | // Heavily rewritten interrupt and LSR subsystems. | |
108 | // Many bugs hopefully squashed. | |
109 | // | |
110 | // Revision 1.11 2001/10/29 17:00:46 gorban | |
111 | // fixed parity sending and tx_fifo resets over- and underrun | |
112 | // | |
113 | // Revision 1.10 2001/10/20 09:58:40 gorban | |
114 | // Small synopsis fixes | |
115 | // | |
116 | // Revision 1.9 2001/08/24 21:01:12 mohor | |
117 | // Things connected to parity changed. | |
118 | // Clock devider changed. | |
119 | // | |
120 | // Revision 1.8 2001/08/23 16:05:05 mohor | |
121 | // Stop bit bug fixed. | |
122 | // Parity bug fixed. | |
123 | // WISHBONE read cycle bug fixed, | |
124 | // OE indicator (Overrun Error) bug fixed. | |
125 | // PE indicator (Parity Error) bug fixed. | |
126 | // Register read bug fixed. | |
127 | // | |
128 | // Revision 1.6 2001/06/23 11:21:48 gorban | |
129 | // DL made 16-bit long. Fixed transmission/reception bugs. | |
130 | // | |
131 | // Revision 1.5 2001/06/02 14:28:14 gorban | |
132 | // Fixed receiver and transmitter. Major bug fixed. | |
133 | // | |
134 | // Revision 1.4 2001/05/31 20:08:01 gorban | |
135 | // FIFO changes and other corrections. | |
136 | // | |
137 | // Revision 1.3 2001/05/27 17:37:49 gorban | |
138 | // Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. | |
139 | // | |
140 | // Revision 1.2 2001/05/21 19:12:02 gorban | |
141 | // Corrected some Linter messages. | |
142 | // | |
143 | // Revision 1.1 2001/05/17 18:34:18 gorban | |
144 | // First 'stable' release. Should be sythesizable now. Also added new header. | |
145 | // | |
146 | // Revision 1.0 2001-05-17 21:27:12+02 jacob | |
147 | // Initial revision | |
148 | // | |
149 | // | |
150 | ||
151 | ||
152 | `timescale 1 ns / 10 ps | |
153 | module uart_transmitter(clk, wb_rst_i, lcr, tf_push, wb_dat_i, enable, | |
154 | stx_pad_o, tstate, tf_count, tx_reset, lsr_mask); | |
155 | ||
156 | parameter s_idle = 3'b0; | |
157 | parameter s_send_start = 3'b1; | |
158 | parameter s_send_byte = 3'd2; | |
159 | parameter s_send_parity = 3'd3; | |
160 | parameter s_send_stop = 3'd4; | |
161 | parameter s_pop_byte = 3'd5; | |
162 | ||
163 | input clk; | |
164 | input wb_rst_i; | |
165 | input [7:0] lcr; | |
166 | input tf_push; | |
167 | input [7:0] wb_dat_i; | |
168 | input enable; | |
169 | input tx_reset; | |
170 | input lsr_mask; | |
171 | output stx_pad_o; | |
172 | output [2:0] tstate; | |
173 | output [(5 - 1):0] tf_count; | |
174 | ||
175 | reg [4:0] counter; | |
176 | reg [2:0] bit_counter; | |
177 | reg [6:0] shift_out; | |
178 | reg stx_o_tmp; | |
179 | reg parity_xor; | |
180 | reg tf_pop; | |
181 | reg bit_out; | |
182 | reg [(8 - 1):0] tf_data_in; | |
183 | wire [(8 - 1):0] tf_data_out; | |
184 | reg [2:0] tstate; | |
185 | wire tf_overrun; | |
186 | ||
187 | assign stx_pad_o = (lcr[6] ? 1'b0 : stx_o_tmp); | |
188 | ||
189 | uart_tfifo fifo_tx( | |
190 | .clk (clk), | |
191 | .wb_rst_i (wb_rst_i), | |
192 | .data_in (tf_data_in), | |
193 | .data_out (tf_data_out), | |
194 | .push (tf_push), | |
195 | .pop (tf_pop), | |
196 | .overrun (tf_overrun), | |
197 | .count (tf_count), | |
198 | .fifo_reset (tx_reset), | |
199 | .reset_status (lsr_mask)); | |
200 | ||
201 | always @(posedge clk) tf_data_in <= wb_dat_i; | |
202 | always @(posedge clk or posedge wb_rst_i) begin | |
203 | if (wb_rst_i) begin | |
204 | tstate <= #(1) s_idle; | |
205 | stx_o_tmp <= #(1) 1'b1; | |
206 | counter <= #(1) 5'b0; | |
207 | shift_out <= #(1) 7'b0; | |
208 | bit_out <= #(1) 1'b0; | |
209 | parity_xor <= #(1) 1'b0; | |
210 | tf_pop <= #(1) 1'b0; | |
211 | bit_counter <= #(1) 3'b0; | |
212 | end | |
213 | else if (enable) begin | |
214 | case (tstate) | |
215 | s_idle: | |
216 | if (~|tf_count) begin | |
217 | tstate <= #(1) s_idle; | |
218 | stx_o_tmp <= #(1) 1'b1; | |
219 | end | |
220 | else | |
221 | begin | |
222 | tf_pop <= #(1) 1'b0; | |
223 | stx_o_tmp <= #(1) 1'b1; | |
224 | tstate <= #(1) s_pop_byte; | |
225 | end | |
226 | s_pop_byte: begin | |
227 | tf_pop <= #(1) 1'b1; | |
228 | case (lcr[1:0]) | |
229 | 2'b0: begin | |
230 | bit_counter <= #(1) 3'd4; | |
231 | parity_xor <= #(1) (^tf_data_out[4:0]); | |
232 | end | |
233 | 2'b1: begin | |
234 | bit_counter <= #(1) 3'd5; | |
235 | parity_xor <= #(1) (^tf_data_out[5:0]); | |
236 | end | |
237 | 2'b10: begin | |
238 | bit_counter <= #(1) 3'd6; | |
239 | parity_xor <= #(1) (^tf_data_out[6:0]); | |
240 | end | |
241 | 2'b11: begin | |
242 | bit_counter <= #(1) 3'd7; | |
243 | parity_xor <= #(1) (^tf_data_out[7:0]); | |
244 | end | |
245 | endcase | |
246 | {shift_out[6:0], bit_out} <= #(1) tf_data_out; | |
247 | tstate <= #(1) s_send_start; | |
248 | end | |
249 | s_send_start: begin | |
250 | tf_pop <= #(1) 1'b0; | |
251 | if (~|counter) begin | |
252 | counter <= #(1) 5'b01111; | |
253 | end | |
254 | else if (counter == 5'b1) begin | |
255 | counter <= #(1) 0; | |
256 | tstate <= #(1) s_send_byte; | |
257 | end | |
258 | else begin | |
259 | counter <= #(1) (counter - 1'b1); | |
260 | end | |
261 | stx_o_tmp <= #(1) 1'b0; | |
262 | end | |
263 | s_send_byte: begin | |
264 | if (~|counter) begin | |
265 | counter <= #(1) 5'b01111; | |
266 | end | |
267 | else if (counter == 5'b1) begin | |
268 | if (bit_counter > 3'b0) begin | |
269 | bit_counter <= #(1) (bit_counter - 1'b1); | |
270 | {shift_out[5:0], bit_out} <= #(1) {shift_out[6:1], | |
271 | shift_out[0]}; | |
272 | tstate <= #(1) s_send_byte; | |
273 | end | |
274 | else if (~lcr[3]) begin | |
275 | tstate <= #(1) s_send_stop; | |
276 | end | |
277 | else | |
278 | begin | |
279 | case ({lcr[4], lcr[5]}) | |
280 | 2'b0: | |
281 | bit_out <= #(1) (~parity_xor); | |
282 | 2'b1: | |
283 | bit_out <= #(1) 1'b1; | |
284 | 2'b10: | |
285 | bit_out <= #(1) parity_xor; | |
286 | 2'b11: | |
287 | bit_out <= #(1) 1'b0; | |
288 | endcase | |
289 | tstate <= #(1) s_send_parity; | |
290 | end | |
291 | counter <= #(1) 0; | |
292 | end | |
293 | else begin | |
294 | counter <= #(1) (counter - 1'b1); | |
295 | end | |
296 | stx_o_tmp <= #(1) bit_out; | |
297 | end | |
298 | s_send_parity: begin | |
299 | if (~|counter) begin | |
300 | counter <= #(1) 5'b01111; | |
301 | end | |
302 | else if (counter == 5'b1) begin | |
303 | counter <= #(1) 4'b0; | |
304 | tstate <= #(1) s_send_stop; | |
305 | end | |
306 | else begin | |
307 | counter <= #(1) (counter - 1'b1); | |
308 | end | |
309 | stx_o_tmp <= #(1) bit_out; | |
310 | end | |
311 | s_send_stop: begin | |
312 | if (~|counter) begin | |
313 | casex ({lcr[2], lcr[1:0]}) | |
314 | 3'b0xx: | |
315 | counter <= #(1) 5'b01101; | |
316 | 3'd4: | |
317 | counter <= #(1) 5'b10101; | |
318 | default: | |
319 | counter <= #(1) 5'b11101; | |
320 | endcase | |
321 | end | |
322 | else if (counter == 5'b1) begin | |
323 | counter <= #(1) 0; | |
324 | tstate <= #(1) s_idle; | |
325 | end | |
326 | else begin | |
327 | counter <= #(1) (counter - 1'b1); | |
328 | end | |
329 | stx_o_tmp <= #(1) 1'b1; | |
330 | end | |
331 | default: | |
332 | tstate <= #(1) s_idle; | |
333 | endcase | |
334 | end | |
335 | else begin | |
336 | tf_pop <= #(1) 1'b0; | |
337 | end | |
338 | end | |
339 | endmodule |