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

Subversion Repositories uart6551

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
// ============================================================================
2
//        __
3 8 robfinch
//   \\__/ o\    (C) 2005-2022  Robert Finch, Waterloo
4 2 robfinch
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//
9 8 robfinch
// 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 2 robfinch
//
13 8 robfinch
// 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 2 robfinch
// ============================================================================
36
//
37
`define IDLE    0
38
`define CNT             1
39
 
40
module uart6551Rx(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 [7: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 [7: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
output [3:0] qcnt;              // count of number of words queued
70
output [9: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 [9:0] cnt;                  // sample bit rate counter / timeout counter
80
reg [10:0] rx_data;             // working receive data register
81
reg [9:0] t2;                   // data minus stop bit(s)
82
reg [7:0] t3,t4;                // data minus parity bit and start bit
83 3 robfinch
reg [7:0] t5;
84 2 robfinch
reg p1;
85
reg gerr;                               // global error status
86
reg perr;                               // parity error
87
reg ferr = 1'b0;                                // framing error
88
wire bz;                                // break detected
89
reg state;                              // state machine
90
reg wf;                                 // fifo write
91
wire empty;
92
reg didRd;
93 3 robfinch
wire [7:0] dout1;
94
reg full1;
95
wire fifoFull, fifoEmpty;
96 2 robfinch
 
97
assign ack = cyc & cs;
98
wire pe_rd;
99
edge_det ued1 (.rst(rst), .clk(clk), .ce(1'b1), .i(ack & ~wr), .pe(pe_rd), .ne(), .ee());
100
 
101
assign bitStream = rx_data[10];
102
assign bz = t4==8'd0;
103
wire rdf = fifoEnable ? pe_rd : wf;
104
 
105
uart6551Fifo #(.WID(11)) uf1
106
(
107
        .clk(clk),
108
        .rst(rst|clear|fifoClear),
109
        .wr(wf),
110
        .rd(rdf),
111
        .din({bz,perr,ferr,t4}),
112 3 robfinch
        .dout({break_o,parityErr,frameErr,dout1}),
113 2 robfinch
        .ctr(qcnt),
114 3 robfinch
        .full(fifoFull),
115
        .empty(fifoEmpty)
116 2 robfinch
);
117
 
118 3 robfinch
assign dout = fifoEnable ? dout1 : t5;
119
assign empty = fifoEnable ? fifoEmpty : ~full1;
120
assign full = fifoEnable ? fifoFull : full1;
121
 
122 2 robfinch
// compute 1/2 the length of the last bit
123
// needed for framing error detection
124
reg [7:0] halfLastBit;
125
always @(stop_bits)
126
if (stop_bits==3'd3)    // 1.5 stop bits ?
127
        halfLastBit <= 8'd4;
128
else
129
        halfLastBit <= 8'd8;
130
 
131
// record a global error status
132 13 robfinch
always_ff @(posedge clk)
133 2 robfinch
if (rst)
134
        gerr <= 0;
135
else begin
136
        if (clearGErr)
137
                gerr <= perr | ferr | bz;
138
        else
139
                gerr <= gerr | perr | ferr | bz;
140
end
141
 
142
 
143
// strip off stop bits
144
always @(stop_bits or rx_data)
145
if (stop_bits==3'd2)
146
        t2 <= rx_data[9:0];
147
else
148
        t2 <= {rx_data[8:0],1'b0};
149
 
150
// grab the parity bit
151
always @(t2)
152 3 robfinch
        p1 <= t2[9];
153 2 robfinch
 
154
// strip off parity and start bit
155
always @(parityCtrl or t2)
156
if (parityCtrl[0])
157
        t3 <= t2[8:1];
158
else
159
        t3 <= t2[9:2];
160
 
161
// mask receive data for word length
162
// depending on the word length, the first few bits in the
163
// recieve shift register will be invalid because the shift
164
// register shifts from MSB to LSB and shorter frames
165
// won't shift as far towards the LSB.
166
always @(wordLength or t3)
167
        t4 <= t3 >> (4'd8 - wordLength);
168
 
169
// detect a parity err
170
always @(parityCtrl or t4 or p1) begin
171
        case (parityCtrl)
172
        3'b001: perr <= p1 != ~^t4;     // odd parity
173
        3'b011: perr <= p1 != ^t4;      // even parity
174
        default: perr <= 0;
175
        endcase
176
end
177
 
178
 
179
// Three stage synchronizer to synchronize incoming data to
180
// the local clock (avoids metastability).
181
 
182
reg [5:0] rxdd          /* synthesis ramstyle = "logic" */; // synchronizer flops
183
reg rxdsmp;             // majority samples
184
reg rdxstart;           // for majority style sample solid 3tik-wide sample
185
reg [1:0] rxdsum [0:1];
186 13 robfinch
always_ff @(posedge clk)
187 2 robfinch
if (baud16x_ce) begin
188
        rxdd <= {rxdd[4:0],rxd};
189
  if (SamplerStyle == 0) begin
190
    rxdsmp <= rxdd[3];
191
    rdxstart <= rxdd[4]&~rxdd[3];
192
  end
193
  else begin
194
    rxdsum[1] <= rxdsum[0];
195
    rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
196
    rxdsmp <= rxdsum[1] > 2'd1;
197
    rdxstart <= (rxdsum[0] == 2'b00) & (rxdsum[1] == 2'b11);
198
  end
199
end
200
 
201
 
202 13 robfinch
always_ff @(posedge clk)
203 2 robfinch
if (rst)
204
        state <= `IDLE;
205
else begin
206
        if (clear)
207
                state <= `IDLE;
208
        else if (baud16x_ce) begin
209
                case (state)
210
                // Sit in the idle state until a start bit is
211
                // detected.
212
                `IDLE:
213
                        if (rdxstart)
214
                                state <= `CNT;
215
                `CNT:
216
                        begin
217
                                // Switch back to the idle state a little
218
                                // bit too soon.
219
                                if (cnt[7:2]==frameSize[7:2])
220
                                        state <= `IDLE;
221
                                // On start bit check make sure the start
222
                                // bit is low, otherwise go back to the
223
                                // idle state because it's a false start.
224
                                if (cnt[7:0]==8'h07) begin
225
                                        if (rxdsmp)
226
                                                state <= `IDLE;
227
                                end
228
                        end
229
                default:        ;
230
                endcase
231
        end
232
end
233
 
234 13 robfinch
always_ff @(posedge clk)
235 2 robfinch
if (rst)
236
        cnt <= 8'h00;
237
else begin
238
        if (clear)
239
                cnt <= 8'h00;
240
        else if (baud16x_ce) begin
241
                cnt <= cnt + 8'h1;
242
                case (state)
243
                `IDLE:
244
                        begin
245
                                // reset counter on read of reciever
246
                                // (resets timeout count).
247
                                if (didRd)
248
                                        cnt <= 8'h0;
249
                                if (rdxstart)
250
                                        cnt <= 8'h0;
251
                        end
252
                default:        ;
253
                endcase
254
        end
255
end
256
 
257 13 robfinch
always_ff @(posedge clk)
258 2 robfinch
if (rst)
259
        wf <= 1'b0;
260
else begin
261
        // Clear write flag
262
        wf <= 1'b0;
263
        if (clear)
264
                wf <= 1'b0;
265
        else if (baud16x_ce) begin
266
                case (state)
267
                `CNT:
268
                        // End of the frame ?
269
                        // - write data to fifo
270
                        if (cnt[7:0]==frameSize-halfLastBit) begin
271
                                if (!full)
272
                                        wf <= 1'b1;
273
                        end
274
                default:        ;
275
                endcase
276
        end
277
end
278
 
279 13 robfinch
always_ff @(posedge clk)
280 2 robfinch
if (rst)
281 3 robfinch
        t5 <= 1'b0;
282
else begin
283
        if (wf)
284
                t5 <= t4;
285
end
286
 
287 13 robfinch
always_ff @(posedge clk)
288 3 robfinch
if (rst)
289
        full1 <= 1'b0;
290
else begin
291
        if (wf)
292
                full1 <= 1'b1;
293
        else if (pe_rd)
294
                full1 <= 1'b0;
295
end
296
 
297 13 robfinch
always_ff @(posedge clk)
298 3 robfinch
if (rst)
299 2 robfinch
        didRd <= 1'b0;
300
else begin
301
        // set a read flag for later reference
302
        if (pe_rd)
303
                didRd <= 1'b1;
304
        if (clear)
305
                didRd <= 1'b0;
306
        else if (baud16x_ce) begin
307
                case (state)
308
                `IDLE:
309
                        begin
310
                                if (didRd)
311
                                        didRd <= 1'b0;
312
                                if (rdxstart)
313
                                        didRd <= 1'b0;
314
                        end
315
                default:        ;
316
                endcase
317
        end
318
end
319
 
320 13 robfinch
always_ff @(posedge clk)
321 2 robfinch
if (rst)
322
        rx_data <= 11'h0;
323
else begin
324
        if (clear)
325
                rx_data <= 11'h0;
326
        else if (baud16x_ce) begin
327
                case (state)
328
                `CNT:
329
                        begin
330
                                //if (cnt[7:2]==frameSize[7:2])
331
                                //      rx_data <= 11'h0;
332
                                if (cnt[3:0]==4'h7)
333
                                        rx_data <= {rxdsmp,rx_data[10:1]};
334
                        end
335
                default:        ;
336
                endcase
337
        end
338
end
339
 
340
// Overrun: trying to recieve data when recieve buffer is already full.
341 13 robfinch
always_ff @(posedge clk)
342 2 robfinch
if (rst)
343
        overrun <= 1'b0;
344
else begin
345
        if (!full)
346
                overrun <= 1'b0;
347
        if (clear)
348
                overrun <= 1'b0;
349
        else if (baud16x_ce) begin
350
                case (state)
351
                `CNT:
352
                        if (cnt[7:0]==frameSize-halfLastBit) begin
353
                                if (full)
354
                                        overrun <= 1'b1;
355
                        end
356
                default:        ;
357
                endcase
358
        end
359
end
360
 
361 13 robfinch
always_ff @(posedge clk)
362 2 robfinch
if (rst)
363
        ferr <= 1'b0;
364
else begin
365
        if (clear)
366
                ferr <= 1'b0;
367
        else if (baud16x_ce) begin
368
                case (state)
369
                `CNT:
370
                        if (cnt[7:0]==frameSize-halfLastBit)
371
                                ferr <= ~rxdsmp;
372
                default:        ;
373
                endcase
374
        end
375
end
376
 
377
endmodule
378
 

powered by: WebSVN 2.1.0

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