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

Subversion Repositories osdvu

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

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 4 pruby
parameter CLOCK_DIVIDE = 1302; // clock rate (50Mhz) / (baud rate (9600) * 4)
39 2 pruby
 
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 4 pruby
                                rx_countdown = 2;
110 2 pruby
                                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 4 pruby
                                        rx_countdown = 4;
121 2 pruby
                                        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 4 pruby
                                rx_countdown = 4;
137 2 pruby
                                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 4 pruby
                        rx_countdown = 8;
161 2 pruby
                        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 4 pruby
                        // cycle while in this state.
167
                        recv_state = RX_IDLE;
168 2 pruby
                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 3 pruby
                                tx_clk_divider = CLOCK_DIVIDE;
182 4 pruby
                                tx_countdown = 4;
183 2 pruby
                                tx_out = 0;
184
                                tx_bits_remaining = 8;
185
                                tx_state = TX_SENDING;
186
                        end
187
                end
188
                TX_SENDING: begin
189
                        if (!tx_countdown) begin
190
                                if (tx_bits_remaining) begin
191
                                        tx_bits_remaining = tx_bits_remaining - 1;
192
                                        tx_out = tx_data[0];
193
                                        tx_data = {1'b0, tx_data[7:1]};
194 4 pruby
                                        tx_countdown = 4;
195 2 pruby
                                        tx_state = TX_SENDING;
196
                                end else begin
197
                                        // Set delay to send out 2 stop bits.
198
                                        tx_out = 1;
199 4 pruby
                                        tx_countdown = 8;
200 2 pruby
                                        tx_state = TX_DELAY_RESTART;
201
                                end
202
                        end
203
                end
204
                TX_DELAY_RESTART: begin
205
                        // Wait until tx_countdown reaches the end before
206
                        // we send another transmission. This covers the
207
                        // "stop bit" delay.
208
                        tx_state = tx_countdown ? TX_DELAY_RESTART : TX_IDLE;
209
                end
210
        endcase
211
end
212
 
213
endmodule

powered by: WebSVN 2.1.0

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