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

Subversion Repositories uart6551

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

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

Line No. Rev Author Line
1 2 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2005-2019  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//
9
// This source file is free software: you can redistribute it and/or modify
10
// it under the terms of the GNU Lesser General Public License as published
11
// by the Free Software Foundation, either version 3 of the License, or
12
// (at your option) any later version.
13
//
14
// This source file is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
// GNU General Public License for more details.
18
//
19
// You should have received a copy of the GNU General Public License
20
// along with this program.  If not, see .
21
//
22
// ============================================================================
23
//
24
`define IDLE    0
25
`define CNT             1
26
 
27
module uart6551Rx(rst, clk,
28
        cyc, cs, wr, dout, ack,
29
        fifoEnable, fifoClear, clearGErr,
30
        parityCtrl, frameSize, stop_bits, wordLength, baud16x_ce, clear, rxd,
31
        full, empty, frameErr, overrun, parityErr, break_o, gerr, qcnt, cnt, bitStream);
32
input rst;
33
input clk;
34
input cyc;                              // valid bus cycle
35
input cs;                               // core select
36
input wr;                               // read reciever
37
output [7:0] dout;              // fifo data out
38
output ack;
39
input fifoEnable;               // enable the fifo
40
input fifoClear;
41
input clearGErr;                // clear global error
42
input [2:0] parityCtrl;
43
input [7:0] frameSize;  // frame count
44
input [2:0] stop_bits;
45
input [3:0] wordLength;
46
input baud16x_ce;               // baud rate clock enable
47
input clear;                    // clear reciever
48
input rxd;                              // external serial input
49
output full;                    // receive fifo full
50
output empty;           // receiver fifo is empty
51
output frameErr;                // framing error
52
output overrun;                 // receiver overrun
53
output parityErr;               // parity error
54
output break_o;                 // break detected
55
output gerr;                    // global error indicator
56
output [3:0] qcnt;              // count of number of words queued
57
output [9:0] cnt;               // receiver counter
58
output bitStream;               // received bit stream
59
 
60
//0 - simple sampling at middle of symbol period
61
//>0 - sampling of 3 middle ticks of sumbol perion and results as majority
62
parameter SamplerStyle = 0;
63
 
64
 
65
reg overrun;
66
reg [9:0] cnt;                  // sample bit rate counter / timeout counter
67
reg [10:0] rx_data;             // working receive data register
68
reg [9:0] t2;                   // data minus stop bit(s)
69
reg [7:0] t3,t4;                // data minus parity bit and start bit
70
reg p1;
71
reg gerr;                               // global error status
72
reg perr;                               // parity error
73
reg ferr = 1'b0;                                // framing error
74
wire bz;                                // break detected
75
reg state;                              // state machine
76
reg wf;                                 // fifo write
77
wire empty;
78
reg didRd;
79
 
80
assign ack = cyc & cs;
81
wire pe_rd;
82
edge_det ued1 (.rst(rst), .clk(clk), .ce(1'b1), .i(ack & ~wr), .pe(pe_rd), .ne(), .ee());
83
 
84
assign bitStream = rx_data[10];
85
assign bz = t4==8'd0;
86
wire rdf = fifoEnable ? pe_rd : wf;
87
 
88
uart6551Fifo #(.WID(11)) uf1
89
(
90
        .clk(clk),
91
        .rst(rst|clear|fifoClear),
92
        .wr(wf),
93
        .rd(rdf),
94
        .din({bz,perr,ferr,t4}),
95
        .dout({break_o,parityErr,frameErr,dout}),
96
        .ctr(qcnt),
97
        .full(full),
98
        .empty(empty)
99
);
100
 
101
// compute 1/2 the length of the last bit
102
// needed for framing error detection
103
reg [7:0] halfLastBit;
104
always @(stop_bits)
105
if (stop_bits==3'd3)    // 1.5 stop bits ?
106
        halfLastBit <= 8'd4;
107
else
108
        halfLastBit <= 8'd8;
109
 
110
// record a global error status
111
always @(posedge clk)
112
if (rst)
113
        gerr <= 0;
114
else begin
115
        if (clearGErr)
116
                gerr <= perr | ferr | bz;
117
        else
118
                gerr <= gerr | perr | ferr | bz;
119
end
120
 
121
 
122
// strip off stop bits
123
always @(stop_bits or rx_data)
124
if (stop_bits==3'd2)
125
        t2 <= rx_data[9:0];
126
else
127
        t2 <= {rx_data[8:0],1'b0};
128
 
129
// grab the parity bit
130
always @(t2)
131
        p1 <= t2[33];
132
 
133
// strip off parity and start bit
134
always @(parityCtrl or t2)
135
if (parityCtrl[0])
136
        t3 <= t2[8:1];
137
else
138
        t3 <= t2[9:2];
139
 
140
// mask receive data for word length
141
// depending on the word length, the first few bits in the
142
// recieve shift register will be invalid because the shift
143
// register shifts from MSB to LSB and shorter frames
144
// won't shift as far towards the LSB.
145
always @(wordLength or t3)
146
        t4 <= t3 >> (4'd8 - wordLength);
147
 
148
// detect a parity err
149
always @(parityCtrl or t4 or p1) begin
150
        case (parityCtrl)
151
        3'b001: perr <= p1 != ~^t4;     // odd parity
152
        3'b011: perr <= p1 != ^t4;      // even parity
153
        default: perr <= 0;
154
        endcase
155
end
156
 
157
 
158
// Three stage synchronizer to synchronize incoming data to
159
// the local clock (avoids metastability).
160
 
161
reg [5:0] rxdd          /* synthesis ramstyle = "logic" */; // synchronizer flops
162
reg rxdsmp;             // majority samples
163
reg rdxstart;           // for majority style sample solid 3tik-wide sample
164
reg [1:0] rxdsum [0:1];
165
always @(posedge clk)
166
if (baud16x_ce) begin
167
        rxdd <= {rxdd[4:0],rxd};
168
  if (SamplerStyle == 0) begin
169
    rxdsmp <= rxdd[3];
170
    rdxstart <= rxdd[4]&~rxdd[3];
171
  end
172
  else begin
173
    rxdsum[1] <= rxdsum[0];
174
    rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
175
    rxdsmp <= rxdsum[1] > 2'd1;
176
    rdxstart <= (rxdsum[0] == 2'b00) & (rxdsum[1] == 2'b11);
177
  end
178
end
179
 
180
 
181
always @(posedge clk)
182
if (rst)
183
        state <= `IDLE;
184
else begin
185
        if (clear)
186
                state <= `IDLE;
187
        else if (baud16x_ce) begin
188
                case (state)
189
                // Sit in the idle state until a start bit is
190
                // detected.
191
                `IDLE:
192
                        if (rdxstart)
193
                                state <= `CNT;
194
                `CNT:
195
                        begin
196
                                // Switch back to the idle state a little
197
                                // bit too soon.
198
                                if (cnt[7:2]==frameSize[7:2])
199
                                        state <= `IDLE;
200
                                // On start bit check make sure the start
201
                                // bit is low, otherwise go back to the
202
                                // idle state because it's a false start.
203
                                if (cnt[7:0]==8'h07) begin
204
                                        if (rxdsmp)
205
                                                state <= `IDLE;
206
                                end
207
                        end
208
                default:        ;
209
                endcase
210
        end
211
end
212
 
213
always @(posedge clk)
214
if (rst)
215
        cnt <= 8'h00;
216
else begin
217
        if (clear)
218
                cnt <= 8'h00;
219
        else if (baud16x_ce) begin
220
                cnt <= cnt + 8'h1;
221
                case (state)
222
                `IDLE:
223
                        begin
224
                                // reset counter on read of reciever
225
                                // (resets timeout count).
226
                                if (didRd)
227
                                        cnt <= 8'h0;
228
                                if (rdxstart)
229
                                        cnt <= 8'h0;
230
                        end
231
                default:        ;
232
                endcase
233
        end
234
end
235
 
236
always @(posedge clk)
237
if (rst)
238
        wf <= 1'b0;
239
else begin
240
        // Clear write flag
241
        wf <= 1'b0;
242
        if (clear)
243
                wf <= 1'b0;
244
        else if (baud16x_ce) begin
245
                case (state)
246
                `CNT:
247
                        // End of the frame ?
248
                        // - write data to fifo
249
                        if (cnt[7:0]==frameSize-halfLastBit) begin
250
                                if (!full)
251
                                        wf <= 1'b1;
252
                        end
253
                default:        ;
254
                endcase
255
        end
256
end
257
 
258
always @(posedge clk)
259
if (rst)
260
        didRd <= 1'b0;
261
else begin
262
        // set a read flag for later reference
263
        if (pe_rd)
264
                didRd <= 1'b1;
265
        if (clear)
266
                didRd <= 1'b0;
267
        else if (baud16x_ce) begin
268
                case (state)
269
                `IDLE:
270
                        begin
271
                                if (didRd)
272
                                        didRd <= 1'b0;
273
                                if (rdxstart)
274
                                        didRd <= 1'b0;
275
                        end
276
                default:        ;
277
                endcase
278
        end
279
end
280
 
281
always @(posedge clk)
282
if (rst)
283
        rx_data <= 11'h0;
284
else begin
285
        if (clear)
286
                rx_data <= 11'h0;
287
        else if (baud16x_ce) begin
288
                case (state)
289
                `CNT:
290
                        begin
291
                                //if (cnt[7:2]==frameSize[7:2])
292
                                //      rx_data <= 11'h0;
293
                                if (cnt[3:0]==4'h7)
294
                                        rx_data <= {rxdsmp,rx_data[10:1]};
295
                        end
296
                default:        ;
297
                endcase
298
        end
299
end
300
 
301
// Overrun: trying to recieve data when recieve buffer is already full.
302
always @(posedge clk)
303
if (rst)
304
        overrun <= 1'b0;
305
else begin
306
        if (!full)
307
                overrun <= 1'b0;
308
        if (clear)
309
                overrun <= 1'b0;
310
        else if (baud16x_ce) begin
311
                case (state)
312
                `CNT:
313
                        if (cnt[7:0]==frameSize-halfLastBit) begin
314
                                if (full)
315
                                        overrun <= 1'b1;
316
                        end
317
                default:        ;
318
                endcase
319
        end
320
end
321
 
322
always @(posedge clk)
323
if (rst)
324
        ferr <= 1'b0;
325
else begin
326
        if (clear)
327
                ferr <= 1'b0;
328
        else if (baud16x_ce) begin
329
                case (state)
330
                `CNT:
331
                        if (cnt[7:0]==frameSize-halfLastBit)
332
                                ferr <= ~rxdsmp;
333
                default:        ;
334
                endcase
335
        end
336
end
337
 
338
endmodule
339
 

powered by: WebSVN 2.1.0

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