1 |
13 |
robfinch |
// ============================================================================
|
2 |
|
|
// (C) 2007,2011,2013 Robert Finch
|
3 |
|
|
// All rights reserved.
|
4 |
|
|
// robfinch@<remove>finitron.ca
|
5 |
|
|
//
|
6 |
|
|
// rtfSimpleUart.v
|
7 |
|
|
// Basic uart with baud rate generator based on a harmonic
|
8 |
|
|
// frequency synthesizer.
|
9 |
|
|
//
|
10 |
|
|
//
|
11 |
|
|
// Redistribution and use in source and binary forms, with or without
|
12 |
|
|
// modification, are permitted provided that the following conditions are met:
|
13 |
|
|
// * Redistributions of source code must retain the above copyright
|
14 |
|
|
// notice, this list of conditions and the following disclaimer.
|
15 |
|
|
// * Redistributions in binary form must reproduce the above copyright
|
16 |
|
|
// notice, this list of conditions and the following disclaimer in the
|
17 |
|
|
// documentation and/or other materials provided with the distribution.
|
18 |
|
|
// * Neither the name of the <organization> nor the
|
19 |
|
|
// names of its contributors may be used to endorse or promote products
|
20 |
|
|
// derived from this software without specific prior written permission.
|
21 |
|
|
//
|
22 |
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
23 |
|
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
24 |
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
25 |
|
|
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
26 |
|
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
27 |
|
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
28 |
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
29 |
|
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
30 |
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
31 |
|
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32 |
|
|
//
|
33 |
|
|
//
|
34 |
|
|
// To use:
|
35 |
|
|
//
|
36 |
|
|
// Set the pClkFreq parameter to the frequency of the system
|
37 |
|
|
// clock (clk_i). This can be done when the core is instanced.
|
38 |
|
|
//
|
39 |
|
|
// 1) set the baud rate value in the clock multiplier
|
40 |
|
|
// registers (CM1,2,3). A default multiplier value may
|
41 |
|
|
// be specified using the pClkMul parameter, so it
|
42 |
|
|
// doesn't have to be programmed at run time. (Note the
|
43 |
|
|
// pBaud parameter may also be set, but it doesn't work
|
44 |
|
|
// in all cases due to arithmetic limitations).
|
45 |
|
|
// 2) enable communication by activating the rts, and
|
46 |
|
|
// dtr signals in the modem control register. These
|
47 |
|
|
// signals are defaulted to be active on reset, so they
|
48 |
|
|
// may not need to be set. The pRts and pDtr parameters
|
49 |
|
|
// may be used to change the default setting.
|
50 |
|
|
// 3) use interrupts or poll the status register to
|
51 |
|
|
// determine when to transmit or receive a byte of data
|
52 |
|
|
// 4) read / write the transmit / recieve data buffer
|
53 |
|
|
// for communication.
|
54 |
|
|
//
|
55 |
|
|
// Notes:
|
56 |
|
|
// This core only supports a single transmission /
|
57 |
|
|
// reception format: 1 start, 8 data, and 1 stop bit (no
|
58 |
|
|
// parity).
|
59 |
|
|
// The baud rate generator uses a 24 bit harmonic
|
60 |
|
|
// frequency synthesizer. Compute the multiplier value
|
61 |
|
|
// as if a 32 bit value was needed, then take the upper
|
62 |
|
|
// 24 bits of the value. (The number of significant bits
|
63 |
|
|
// in the value determine the minimum frequency
|
64 |
|
|
// resolution or the precision of the value).
|
65 |
|
|
//
|
66 |
|
|
// baud rate * 16
|
67 |
|
|
// value = -----------------------
|
68 |
|
|
// (clock frequency / 2^32)
|
69 |
|
|
//
|
70 |
|
|
// eg 38400 * 16
|
71 |
|
|
// value = -----------------------
|
72 |
|
|
// (28.63636MHz / 2^32)
|
73 |
|
|
//
|
74 |
|
|
// = 92149557.65
|
75 |
|
|
// = 057E1736 (hex)
|
76 |
|
|
//
|
77 |
|
|
//
|
78 |
|
|
// taking the upper 24 bits
|
79 |
|
|
// top 24 = 057E17
|
80 |
|
|
// = 359959
|
81 |
|
|
//
|
82 |
|
|
// so the value needed to be programmed into the register
|
83 |
|
|
// for 38.4k baud is 57E17 (hex)
|
84 |
|
|
// eg CM0 = 0 (not used)
|
85 |
|
|
// CM1 = 17 hex
|
86 |
|
|
// CM2 = 7E hex
|
87 |
|
|
// CM3 = 05 hex
|
88 |
|
|
//
|
89 |
|
|
//
|
90 |
|
|
// Register Description
|
91 |
|
|
//
|
92 |
|
|
// reg
|
93 |
|
|
// 0 read / write (RW)
|
94 |
|
|
// TRB - transmit / receive buffer
|
95 |
|
|
// transmit / receive buffer
|
96 |
|
|
// write - write to transmit buffer
|
97 |
|
|
// read - read from receive buffer
|
98 |
|
|
//
|
99 |
|
|
// 1 read only (RO)
|
100 |
|
|
// LS - line status register
|
101 |
|
|
// bit 0 = receiver not empty, this bit is set if there is
|
102 |
|
|
// any data available in the receiver fifo
|
103 |
|
|
// bit 1 = overrun, this bit is set if receiver overrun occurs
|
104 |
|
|
// bit 3 = framing error, this bit is set if there was a
|
105 |
|
|
// framing error with the current byte in the receiver
|
106 |
|
|
// buffer.
|
107 |
|
|
// bit 5 = transmitter not full, this bit is set if the transmitter
|
108 |
|
|
// can accept more data
|
109 |
|
|
// bit 6 = transmitter empty, this bit is set if the transmitter is
|
110 |
|
|
// completely empty
|
111 |
|
|
//
|
112 |
|
|
// 2 MS - modem status register (RO)
|
113 |
|
|
// writing to the modem status register clears the change
|
114 |
|
|
// indicators, which should clear a modem status interrupt
|
115 |
|
|
// bit 3 = change on dcd signal
|
116 |
|
|
// bit 4 = cts signal level
|
117 |
|
|
// bit 5 = dsr signal level
|
118 |
|
|
// bit 6 = ri signal level
|
119 |
|
|
// bit 7 = dcd signal level
|
120 |
|
|
//
|
121 |
|
|
// 3 IS - interrupt status register (RO)
|
122 |
|
|
// bit 0-4 = mailbox number
|
123 |
|
|
// bit 0,1 = 00
|
124 |
|
|
// bit 2-4 = encoded interrupt value
|
125 |
|
|
// bit 5-6 = not used, reserved
|
126 |
|
|
// bit 7 = 1 = interrupt pending, 0 = no interrupt
|
127 |
|
|
//
|
128 |
|
|
// 4 IE - interrupt enable register (RW)
|
129 |
|
|
// bit 0 = receive interrupt (data present)
|
130 |
|
|
// bit 1 = transmit interrupt (data empty)
|
131 |
|
|
// bit 3 = modem status (dcd) register change
|
132 |
|
|
// bit 5-7 = unused, reserved
|
133 |
|
|
//
|
134 |
|
|
// 5 FF - frame format register (RW)
|
135 |
|
|
// this register doesn't do anything in the simpleUart
|
136 |
|
|
// but is reserved for compatiblity with the more
|
137 |
|
|
// advanced uart
|
138 |
|
|
//
|
139 |
|
|
// 6 MC - modem control register (RW)
|
140 |
|
|
// bit 0 = dtr signal level output
|
141 |
|
|
// bit 1 = rts signal level output
|
142 |
|
|
//
|
143 |
|
|
// 7 - control register
|
144 |
|
|
// bit 0 = hardware flow control,
|
145 |
|
|
// when this bit is set, the transmitter output is
|
146 |
|
|
// controlled by the cts signal line automatically
|
147 |
|
|
//
|
148 |
|
|
//
|
149 |
|
|
// * Clock multiplier steps the 16xbaud clock frequency
|
150 |
|
|
// in increments of 1/2^32 of the clk_i input using a
|
151 |
|
|
// harmonic frequency synthesizer
|
152 |
|
|
// eg. to get a 9600 baud 16x clock (153.6 kHz) with a
|
153 |
|
|
// 27.175 MHz clock input,
|
154 |
|
|
// value = upper24(9600 * 16 / (27.175MHz / 2^32))
|
155 |
|
|
// Higher frequency baud rates will exhibit more jitter
|
156 |
|
|
// on the 16x clock, but this will mostly be masked by the
|
157 |
|
|
// 16x clock factor.
|
158 |
|
|
//
|
159 |
|
|
// 8 CM0 - Clock Multiplier byte 0 (RW)
|
160 |
|
|
// this is the least significant byte
|
161 |
|
|
// of the clock multiplier value
|
162 |
|
|
// this register is not used unless the clock
|
163 |
|
|
// multiplier is set to contain 32 bit values
|
164 |
|
|
//
|
165 |
|
|
// 9 CM1 - Clock Multiplier byte 1 (RW)
|
166 |
|
|
// this is the third most significant byte
|
167 |
|
|
// of the clock multiplier value
|
168 |
|
|
// this register is not used unless the clock
|
169 |
|
|
// multiplier is set to contain 24 or 32 bit values
|
170 |
|
|
//
|
171 |
|
|
// 10 CM2 - Clock Multiplier byte 2 (RW)
|
172 |
|
|
// this is the second most significant byte of the clock
|
173 |
|
|
// multiplier value
|
174 |
|
|
//
|
175 |
|
|
// 11 CM3 - Clock Multiplier byte 3 (RW)
|
176 |
|
|
// this is the most significant byte of the multiplier value
|
177 |
|
|
//
|
178 |
|
|
// 12 FC - Fifo control register (RW)
|
179 |
|
|
// this register doesnt' do anything in the simpleUart
|
180 |
|
|
// but is reserved for compatibility with the more
|
181 |
|
|
// advanced uart
|
182 |
|
|
//
|
183 |
|
|
// 13-14 reserved registers
|
184 |
|
|
//
|
185 |
|
|
// 15 SPR - scratch pad register (RW)
|
186 |
|
|
//
|
187 |
|
|
//
|
188 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
189 |
|
|
// |WISHBONE Datasheet
|
190 |
|
|
// |WISHBONE SoC Architecture Specification, Revision B.3
|
191 |
|
|
// |
|
192 |
|
|
// |Description: Specifications:
|
193 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
194 |
|
|
// |General Description: simple UART core
|
195 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
196 |
|
|
// |Supported Cycles: SLAVE,READ/WRITE
|
197 |
|
|
// | SLAVE,BLOCK READ/WRITE
|
198 |
|
|
// | SLAVE,RMW
|
199 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
200 |
|
|
// |Data port, size: 8 bit
|
201 |
|
|
// |Data port, granularity: 8 bit
|
202 |
|
|
// |Data port, maximum operand size: 8 bit
|
203 |
|
|
// |Data transfer ordering: Undefined
|
204 |
|
|
// |Data transfer sequencing: Undefined
|
205 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
206 |
|
|
// |Clock frequency constraints: none
|
207 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
208 |
|
|
// |Supported signal list and Signal Name WISHBONE equiv.
|
209 |
|
|
// |cross reference to equivalent ack_o ACK_O
|
210 |
|
|
// |WISHBONE signals adr_i[3:0] ADR_I()
|
211 |
|
|
// | clk_i CLK_I
|
212 |
|
|
// | rst_i RST_I()
|
213 |
|
|
// | dat_i(7:0) DAT_I()
|
214 |
|
|
// | dat_o(7:0) DAT_O()
|
215 |
|
|
// | cyc_i CYC_I
|
216 |
|
|
// | stb_i STB_I
|
217 |
|
|
// | we_i WE_I
|
218 |
|
|
// |
|
219 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
220 |
|
|
// |Special requirements:
|
221 |
|
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
222 |
|
|
//
|
223 |
|
|
//=============================================================================
|
224 |
6 |
robfinch |
|
225 |
|
|
`define UART_TRB 4'd0 // transmit/receive buffer
|
226 |
|
|
`define UART_LS 4'd1 // line status register
|
227 |
|
|
`define UART_MS 4'd2 // modem status register
|
228 |
|
|
`define UART_IS 4'd3 // interrupt status register
|
229 |
|
|
`define UART_IER 4'd4 // interrupt enable
|
230 |
|
|
`define UART_FF 4'd5 // frame format register
|
231 |
|
|
`define UART_MC 4'd6 // modem control register
|
232 |
|
|
`define UART_CTRL 4'd7 // control register
|
233 |
|
|
`define UART_CLKM0 4'd8 // clock multiplier byte 0
|
234 |
|
|
`define UART_CLKM1 4'd9 // clock multiplier byte 1
|
235 |
|
|
`define UART_CLKM2 4'd10 // clock multiplier byte 2
|
236 |
|
|
`define UART_CLKM3 4'd11 // clock multiplier byte 3
|
237 |
|
|
`define UART_FC 4'd12 // fifo control register
|
238 |
|
|
|
239 |
|
|
module rtfSimpleUart(
|
240 |
|
|
// WISHBONE Slave interface
|
241 |
|
|
input rst_i, // reset
|
242 |
|
|
input clk_i, // eg 100.7MHz
|
243 |
|
|
input cyc_i, // cycle valid
|
244 |
|
|
input stb_i, // strobe
|
245 |
|
|
input we_i, // 1 = write
|
246 |
|
|
input [31:0] adr_i, // register address
|
247 |
|
|
input [7:0] dat_i, // data input bus
|
248 |
|
|
output reg [7:0] dat_o, // data output bus
|
249 |
|
|
output ack_o, // transfer acknowledge
|
250 |
|
|
output vol_o, // volatile register selected
|
251 |
|
|
output irq_o, // interrupt request
|
252 |
|
|
//----------------
|
253 |
|
|
input cts_ni, // clear to send - active low - (flow control)
|
254 |
|
|
output reg rts_no, // request to send - active low - (flow control)
|
255 |
|
|
input dsr_ni, // data set ready - active low
|
256 |
|
|
input dcd_ni, // data carrier detect - active low
|
257 |
|
|
output reg dtr_no, // data terminal ready - active low
|
258 |
|
|
input rxd_i, // serial data in
|
259 |
|
|
output txd_o, // serial data out
|
260 |
|
|
output data_present_o
|
261 |
|
|
);
|
262 |
|
|
parameter pClkFreq = 20000000; // clock frequency in MHz
|
263 |
|
|
parameter pBaud = 19200;
|
264 |
|
|
parameter pClkMul = (4096 * pBaud) / (pClkFreq / 65536);
|
265 |
|
|
parameter pRts = 1; // default to active
|
266 |
|
|
parameter pDtr = 1;
|
267 |
|
|
|
268 |
|
|
wire cs = cyc_i && stb_i && (adr_i[31:4]==28'hFFDC_0A0);
|
269 |
|
|
assign ack_o = cs;
|
270 |
|
|
assign vol_o = cs && adr_i[3:2]==2'b00;
|
271 |
|
|
|
272 |
|
|
//-------------------------------------------
|
273 |
|
|
// variables
|
274 |
|
|
reg [23:0] c; // current count
|
275 |
|
|
reg [23:0] ck_mul; // baud rate clock multiplier
|
276 |
|
|
wire tx_empty;
|
277 |
|
|
wire baud16; // edge detector (active one cycle only!)
|
278 |
|
|
reg rx_present_ie;
|
279 |
|
|
reg tx_empty_ie;
|
280 |
|
|
reg dcd_ie;
|
281 |
|
|
reg hwfc; // hardware flow control enable
|
282 |
|
|
wire clear = cyc_i && stb_i && we_i && adr_i==4'd13;
|
283 |
|
|
wire frame_err; // receiver char framing error
|
284 |
|
|
wire over_run; // receiver over run
|
285 |
|
|
reg [1:0] ctsx; // cts_ni sampling
|
286 |
|
|
reg [1:0] dcdx;
|
287 |
|
|
reg [1:0] dsrx;
|
288 |
|
|
wire dcd_chg = dcdx[1]^dcdx[0];
|
289 |
|
|
|
290 |
|
|
|
291 |
|
|
wire rxIRQ = data_present_o & rx_present_ie;
|
292 |
|
|
wire txIRQ = tx_empty & tx_empty_ie;
|
293 |
|
|
wire msIRQ = dcd_chg & dcd_ie;
|
294 |
|
|
|
295 |
|
|
assign irq_o =
|
296 |
|
|
rxIRQ
|
297 |
|
|
| txIRQ
|
298 |
|
|
| msIRQ
|
299 |
|
|
;
|
300 |
|
|
|
301 |
|
|
wire [2:0] irqenc =
|
302 |
|
|
rxIRQ ? 1 :
|
303 |
|
|
txIRQ ? 3 :
|
304 |
|
|
msIRQ ? 4 :
|
305 |
|
|
0;
|
306 |
|
|
|
307 |
|
|
wire [7:0] rx_do;
|
308 |
|
|
wire txrx = cs && adr_i[3:0]==4'd0;
|
309 |
|
|
|
310 |
|
|
rtfSimpleUartRx uart_rx0(
|
311 |
|
|
.rst_i(rst_i),
|
312 |
|
|
.clk_i(clk_i),
|
313 |
|
|
.cyc_i(cyc_i),
|
314 |
|
|
.stb_i(stb_i),
|
315 |
|
|
.cs_i(txrx),
|
316 |
|
|
.we_i(we_i),
|
317 |
|
|
.dat_o(rx_do),
|
318 |
|
|
.baud16x_ce(baud16),
|
319 |
|
|
.clear(clear),
|
320 |
|
|
.rxd(rxd_i),
|
321 |
|
|
.data_present(data_present_o),
|
322 |
|
|
.frame_err(frame_err),
|
323 |
|
|
.overrun(over_run)
|
324 |
|
|
);
|
325 |
|
|
|
326 |
|
|
rtfSimpleUartTx uart_tx0(
|
327 |
|
|
.rst_i(rst_i),
|
328 |
|
|
.clk_i(clk_i),
|
329 |
|
|
.cyc_i(cyc_i),
|
330 |
|
|
.stb_i(stb_i),
|
331 |
|
|
.cs_i(txrx),
|
332 |
|
|
.we_i(we_i),
|
333 |
|
|
.dat_i(dat_i),
|
334 |
|
|
.baud16x_ce(baud16),
|
335 |
|
|
.cts(ctsx[1]|~hwfc),
|
336 |
|
|
.txd(txd_o),
|
337 |
|
|
.empty(tx_empty)
|
338 |
|
|
);
|
339 |
|
|
|
340 |
|
|
// mux the reg outputs
|
341 |
|
|
always @*
|
342 |
|
|
if (cs) begin
|
343 |
|
|
case(adr_i[3:0]) // synopsys full_case parallel_case
|
344 |
|
|
`UART_MS: dat_o <= {dcdx[1],1'b0,dsrx[1],ctsx[1],dcd_chg,3'b0};
|
345 |
|
|
`UART_IS: dat_o <= {irq_o, 2'b0, irqenc, 2'b0};
|
346 |
|
|
`UART_LS: dat_o <= {1'b0, tx_empty, tx_empty, 1'b0, frame_err, 1'b0, over_run, data_present_o};
|
347 |
|
|
default: dat_o <= rx_do;
|
348 |
|
|
endcase
|
349 |
|
|
end
|
350 |
|
|
else
|
351 |
|
|
dat_o <= 8'b0;
|
352 |
|
|
|
353 |
|
|
// Note: baud clock should pulse high for only a single
|
354 |
|
|
// cycle!
|
355 |
|
|
always @(posedge clk_i)
|
356 |
|
|
if (rst_i)
|
357 |
|
|
c <= 0;
|
358 |
|
|
else
|
359 |
|
|
c <= c + ck_mul;
|
360 |
|
|
|
361 |
|
|
// for detecting an edge on the msb
|
362 |
|
|
edge_det ed0(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(c[23]), .pe(baud16), .ne(), .ee() );
|
363 |
|
|
|
364 |
|
|
// register updates
|
365 |
|
|
always @(posedge clk_i) begin
|
366 |
|
|
if (rst_i) begin
|
367 |
|
|
rts_no <= ~pRts;
|
368 |
|
|
rx_present_ie <= 1'b0;
|
369 |
|
|
tx_empty_ie <= 1'b0;
|
370 |
|
|
dcd_ie <= 1'b0;
|
371 |
|
|
hwfc <= 1'b1;
|
372 |
|
|
dtr_no <= ~pDtr;
|
373 |
|
|
ck_mul <= pClkMul;
|
374 |
|
|
end
|
375 |
|
|
else if (cs & we_i) begin
|
376 |
|
|
case (adr_i)
|
377 |
|
|
`UART_IER:
|
378 |
|
|
begin
|
379 |
|
|
rx_present_ie <= dat_i[0];
|
380 |
|
|
tx_empty_ie <= dat_i[1];
|
381 |
|
|
dcd_ie <= dat_i[3];
|
382 |
|
|
end
|
383 |
|
|
`UART_MC:
|
384 |
|
|
begin
|
385 |
|
|
dtr_no <= ~dat_i[0];
|
386 |
|
|
rts_no <= ~dat_i[1];
|
387 |
|
|
end
|
388 |
|
|
`UART_CTRL: hwfc <= dat_i[0];
|
389 |
|
|
`UART_CLKM1: ck_mul[7:0] <= dat_i;
|
390 |
|
|
`UART_CLKM2: ck_mul[15:8] <= dat_i;
|
391 |
|
|
`UART_CLKM3: ck_mul[23:16] <= dat_i;
|
392 |
|
|
default:
|
393 |
|
|
;
|
394 |
|
|
endcase
|
395 |
|
|
end
|
396 |
|
|
end
|
397 |
|
|
|
398 |
|
|
|
399 |
|
|
// synchronize external signals
|
400 |
|
|
always @(posedge clk_i)
|
401 |
|
|
ctsx <= {ctsx[0],~cts_ni};
|
402 |
|
|
|
403 |
|
|
always @(posedge clk_i)
|
404 |
|
|
dcdx <= {dcdx[0],~dcd_ni};
|
405 |
|
|
|
406 |
|
|
always @(posedge clk_i)
|
407 |
|
|
dsrx <= {dsrx[0],~dsr_ni};
|
408 |
|
|
|
409 |
|
|
endmodule
|
410 |
|
|
|