Root/lm32/logic/sakc/cores/uart/rtl/uart_transceiver.v

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
19module 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//-----------------------------------------------------------------
39reg [15:0] enable16_counter;
40
41wire enable16;
42assign enable16 = (enable16_counter == 16'd0);
43
44always @(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
52end
53
54//-----------------------------------------------------------------
55// Synchronize uart_rxd
56//-----------------------------------------------------------------
57reg uart_rxd1;
58reg uart_rxd2;
59
60always @(posedge sys_clk) begin
61    uart_rxd1 <= uart_rxd;
62    uart_rxd2 <= uart_rxd1;
63end
64
65//-----------------------------------------------------------------
66// UART RX Logic
67//-----------------------------------------------------------------
68reg rx_busy;
69reg [3:0] rx_count16;
70reg [3:0] rx_bitcount;
71reg [7:0] rxd_reg;
72
73always @(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
110end
111
112//-----------------------------------------------------------------
113// UART TX Logic
114//-----------------------------------------------------------------
115reg tx_busy;
116reg [3:0] tx_bitcount;
117reg [3:0] tx_count16;
118reg [7:0] txd_reg;
119
120always @(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
155end
156
157endmodule
158

Archive Download this file

Branches:
master



interactive