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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [fpga/] [xilinx_avnet_lx9microbard/] [rtl/] [verilog/] [omsp_uart.v] - Blame information for rev 202

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 157 olivier.gi
//----------------------------------------------------------------------------
2
// Copyright (C) 2009 , Olivier Girard
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions
6
// are met:
7
//     * Redistributions of source code must retain the above copyright
8
//       notice, this list of conditions and the following disclaimer.
9
//     * Redistributions in binary form must reproduce the above copyright
10
//       notice, this list of conditions and the following disclaimer in the
11
//       documentation and/or other materials provided with the distribution.
12
//     * Neither the name of the authors nor the names of its contributors
13
//       may be used to endorse or promote products derived from this software
14
//       without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
// THE POSSIBILITY OF SUCH DAMAGE
27
//
28
//----------------------------------------------------------------------------
29
//
30
// *File Name: omsp_uart.v
31 202 olivier.gi
//
32 157 olivier.gi
// *Module Description:
33
//                       Simple full duplex UART (8N1 protocol).
34
//
35
// *Author(s):
36
//              - Olivier Girard,    olgirard@gmail.com
37
//
38
//----------------------------------------------------------------------------
39
// $Rev: 111 $
40
// $LastChangedBy: olivier.girard $
41
// $LastChangedDate: 2011-05-20 22:39:02 +0200 (Fri, 20 May 2011) $
42
//----------------------------------------------------------------------------
43
 
44
module  omsp_uart (
45
 
46
// OUTPUTs
47
    irq_uart_rx,                    // UART receive interrupt
48
    irq_uart_tx,                    // UART transmit interrupt
49
    per_dout,                       // Peripheral data output
50
    uart_txd,                       // UART Data Transmit (TXD)
51
 
52
// INPUTs
53
    mclk,                           // Main system clock
54
    per_addr,                       // Peripheral address
55
    per_din,                        // Peripheral data input
56
    per_en,                         // Peripheral enable (high active)
57
    per_we,                         // Peripheral write enable (high active)
58
    puc_rst,                        // Main system reset
59
    smclk_en,                       // SMCLK enable (from CPU)
60
    uart_rxd                        // UART Data Receive (RXD)
61
);
62
 
63
// OUTPUTs
64
//=========
65
output             irq_uart_rx;     // UART receive interrupt
66
output             irq_uart_tx;     // UART transmit interrupt
67
output      [15:0] per_dout;        // Peripheral data output
68
output             uart_txd;        // UART Data Transmit (TXD)
69
 
70
// INPUTs
71
//=========
72
input              mclk;            // Main system clock
73
input       [13:0] per_addr;        // Peripheral address
74
input       [15:0] per_din;         // Peripheral data input
75
input              per_en;          // Peripheral enable (high active)
76
input        [1:0] per_we;          // Peripheral write enable (high active)
77
input              puc_rst;         // Main system reset
78
input              smclk_en;        // SMCLK enable (from CPU)
79
input              uart_rxd;        // UART Data Receive (RXD)
80
 
81
 
82
//=============================================================================
83
// 1)  PARAMETER DECLARATION
84
//=============================================================================
85
 
86
// Register base address (must be aligned to decoder bit width)
87
parameter       [14:0] BASE_ADDR   = 15'h0080;
88
 
89
// Decoder bit width (defines how many bits are considered for address decoding)
90
parameter              DEC_WD      =  3;
91
 
92
// Register addresses offset
93
parameter [DEC_WD-1:0] CTRL        =  'h0,
94
                       STATUS      =  'h1,
95
                       BAUD_LO     =  'h2,
96
                       BAUD_HI     =  'h3,
97
                       DATA_TX     =  'h4,
98
                       DATA_RX     =  'h5;
99
 
100 202 olivier.gi
 
101 157 olivier.gi
// Register one-hot decoder utilities
102
parameter              DEC_SZ      =  (1 << DEC_WD);
103
parameter [DEC_SZ-1:0] BASE_REG    =  {{DEC_SZ-1{1'b0}}, 1'b1};
104
 
105
// Register one-hot decoder
106
parameter [DEC_SZ-1:0] CTRL_D      = (BASE_REG << CTRL),
107 202 olivier.gi
                       STATUS_D    = (BASE_REG << STATUS),
108
                       BAUD_LO_D   = (BASE_REG << BAUD_LO),
109
                       BAUD_HI_D   = (BASE_REG << BAUD_HI),
110
                       DATA_TX_D   = (BASE_REG << DATA_TX),
111
                       DATA_RX_D   = (BASE_REG << DATA_RX);
112 157 olivier.gi
 
113
 
114
//============================================================================
115
// 2)  REGISTER DECODER
116
//============================================================================
117
 
118
// Local register selection
119
wire              reg_sel      =  per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]);
120
 
121
// Register local address
122
wire [DEC_WD-1:0] reg_addr     =  {1'b0, per_addr[DEC_WD-2:0]};
123
 
124
// Register address decode
125
wire [DEC_SZ-1:0] reg_dec      = (CTRL_D    &  {DEC_SZ{(reg_addr==(CTRL    >>1))}}) |
126
                                 (STATUS_D  &  {DEC_SZ{(reg_addr==(STATUS  >>1))}}) |
127
                                 (BAUD_LO_D &  {DEC_SZ{(reg_addr==(BAUD_LO >>1))}}) |
128
                                 (BAUD_HI_D &  {DEC_SZ{(reg_addr==(BAUD_HI >>1))}}) |
129
                                 (DATA_TX_D &  {DEC_SZ{(reg_addr==(DATA_TX >>1))}}) |
130
                                 (DATA_RX_D &  {DEC_SZ{(reg_addr==(DATA_RX >>1))}});
131
 
132
// Read/Write probes
133
wire              reg_lo_write =  per_we[0] & reg_sel;
134
wire              reg_hi_write =  per_we[1] & reg_sel;
135
wire              reg_read     = ~|per_we   & reg_sel;
136
 
137
// Read/Write vectors
138
wire [DEC_SZ-1:0] reg_hi_wr    = reg_dec & {DEC_SZ{reg_hi_write}};
139
wire [DEC_SZ-1:0] reg_lo_wr    = reg_dec & {DEC_SZ{reg_lo_write}};
140
wire [DEC_SZ-1:0] reg_rd       = reg_dec & {DEC_SZ{reg_read}};
141
 
142
 
143
//============================================================================
144
// 3) REGISTERS
145
//============================================================================
146
 
147
// CTRL Register
148
//-----------------
149
reg  [7:0] ctrl;
150
 
151
wire       ctrl_wr  = CTRL[0] ? reg_hi_wr[CTRL] : reg_lo_wr[CTRL];
152
wire [7:0] ctrl_nxt = CTRL[0] ? per_din[15:8]   : per_din[7:0];
153
 
154
always @ (posedge mclk or posedge puc_rst)
155
  if (puc_rst)       ctrl <=  8'h00;
156
  else if (ctrl_wr)  ctrl <=  ctrl_nxt & 8'h73;
157
 
158
wire       ctrl_ien_tx_empty = ctrl[7];
159
wire       ctrl_ien_tx       = ctrl[6];
160
wire       ctrl_ien_rx_ovflw = ctrl[5];
161
wire       ctrl_ien_rx       = ctrl[4];
162
wire       ctrl_smclk_sel    = ctrl[1];
163
wire       ctrl_en           = ctrl[0];
164
 
165
 
166
// STATUS Register
167
//-----------------
168
wire [7:0] status;
169
reg        status_tx_empty_pnd;
170
reg        status_tx_pnd;
171
reg        status_rx_ovflw_pnd;
172
reg        status_rx_pnd;
173
wire       status_tx_full;
174
wire       status_tx_busy;
175
wire       status_rx_busy;
176
 
177
wire       status_wr  = STATUS[0] ? reg_hi_wr[STATUS] : reg_lo_wr[STATUS];
178
wire [7:0] status_nxt = STATUS[0] ? per_din[15:8]     : per_din[7:0];
179
 
180
wire       status_tx_empty_pnd_clr = status_wr & status_nxt[7];
181
wire       status_tx_pnd_clr       = status_wr & status_nxt[6];
182
wire       status_rx_ovflw_pnd_clr = status_wr & status_nxt[5];
183
wire       status_rx_pnd_clr       = status_wr & status_nxt[4];
184
wire       status_tx_empty_pnd_set;
185
wire       status_tx_pnd_set;
186
wire       status_rx_ovflw_pnd_set;
187
wire       status_rx_pnd_set;
188
 
189
always @ (posedge mclk or posedge puc_rst)
190
  if (puc_rst)                      status_tx_empty_pnd <=  1'b0;
191
  else if (status_tx_empty_pnd_set) status_tx_empty_pnd <=  1'b1;
192
  else if (status_tx_empty_pnd_clr) status_tx_empty_pnd <=  1'b0;
193
 
194
always @ (posedge mclk or posedge puc_rst)
195
  if (puc_rst)                      status_tx_pnd       <=  1'b0;
196
  else if (status_tx_pnd_set)       status_tx_pnd       <=  1'b1;
197
  else if (status_tx_pnd_clr)       status_tx_pnd       <=  1'b0;
198
 
199
always @ (posedge mclk or posedge puc_rst)
200
  if (puc_rst)                      status_rx_ovflw_pnd <=  1'b0;
201
  else if (status_rx_ovflw_pnd_set) status_rx_ovflw_pnd <=  1'b1;
202
  else if (status_rx_ovflw_pnd_clr) status_rx_ovflw_pnd <=  1'b0;
203
 
204
always @ (posedge mclk or posedge puc_rst)
205
  if (puc_rst)                      status_rx_pnd       <=  1'b0;
206
  else if (status_rx_pnd_set)       status_rx_pnd       <=  1'b1;
207
  else if (status_rx_pnd_clr)       status_rx_pnd       <=  1'b0;
208
 
209
assign     status = {status_tx_empty_pnd, status_tx_pnd,   status_rx_ovflw_pnd, status_rx_pnd,
210
                     status_tx_full,      status_tx_busy,  1'b0,                status_rx_busy};
211
 
212 202 olivier.gi
 
213 157 olivier.gi
// BAUD_LO Register
214
//-----------------
215
reg  [7:0] baud_lo;
216
 
217
wire       baud_lo_wr  = BAUD_LO[0] ? reg_hi_wr[BAUD_LO] : reg_lo_wr[BAUD_LO];
218
wire [7:0] baud_lo_nxt = BAUD_LO[0] ? per_din[15:8]      : per_din[7:0];
219
 
220
always @ (posedge mclk or posedge puc_rst)
221
  if (puc_rst)         baud_lo <=  8'h00;
222
  else if (baud_lo_wr) baud_lo <=  baud_lo_nxt;
223
 
224
 
225
// BAUD_HI Register
226
//-----------------
227
reg  [7:0] baud_hi;
228
 
229
wire       baud_hi_wr  = BAUD_HI[0] ? reg_hi_wr[BAUD_HI] : reg_lo_wr[BAUD_HI];
230
wire [7:0] baud_hi_nxt = BAUD_HI[0] ? per_din[15:8]      : per_din[7:0];
231
 
232
always @ (posedge mclk or posedge puc_rst)
233
  if (puc_rst)         baud_hi <=  8'h00;
234 197 olivier.gi
  else if (baud_hi_wr) baud_hi <=  baud_hi_nxt;
235 157 olivier.gi
 
236
 
237
wire [15:0] baudrate = {baud_hi, baud_lo};
238
 
239 202 olivier.gi
 
240 157 olivier.gi
// DATA_TX Register
241
//-----------------
242
reg  [7:0] data_tx;
243
 
244
wire       data_tx_wr  = DATA_TX[0] ? reg_hi_wr[DATA_TX] : reg_lo_wr[DATA_TX];
245
wire [7:0] data_tx_nxt = DATA_TX[0] ? per_din[15:8]      : per_din[7:0];
246
 
247
always @ (posedge mclk or posedge puc_rst)
248
  if (puc_rst)         data_tx <=  8'h00;
249
  else if (data_tx_wr) data_tx <=  data_tx_nxt;
250
 
251
 
252
// DATA_RX Register
253
//-----------------
254
reg  [7:0] data_rx;
255
 
256
reg  [7:0] rxfer_buf;
257
 
258
always @ (posedge mclk or posedge puc_rst)
259
  if (puc_rst)                data_rx <=  8'h00;
260
  else if (status_rx_pnd_set) data_rx <=  rxfer_buf;
261
 
262
 
263
//============================================================================
264
// 4) DATA OUTPUT GENERATION
265
//============================================================================
266
 
267
// Data output mux
268
wire [15:0] ctrl_rd     = {8'h00, (ctrl     & {8{reg_rd[CTRL]}})}     << (8 & {4{CTRL[0]}});
269
wire [15:0] status_rd   = {8'h00, (status   & {8{reg_rd[STATUS]}})}   << (8 & {4{STATUS[0]}});
270
wire [15:0] baud_lo_rd  = {8'h00, (baud_lo  & {8{reg_rd[BAUD_LO]}})}  << (8 & {4{BAUD_LO[0]}});
271
wire [15:0] baud_hi_rd  = {8'h00, (baud_hi  & {8{reg_rd[BAUD_HI]}})}  << (8 & {4{BAUD_HI[0]}});
272
wire [15:0] data_tx_rd  = {8'h00, (data_tx  & {8{reg_rd[DATA_TX]}})}  << (8 & {4{DATA_TX[0]}});
273
wire [15:0] data_rx_rd  = {8'h00, (data_rx  & {8{reg_rd[DATA_RX]}})}  << (8 & {4{DATA_RX[0]}});
274
 
275
wire [15:0] per_dout  =  ctrl_rd    |
276
                         status_rd  |
277
                         baud_lo_rd |
278
                         baud_hi_rd |
279
                         data_tx_rd |
280
                         data_rx_rd;
281
 
282
 
283
//=============================================================================
284
// 5)  UART CLOCK SELECTION
285
//=============================================================================
286
 
287
wire uclk_en = ctrl_smclk_sel ? smclk_en : 1'b1;
288
 
289 202 olivier.gi
 
290 157 olivier.gi
//=============================================================================
291
// 5)  UART RECEIVE LINE SYNCHRONIZTION & FILTERING
292
//=============================================================================
293
 
294
// Synchronize RXD input
295
//--------------------------------
296
wire     uart_rxd_sync_n;
297
 
298
omsp_sync_cell sync_cell_uart_rxd (
299
    .data_out  (uart_rxd_sync_n),
300
    .data_in   (~uart_rxd),
301
    .clk       (mclk),
302
    .rst       (puc_rst)
303
);
304
wire uart_rxd_sync = ~uart_rxd_sync_n;
305 202 olivier.gi
 
306 157 olivier.gi
// RXD input buffer
307
//--------------------------------
308
reg  [1:0] rxd_buf;
309
always @ (posedge mclk or posedge puc_rst)
310
  if (puc_rst) rxd_buf <=  2'h3;
311
  else         rxd_buf <=  {rxd_buf[0], uart_rxd_sync};
312
 
313
// Majority decision
314
//------------------------
315
reg        rxd_maj;
316
 
317
wire [1:0] rxd_maj_cnt = {1'b0, uart_rxd_sync}   +
318
                         {1'b0, rxd_buf[0]}      +
319
                         {1'b0, rxd_buf[1]};
320
wire       rxd_maj_nxt = (rxd_maj_cnt>=2'b10);
321 202 olivier.gi
 
322 157 olivier.gi
always @ (posedge mclk or posedge puc_rst)
323
  if (puc_rst) rxd_maj <=  1'b1;
324
  else         rxd_maj <=  rxd_maj_nxt;
325
 
326
wire rxd_s  =  rxd_maj;
327
wire rxd_fe =  rxd_maj & ~rxd_maj_nxt;
328
 
329 202 olivier.gi
 
330 157 olivier.gi
//=============================================================================
331
// 6)  UART RECEIVE
332
//=============================================================================
333 202 olivier.gi
 
334 157 olivier.gi
// RX Transfer counter
335
//------------------------
336
reg  [3:0] rxfer_bit;
337
reg [15:0] rxfer_cnt;
338
 
339
wire       rxfer_start   = (rxfer_bit==4'h0) & rxd_fe;
340
wire       rxfer_bit_inc = (rxfer_bit!=4'h0) & (rxfer_cnt=={16{1'b0}});
341
wire       rxfer_done    = (rxfer_bit==4'ha);
342
 
343
always @ (posedge mclk or posedge puc_rst)
344
  if (puc_rst)                 rxfer_bit <=  4'h0;
345
  else if (~ctrl_en)           rxfer_bit <=  4'h0;
346
  else if (rxfer_start)        rxfer_bit <=  4'h1;
347
  else if (uclk_en)
348
    begin
349
       if (rxfer_done)         rxfer_bit <=  4'h0;
350
       else if (rxfer_bit_inc) rxfer_bit <=  rxfer_bit+4'h1;
351
    end
352
 
353
always @ (posedge mclk or posedge puc_rst)
354
  if (puc_rst)                 rxfer_cnt <=  {16{1'b0}};
355
  else if (~ctrl_en)           rxfer_cnt <=  {16{1'b0}};
356
  else if (rxfer_start)        rxfer_cnt <=  {1'b0, baudrate[15:1]};
357
  else if (uclk_en)
358
    begin
359
       if (rxfer_bit_inc)      rxfer_cnt <=  baudrate;
360
       else if (|rxfer_cnt)    rxfer_cnt <=  rxfer_cnt+{16{1'b1}};
361
    end
362
 
363
 
364
// Receive buffer
365
//-------------------------
366
wire [7:0] rxfer_buf_nxt =  {rxd_s, rxfer_buf[7:1]};
367
 
368
always @ (posedge mclk or posedge puc_rst)
369
  if (puc_rst)            rxfer_buf <=  8'h00;
370
  else if (~ctrl_en)      rxfer_buf <=  8'h00;
371
  else if (uclk_en)
372
    begin
373
       if (rxfer_bit_inc) rxfer_buf <=  rxfer_buf_nxt;
374
    end
375
 
376
 
377
// Status flags
378
//-------------------------
379
 
380
// Edge detection required for the case when
381
// the transmit base clock is SMCLK
382
reg rxfer_done_dly;
383
always @ (posedge mclk or posedge puc_rst)
384
  if (puc_rst) rxfer_done_dly <=  1'b0;
385
  else         rxfer_done_dly <=  rxfer_done;
386
 
387
 
388
assign  status_rx_pnd_set       = rxfer_done & ~rxfer_done_dly;
389
assign  status_rx_ovflw_pnd_set = status_rx_pnd_set & status_rx_pnd;
390
assign  status_rx_busy          = (rxfer_bit!=4'h0);
391
 
392
 
393
//============================================================================
394
// 5) UART TRANSMIT
395
//============================================================================
396
 
397
// TX Transfer start detection
398
//-----------------------------
399
reg        txfer_triggered;
400
wire       txfer_start;
401 202 olivier.gi
 
402 157 olivier.gi
always @ (posedge mclk or posedge puc_rst)
403
  if (puc_rst)          txfer_triggered <=  1'b0;
404
  else if (data_tx_wr)  txfer_triggered <=  1'b1;
405
  else if (txfer_start) txfer_triggered <=  1'b0;
406
 
407 202 olivier.gi
 
408 157 olivier.gi
// TX Transfer counter
409
//------------------------
410
reg  [3:0] txfer_bit;
411
reg [15:0] txfer_cnt;
412
 
413
assign     txfer_start   = (txfer_bit==4'h0) & txfer_triggered;
414
wire       txfer_bit_inc = (txfer_bit!=4'h0) & (txfer_cnt=={16{1'b0}});
415
wire       txfer_done    = (txfer_bit==4'hb);
416
 
417
always @ (posedge mclk or posedge puc_rst)
418
  if (puc_rst)                 txfer_bit <=  4'h0;
419
  else if (~ctrl_en)           txfer_bit <=  4'h0;
420
  else if (txfer_start)        txfer_bit <=  4'h1;
421
  else if (uclk_en)
422
    begin
423
       if (txfer_done)         txfer_bit <=  4'h0;
424
       else if (txfer_bit_inc) txfer_bit <=  txfer_bit+4'h1;
425
    end
426
 
427
always @ (posedge mclk or posedge puc_rst)
428
  if (puc_rst)                 txfer_cnt <=  {16{1'b0}};
429
  else if (~ctrl_en)           txfer_cnt <=  {16{1'b0}};
430
  else if (txfer_start)        txfer_cnt <=  baudrate;
431
  else if (uclk_en)
432
    begin
433
       if (txfer_bit_inc)      txfer_cnt <=  baudrate;
434
       else if (|txfer_cnt)    txfer_cnt <=  txfer_cnt+{16{1'b1}};
435
    end
436
 
437
 
438
// Transmit buffer
439
//-------------------------
440
reg  [8:0] txfer_buf;
441
 
442
wire [8:0] txfer_buf_nxt =  {1'b1, txfer_buf[8:1]};
443
 
444
always @ (posedge mclk or posedge puc_rst)
445
  if (puc_rst)            txfer_buf <=  9'h1ff;
446
  else if (~ctrl_en)      txfer_buf <=  9'h1ff;
447
  else if (txfer_start)   txfer_buf <=  {data_tx, 1'b0};
448
  else if (uclk_en)
449
    begin
450
       if (txfer_bit_inc) txfer_buf <=  txfer_buf_nxt;
451
    end
452
 
453
assign  uart_txd = txfer_buf[0];
454
 
455 202 olivier.gi
 
456 157 olivier.gi
// Status flags
457
//-------------------------
458
 
459
// Edge detection required for the case when
460
// the transmit base clock is SMCLK
461
reg txfer_done_dly;
462
always @ (posedge mclk or posedge puc_rst)
463
  if (puc_rst) txfer_done_dly <=  1'b0;
464
  else         txfer_done_dly <=  txfer_done;
465
 
466
 
467
assign  status_tx_pnd_set       = txfer_done & ~txfer_done_dly;
468
assign  status_tx_empty_pnd_set = status_tx_pnd_set & ~txfer_triggered;
469
assign  status_tx_busy          = (txfer_bit!=4'h0) | txfer_triggered;
470
assign  status_tx_full          = status_tx_busy & txfer_triggered;
471
 
472
 
473
//============================================================================
474
// 6) INTERRUPTS
475
//============================================================================
476
 
477
// Receive interrupt can be generated with the completion of a received byte
478
// or an overflow occures.
479
assign  irq_uart_rx    = (status_rx_pnd       & ctrl_ien_rx)        |
480
                         (status_rx_ovflw_pnd & ctrl_ien_rx_ovflw);
481
 
482
 
483
// Transmit interrupt can be generated with the transmition completion of
484
// a byte or when the tranmit buffer is empty (i.e. nothing left to transmit)
485
assign  irq_uart_tx    = (status_tx_pnd       & ctrl_ien_tx)        |
486
                         (status_tx_empty_pnd & ctrl_ien_tx_empty);
487
 
488 202 olivier.gi
 
489 157 olivier.gi
endmodule // uart

powered by: WebSVN 2.1.0

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