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

Subversion Repositories uart6551

[/] [uart6551/] [trunk/] [trunk/] [rtl/] [uart6551pci.sv] - Blame information for rev 13

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

Line No. Rev Author Line
1 11 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2005-2023  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//
9
// BSD 3-Clause License
10
// Redistribution and use in source and binary forms, with or without
11
// modification, are permitted provided that the following conditions are met:
12
//
13
// 1. Redistributions of source code must retain the above copyright notice, this
14
//    list of conditions and the following disclaimer.
15
//
16
// 2. Redistributions in binary form must reproduce the above copyright notice,
17
//    this list of conditions and the following disclaimer in the documentation
18
//    and/or other materials provided with the distribution.
19
//
20
// 3. Neither the name of the copyright holder nor the names of its
21
//    contributors may be used to endorse or promote products derived from
22
//    this software without specific prior written permission.
23
//
24
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
28
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
//
35
// 369 LUTs / 409 FFs
36
// ============================================================================
37
//
38
`define UART_ADDR               32'hFE000001
39
`define UART_TRB                2'd0    // transmit/receive buffer
40
`define UART_STAT               2'd1
41
`define UART_CMD                2'd2
42
`define UART_CTRL               2'd3
43
 
44
module uart6551pci(rst_i, clk_i, cs_config_i, cs_io_i, irq_o,
45
        cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
46
        cts_ni, rts_no, dsr_ni, dcd_ni, dtr_no, ri_ni,
47
        rxd_i, txd_o, data_present,
48
        rxDRQ_o, txDRQ_o,
49
        xclk_i, RxC_i
50
);
51
parameter pClkFreq = 100;
52
parameter pCounterBits = 24;
53
parameter pFifoSize = 1024;
54
parameter pClkDiv = 24'd1302;   // 9.6k baud, 200.000MHz clock
55
parameter HIGH = 1'b1;
56
parameter LOW = 1'b0;
57
 
58
parameter CFG_BUS = 8'd0;
59
parameter CFG_DEVICE = 5'd16;
60
parameter CFG_FUNC = 3'd0;
61
parameter CFG_VENDOR_ID =       16'h0;
62
parameter CFG_DEVICE_ID =       16'h0;
63
parameter CFG_SUBSYSTEM_VENDOR_ID       = 16'h0;
64
parameter CFG_SUBSYSTEM_ID = 16'h0;
65
parameter CFG_ROM_ADDR = 32'hFFFFFFF0;
66
 
67
parameter CFG_REVISION_ID = 8'd0;
68
parameter CFG_PROGIF = 8'd1;
69
parameter CFG_SUBCLASS = 8'h80;                                 // 80 = Other
70
parameter CFG_CLASS = 8'h03;                                            // 03 = display controller
71
parameter CFG_CACHE_LINE_SIZE = 8'd8;           // 32-bit units
72
parameter CFG_MIN_GRANT = 8'h00;
73
parameter CFG_MAX_LATENCY = 8'h00;
74
parameter CFG_IRQ_LINE = 8'd16;
75
 
76
localparam CFG_HEADER_TYPE = 8'h00;                     // 00 = a general device
77
 
78
parameter MSIX = 1'b0;
79
input rst_i;
80
input clk_i;                    // eg 50.000MHz
81
input cs_config_i;              // config region circuit select
82
input cs_io_i;          // IO region circuit select
83
// WISHBONE -------------------------------
84
input cyc_i;            // bus cycle valid
85
input stb_i;
86
output ack_o;
87
input we_i;                     // 1 = write
88
input [3:0] sel_i;
89
input [31:0] adr_i;     // register address
90
input [31:0] dat_i;     // data input bus
91
output reg [31:0] dat_o;        // data output bus
92
//------------------------------------------
93
output reg [31:0] irq_o;                // interrupt request
94
input cts_ni;                   // clear to send - (flow control) active low
95
output reg rts_no;              // request to send - (flow control) active low
96
input dsr_ni;   // data set ready - active low
97
input dcd_ni;   // data carrier detect - active low
98
output reg dtr_no;      // data terminal ready - active low
99
input ri_ni;            // ring indicator
100
input rxd_i;            // serial data in
101
output txd_o;           // serial data out
102
output data_present;
103
output rxDRQ_o; // reciever DMA request
104
output txDRQ_o; // transmitter DMA request
105
input xclk_i;           // external clock source
106
input RxC_i;            // external receiver clock source
107
 
108
reg [31:0] uart_addr;
109
reg accessCD;           // clock multiplier access flag
110
reg llb;                        // local loopback mode
111
reg dmaEnable;
112
// baud rate clock control
113
reg [4:0] baudRateSel;
114
reg selCD;                              // Use clock multiplier register
115
reg [pCounterBits-1:0] c;       // current count
116
reg [pCounterBits-1:0] ckdiv;   // baud rate clock divider
117
reg [pCounterBits-1:0] clkdiv;  // clock multiplier register
118
reg [1:0] xclks;        // synchronized external clock
119
reg [1:0] RxCs;         // synchronized external receiver clock
120
reg baud16;                     // 16x baud rate clock
121
wire baud16rx;          // reciever clock
122
reg xClkSrc;            // uart baud clock is external
123
reg rxClkSrc;           // receiver clock is external
124
 
125
// frame format registers
126
reg [3:0] wordLength;
127
reg stopBit;
128
reg [2:0] stopBits;
129
reg [2:0] parityCtrl;
130
wire [7:0] frameSize;
131
 
132
reg txBreak;            // transmit a break
133
 
134
wire rxFull;
135
wire rxEmpty;
136
wire txFull;
137
wire txEmpty;
138
reg hwfc;                       // hardware flow control enable
139
wire [7:0] lineStatusReg;
140
wire [7:0] modemStatusReg;
141
wire [7:0] irqStatusReg;
142
// interrupt
143
wire irq_en;            // global IRQ enable
144
reg irq;
145
reg rxIe;
146
reg txIe;
147
reg modemStatusChangeIe;
148
wire modemStatusChange;
149
reg lineStatusChangeIe;
150
wire lineStatusChange;
151
reg rxToutIe;           // receiver timeout interrupt enable
152
reg [3:0] rxThres;      // receiver threshold for interrupt
153
reg [3:0] txThres;      // transmitter threshold for interrupt
154
reg rxTout;                     // receiver timeout
155
wire [9:0] rxCnt;       // reciever counter value
156
reg [7:0] rxToutMax;
157
reg [2:0] irqenc;       // encoded irq cause
158
wire rxITrig;           // receiver interrupt trigger level
159
wire txITrig;           // transmitter interrupt trigger level
160
// reciever errors
161
wire parityErr;         // reciever detected a parity error
162
wire frameErr;          // receiver char framing error
163
wire overrun;           // receiver over run
164
wire rxBreak;           // reciever detected a break
165
wire rxGErr;            // global error: there is at least one error in the reciever fifo
166
// modem controls
167
reg [1:0] ctsx;         // cts_n sampling
168
reg [1:0] dcdx;
169
reg [1:0] dsrx;
170
reg [1:0] rix;
171
reg deltaCts;
172
reg deltaDcd;
173
reg deltaDsr;
174
reg deltaRi;
175
 
176
// fifo
177
reg rxFifoClear;
178
reg txFifoClear;
179
reg txClear;
180
reg fifoEnable;
181
wire [3:0] rxQued;
182
wire [3:0] txQued;
183
 
184
// config
185
reg [31:0] cfg_out;
186
 
187
// test
188
wire txd1;
189
 
190
assign data_present = ~rxEmpty;
191
 
192
assign rxITrig = rxQued >= rxThres;
193
assign txITrig = txQued <= txThres;
194
wire rxDRQ1 = (fifoEnable ? rxITrig : ~rxEmpty);
195
wire txDRQ1 = (fifoEnable ? txITrig : txEmpty);
196
assign rxDRQ_o = dmaEnable & rxDRQ1;
197
assign txDRQ_o = dmaEnable & txDRQ1;
198
wire rxIRQ = rxIe & rxDRQ1;
199
wire txIRQ = txIe & txDRQ1;
200
 
201
reg [7:0] cmd0, cmd1, cmd2, cmd3;
202
reg [7:0] ctrl0, ctrl1, ctrl2, ctrl3;
203
 
204
always_ff @(posedge clk_i)
205
        irq <= (
206
          rxIRQ
207
        | txIRQ
208
        | (rxTout & rxToutIe)
209
        | (lineStatusChange & lineStatusChangeIe)
210
        | (modemStatusChange & modemStatusChangeIe)
211
        ) & irq_en;
212
        ;
213
 
214
// Hold onto address and data an extra cycle.
215
// The extra cycle updates or reads the serial transmit / receive.
216
reg [31:0] dati;
217
always @(posedge clk_i)
218
        dati <= dat_i;
219
reg [31:0] adr_h;
220
always @(posedge clk_i)
221
        adr_h <= adr_i;
222
reg we;
223
always @(posedge clk_i)
224
        we <= we_i;
225
reg [3:0] sel;
226
always @(posedge clk_i)
227
        sel <= sel_i;
228
 
229
wire [7:0] rx_do;
230
wire rdrx = cs_io && ack_o && adr_h==`UART_TRB && ~we && !accessCD;
231
wire txrx = cs_io && ack_o && adr_h==`UART_TRB && !accessCD;
232
 
233
wire cs_config = cs_config_i & cyc_i & stb_i &&
234
        adr_i[27:20]==CFG_BUS &&
235
        adr_i[19:15]==CFG_DEVICE &&
236
        adr_i[14:12]==CFG_FUNC;
237
wire cs_io = cs_io_i & cyc_i & stb_i && adr_i[27:4]==uart_addr[27:4];
238
 
239
ack_gen #(
240
        .READ_STAGES(1),
241
        .WRITE_STAGES(0),
242
        .REGISTER_OUTPUT(1)
243
) uag1
244
(
245
        .rst_i(rst_i),
246
        .clk_i(clk_i),
247
        .ce_i(1'b1),
248
        .rid_i('d0),
249
        .wid_i('d0),
250
        .i((cs_config|cs_io) & ~we_i),
251
        .we_i((cs_config|cs_io) & we_i),
252
        .o(ack_o),
253
        .rid_o(),
254
        .wid_o()
255
);
256
 
257
pci32_config #(
258
        .CFG_BUS(CFG_BUS),
259
        .CFG_DEVICE(CFG_DEVICE),
260
        .CFG_FUNC(CFG_FUNC),
261
        .CFG_VENDOR_ID(CFG_VENDOR_ID),
262
        .CFG_DEVICE_ID(CFG_DEVICE_ID),
263
        .CFG_BAR0(`UART_ADDR),
264
        .CFG_SUBSYSTEM_VENDOR_ID(CFG_SUBSYSTEM_VENDOR_ID),
265
        .CFG_SUBSYSTEM_ID(CFG_SUBSYSTEM_ID),
266
        .CFG_ROM_ADDR(CFG_ROM_ADDR),
267
        .CFG_REVISION_ID(CFG_REVISION_ID),
268
        .CFG_PROGIF(CFG_PROGIF),
269
        .CFG_SUBCLASS(CFG_SUBCLASS),
270
        .CFG_CLASS(CFG_CLASS),
271
        .CFG_CACHE_LINE_SIZE(CFG_CACHE_LINE_SIZE),
272
        .CFG_MIN_GRANT(CFG_MIN_GRANT),
273
        .CFG_MAX_LATENCY(CFG_MAX_LATENCY),
274
        .CFG_IRQ_LINE(CFG_IRQ_LINE)
275
)
276
ucfg1
277
(
278
        .rst_i(rst_i),
279
        .clk_i(clk_i),
280
        .irq_i(irq),
281
        .irq_o(irq_o),
282
        .cs_config_i(cs_config),
283
        .we_i(we),
284
        .sel_i(sel),
285
        .adr_i(adr_h),
286
        .dat_i(dati),
287
        .dat_o(cfg_out),
288
        .bar0_o(uart_addr),
289
        .bar1_o(),
290
        .bar2_o(),
291
        .irq_en_o(irq_en)
292
);
293
 
294
uart6551Rx uart_rx0
295
(
296
        .rst(rst_i),
297
        .clk(clk_i),
298
        .cyc(cyc_i),
299
        .cs(rdrx),
300
        .wr(we),
301
        .dout(rx_do),
302
        .ack(),
303
        .fifoEnable(fifoEnable),
304
        .fifoClear(rxFifoClear),
305
        .clearGErr(1'b0),
306
        .wordLength(wordLength),
307
        .parityCtrl(parityCtrl),
308
        .frameSize(frameSize),
309
        .stop_bits(stopBits),
310
        .baud16x_ce(baud16rx),
311
        .clear(1'b0),
312
        .rxd(llb ? txd1 : rxd_i),
313
        .full(),
314
        .empty(rxEmpty),
315
        .frameErr(frameErr),
316
        .overrun(overrun),
317
        .parityErr(parityErr),
318
        .break_o(rxBreak),
319
        .gerr(rxGErr),
320
        .qcnt(rxQued),
321
        .cnt(rxCnt)
322
);
323
 
324
uart6551Tx uart_tx0
325
(
326
        .rst(rst_i),
327
        .clk(clk_i),
328
        .cyc(cyc_i),
329
        .cs(txrx),
330
        .wr(we),
331
        .din(dati[7:0]),
332
        .ack(),
333
        .fifoEnable(fifoEnable),
334
        .fifoClear(txFifoClear),
335
        .txBreak(txBreak),
336
        .frameSize(frameSize),  // 16 x 10 bits
337
        .wordLength(wordLength),// 8 bits
338
        .parityCtrl(parityCtrl),// no parity
339
        .baud16x_ce(baud16),
340
        .cts(ctsx[1]|~hwfc),
341
        .clear(txClear),
342
        .txd(txd1),
343
        .full(txFull),
344
        .empty(txEmpty),
345
        .qcnt(txQued)
346
);
347
 
348
assign txd_o = llb ? 1'b1 : txd1;
349
 
350
assign lineStatusReg = {rxGErr,1'b0,txFull,rxBreak,1'b0,1'b0,1'b0,1'b0};
351
assign modemStatusChange = deltaDcd|deltaRi|deltaDsr|deltaCts;  // modem status delta
352
assign modemStatusReg = {1'b0,~rix[1],1'b0,~ctsx[1],deltaDcd, deltaRi, deltaDsr, deltaCts};
353
assign irqStatusReg = {irq_o,2'b00,irqenc,2'b00};
354
 
355
// mux the reg outputs
356
always @(posedge clk_i)
357
if (cs_config)
358
        dat_o <= cfg_out;
359
else if (cs_io) begin
360
        case(adr_i)
361
        `UART_TRB:      dat_o <= accessCD ? {8'h0,clkdiv} : {24'h0,rx_do};      // receiver holding register
362
        `UART_STAT:     dat_o <= {irqStatusReg,modemStatusReg,lineStatusReg,irq_o,dsrx[1],dcdx[1],fifoEnable ? ~txFull : txEmpty,~rxEmpty,overrun,frameErr,parityErr};
363
        `UART_CMD:      dat_o <= {cmd3,cmd2,cmd1,cmd0};
364
        `UART_CTRL:     dat_o <= {ctrl3,ctrl2,ctrl1,ctrl0};
365
        endcase
366
end
367
else
368
        dat_o <= 'd0;
369
 
370
 
371
// register updates
372
always @(posedge clk_i)
373
if (rst_i) begin
374
        rts_no <= HIGH;
375
        dtr_no <= HIGH;
376
        // interrupts
377
        rxIe                            <= 1'b0;
378
        txIe                            <= 1'b0;
379
        modemStatusChangeIe     <= 1'b0;
380
        lineStatusChangeIe      <= 1'b0;
381
        hwfc                            <= 1'b0;
382
        modemStatusChangeIe     <= 1'b0;
383
        lineStatusChangeIe      <= 1'b0;
384
        dmaEnable                       <= 1'b0;
385
        // clock control
386
        baudRateSel <= 5'h0;
387
        rxClkSrc        <= 1'b0;                // ** 6551 defaults to zero (external receiver clock)
388
        clkdiv <= pClkDiv;
389
        // frame format
390
        wordLength      <= 4'd8;        // 8 bits
391
        stopBit         <= 1'b0;                // 1 stop bit
392
        parityCtrl      <= 3'd0;        // no parity
393
 
394
        txBreak         <= 1'b0;
395
        // Fifo control
396
        txFifoClear     <= 1'b1;
397
        rxFifoClear <= 1'b1;
398
        txClear <= 1'b1;
399
        fifoEnable      <= 1'b1;
400
        // Test
401
        llb                     <= 1'b0;
402
        selCD           <= 1'b0;
403
        accessCD   <= 1'b0;
404
end
405
else begin
406
 
407
        //llb <= 1'b1;
408
        rxFifoClear <= 1'b0;
409
        txFifoClear <= 1'b0;
410
        txClear <= 1'b0;
411
        ctrl2[1] <= 1'b0;
412
        ctrl2[2] <= 1'b0;
413
 
414
        if (cs_io & ack_o & we) begin
415
                case (adr_h)    // synopsys full_case parallel_case
416
 
417
                `UART_TRB:
418
                        if (accessCD) begin
419
                                clkdiv <= dati;
420
                                accessCD <= 1'b0;
421
                                ctrl3[7] <= 1'b0;
422
                        end
423
 
424
                // Writing to the status register does a software reset of some bits.
425
                `UART_STAT:
426
                        begin
427
                                dtr_no <= HIGH;
428
                                rxIe <= 1'b0;
429
                                rts_no <= HIGH;
430
                                txIe <= 1'b0;
431
                                txBreak <= 1'b0;
432
                                llb <= 1'b0;
433
                        end
434
                `UART_CMD:
435
      begin
436
        if (sel[0]) begin
437
                cmd0 <= dati[7:0];
438
                                        dtr_no <= ~dati[0];
439
                rxIe   <= ~dati[1];
440
                case(dati[3:2])
441
                2'd0:   begin rts_no <= 1'b1; txIe <= 1'b0; txBreak <= 1'b0; end
442
                2'd1: begin rts_no <= 1'b0; txIe <= 1'b1; txBreak <= 1'b0; end
443
                2'd2: begin rts_no <= 1'b0; txIe <= 1'b0; txBreak <= 1'b0; end
444
                2'd3: begin rts_no <= 1'b0; txIe <= 1'b0; txBreak <= 1'b1; end
445
                endcase
446
                llb <= dati[4];
447
          parityCtrl <= dati[7:5];    //000=none,001=odd,011=even,101=force 1,111 = force 0
448
        end
449
        if (sel[1]) begin
450
                cmd1 <= dati[15:8];
451
                lineStatusChangeIe  <= dati[8];
452
                modemStatusChangeIe <= dati[9];
453
                rxToutIe <= dati[10];
454
        end
455
        if (sel[2])
456
                cmd2 <= dati[23:16];
457
        if (sel[3])
458
                cmd3 <= dati[31:24];
459
      end
460
 
461
    `UART_CTRL:
462
        begin
463
                if (sel[0]) begin
464
                        ctrl0 <= dati[7:0];
465
                baudRateSel[3:0] <= dati[3:0];
466
                                        rxClkSrc <= dati[4];                            // 1 = baud rate generator, 0 = external
467
          //11=5,10=6,01=7,00=8
468
          case(dati[6:5])
469
          2'd0: wordLength <= 6'd8;
470
          2'd1: wordLength <= 6'd7;
471
          2'd2: wordLength <= 6'd6;
472
          2'd3: wordLength <= 6'd5;
473
                endcase
474
          stopBit    <= dati[7];      //0=1,1=1.5 or 2
475
        end
476
                // Extended word length, values beyond 11 not supported.
477
        if (sel[1]) begin
478
                ctrl1 <= dati[15:8];
479
        end
480
        if (sel[2]) begin
481
                ctrl2 <= dati[23:16];
482
                fifoEnable <= dati[16];
483
                rxFifoClear <= dati[17];
484
                txFifoClear <= dati[18];
485
                case (dati[21:20])
486
                2'd0:   txThres <= 4'd1;                // one-byte
487
                2'd1:   txThres <= pFifoSize / 4;       // one-quarter full
488
                2'd2:   txThres <= pFifoSize / 2;       // one-half full
489
                2'd3:   txThres <= pFifoSize * 3 / 4;   // three-quarters full
490
                endcase
491
                case (dati[23:22])
492
                2'd0:   rxThres <= 4'd1;                // one-byte
493
                2'd1:   rxThres <= pFifoSize / 4;       // one-quarter full
494
                2'd2:   rxThres <= pFifoSize / 2;       // one-half full
495
                2'd3:   rxThres <= pFifoSize * 3 / 4;   // three quarters full
496
                endcase
497
        end
498
        if (sel[3]) begin
499
                ctrl3 <= dati[31:24];
500
                                        hwfc <= dati[24];
501
                                        dmaEnable <= dati[26];
502
                baudRateSel[4] <= dati[27];
503
                txClear <= dati[29];
504
                selCD <= dati[30];
505
                accessCD <= dati[31];
506
        end
507
      end
508
 
509
                default:
510
                        ;
511
                endcase
512
        end
513
end
514
 
515
// ----------------------------------------------------------------------------
516
// Baud rate control.
517
// ----------------------------------------------------------------------------
518
 
519
always @(posedge clk_i)
520
        xClkSrc <= baudRateSel==5'd0;
521
 
522
wire [pCounterBits-1:0] bclkdiv;
523
uart6551BaudLUT #(.pClkFreq(pClkFreq), .pCounterBits(pCounterBits)) ublt1 (.a(baudRateSel), .o(bclkdiv));
524
 
525
reg [pCounterBits-1:0] clkdiv2;
526
always @(posedge clk_i)
527
        clkdiv2 <= selCD ? clkdiv : bclkdiv;
528
 
529
always @(posedge clk_i)
530
if (rst_i)
531
        c <= 24'd1;
532
else begin
533
        c <= c + 2'd1;
534
        if (c >= clkdiv2)
535
                c <= 2'd1;
536
end
537
 
538
// for detecting an edge on the baud clock
539
wire ibaud16 = c == 2'd1;
540
 
541
// Detect an edge on the external clock
542
wire xclkEdge;
543
edge_det ed1(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(xclks[1]), .pe(xclkEdge), .ne() );
544
 
545
// Detect an edge on the external clock
546
wire rxClkEdge;
547
edge_det ed2(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(RxCs[1]), .pe(rxClkEdge), .ne() );
548
 
549
always_comb
550
if (xClkSrc)            // 16x external clock (xclk)
551
        baud16 <= xclkEdge;
552
else
553
        baud16 <= ibaud16;
554
 
555
assign baud16rx = rxClkSrc ? baud16 : rxClkEdge;
556
 
557
//------------------------------------------------------------
558
// external signal synchronization
559
//------------------------------------------------------------
560
 
561
// External receiver clock
562
always @(posedge clk_i)
563
        RxCs <= {RxCs[1:0],RxC_i};
564
 
565
// External baud clock
566
always @(posedge clk_i)
567
        xclks <= {xclks[1:0],xclk_i};
568
 
569
 
570
always @(posedge clk_i)
571
        ctsx <= {ctsx[0],llb?~rts_no:~cts_ni};
572
 
573
always @(posedge clk_i)
574
        dcdx <= {dcdx[0],~dcd_ni};
575
 
576
always @(posedge clk_i)
577
        dsrx <= {dsrx[0],llb?~dtr_no:~dsr_ni};
578
 
579
always @(posedge clk_i)
580
        rix <= {rix[0],~ri_ni};
581
 
582
//------------------------------------------------------------
583
// state change detectors
584
//------------------------------------------------------------
585
 
586
wire ne_stat;
587
edge_det ued3 (
588
        .rst(rst_i),
589
        .clk(clk_i),
590
        .ce(1'b1),
591
        .i(ack_o && adr_i==`UART_STAT && ~we_i && sel_i[2]),
592
        .pe(),
593
        .ne(ne_stat),
594
        .ee()
595
);
596
 
597
// detect a change on the dsr signal
598
always @(posedge clk_i)
599
if (rst_i)
600
        deltaDsr <= 1'b0;
601
else begin
602
        if (ne_stat)
603
                deltaDsr <= 0;
604
        else if (~deltaDsr)
605
                deltaDsr <= dsrx[1] ^ dsrx[0];
606
end
607
 
608
// detect a change on the dcd signal
609
always @(posedge clk_i)
610
if (rst_i)
611
        deltaDcd <= 1'b0;
612
else begin
613
        if (ne_stat)
614
                deltaDcd <= 0;
615
        else if (~deltaDcd)
616
                deltaDcd <= dcdx[1] ^ dcdx[0];
617
end
618
 
619
// detect a change on the cts signal
620
always @(posedge clk_i)
621
if (rst_i)
622
        deltaCts <= 1'b0;
623
else begin
624
        if (ne_stat)
625
                deltaCts <= 0;
626
        else if (~deltaCts)
627
                deltaCts <= ctsx[1] ^ ctsx[0];
628
end
629
 
630
// detect a change on the ri signal
631
always @(posedge clk_i)
632
if (rst_i)
633
        deltaRi <= 1'b0;
634
else begin
635
        if (ne_stat)
636
                deltaRi <= 0;
637
        else if (~deltaRi)
638
                deltaRi <= rix[1] ^ rix[0];
639
end
640
 
641
// detect a change in line status
642
reg [7:0] pLineStatusReg;
643
always @(posedge clk_i)
644
        pLineStatusReg <= lineStatusReg;
645
 
646
assign lineStatusChange = pLineStatusReg != lineStatusReg;
647
 
648
//-----------------------------------------------------
649
 
650
// compute recieve timeout
651
always @(wordLength)
652
        rxToutMax <= (wordLength << 2) + 6'd12;
653
 
654
always @(posedge clk_i)
655
if (rst_i)
656
        rxTout <= 1'b0;
657
else begin
658
        // read of receiver clears timeout counter
659
        if (rdrx)
660
                rxTout <= 1'b0;
661
        // Don't time out if the fifo is empty
662
        else if (rxCnt[9:4]==rxToutMax && ~rxEmpty)
663
                rxTout <= 1'b1;
664
end
665
 
666
 
667
//-----------------------------------------------------
668
// compute the 2x number of stop bits
669
always @*
670
if (stopBit==1'b0)          // one stop bit
671
        stopBits <= 3'd2;
672
else if (wordLength==6'd8 && parityCtrl != 3'd0)
673
        stopBits <= 3'd2;
674
else if (wordLength==6'd5 && parityCtrl == 3'd0)        // 5 bits - 1 1/2 stop bit
675
        stopBits <= 3'd3;
676
else
677
        stopBits <= 3'd4;          // two stop bits
678
 
679
 
680
// compute frame size
681
// frame size is one less
682
assign frameSize = {wordLength + 4'd1 + stopBits[2:1] + parityCtrl[0], stopBits[0],3'b0} - 1;
683
 
684
//-----------------------------------------------------
685
// encode IRQ mailbox
686
always @(rxDRQ_o or rxTout or txDRQ_o or lineStatusChange or modemStatusChange)
687
        irqenc <=
688
                lineStatusChange ? 3'd0 :
689
                ~rxDRQ_o ? 3'd1 :
690
                rxTout ? 3'd2 :
691
                ~txDRQ_o ? 3'd3 :
692
                modemStatusChange ? 3'd4 :
693
                3'd0;
694
 
695
endmodule

powered by: WebSVN 2.1.0

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