Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | /* |
| 2 | * Milkymist VJ SoC |
| 3 | * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq |
| 4 | * Copyright (C) 2007 Das Labor |
| 5 | * |
| 6 | * This program is free software: you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation, version 3 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ |
| 18 | |
| 19 | module uart_transceiver( |
| 20 | input sys_rst, |
| 21 | input sys_clk, |
| 22 | |
| 23 | input uart_rxd, |
| 24 | output reg uart_txd, |
| 25 | |
| 26 | input [15:0] divisor, |
| 27 | |
| 28 | output reg [7:0] rx_data, |
| 29 | output reg rx_done, |
| 30 | |
| 31 | input [7:0] tx_data, |
| 32 | input tx_wr, |
| 33 | output reg tx_done |
| 34 | ); |
| 35 | |
| 36 | //----------------------------------------------------------------- |
| 37 | // enable16 generator |
| 38 | //----------------------------------------------------------------- |
| 39 | reg [15:0] enable16_counter; |
| 40 | |
| 41 | wire enable16; |
| 42 | assign enable16 = (enable16_counter == 16'd0); |
| 43 | |
| 44 | always @(posedge sys_clk) begin |
| 45 | if(sys_rst) |
| 46 | enable16_counter <= divisor - 16'b1; |
| 47 | else begin |
| 48 | enable16_counter <= enable16_counter - 16'd1; |
| 49 | if(enable16) |
| 50 | enable16_counter <= divisor - 16'b1; |
| 51 | end |
| 52 | end |
| 53 | |
| 54 | //----------------------------------------------------------------- |
| 55 | // Synchronize uart_rxd |
| 56 | //----------------------------------------------------------------- |
| 57 | reg uart_rxd1; |
| 58 | reg uart_rxd2; |
| 59 | |
| 60 | always @(posedge sys_clk) begin |
| 61 | uart_rxd1 <= uart_rxd; |
| 62 | uart_rxd2 <= uart_rxd1; |
| 63 | end |
| 64 | |
| 65 | //----------------------------------------------------------------- |
| 66 | // UART RX Logic |
| 67 | //----------------------------------------------------------------- |
| 68 | reg rx_busy; |
| 69 | reg [3:0] rx_count16; |
| 70 | reg [3:0] rx_bitcount; |
| 71 | reg [7:0] rxd_reg; |
| 72 | |
| 73 | always @(posedge sys_clk) begin |
| 74 | if(sys_rst) begin |
| 75 | rx_done <= 1'b0; |
| 76 | rx_busy <= 1'b0; |
| 77 | rx_count16 <= 4'd0; |
| 78 | rx_bitcount <= 4'd0; |
| 79 | end else begin |
| 80 | rx_done <= 1'b0; |
| 81 | |
| 82 | if(enable16) begin |
| 83 | if(~rx_busy) begin // look for start bit |
| 84 | if(~uart_rxd2) begin // start bit found |
| 85 | rx_busy <= 1'b1; |
| 86 | rx_count16 <= 4'd7; |
| 87 | rx_bitcount <= 4'd0; |
| 88 | end |
| 89 | end else begin |
| 90 | rx_count16 <= rx_count16 + 4'd1; |
| 91 | |
| 92 | if(rx_count16 == 4'd0) begin // sample |
| 93 | rx_bitcount <= rx_bitcount + 4'd1; |
| 94 | |
| 95 | if(rx_bitcount == 4'd0) begin // verify startbit |
| 96 | if(uart_rxd2) |
| 97 | rx_busy <= 1'b0; |
| 98 | end else if(rx_bitcount == 4'd9) begin |
| 99 | rx_busy <= 1'b0; |
| 100 | if(uart_rxd2) begin // stop bit ok |
| 101 | rx_data <= rxd_reg; |
| 102 | rx_done <= 1'b1; |
| 103 | end // ignore RX error |
| 104 | end else |
| 105 | rxd_reg <= {uart_rxd2, rxd_reg[7:1]}; |
| 106 | end |
| 107 | end |
| 108 | end |
| 109 | end |
| 110 | end |
| 111 | |
| 112 | //----------------------------------------------------------------- |
| 113 | // UART TX Logic |
| 114 | //----------------------------------------------------------------- |
| 115 | reg tx_busy; |
| 116 | reg [3:0] tx_bitcount; |
| 117 | reg [3:0] tx_count16; |
| 118 | reg [7:0] txd_reg; |
| 119 | |
| 120 | always @(posedge sys_clk) begin |
| 121 | if(sys_rst) begin |
| 122 | tx_done <= 1'b0; |
| 123 | tx_busy <= 1'b0; |
| 124 | uart_txd <= 1'b1; |
| 125 | end else begin |
| 126 | tx_done <= 1'b0; |
| 127 | if(tx_wr) begin |
| 128 | txd_reg <= tx_data; |
| 129 | tx_bitcount <= 4'd0; |
| 130 | tx_count16 <= 4'd1; |
| 131 | tx_busy <= 1'b1; |
| 132 | uart_txd <= 1'b0; |
| 133 | `ifdef SIMULATION |
| 134 | $display("UART: %c", tx_data); |
| 135 | `endif |
| 136 | end else if(enable16 && tx_busy) begin |
| 137 | tx_count16 <= tx_count16 + 4'd1; |
| 138 | |
| 139 | if(tx_count16 == 4'd0) begin |
| 140 | tx_bitcount <= tx_bitcount + 4'd1; |
| 141 | |
| 142 | if(tx_bitcount == 4'd8) begin |
| 143 | uart_txd <= 1'b1; |
| 144 | end else if(tx_bitcount == 4'd9) begin |
| 145 | uart_txd <= 1'b1; |
| 146 | tx_busy <= 1'b0; |
| 147 | tx_done <= 1'b1; |
| 148 | end else begin |
| 149 | uart_txd <= txd_reg[0]; |
| 150 | txd_reg <= {1'b0, txd_reg[7:1]}; |
| 151 | end |
| 152 | end |
| 153 | end |
| 154 | end |
| 155 | end |
| 156 | |
| 157 | endmodule |
| 158 |
Branches:
master
