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

Subversion Repositories osdvu

[/] [osdvu/] [trunk/] [uart.v] - Blame information for rev 3

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

Line No. Rev Author Line
1 2 pruby
`timescale 1ns / 1ps
2
// Documented Verilog UART
3
// Copyright (C) 2010 Timothy Goddard (tim@goddard.net.nz)
4
// Distributed under the MIT licence.
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining a copy
7
// of this software and associated documentation files (the "Software"), to deal
8
// in the Software without restriction, including without limitation the rights
9
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
// copies of the Software, and to permit persons to whom the Software is
11
// furnished to do so, subject to the following conditions:
12
// 
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
// 
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
// THE SOFTWARE.
23
// 
24
module uart(
25
    input clk, // The master clock for this module
26
    input rst, // Synchronous reset.
27
    input rx, // Incoming serial line
28
    output tx, // Outgoing serial line
29
    input transmit, // Signal to transmit
30
    input [7:0] tx_byte, // Byte to transmit
31
    output received, // Indicated that a byte has been received.
32
    output [7:0] rx_byte, // Byte received
33
    output is_receiving, // Low when receive line is idle.
34
    output is_transmitting, // Low when transmit line is idle.
35
    output recv_error // Indicates error in receiving packet.
36
    );
37
 
38
parameter CLOCK_DIVIDE = 325; // clock rate (50Mhz) / baud rate (9600) / 16
39
 
40
// States for the receiving state machine.
41
// These are just constants, not parameters to override.
42
parameter RX_IDLE = 0;
43
parameter RX_CHECK_START = 1;
44
parameter RX_READ_BITS = 2;
45
parameter RX_CHECK_STOP = 3;
46
parameter RX_DELAY_RESTART = 4;
47
parameter RX_ERROR = 5;
48
parameter RX_RECEIVED = 6;
49
 
50
// States for the transmitting state machine.
51
// Constants - do not override.
52
parameter TX_IDLE = 0;
53
parameter TX_SENDING = 1;
54
parameter TX_DELAY_RESTART = 2;
55
 
56 3 pruby
reg [10:0] rx_clk_divider = CLOCK_DIVIDE;
57
reg [10:0] tx_clk_divider = CLOCK_DIVIDE;
58 2 pruby
 
59
reg [2:0] recv_state = RX_IDLE;
60
reg [5:0] rx_countdown;
61
reg [3:0] rx_bits_remaining;
62
reg [7:0] rx_data;
63
 
64
reg tx_out = 1'b1;
65
reg [1:0] tx_state = TX_IDLE;
66
reg [5:0] tx_countdown;
67
reg [3:0] tx_bits_remaining;
68
reg [7:0] tx_data;
69
 
70
assign received = recv_state == RX_RECEIVED;
71
assign recv_error = recv_state == RX_ERROR;
72
assign is_receiving = recv_state != RX_IDLE;
73
assign rx_byte = rx_data;
74
 
75
assign tx = tx_out;
76
assign is_transmitting = tx_state != TX_IDLE;
77
 
78
always @(posedge clk) begin
79
        if (rst) begin
80
                recv_state = RX_IDLE;
81
                tx_state = TX_IDLE;
82
        end
83
 
84
        // The clk_divider counter counts down from
85
        // the CLOCK_DIVIDE constant. Whenever it
86
        // reaches 0, 1/16 of the bit period has elapsed.
87
   // Countdown timers for the receiving and transmitting
88
        // state machines are decremented.
89 3 pruby
        rx_clk_divider = rx_clk_divider - 1;
90
        if (!rx_clk_divider) begin
91
                rx_clk_divider = CLOCK_DIVIDE;
92 2 pruby
                rx_countdown = rx_countdown - 1;
93 3 pruby
        end
94
        tx_clk_divider = tx_clk_divider - 1;
95
        if (!tx_clk_divider) begin
96
                tx_clk_divider = CLOCK_DIVIDE;
97 2 pruby
                tx_countdown = tx_countdown - 1;
98
        end
99
 
100
        // Receive state machine
101
        case (recv_state)
102
                RX_IDLE: begin
103
                        // A low pulse on the receive line indicates the
104
                        // start of data.
105
                        if (!rx) begin
106
                                // Wait half the period - should resume in the
107
                                // middle of this first pulse.
108 3 pruby
                                rx_clk_divider = CLOCK_DIVIDE;
109 2 pruby
                                rx_countdown = 8;
110
                                recv_state = RX_CHECK_START;
111
                        end
112
                end
113
                RX_CHECK_START: begin
114
                        if (!rx_countdown) begin
115
                                // Check the pulse is still there
116
                                if (!rx) begin
117
                                        // Pulse still there - good
118
                                        // Wait the bit period to resume half-way
119
                                        // through the first bit.
120
                                        rx_countdown = 16;
121
                                        rx_bits_remaining = 8;
122
                                        recv_state = RX_READ_BITS;
123
                                end else begin
124
                                        // Pulse lasted less than half the period -
125
                                        // not a valid transmission.
126
                                        recv_state = RX_ERROR;
127
                                end
128
                        end
129
                end
130
                RX_READ_BITS: begin
131
                        if (!rx_countdown) begin
132
                                // Should be half-way through a bit pulse here.
133
                                // Read this bit in, wait for the next if we
134
                                // have more to get.
135
                                rx_data = {rx, rx_data[7:1]};
136
                                rx_countdown = 16;
137
                                rx_bits_remaining = rx_bits_remaining - 1;
138
                                recv_state = rx_bits_remaining ? RX_READ_BITS : RX_CHECK_STOP;
139
                        end
140
                end
141
                RX_CHECK_STOP: begin
142
                        if (!rx_countdown) begin
143
                                // Should resume half-way through the stop bit
144
                                // This should be high - if not, reject the
145
                                // transmission and signal an error.
146
                                recv_state = rx ? RX_RECEIVED : RX_ERROR;
147
                        end
148
                end
149
                RX_DELAY_RESTART: begin
150
                        // Waits a set number of cycles before accepting
151
                        // another transmission.
152
                        recv_state = rx_countdown ? RX_DELAY_RESTART : RX_IDLE;
153
                end
154
                RX_ERROR: begin
155
                        // There was an error receiving.
156
                        // Raises the recv_error flag for one clock
157
                        // cycle while in this state and then waits
158
                        // 2 bit periods before accepting another
159
                        // transmission.
160
                        rx_countdown = 32;
161
                        recv_state = RX_DELAY_RESTART;
162
                end
163
                RX_RECEIVED: begin
164
                        // Successfully received a byte.
165
                        // Raises the received flag for one clock
166
                        // cycle while in this state and then waits
167
                        // 1/4 bit period before starting back in the
168
                        // idle state. This only actually waits for
169
                        // 3/4 of the stop bit before resuming, but
170
                        // this should not do any harm as the stop bit
171
                        // is received the same as the line idle state.
172
                        rx_countdown = 4;
173
                        recv_state = RX_DELAY_RESTART;
174
                end
175
        endcase
176
 
177
        // Transmit state machine
178
        case (tx_state)
179
                TX_IDLE: begin
180
                        if (transmit) begin
181
                                // If the transmit flag is raised in the idle
182
                                // state, start transmitting the current content
183
                                // of the tx_byte input.
184
                                tx_data = tx_byte;
185
                                // Send the initial, low pulse of 1 bit period
186
                                // to signal the start, followed by the data
187 3 pruby
                                tx_clk_divider = CLOCK_DIVIDE;
188 2 pruby
                                tx_countdown = 16;
189
                                tx_out = 0;
190
                                tx_bits_remaining = 8;
191
                                tx_state = TX_SENDING;
192
                        end
193
                end
194
                TX_SENDING: begin
195
                        if (!tx_countdown) begin
196
                                if (tx_bits_remaining) begin
197
                                        tx_bits_remaining = tx_bits_remaining - 1;
198
                                        tx_out = tx_data[0];
199
                                        tx_data = {1'b0, tx_data[7:1]};
200
                                        tx_countdown = 16;
201
                                        tx_state = TX_SENDING;
202
                                end else begin
203
                                        // Set delay to send out 2 stop bits.
204
                                        tx_out = 1;
205
                                        tx_countdown = 32;
206
                                        tx_state = TX_DELAY_RESTART;
207
                                end
208
                        end
209
                end
210
                TX_DELAY_RESTART: begin
211
                        // Wait until tx_countdown reaches the end before
212
                        // we send another transmission. This covers the
213
                        // "stop bit" delay.
214
                        tx_state = tx_countdown ? TX_DELAY_RESTART : TX_IDLE;
215
                end
216
        endcase
217
end
218
 
219
endmodule

powered by: WebSVN 2.1.0

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