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

Subversion Repositories attiny_atmega_xmega_core

[/] [attiny_atmega_xmega_core/] [trunk/] [rtl/] [io/] [uart_s.v] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 morgothcre
/*
2
 * This IP is a simple paralel IO adapter implementation.
3
 *
4
 * Copyright (C) 2018  Iulian Gheorghiu
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
 */
20
 
21
`timescale 1ns / 1ps
22
 
23
`include "io_s_h.v"
24
 
25
module uart_s #(
26
        parameter BAUDRATE_COUNTER_LENGTH = 12,
27
        parameter DINAMIC_BAUDRATE = "TRUE",
28
        parameter BAUDRATE_DIVIDER = 19200,
29
        parameter ADDRESS = 0,
30
        parameter BUS_ADDR_DATA_LEN = 16
31
    )(
32
        input rst,
33
    input clk,
34
    input [BUS_ADDR_DATA_LEN-1:0]addr,
35
    input wr,
36
    input rd,
37
    input [7:0]bus_in,
38
    output reg[7:0]bus_out,
39
    output int_rx_rcv,
40
    output int_tx_compl,
41
    output int_tx_buff_empty,
42
    inout int_rst,
43
    inout rtx_clk,
44
    output reg tx,
45
    input rx
46
    );
47
 
48
localparam [6:0]MAX_WORD_LEN = 9;
49
 
50
localparam      state_idle      =       1'b0;
51
localparam      state_busy      =       1'b1;
52
 
53
reg [7:0]DATA_in;
54
reg [7:0]DATA_out;
55
reg [7:0]STATUS;
56
reg [7:0]CTRLA;
57
reg [7:0]CTRLB;
58
reg [7:0]CTRLC;
59
reg [7:0]BAUDCTRLA;
60
reg [7:0]BAUDCTRLB;
61
reg [7:0]BAUDCTRLB_tmp_read;
62
reg [7:0]BAUDCTRLB_tmp_write;
63
 
64
wire cs_int = addr >= ADDRESS && addr < (ADDRESS + 16);
65
wire rd_int = cs_int && rd;
66
wire wr_int = cs_int && wr;
67
 
68
reg [BAUDRATE_COUNTER_LENGTH == 0 ? 0 : BAUDRATE_COUNTER_LENGTH - 1:0]baud_cnt;
69
 
70
reg receiveoverrunp;
71
reg receiveoverrunn;
72
wire receiveoverrunpn;
73
 
74
reg [2:0]rxbitcntstate;
75
 
76
reg     charreceivedp;
77
reg     charreceivedn;
78
 
79
reg     state_rx;
80
reg     state_tx;
81
reg     [(MAX_WORD_LEN - 1) + 4:0]shift_reg_in;
82
reg     [(MAX_WORD_LEN - 1) + 4:0]shift_reg_out;
83
//reg   [MAX_WORD_LEN - 1:0]temp_output_buffer;
84
reg     [7:0]sckint_rx;
85
//reg   [3:0]bitcount_rx;
86
reg [3:0]total_word_len_rx;
87
 
88
wire _chk_int;
89
wire chk_int;
90
reg [(MAX_WORD_LEN - 1) + 4:0]parity_mask;
91
wire [(MAX_WORD_LEN - 1) + 4:0]valid_data;
92
wire parity_bit;
93
reg [3:0]wordlen;
94
 
95
reg     inbufffullp;
96
reg     inbufffulln;
97
 
98
reg last_state_rxp;
99
reg last_state_rxn;
100
wire rx_start_detected;
101
 
102
reg     [3:0]sckint_tx;
103
reg     [3:0]bitcount_tx;
104
reg [3:0]total_word_len_tx;
105
 
106
wire buffempty = ~(inbufffullp ^ inbufffulln);
107
reg [11:0]prescallerbuff;
108
 
109
reg int_tx_compl_int;
110
reg int_tx_buff_empty_int;
111
assign int_tx_compl = CTRLB[`USART_TXEN_bp] ? int_tx_compl_int : 1'b0;
112
assign int_tx_buff_empty = CTRLB[`USART_TXEN_bp] ? int_tx_buff_empty_int : 1'b0;
113
reg int_rx_rcv_int;
114
assign int_rx_rcv = CTRLB[`USART_RXEN_bp] ? int_rx_rcv_int : 1'b0;
115
 
116
wire [15:0]static_baudrate = {BAUDCTRLB, BAUDCTRLA};
117
 
118
always @ (posedge rd_int or posedge rst)
119
begin
120
        if(rst)
121
        begin
122
                charreceivedn   <=      1'b0;
123
                receiveoverrunp <= 1'b0;
124
        end
125
        else if(rd_int)
126
        begin
127
                case(addr[3:0])
128
                `USART_DATA:
129
                begin
130
                        if(charreceivedp !=     charreceivedn)
131
                                charreceivedn <= ~charreceivedn;
132
                        if(receiveoverrunn != receiveoverrunp)
133
                                receiveoverrunp <= ~receiveoverrunp;
134
                end
135
                endcase
136
        end
137
end
138
 
139
always @ (*)
140
begin
141
        if(rst)
142
        begin
143
                BAUDCTRLB_tmp_read <= 'h0;
144
        end
145
        else if(rd_int)
146
        begin
147
                case(addr[3:0])
148
                `USART_DATA: bus_out <= DATA_out;
149
                `USART_STATUS: bus_out <= STATUS;
150
                `USART_CTRLA: bus_out <= CTRLA;
151
                `USART_CTRLB: bus_out <= CTRLB;
152
                `USART_CTRLC: bus_out <= CTRLC;
153
                `USART_BAUDCTRLA:
154
                begin
155
                        if(DINAMIC_BAUDRATE == "TRUE")
156
                        begin
157
                                bus_out <= BAUDCTRLA;
158
                                BAUDCTRLB_tmp_read <= BAUDCTRLB;
159
                        end
160
                        else
161
                        begin
162
                                bus_out <= static_baudrate[7:0];
163
                        end
164
                end
165
                `USART_BAUDCTRLB:
166
                begin
167
                        if(DINAMIC_BAUDRATE == "TRUE")
168
                                bus_out <= BAUDCTRLB_tmp_read;
169
                        else
170
                                bus_out <= static_baudrate[15:8];
171
                end
172
                default: bus_out <= 8'bz;
173
                endcase
174
        end
175
        else
176
        begin
177
                bus_out <= 8'bz;
178
        end
179
end
180
 
181
 
182
always @ (*)
183
begin
184
        case(CTRLC[`USART_CHSIZE_gp + 2:`USART_CHSIZE_gp])
185
                3'h00: wordlen <= 12'd5;
186
                3'h01: wordlen <= 12'd6;
187
                3'h02: wordlen <= 12'd7;
188
                3'h03: wordlen <= 12'd8;
189
                3'h07: wordlen <= 12'd9;
190
                default: wordlen <= 12'd8;
191
        endcase
192
end
193
 
194
always @ (*)
195
begin
196
        case(wordlen)
197
                4'h05: parity_mask <= 12'b000000111110;
198
                4'h06: parity_mask <= 12'b000001111110;
199
                4'h07: parity_mask <= 12'b000011111110;
200
                4'h09: parity_mask <= 12'b001111111110;
201
                default: parity_mask <= 12'b000111111110;
202
        endcase
203
end
204
 
205
assign valid_data = shift_reg_in & parity_mask;
206
assign _chk_int = ^valid_data;
207
assign chk_int = (CTRLC[`USART_CMODE_gp + 1:`USART_CMODE_gp] == 2'b10) ? ~_chk_int:_chk_int;
208
assign parity_bit = (shift_reg_in & (1 << wordlen + 1)) ? 1:0;
209
 
210
always @ (negedge rx or posedge rst)
211
begin
212
        if(rst)
213
                last_state_rxn <= 0;
214
        else
215
        begin
216
                if(last_state_rxn == last_state_rxp)
217
                begin
218
                        last_state_rxn <= ~last_state_rxp;
219
                end
220
        end
221
end
222
 
223
assign rx_start_detected = (last_state_rxn ^ last_state_rxp);
224
 
225
always @ (posedge clk or posedge rst)
226
begin
227
        if(rst)
228
        begin
229
                baud_cnt = 'h00;
230
        charreceivedn <= 1'b0;
231
                inbufffullp <= 1'b0;
232
                inbufffulln <= 1'b0;
233
                DATA_in <=      'h0;
234
                STATUS <= 'h0;
235
                CTRLA <= 'h0;
236
                CTRLB <= 'h0;
237
                CTRLC <= `USART_CHSIZE_8BIT_gc;
238
                BAUDCTRLA <= 'h0;
239
                BAUDCTRLB <= 'h0;
240
                BAUDCTRLB_tmp_write <= 'h0;
241
                last_state_rxp <= 'h0;
242
                state_rx <=     state_idle;
243
                state_tx <=     state_idle;
244
                shift_reg_in <= 'h0;
245
                sckint_rx <= 'h0;
246
                charreceivedp <= 'h0;
247
                receiveoverrunn <= 'h0;
248
                rxbitcntstate <= 'h0;
249
                total_word_len_rx <= 'h0;
250
                int_rx_rcv_int <= 'h0;
251
                int_tx_compl_int <= 'h0;
252
                int_tx_buff_empty_int <= 'h0;
253
                tx <= 1'b1;
254
        end
255
        else
256
        begin
257
                STATUS[`USART_DREIF_bp] <= buffempty;
258
/*
259
                 * Read from IO logic
260
                 */
261
                if(wr_int)
262
                begin
263
                        case(addr[3:0])
264
                        `USART_STATUS: STATUS <= STATUS ^ bus_in;
265
                        `USART_CTRLA: CTRLA <= bus_in;
266
                        `USART_CTRLB: CTRLB <= bus_in;
267
                        `USART_CTRLC: CTRLC <= bus_in;
268
                        `USART_BAUDCTRLA:
269
                        begin
270
                                if(DINAMIC_BAUDRATE == "TRUE")
271
                                begin
272
                                        BAUDCTRLA <= bus_in;
273
                                        BAUDCTRLB <= BAUDCTRLB_tmp_write;
274
                                end
275
                        end
276
                        `USART_BAUDCTRLB:
277
                        begin
278
                                if(DINAMIC_BAUDRATE == "TRUE")
279
                                begin
280
                                        BAUDCTRLB_tmp_write <= bus_in;
281
                                end
282
                        end
283
                        `USART_DATA:
284
                        begin
285
                                if(inbufffullp == inbufffulln && buffempty && CTRLB[`USART_TXEN_bp])
286
                                begin
287
                                        inbufffullp <= ~inbufffullp;
288
                                        prescallerbuff <= {BAUDCTRLB[3:0], BAUDCTRLA};
289
                                        DATA_in <= bus_in;
290
                                        int_tx_compl_int <= 1'b0;
291
                                        int_tx_buff_empty_int <= 'h0;
292
                                end
293
                        end
294
                        endcase
295
                end
296
                if(rd_int)
297
                begin
298
                        case(addr[3:0])
299
                        `USART_DATA: int_rx_rcv_int <= 1'b0;
300
                        endcase
301
                end
302
                if(DINAMIC_BAUDRATE == "TRUE" ? baud_cnt == prescallerbuff : baud_cnt == {BAUDRATE_DIVIDER})
303
                begin
304
                        baud_cnt <= 'h00;
305
                        if(CTRLB[`USART_RXEN_bp])
306
                        begin
307
/*
308
 * Rx logic
309
 */
310
                                if(state_rx == state_idle)
311
                                begin
312
                                        // Wait for a transition from hi to low that indicate a start condition.
313
                                        if(rx_start_detected)
314
                                        begin
315
                                                shift_reg_in <= 0;
316
                                                sckint_rx <= 0;
317
                                                rxbitcntstate <= 7;
318
                                                // Calculate the total number of bits to receive including end.
319
                                                total_word_len_rx <= CTRLC[`USART_CMODE_gp + 1:`USART_CMODE_gp] ? 1 : 0 + 1 + CTRLC[`USART_SBMODE_bp] + wordlen;
320
                                                state_rx <= state_busy;
321
                                        end
322
                                end
323
                                else
324
                                begin
325
                                        case(sckint_rx[3:0])
326
                                                7,8,9:
327
                                                begin
328
                                                        rxbitcntstate <= rxbitcntstate + (rx ? 3'd7 : 3'd1);
329
                                                        sckint_rx <= sckint_rx + 1;
330
                                                end
331
                                                10:
332
                                                begin
333
                                                        if(sckint_rx[7:4] == total_word_len_rx)// If is stop bit check-it and out the received data.
334
                                                        begin
335
                                                                // Verify stop bit to be valid, else report a frame error.
336
                                                                STATUS[`USART_FERR_bp] <= ~rxbitcntstate[2];
337
                                                                // Verify the parity bit
338
                                                                if(CTRLC[`USART_CMODE_gp + 1:`USART_CMODE_gp])
339
                                                                        STATUS[`USART_PERR_bp] <= parity_bit ^ chk_int;
340
                                                                else
341
                                                                        STATUS[`USART_PERR_bp] <= 'h0;
342
                                                                // Put data from shift register to output data register.
343
                                                                {STATUS[`USART_RXB8_bp], DATA_out} <= valid_data[9:1];
344
                                                                // Check if the previous received data has been read from output register, if not report a overrun situation..
345
                                                                if(charreceivedn == charreceivedp)
346
                                                                        charreceivedp <= ~charreceivedp;
347
                                                                else
348
                                                                begin
349
                                                                        if(receiveoverrunn == receiveoverrunp)
350
                                                                                receiveoverrunn <= ~receiveoverrunn;
351
                                                                end
352
                                                                if(CTRLA[`USART_RXCINTLVL_gp + 1 : `USART_RXCINTLVL_gp])
353
                                                                begin
354
                                                                        int_rx_rcv_int <= 1'b1;
355
                                                                end
356
                                                                state_rx <= state_idle;
357
                                                                sckint_rx <= 0;
358
                                                                last_state_rxp <= last_state_rxn;
359
                                                        end
360
                                                        else
361
                                                        begin
362
                                                                shift_reg_in[sckint_rx[7:4]] <= rxbitcntstate[2];
363
                                                                sckint_rx <= sckint_rx + 1;
364
                                                        end
365
                                                end
366
                                                15:
367
                                                begin
368
                                                        rxbitcntstate <= 7;
369
                                                        sckint_rx <= sckint_rx + 1;
370
                                                end
371
                                                default:
372
                                                begin
373
                                                        sckint_rx <= sckint_rx + 1;
374
                                                end
375
                                        endcase
376
                                end
377
                        end
378
                        else
379
                        begin
380
                                int_rx_rcv_int <= 'h0;
381
                        end
382
/*
383
 * Tx logic
384
 */
385
                        if(CTRLB[`USART_TXEN_bp])
386
                        begin
387
                                case(state_tx)
388
                                        state_idle:
389
                                        begin
390
                                                if(inbufffullp != inbufffulln)
391
                                                begin
392
                                                        inbufffulln <= ~inbufffulln;
393
                                                        sckint_tx <= 5'h01;
394
                                                        int_tx_compl_int <= 1'b0;
395
                                                        if(CTRLA[`USART_DREINTLVL_gc + 1 : `USART_DREINTLVL_gc])
396
                                                        begin
397
                                                                int_tx_buff_empty_int <= 'h1;
398
                                                        end
399
                                                        case({CTRLC[`USART_PMODE_gp + 1 : `USART_PMODE_gp], CTRLC[`USART_SBMODE_bp], wordlen})
400
                                                                {2'b00, 4'h05}: shift_reg_out   <=      {1'b1, DATA_in[4:0], 1'h0};
401
                                                                {2'b00, 4'h06}: shift_reg_out   <=      {1'b1, DATA_in[5:0], 1'h0};
402
                                                                {2'b00, 4'h07}: shift_reg_out   <=      {1'b1, DATA_in[6:0], 1'h0};
403
                                                                {2'b00, 4'h08}: shift_reg_out   <=      {1'b1, DATA_in, 1'h0};
404
                                                                {2'b00, 4'h09}: shift_reg_out   <=      {1'b1, CTRLB[`USART_TXB8_bp], DATA_in, 1'h0};
405
                                                                {2'b01, 4'h05}: shift_reg_out   <=      {2'b11, DATA_in[4:0], 1'h0};
406
                                                                {2'b01, 4'h06}: shift_reg_out   <=      {2'b11, DATA_in[5:0], 1'h0};
407
                                                                {2'b01, 4'h07}: shift_reg_out   <=      {2'b11, DATA_in[6:0], 1'h0};
408
                                                                {2'b01, 4'h08}: shift_reg_out   <=      {2'b11, DATA_in, 1'h0};
409
                                                                {2'b01, 4'h09}: shift_reg_out   <=      {2'b11, CTRLB[`USART_TXB8_bp], DATA_in, 1'h0};
410
                                                                {2'b10, 4'h05}: shift_reg_out   <=      {1'b1, chk_int, DATA_in[4:0], 1'h0};
411
                                                                {2'b10, 4'h06}: shift_reg_out   <=      {1'b1, chk_int, DATA_in[5:0], 1'h0};
412
                                                                {2'b10, 4'h07}: shift_reg_out   <=      {1'b1, chk_int, DATA_in[6:0], 1'h0};
413
                                                                {2'b10, 4'h08}: shift_reg_out   <=      {1'b1, chk_int, DATA_in, 1'h0};
414
                                                                {2'b10, 4'h09}: shift_reg_out   <=      {1'b1, chk_int, CTRLB[`USART_TXB8_bp], DATA_in, 1'h0};
415
                                                                {2'b11, 4'h05}:shift_reg_out    <=      {2'b11, chk_int, DATA_in[4:0], 1'h0};
416
                                                                {2'b11, 4'h06}:shift_reg_out    <=      {2'b11, chk_int, DATA_in[5:0], 1'h0};
417
                                                                {2'b11, 4'h07}:shift_reg_out    <=      {2'b11, chk_int, DATA_in[6:0], 1'h0};
418
                                                                {2'b11, 4'h08}:shift_reg_out    <=      {2'b11, chk_int, DATA_in, 1'h0};
419
                                                                {2'b11, 4'h09}:shift_reg_out    <=      {2'b11, chk_int, CTRLB[`USART_TXB8_bp], DATA_in, 1'h0};
420
                                                                default: shift_reg_out  <=      {1'b1, DATA_in[7:0], 1'h0};
421
                                                        endcase
422
                                                        bitcount_tx <= 4'b0000;
423
                                                        total_word_len_tx <= CTRLC[`USART_PMODE_gp + 1:`USART_PMODE_gp] ? 1 : 0 + 1 + CTRLC[`USART_SBMODE_bp] + wordlen + 1;
424
                                                        state_tx <=     state_busy;
425
                                                        /*Put start, first bit from shift_reg_out*/
426
                                                        tx <= 1'b0;
427
                                                end
428
                                        end
429
                                        state_busy:
430
                                        begin
431
                                                case(sckint_tx)
432
                                                4'h0D:
433
                                                begin
434
                                                        sckint_tx <= sckint_tx + 1;
435
                                                        bitcount_tx <= bitcount_tx + 'b0001;
436
                                                end
437
                                                4'h0E:
438
                                                begin
439
                                                        if(bitcount_tx == total_word_len_tx)
440
                                                        begin
441
                                                                state_tx <= state_idle;
442
                                                                if(CTRLA[`USART_TXCINTLVL_gp + 1 : `USART_TXCINTLVL_gp])
443
                                                                begin
444
                                                                        int_tx_compl_int <= 1'b1;
445
                                                                end
446
                                                        end
447
                                                        sckint_tx <= sckint_tx + 1;
448
                                                end
449
                                                4'h0F:
450
                                                begin
451
                                                        sckint_tx       <= sckint_tx + 1;
452
                                                        tx <= shift_reg_out[bitcount_tx];
453
                                                end
454
                                                default:
455
                                                begin
456
                                                        sckint_tx <= sckint_tx + 1;
457
                                                end
458
                                                endcase
459
                                        end
460
                                endcase
461
                        end
462
                        else
463
                        begin
464
                                int_tx_compl_int <= 'h0;
465
                                int_tx_buff_empty_int <= 'h0;
466
                        end
467
                end
468
                else
469
                begin
470
                        baud_cnt <= baud_cnt + 1;
471
                end
472
        end
473
end
474
 
475
 
476
endmodule

powered by: WebSVN 2.1.0

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