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

Subversion Repositories softavrcore

[/] [softavrcore/] [trunk/] [peripherals/] [avr_io_uart.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 apal
/*****************************************************************************/
2
/* avr_io_uart.v                                                             */
3
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4
/* (c) 2019-2020; Andras Pal <apal@szofi.net>                                */
5
/*****************************************************************************/
6
 
7
module uart_tx (input clk, input [7:0] prescaler, input [7:0] tx_in, input strobe, output reg txd, output busy, output prefetch);
8
 
9
parameter TX_STATE_IDLE = 0;
10
parameter TX_STATE_TRANSMIT = 1;
11
 
12
reg state = TX_STATE_IDLE;
13
 
14
//reg txd = 1;
15
 
16
reg [7:0] count = 0;
17
reg [7:0] scaler_counter = 0;
18
 
19
reg [7:0] dataout = 0;
20
 
21
parameter count_step = 2;
22
assign busy = state;
23
 
24
wire scaler_limit = (scaler_counter==0);
25
wire bit_limit = (count[3:0] == 4'b0000);
26
wire last_bit = (count[7:4]==4'd10);
27
 
28
assign prefetch = ( state==TX_STATE_TRANSMIT ) & scaler_limit & bit_limit & last_bit;
29
 
30
always @(posedge clk) begin
31
 
32
        if ( state==TX_STATE_IDLE && strobe ) begin
33
                state <= TX_STATE_TRANSMIT;
34
                txd <= 0;
35
                count <= count_step;
36
                dataout <= tx_in;
37
                scaler_counter <= prescaler;
38
        end else if ( state==TX_STATE_TRANSMIT && scaler_limit ) begin
39
                if ( bit_limit ) begin
40
                        if ( last_bit ) begin
41
                                if ( strobe ) begin
42
                                        txd <= 0;
43
                                        count <= count_step;
44
                                        dataout <= tx_in;
45
                                end else begin
46
                                        txd <= 1;
47
                                        state <= TX_STATE_IDLE;
48
                                end
49
                        end else begin
50
                                txd <= dataout[0];
51
                                dataout <= { 1'b1, dataout[7:1] };
52
                                count <= count + count_step;
53
                        end
54
                end else begin
55
                        count <= count + count_step;
56
                end
57
                scaler_counter <= prescaler;
58
        end else if ( state==TX_STATE_TRANSMIT ) begin
59
                scaler_counter <= scaler_counter - 1;
60
        end
61
 
62
end
63
 
64
endmodule
65
 
66
/*****************************************************************************/
67
 
68
module uart_rx (input clk, input [7:0] prescaler, input rxd, input reset, output [7:0] rx_out, output reg avail);
69
 
70
parameter STATE_IDLE = 0;
71
parameter STATE_STARTBIT = 2;
72
parameter STATE_RECEIVE = 3;
73
 
74
reg [1:0] state = STATE_IDLE;
75
 
76
reg [7:0] count = 0;
77
reg [7:0] scaler_counter = 0;
78
 
79
reg [7:0] datain = 0;
80
//reg avail = 0;
81
 
82
parameter count_step = 2;
83
 
84
wire rx_sub_bit = ( state==STATE_RECEIVE && scaler_counter==0 );
85
wire rx_bit = (rx_sub_bit && count[3:0] == 4'b0000);
86
wire rx_completed = (rx_bit && count[7:4]==4'd9 );
87
 
88
assign rx_out = datain;
89
 
90
always @(posedge clk) begin
91
 
92
        if ( state==STATE_IDLE && rxd==0 ) begin
93
                state <= STATE_STARTBIT;
94
                count <= count_step;
95
                scaler_counter <= prescaler;
96
        end else if ( state==STATE_STARTBIT && scaler_counter==0 ) begin
97
                if ( count[3:0] == 4'b1000 ) begin
98
                        state <= STATE_RECEIVE;
99
                        count <= count_step;
100
                end else begin
101
                        count <= count + count_step;
102
                end
103
                scaler_counter <= prescaler;
104
        end else if ( state==STATE_RECEIVE && scaler_counter==0 ) begin
105
                if ( count[3:0] == 4'b0000 ) begin
106
                        if ( count[7:4]==4'd9 ) begin
107
                                state <= STATE_IDLE;
108
                        end else begin
109
                                datain <= { rxd, datain[7:1] };
110
                                count <= count + count_step;
111
                        end
112
                end else begin
113
                        count <= count + count_step;
114
                end
115
                scaler_counter <= prescaler;
116
        end else if ( state[1] ) begin
117
                scaler_counter <= scaler_counter - 1;
118
        end
119
 
120
        avail <= rx_completed | (avail & ~reset);
121
 
122
end
123
 
124
endmodule
125
 
126
/*****************************************************************************/
127
 
128
module avr_io_uart
129
 (      input clk,
130
        input rst,
131
 
132
        input io_re,
133
        input io_we,
134
        input [1:0] io_a,
135
        output [7:0] io_do,
136
        input [7:0] io_di,
137
 
138
        output txd,
139
        input rxd,
140
 
141
        output  [2:0] irq
142
 );
143
 
144
reg [7:0] UDR_TX = 0;
145
reg [7:0] UDR_RX  = 0;
146
reg [7:0] UCSRB  = 0;
147
reg [7:0] UBRR  = 0;
148
 
149
parameter UCSRA_RXB8    = 3'd0;
150
parameter UCSRA_x1      = 3'd1;
151
parameter UCSRA_PE      = 3'd2;
152
parameter UCSRA_DOR     = 3'd3;
153
parameter UCSRA_FE      = 3'd4;
154
parameter UCSRA_UDRE    = 3'd5;
155
parameter UCSRA_TXC     = 3'd6;
156
parameter UCSRA_RXC     = 3'd7;
157
 
158
wire    RXCIE, TXCIE, UDRIE, USBS, UPM1, UPM0, UCSZ, TXB8;
159
assign  { RXCIE, TXCIE, UDRIE, USBS, UPM1, UPM0, UCSZ, TXB8 } = UCSRB;
160
 
161
reg     rx0_non_empty = 0, rx0_overrun = 0, rx0_reset = 0;
162
wire    tx0_txd,tx0_busy,tx0_prefetch;
163
reg     tx0_non_empty = 0;
164
 
165
wire [7:0] UCSRA = { rx0_non_empty, ~tx0_busy, ~tx0_non_empty, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0 };
166
 
167
assign  irq = UCSRB[7:5] & UCSRA[7:5];
168
 
169
/* I/O read: */
170
reg [7:0] io_do_data;
171
always @(*) begin
172
        casex (io_a)
173
                2'b00: io_do_data = UDR_RX[7:0];
174
                2'b01: io_do_data = UCSRA;
175
                2'b10: io_do_data = UCSRB;
176
                2'b11: io_do_data = UBRR;
177
        endcase
178
end
179
assign io_do = io_re ? io_do_data : 8'b00000000;
180
 
181
/* I/O write: configuration: */
182
always @(posedge clk) begin
183
        if ( io_we ) begin
184
                casex (io_a)
185
                        2'b10: UCSRB <= io_di;
186
                        2'b11: UBRR <= io_di;
187
                endcase
188
        end
189
end
190
 
191
/* TX */
192
 
193
 
194
uart_tx tx0 (clk, UBRR, UDR_TX, tx0_non_empty, tx0_txd, tx0_busy, tx0_prefetch);
195
 
196
/* transmitter state changes: */
197
always @(posedge clk) begin
198
        if ( io_we && io_a == 2'b00 && ~tx0_non_empty ) begin
199
                tx0_non_empty <= 1;
200
                UDR_TX <= io_di;
201
        end else if ( (tx0_non_empty & ~tx0_busy) | tx0_prefetch )
202
                tx0_non_empty <= 0;
203
end
204
 
205
assign  txd = tx0_txd | (~tx0_busy);
206
 
207
/* RX */
208
 
209
wire [7:0] rx0_data;
210
wire    rx0_avail;
211
 
212
uart_rx rx0 (clk, UBRR, rxd, rx0_reset, rx0_data, rx0_avail);
213
 
214
/* receiver state changes: */
215
always @(posedge clk) begin
216
        if ( io_re && io_a == 2'b00 ) begin
217
                rx0_non_empty <= 0;
218
                rx0_overrun   <= 0;
219
        end else if ( rx0_avail && ~rx0_reset ) begin
220
                UDR_RX <= rx0_data;
221
                rx0_non_empty <= 1;
222
                rx0_overrun   <= rx0_non_empty;
223
                rx0_reset <= 1;
224
        end else begin
225
                rx0_reset <= 0;
226
        end
227
end
228
 
229
/*****************************************************************************/
230
/* Debug section starts here */
231
 
232
`ifdef SIMULATOR
233
initial begin
234
        $dumpvars(1,UDR_TX,UDR_RX,UCSRB,UBRR,tx0_non_empty,tx0_busy,tx0_prefetch);
235
        $dumpvars(1,rxd,rx0_non_empty,rx0_avail,rx0_data,rx0_reset,rx0_overrun);
236
end
237
`endif
238
 
239
/* end of debug section */
240
/*****************************************************************************/
241
 
242
endmodule
243
 
244
/*****************************************************************************/

powered by: WebSVN 2.1.0

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