OpenCores
URL https://opencores.org/ocsvn/rtfsimpleuart/rtfsimpleuart/trunk

Subversion Repositories rtfsimpleuart

[/] [rtfsimpleuart/] [trunk/] [rtl/] [verilog/] [rtfSimpleUart.v] - Blame information for rev 14

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.