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

Subversion Repositories tv80

[/] [tv80/] [trunk/] [rtl/] [uart/] [T16450.v] - Blame information for rev 90

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 71 ghutchis
//
2
// 16450 compatible UART with synchronous bus interface
3
// rclk/baudout is clk enable instead of actual clock
4
//
5
// Copyright (c) 2005 Guy Hutchison (ghutchis@opencores.org)
6
// Based on VHDL 16450 UART by Daniel Wallner
7
//
8
// Permission is hereby granted, free of charge, to any person obtaining a 
9
// copy of this software and associated documentation files (the "Software"), 
10
// to deal in the Software without restriction, including without limitation 
11
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
12
// and/or sell copies of the Software, and to permit persons to whom the 
13
// Software is furnished to do so, subject to the following conditions:
14
//
15
// The above copyright notice and this permission notice shall be included 
16
// in all copies or substantial portions of the Software.
17
//
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
19
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
20
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
21
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
22
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
23
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
24
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 
26
module T16450
27
  (
28
   input reset_n,
29
   input clk,
30
   input rclk,
31
   input cs_n,
32
   input rd_n,
33
   input wr_n,
34
   input [2:0] addr,
35
   input [7:0] wr_data,
36
   output reg [7:0] rd_data,
37
   input sin,
38
   input cts_n,
39
   input dsr_n,
40
   input ri_n,
41
   input dcd_n,
42
   output reg sout,
43
   output reg rts_n,
44
   output reg dtr_n,
45
   output reg out1_n,
46
   output reg out2_n,
47
   output reg baudout,
48
   output reg intr
49
   );
50
 
51
  reg [7:0] RBR;        // Reciever Buffer Register
52
  reg [7:0] THR;        // Transmitter Holding Register
53
  reg [7:0] IER;        // Interrupt Enable Register
54
  reg [7:0] IIR;        // Interrupt Ident. Register
55
  reg [7:0] LCR;        // Line Control Register
56
  reg [7:0] MCR;        // MODEM Control Register
57
  reg [7:0] LSR;        // Line Status Register
58
  reg [7:0] MSR;        // MODEM Status Register
59
  reg [7:0] SCR;        // Scratch Register
60
  reg [7:0] DLL;        // Divisor Latch (LS)
61
  reg [7:0] DLM;        // Divisor Latch (MS)
62
 
63
  reg [7:0] DM0;
64
  reg [7:0] DM1;
65
 
66
  reg [3:0] MSR_In;
67
 
68
  reg [3:0] Bit_Phase;
69
  reg [3:0] Brk_Cnt;
70
  reg       RX_Filtered;
71
  reg [7:0] RX_ShiftReg;
72
  reg [3:0] RX_Bit_Cnt;
73
  reg       RX_Parity;
74
  reg       RXD;
75
 
76
  reg       TX_Tick;
77
  reg [7:0] TX_ShiftReg;
78
  reg [3:0] TX_Bit_Cnt;
79
  reg       TX_Parity;
80
  reg       TX_Next_Is_Stop;
81
  reg       TX_Stop_Bit;
82
  reg       TXD;
83
 
84
  always @*
85
    begin
86
      dtr_n = MCR[4] || ~ MCR[0];
87
      rts_n = MCR[4] || ~ MCR[1];
88
      out1_n = MCR[4] || ~ MCR[2];
89
      out2_n = MCR[4] || ~ MCR[3];
90
      sout = MCR[4] || (TXD && ~ LCR[6]);
91
      if (!MCR[4]) RXD = sin;
92
      else RXD = (TXD && !LCR[6]);
93
 
94
      intr = ~IIR[0];
95
 
96
      if (LCR[7])
97
        begin
98
          DM0 = DLL;
99
          DM1 = DLM;
100
        end
101
      else
102
        begin
103
          DM0 = RBR;
104
          DM1 = IER;
105
        end
106
 
107
      case (addr)
108
        3'h0 : rd_data = DM0;
109
        3'h1 : rd_data = DM1;
110
        3'h2 : rd_data = IIR;
111
        3'h3 : rd_data = LCR;
112
        3'h4 : rd_data = MCR;
113
        3'h5 : rd_data = LSR;
114
        3'h6 : rd_data = MSR;
115
        default : rd_data = SCR;
116
      endcase
117
    end
118
 
119
  always @ (posedge clk)
120
    begin
121
      if (!reset_n)
122
        begin
123
          THR <= #1 8'b00000000;
124
          IER <= #1 8'b00000000;
125
          LCR <= #1 8'b00000000;
126
          MCR <= #1 8'b00000000;
127
          MSR[3:0] <= #1 4'b0000;
128
          SCR <= #1 8'b00000000;
129
          DLL <= #1 8'b00000000;
130
          DLM <= #1 8'b00000000;
131
        end
132
      else
133
        begin
134
          if (!wr_n && !cs_n )
135
            begin
136
              case (addr)
137
                3'b000  :
138
                  begin
139
                    if (LCR[7])
140
                      DLL <= #1 wr_data;
141
                    else
142
                      THR <= #1 wr_data;
143
                  end
144
                3'b001  :
145
                  begin
146
                    if (LCR[7])
147
                      DLM <= #1 wr_data;
148
                    else
149
                      IER[3:0] <= #1 wr_data[3:0];
150
                  end
151
                3'b011  : LCR <= #1 wr_data;
152
                3'b100  : MCR <= #1 wr_data;
153
                3'b111  : SCR <= #1 wr_data;
154
                default : ;
155
              endcase
156
            end
157
          if (!rd_n && !cs_n && (addr == 3'b110))
158
            MSR[3:0] <= #1 4'b0000;
159
          if (MSR[4] != MSR_In[0])
160
            MSR[0] <= #1 1'b1;
161
          if (MSR[5] != MSR_In[1])
162
            MSR[1] <= #1 1'b1;
163
          if (!MSR[6] && MSR_In[2])
164
            MSR[2] <= #1 1'b1;
165
          if (MSR[7] != MSR_In[3])
166
            MSR[3] <= #1 1'b1;
167
        end
168
    end
169
  always @ (posedge clk)
170
    begin
171
      if (!MCR[4])
172
        begin
173
          MSR[4] <= #1 MSR_In[0];
174
          MSR[5] <= #1 MSR_In[1];
175
          MSR[6] <= #1 MSR_In[2];
176
          MSR[7] <= #1 MSR_In[3];
177
        end
178
      else
179
        begin
180
          MSR[4] <= #1 MCR[1];
181
          MSR[5] <= #1 MCR[0];
182
          MSR[6] <= #1 MCR[2];
183
          MSR[7] <= #1 MCR[3];
184
        end
185
      MSR_In[0] <= #1 cts_n;
186
      MSR_In[1] <= #1 dsr_n;
187
      MSR_In[2] <= #1 ri_n;
188
      MSR_In[3] <= #1 dcd_n;
189
    end
190
 
191
  always @*
192
    begin
193 90 ghutchis
      IIR[7:3] = #1 5'b00000;
194 71 ghutchis
      if (IER[2] && (LSR[4:1] != 4'b0000))
195 90 ghutchis
        IIR[2:0] = #1 3'b110;
196 71 ghutchis
      else if (IER[0] && LSR[0])
197 90 ghutchis
        IIR[2:0] = #1 3'b100;
198 71 ghutchis
      else if (IER[1] && LSR[5])
199 90 ghutchis
        IIR[2:0] = #1 3'b010;
200 71 ghutchis
      else if (IER[3] && ((!MCR[4] && (MSR[3:0] != 0)) || (MCR[4] && (MCR[3:0] != 0))))
201 90 ghutchis
        IIR[2:0] = #1 3'b000;
202 71 ghutchis
      else
203 90 ghutchis
        IIR[2:0] = #1 3'b001;
204 71 ghutchis
    end
205
 
206
  // Baud x 16 clock generator
207
  always @ (posedge clk)
208
    begin : clk_gen
209
      reg [15:0] Baud_Cnt;
210
      if (!reset_n)
211
        begin
212
          Baud_Cnt = 16'b0000000000000000;
213
          baudout <= #1 1'b0;
214
        end
215
      else
216
        begin
217
          if ((Baud_Cnt[15:1] == 15'h0) ||
218
              (!wr_n && !cs_n && (addr[2:1] == 2'b00) && LCR[7]) )
219
            begin
220
              Baud_Cnt[15:8] = DLM;
221
              Baud_Cnt[7:0] = DLL;
222
              baudout <= #1 1'b1;
223
            end
224
          else
225
            begin
226
              Baud_Cnt = Baud_Cnt - 1;
227
              baudout <= #1 1'b0;
228
            end
229
        end
230
    end
231
 
232
  // Input filter
233
  always @ (posedge clk)
234
    begin : input_filter
235
      reg [1:0] Samples;
236
      if (!reset_n)
237
        begin
238
          Samples = 2'b11;
239
          RX_Filtered <= #1 1'b1;
240
        end
241
      else
242
        begin
243
          if (rclk)
244
            begin
245
              Samples[1] = Samples[0];
246
              Samples[0] = RXD;
247
            end
248
          if (Samples == 2'b00)
249
            begin
250
              RX_Filtered <= #1 1'b0;
251
            end
252
          if (Samples == 2'b11)
253
            begin
254
              RX_Filtered <= #1 1'b1;
255
            end
256
        end
257
    end
258
 
259
  // Receive state machine
260
  always @ (posedge clk)
261
    begin
262
      if (!reset_n)
263
        begin
264
          RBR <= #1 8'b00000000;
265
          LSR[4:0] <= #1 5'b00000;
266
          Bit_Phase <= #1 4'b0000;
267
          Brk_Cnt <= #1 4'b0000;
268
          RX_ShiftReg[7:0] <= #1 8'b00000000;
269
          RX_Bit_Cnt <= #1 0;
270
          RX_Parity <= #1 1'b0;
271
        end
272
      else
273
        begin
274 78 ghutchis
          if (addr == 3'b000 && !LCR[7] && !rd_n && !cs_n )
275 71 ghutchis
            begin
276
              LSR[0] <= #1 1'b0;   // DR
277
            end
278
          if (addr == 3'b101 && !rd_n && !cs_n )
279
            begin
280
              LSR[4] <= #1 1'b0;   // BI
281
              LSR[3] <= #1 1'b0;   // FE
282
              LSR[2] <= #1 1'b0;   // PE
283
              LSR[1] <= #1 1'b0;   // OE
284
            end
285
          if (rclk)
286
            begin
287 90 ghutchis
              if ((RX_Bit_Cnt == 0) && (RX_Filtered || (Bit_Phase == 4'b0111)))
288 71 ghutchis
                begin
289
                  Bit_Phase <= #1 4'b0000;
290
                end
291
              else
292
                begin
293
                  Bit_Phase <= #1 Bit_Phase + 1;
294
                end
295
              if (Bit_Phase == 4'b1111 )
296
                begin
297
                  if (RX_Filtered)
298
                    begin
299
                      Brk_Cnt <= #1 4'b0000;
300
                    end
301
                  else
302
                    begin
303
                      Brk_Cnt <= #1 Brk_Cnt + 1;
304
                    end
305
                  if (Brk_Cnt == 4'b1100)
306
                    begin
307
                      LSR[4] <= #1 1'b1;     // BI
308
                    end
309
                end
310 90 ghutchis
              if (RX_Bit_Cnt == 0)
311 71 ghutchis
                begin
312
                  if (Bit_Phase == 4'b0111)
313
                    begin
314
                      RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
315
                      RX_Parity <= #1 ! LCR[4];    // EPS
316
                    end
317
                end
318
              else if (Bit_Phase == 4'b1111)
319
                begin
320
                  RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
321
                  if (RX_Bit_Cnt == 10 )
322
                    begin // Parity stop bit
323
                      RX_Bit_Cnt <= #1 0;
324
                      LSR[0] <= #1 1'b1; // UART Receive complete
325
                      LSR[3] <= #1 ~RX_Filtered; // Framing error
326
                    end
327
                  else if ((RX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
328
                           (RX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
329
                           (RX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
330
                           (RX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
331
                    begin // Stop bit/Parity
332
                      RX_Bit_Cnt <= #1 0;
333
                      if (LCR[3])
334
                        begin   // PEN
335
                          RX_Bit_Cnt <= #1 10;
336
                          if (LCR[5])
337
                            begin       // Stick parity
338
                              if (RX_Filtered == LCR[4])
339
                                begin
340
                                  LSR[2] <= #1 1'b1;
341
                                end
342
                            end
343
                          else
344
                            begin
345
                              if (RX_Filtered != RX_Parity)
346
                                begin
347
                                  LSR[2] <= #1 1'b1;
348
                                end
349
                            end
350
                        end
351
                      else
352
                        begin
353
                          LSR[0] <= #1 1'b1; // UART Receive complete
354
                          LSR[3] <= #1 ~RX_Filtered; // Framing error
355
                        end
356
                      RBR <= #1 RX_ShiftReg[7:0];
357
                      LSR[1] <= #1 LSR[0];
358
                      if (addr == 3'b101 && !rd_n && !cs_n )
359
                        begin
360
                          LSR[1] <= #1 1'b0;
361
                        end
362
                    end
363
                  else
364
                    begin
365
                      RX_ShiftReg[6:0] <= #1 RX_ShiftReg[7:1];
366
                      RX_ShiftReg[7] <= #1 RX_Filtered;
367
                      if (LCR[1:0] == 2'b10)
368
                        begin
369
                          RX_ShiftReg[7] <= #1 1'b0;
370
                          RX_ShiftReg[6] <= #1 RX_Filtered;
371
                        end
372
                      if (LCR[1:0] == 2'b01)
373
                        begin
374
                          RX_ShiftReg[7] <= #1 1'b0;
375
                          RX_ShiftReg[6] <= #1 1'b0;
376
                          RX_ShiftReg[5] <= #1 RX_Filtered;
377
                        end
378
                      if (LCR[1:0] == 2'b00)
379
                        begin
380
                          RX_ShiftReg[7] <= #1 1'b0;
381
                          RX_ShiftReg[6] <= #1 1'b0;
382
                          RX_ShiftReg[5] <= #1 1'b0;
383
                          RX_ShiftReg[4] <= #1 RX_Filtered;
384
                        end
385
                      RX_Parity <= #1 RX_Filtered ^ RX_Parity;
386
                    end
387
                end
388
            end
389
        end
390
    end
391
 
392
  // Transmit bit tick
393
  always @ (posedge clk)
394
    begin : bit_tick
395
      reg [4:0] TX_Cnt;
396
      if (!reset_n)
397
        begin
398
          TX_Cnt = 5'b00000;
399
          TX_Tick <= #1 1'b0;
400
        end
401
      else
402
        begin
403
          TX_Tick <= #1 1'b0;
404
          if (rclk)
405
            begin
406
              TX_Cnt = TX_Cnt + 1;
407
              if (LCR[2] && TX_Stop_Bit)
408
                begin
409
                  if (LCR[1:0] == 2'b00)
410
                    begin
411
                      if (TX_Cnt == 5'b10111)
412
                        begin
413
                          TX_Tick <= #1 1'b1;
414
                          TX_Cnt[3:0] = 4'b0000;
415
                        end
416
                    end
417
                  else
418
                    begin
419
                      if (TX_Cnt == 5'b11111)
420
                        begin
421
                          TX_Tick <= #1 1'b1;
422
                          TX_Cnt[3:0] = 4'b0000;
423
                        end
424
                    end
425
                end
426
              else
427
                begin
428
                  TX_Cnt[4] = 1'b1;
429
                  if (TX_Cnt[3:0] == 4'b1111)
430
                    begin
431
                      TX_Tick <= #1 1'b1;
432
                    end
433
                end
434
            end
435
        end
436
    end
437
 
438
  // Transmit state machine
439
  always @ (posedge clk)
440
    begin
441
      if (!reset_n)
442
        begin
443
          LSR[7:5] <= #1 3'b011;
444
          TX_Bit_Cnt <= #1 0;
445
          TX_ShiftReg <= #1 0;
446
          TXD <= #1 1'b1;
447
          TX_Parity <= #1 1'b0;
448
          TX_Next_Is_Stop <= #1 1'b0;
449
          TX_Stop_Bit <= #1 1'b0;
450
        end
451
      else
452
        begin
453
          if (TX_Tick == 1'b1)
454
            begin
455
              TX_Next_Is_Stop <= #1 1'b0;
456
              TX_Stop_Bit <= #1 TX_Next_Is_Stop;
457
              case (TX_Bit_Cnt)
458
 
459
                  begin
460
                    if (!LSR[5])
461
                      begin     // THRE
462
                        TX_Bit_Cnt <= #1 1;
463
                      end
464
                    TXD <= #1 1'b1;
465
                  end
466
                1  : // Start bit
467
                  begin
468
                    TX_ShiftReg[7:0] <= #1 THR;
469
                    LSR[5] <= #1 1'b1;     // THRE
470
                    TXD <= #1 1'b0;
471
                    TX_Parity <= #1 ~LCR[4];       // EPS
472
                    TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
473
                  end
474
                10  : // Parity bit
475
                  begin
476
                    TXD <= #1 TX_Parity;
477
                    if (LCR[5] == 1'b1 )
478
                      begin  // Stick parity
479
                        TXD <= #1 ~LCR[4];
480
                      end
481
                    TX_Bit_Cnt <= #1 0;
482
                    TX_Next_Is_Stop <= #1 1'b1;
483
                  end
484
                default :
485
                  begin
486
                    TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
487
                    if ((TX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
488
                        (TX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
489
                        (TX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
490
                        (TX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
491
                      begin
492
                        TX_Bit_Cnt <= #1 0;
493
                        if (LCR[3] == 1'b1 )
494
                          begin // PEN
495
                            TX_Bit_Cnt <= #1 10;
496
                          end
497
                        else
498
                          begin
499
                            TX_Next_Is_Stop <= #1 1'b1;
500
                          end
501
                        LSR[6] <= #1 1'b1; // TEMT
502
                      end
503
                    TXD <= #1 TX_ShiftReg[0];
504
                    TX_ShiftReg[6:0] <= #1 TX_ShiftReg[7:1];
505
                    TX_Parity <= #1 TX_ShiftReg[0] ^ TX_Parity;
506
                  end
507
              endcase
508
            end
509
          if (!wr_n && !cs_n && addr == 3'b000 && !LCR[7] )
510
            begin
511
              LSR[5] <= #1 1'b0;   // THRE
512
              LSR[6] <= #1 1'b0;   // TEMT
513
            end
514
        end
515
    end
516
 
517
endmodule
518
 

powered by: WebSVN 2.1.0

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