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

Subversion Repositories osdvu

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

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
reg [10:0] clk_divider = CLOCK_DIVIDE;
57
 
58
reg [2:0] recv_state = RX_IDLE;
59
reg [5:0] rx_countdown;
60
reg [3:0] rx_bits_remaining;
61
reg [7:0] rx_data;
62
 
63
reg tx_out = 1'b1;
64
reg [1:0] tx_state = TX_IDLE;
65
reg [5:0] tx_countdown;
66
reg [3:0] tx_bits_remaining;
67
reg [7:0] tx_data;
68
 
69
assign received = recv_state == RX_RECEIVED;
70
assign recv_error = recv_state == RX_ERROR;
71
assign is_receiving = recv_state != RX_IDLE;
72
assign rx_byte = rx_data;
73
 
74
assign tx = tx_out;
75
assign is_transmitting = tx_state != TX_IDLE;
76
 
77
always @(posedge clk) begin
78
        if (rst) begin
79
                recv_state = RX_IDLE;
80
                tx_state = TX_IDLE;
81
        end
82
 
83
        // The clk_divider counter counts down from
84
        // the CLOCK_DIVIDE constant. Whenever it
85
        // reaches 0, 1/16 of the bit period has elapsed.
86
   // Countdown timers for the receiving and transmitting
87
        // state machines are decremented.
88
        clk_divider = clk_divider - 1;
89
        if (!clk_divider) begin
90
                clk_divider = CLOCK_DIVIDE;
91
                rx_countdown = rx_countdown - 1;
92
                tx_countdown = tx_countdown - 1;
93
        end
94
 
95
        // Receive state machine
96
        case (recv_state)
97
                RX_IDLE: begin
98
                        // A low pulse on the receive line indicates the
99
                        // start of data.
100
                        if (!rx) begin
101
                                // Wait half the period - should resume in the
102
                                // middle of this first pulse.
103
                                rx_countdown = 8;
104
                                recv_state = RX_CHECK_START;
105
                        end
106
                end
107
                RX_CHECK_START: begin
108
                        if (!rx_countdown) begin
109
                                // Check the pulse is still there
110
                                if (!rx) begin
111
                                        // Pulse still there - good
112
                                        // Wait the bit period to resume half-way
113
                                        // through the first bit.
114
                                        rx_countdown = 16;
115
                                        rx_bits_remaining = 8;
116
                                        recv_state = RX_READ_BITS;
117
                                end else begin
118
                                        // Pulse lasted less than half the period -
119
                                        // not a valid transmission.
120
                                        recv_state = RX_ERROR;
121
                                end
122
                        end
123
                end
124
                RX_READ_BITS: begin
125
                        if (!rx_countdown) begin
126
                                // Should be half-way through a bit pulse here.
127
                                // Read this bit in, wait for the next if we
128
                                // have more to get.
129
                                rx_data = {rx, rx_data[7:1]};
130
                                rx_countdown = 16;
131
                                rx_bits_remaining = rx_bits_remaining - 1;
132
                                recv_state = rx_bits_remaining ? RX_READ_BITS : RX_CHECK_STOP;
133
                        end
134
                end
135
                RX_CHECK_STOP: begin
136
                        if (!rx_countdown) begin
137
                                // Should resume half-way through the stop bit
138
                                // This should be high - if not, reject the
139
                                // transmission and signal an error.
140
                                recv_state = rx ? RX_RECEIVED : RX_ERROR;
141
                        end
142
                end
143
                RX_DELAY_RESTART: begin
144
                        // Waits a set number of cycles before accepting
145
                        // another transmission.
146
                        recv_state = rx_countdown ? RX_DELAY_RESTART : RX_IDLE;
147
                end
148
                RX_ERROR: begin
149
                        // There was an error receiving.
150
                        // Raises the recv_error flag for one clock
151
                        // cycle while in this state and then waits
152
                        // 2 bit periods before accepting another
153
                        // transmission.
154
                        rx_countdown = 32;
155
                        recv_state = RX_DELAY_RESTART;
156
                end
157
                RX_RECEIVED: begin
158
                        // Successfully received a byte.
159
                        // Raises the received flag for one clock
160
                        // cycle while in this state and then waits
161
                        // 1/4 bit period before starting back in the
162
                        // idle state. This only actually waits for
163
                        // 3/4 of the stop bit before resuming, but
164
                        // this should not do any harm as the stop bit
165
                        // is received the same as the line idle state.
166
                        rx_countdown = 4;
167
                        recv_state = RX_DELAY_RESTART;
168
                end
169
        endcase
170
 
171
        // Transmit state machine
172
        case (tx_state)
173
                TX_IDLE: begin
174
                        if (transmit) begin
175
                                // If the transmit flag is raised in the idle
176
                                // state, start transmitting the current content
177
                                // of the tx_byte input.
178
                                tx_data = tx_byte;
179
                                // Send the initial, low pulse of 1 bit period
180
                                // to signal the start, followed by the data
181
                                tx_countdown = 16;
182
                                tx_out = 0;
183
                                tx_bits_remaining = 8;
184
                                tx_state = TX_SENDING;
185
                        end
186
                end
187
                TX_SENDING: begin
188
                        if (!tx_countdown) begin
189
                                if (tx_bits_remaining) begin
190
                                        tx_bits_remaining = tx_bits_remaining - 1;
191
                                        tx_out = tx_data[0];
192
                                        tx_data = {1'b0, tx_data[7:1]};
193
                                        tx_countdown = 16;
194
                                        tx_state = TX_SENDING;
195
                                end else begin
196
                                        // Set delay to send out 2 stop bits.
197
                                        tx_out = 1;
198
                                        tx_countdown = 32;
199
                                        tx_state = TX_DELAY_RESTART;
200
                                end
201
                        end
202
                end
203
                TX_DELAY_RESTART: begin
204
                        // Wait until tx_countdown reaches the end before
205
                        // we send another transmission. This covers the
206
                        // "stop bit" delay.
207
                        tx_state = tx_countdown ? TX_DELAY_RESTART : TX_IDLE;
208
                end
209
        endcase
210
end
211
 
212
endmodule

powered by: WebSVN 2.1.0

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