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

Subversion Repositories uart6551

[/] [uart6551/] [trunk/] [trunk/] [rtl/] [uart6551Rx_x12.sv] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2005-2022  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
// ============================================================================
36
//
37
`define IDLE    0
38
`define CNT             1
39
 
40
module uart6551Rx_x12(rst, clk,
41
        cyc, cs, wr, dout, ack,
42
        fifoEnable, fifoClear, clearGErr,
43
        parityCtrl, frameSize, stop_bits, wordLength, baud16x_ce, clear, rxd,
44
        full, empty, frameErr, overrun, parityErr, break_o, gerr, qcnt, cnt, bitStream);
45
input rst;
46
input clk;
47
input cyc;                              // valid bus cycle
48
input cs;                               // core select
49
input wr;                               // read reciever
50
output [11:0] dout;             // fifo data out
51
output ack;
52
input fifoEnable;               // enable the fifo
53
input fifoClear;
54
input clearGErr;                // clear global error
55
input [2:0] parityCtrl;
56
input [8:0] frameSize;  // frame count
57
input [2:0] stop_bits;
58
input [3:0] wordLength;
59
input baud16x_ce;               // baud rate clock enable
60
input clear;                    // clear reciever
61
input rxd;                              // external serial input
62
output full;                    // receive fifo full
63
output empty;           // receiver fifo is empty
64
output frameErr;                // framing error
65
output overrun;                 // receiver overrun
66
output parityErr;               // parity error
67
output break_o;                 // break detected
68
output gerr;                    // global error indicator
69 6 robfinch
output [5:0] qcnt;              // count of number of words queued
70 5 robfinch
output [10:0] cnt;              // receiver counter
71
output bitStream;               // received bit stream
72
 
73
//0 - simple sampling at middle of symbol period
74
//>0 - sampling of 3 middle ticks of sumbol perion and results as majority
75
parameter SamplerStyle = 0;
76
 
77
 
78
reg overrun;
79
reg [10:0] cnt;                 // sample bit rate counter / timeout counter
80
reg [14:0] rx_data;             // working receive data register
81
reg [13:0] t4;                  // data minus stop bit(s)
82
reg [11:0] t3;                  // data minus parity bit and start bit
83
reg [11:0] t5;
84
reg [3:0] shft_amt;
85
reg p1;
86
reg gerr;                               // global error status
87
reg perr;                               // parity error
88
reg ferr = 1'b0;                                // framing error
89
wire bz;                                // break detected
90
reg state;                              // state machine
91
reg wf;                                 // fifo write
92
wire empty;
93
reg didRd;
94
wire [11:0] dout1;
95
reg full1;
96
wire fifoFull, fifoEmpty;
97
 
98 6 robfinch
ack_gen #(
99
        .READ_STAGES(1),
100
        .WRITE_STAGES(0),
101
        .REGISTER_OUTPUT(1)
102
) uag1
103
(
104
        .rst_i(rst),
105
        .clk_i(clk),
106
        .ce_i(1'b1),
107
        .i(cs & cyc & ~wr),
108
        .we_i(cs & cyc & wr),
109
        .o(ack),
110
        .rid_i(0),
111
        .wid_i(0),
112
        .rid_o(),
113
        .wid_o()
114
);
115
 
116 5 robfinch
wire pe_rd, pe_wf;
117 6 robfinch
edge_det ued1 (.rst(rst), .clk(clk), .ce(1'b1), .i(cs & cyc & ~wr), .pe(pe_rd), .ne(), .ee());
118 5 robfinch
edge_det ued2 (.rst(rst), .clk(clk), .ce(1'b1), .i(wf), .pe(pe_wf), .ne(), .ee());
119
 
120
assign bitStream = rx_data[14];
121
assign bz = t3==12'd0;
122
wire rdf = fifoEnable ? pe_rd : pe_wf;
123
 
124 6 robfinch
// Distributed RAM fifo (vendor supplied):
125
//      First word fall-through
126
//      64 entries deep
127
//      15 bits wide
128
uart6551RxFifo uf1
129 5 robfinch
(
130
        .clk(clk),
131 6 robfinch
        .srst(rst|clear|fifoClear),
132
        .wr_en(wf),
133
        .rd_en(rdf),
134 5 robfinch
        .din({bz,perr,ferr,t3}),
135
        .dout({break_o,parityErr,frameErr,dout1}),
136 6 robfinch
        .data_count(qcnt),
137 5 robfinch
        .full(fifoFull),
138
        .empty(fifoEmpty)
139
);
140
 
141
assign dout = fifoEnable ? dout1 : t5;
142
assign empty = fifoEnable ? fifoEmpty : ~full1;
143
assign full = fifoEnable ? fifoFull : full1;
144
 
145
// compute 1/2 the length of the last bit
146
// needed for framing error detection
147
reg [8:0] halfLastBit;
148
always_ff @(posedge clk)
149
if (stop_bits==3'd3)    // 1.5 stop bits ?
150
        halfLastBit <= 9'd8;
151
else
152
        halfLastBit <= 9'd16;
153
 
154
reg [8:0] fhb;
155
always_ff @(posedge clk)
156
  fhb <= frameSize-halfLastBit;
157
 
158
// record a global error status
159
always_ff @(posedge clk)
160
if (rst)
161
        gerr <= 0;
162
else begin
163
        if (clearGErr)
164
                gerr <= perr | ferr | bz;
165
        else
166
                gerr <= gerr | perr | ferr | bz;
167
end
168
 
169
 
170
// right align data for word length, strip start bit
171
// depending on the word length, the first few bits in the
172
// recieve shift register will be invalid because the shift
173
// register shifts from MSB to LSB and shorter frames
174
// won't shift as far towards the LSB.
175
always_ff @(posedge clk)
176
        shft_amt <= (5'd16 - (wordLength + ({stop_bits[3],~stop_bits[3]}) + parityCtrl[0]));
177
always_comb
178
        t4 <= rx_data >> shft_amt;
179
 
180
// grab the parity bit
181
// Note the data is right aligned
182
always_comb
183
        p1 <= t4[wordLength];
184
 
185
// strip off parity, stop
186
integer n2;
187
always_comb
188
        for (n2 = 0; n2 < 12; n2 = n2 + 1)
189
                if (n2 < wordLength)
190
                        t3[n2] <= t4[n2];
191
                else
192
                        t3[n2] <= 1'b0;
193
 
194
// detect a parity err
195
always_comb begin
196
        case (parityCtrl)
197
        3'b001: perr <= p1 != ~^t3;     // odd parity
198
        3'b011: perr <= p1 != ^t3;      // even parity
199
        default: perr <= 0;
200
        endcase
201
end
202
 
203
 
204
// Three stage synchronizer to synchronize incoming data to
205
// the local clock (avoids metastability).
206
 
207
reg [5:0] rxdd          /* synthesis ramstyle = "logic" */; // synchronizer flops
208
reg rxdsmp;             // majority samples
209
reg rdxstart;           // for majority style sample solid 3tik-wide sample
210
reg [1:0] rxdsum [0:1];
211
always_ff @(posedge clk)
212
if (baud16x_ce) begin
213
        rxdd <= {rxdd[4:0],rxd};
214
  if (SamplerStyle == 0) begin
215
    rxdsmp <= rxdd[3];
216
    rdxstart <= rxdd[4]&~rxdd[3];
217
  end
218
  else begin
219
    rxdsum[1] <= rxdsum[0];
220
    rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
221
    rxdsmp <= rxdsum[1] > 2'd1;
222
    rdxstart <= (rxdsum[0] == 2'b00) & (rxdsum[1] == 2'b11);
223
  end
224
end
225
 
226
 
227
always_ff @(posedge clk)
228
if (rst)
229
        state <= `IDLE;
230
else begin
231
        if (clear)
232
                state <= `IDLE;
233
        else if (baud16x_ce) begin
234
                case (state)
235
                // Sit in the idle state until a start bit is
236
                // detected.
237
                `IDLE:
238
                        if (rdxstart)
239
                                state <= `CNT;
240
                `CNT:
241
                        begin
242
                                // Switch back to the idle state a little
243
                                // bit too soon.
244
                                if (cnt[8:2]==frameSize[8:2])
245
                                        state <= `IDLE;
246
                                // On start bit check make sure the start
247
                                // bit is low, otherwise go back to the
248
                                // idle state because it's a false start.
249
                                if (cnt[8:0]==8'h07) begin
250
                                        if (rxdsmp)
251
                                                state <= `IDLE;
252
                                end
253
                        end
254
                endcase
255
        end
256
end
257
 
258
always_ff @(posedge clk)
259
if (rst)
260
        cnt <= 9'h00;
261
else begin
262
        if (clear)
263
                cnt <= 9'h00;
264
        else if (baud16x_ce) begin
265
                cnt <= cnt + 2'h1;
266
                case (state)
267
                `IDLE:
268
                        begin
269
                                // reset counter on read of reciever
270
                                // (resets timeout count).
271
                                if (didRd)
272
                                        cnt <= 9'h0;
273
                                if (rdxstart)
274
                                        cnt <= 9'h0;
275
                        end
276
                default:        ;
277
                endcase
278
        end
279
end
280
 
281
always_ff @(posedge clk)
282
if (rst)
283
        wf <= 1'b0;
284
else begin
285
        // Clear write flag
286
        wf <= 1'b0;
287
        if (baud16x_ce) begin
288
                case (state)
289
                `CNT:
290
                        // End of the frame ?
291
                        // - write data to fifo
292
                        if (cnt[8:0]==fhb) begin
293
                                if (!full)
294
                                        wf <= 1'b1;
295
                        end
296
                default:        ;
297
                endcase
298
        end
299
end
300
 
301
always_ff @(posedge clk)
302
if (rst)
303
        t5 <= 1'b0;
304
else begin
305
        if (pe_wf)
306
                t5 <= t3;
307
end
308
 
309
always_ff @(posedge clk)
310
if (rst)
311
        full1 <= 1'b0;
312
else begin
313
        if (pe_wf)
314
                full1 <= 1'b1;
315
        else if (pe_rd)
316
                full1 <= 1'b0;
317
end
318
 
319
always_ff @(posedge clk)
320
if (rst)
321
        didRd <= 1'b0;
322
else begin
323
        // set a read flag for later reference
324
        if (pe_rd)
325
                didRd <= 1'b1;
326
        if (clear)
327
                didRd <= 1'b0;
328
        else if (baud16x_ce) begin
329
                case (state)
330
                `IDLE:
331
                        begin
332
                                if (didRd)
333
                                        didRd <= 1'b0;
334
                                if (rdxstart)
335
                                        didRd <= 1'b0;
336
                        end
337
                default:        ;
338
                endcase
339
        end
340
end
341
 
342
always_ff @(posedge clk)
343
if (rst)
344
        rx_data <= 15'h0;
345
else begin
346
        if (clear)
347
                rx_data <= 15'h0;
348
        else if (baud16x_ce) begin
349
                case (state)
350
                `CNT:
351
                        begin
352
                                //if (cnt[7:2]==frameSize[7:2])
353
                                //      rx_data <= 11'h0;
354
                                if (cnt[3:0]==4'h7)
355
                                        rx_data <= {rxdsmp,rx_data[14:1]};
356
                        end
357
                default:        ;
358
                endcase
359
        end
360
end
361
 
362
// Overrun: trying to recieve data when recieve buffer is already full.
363
always_ff @(posedge clk)
364
if (rst)
365
        overrun <= 1'b0;
366
else begin
367
        if (!full)
368
                overrun <= 1'b0;
369
        if (clear)
370
                overrun <= 1'b0;
371
        else if (baud16x_ce) begin
372
                case (state)
373
                `CNT:
374
                        if (cnt[8:0]==fhb) begin
375
                                if (full)
376
                                        overrun <= 1'b1;
377
                        end
378
                default:        ;
379
                endcase
380
        end
381
end
382
 
383
always_ff @(posedge clk)
384
if (rst)
385
        ferr <= 1'b0;
386
else begin
387
        if (clear)
388
                ferr <= 1'b0;
389
        else if (baud16x_ce) begin
390
                case (state)
391
                `CNT:
392
                        if (cnt[8:0]==fhb)
393
                                ferr <= ~rxdsmp;
394
                default:        ;
395
                endcase
396
        end
397
end
398
 
399
endmodule
400
 

powered by: WebSVN 2.1.0

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