| 1 | `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 = 1302; // clock rate (50Mhz) / (baud rate (9600) * 4) |
| 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] rx_clk_divider = CLOCK_DIVIDE; |
| 57 | reg [10:0] tx_clk_divider = CLOCK_DIVIDE; |
| 58 | |
| 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 | rx_clk_divider = rx_clk_divider - 1; |
| 90 | if (!rx_clk_divider) begin |
| 91 | rx_clk_divider = CLOCK_DIVIDE; |
| 92 | rx_countdown = rx_countdown - 1; |
| 93 | end |
| 94 | tx_clk_divider = tx_clk_divider - 1; |
| 95 | if (!tx_clk_divider) begin |
| 96 | tx_clk_divider = CLOCK_DIVIDE; |
| 97 | 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 | rx_clk_divider = CLOCK_DIVIDE; |
| 109 | rx_countdown = 2; |
| 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 = 4; |
| 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 = 4; |
| 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 = 8; |
| 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. |
| 167 | recv_state = RX_IDLE; |
| 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_clk_divider = CLOCK_DIVIDE; |
| 182 | tx_countdown = 4; |
| 183 | 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 | tx_countdown = 4; |
| 195 | tx_state = TX_SENDING; |
| 196 | end else begin |
| 197 | // Set delay to send out 2 stop bits. |
| 198 | tx_out = 1; |
| 199 | tx_countdown = 8; |
| 200 | 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 |