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

Subversion Repositories uart6551

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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