Edge sensitive IRQ on UART
[mw/milkymist.git] / cores / uart / rtl / uart.v
1 /*
2  * Milkymist VJ SoC
3  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 module uart #(
19         parameter csr_addr = 4'h0,
20         parameter clk_freq = 100000000,
21         parameter baud = 115200
22 ) (
23         input sys_clk,
24         input sys_rst,
25         
26         input [13:0] csr_a,
27         input csr_we,
28         input [31:0] csr_di,
29         output reg [31:0] csr_do,
30
31         output rx_irq,
32         output tx_irq,
33
34         input uart_rxd,
35         output uart_txd
36 );
37
38 reg [15:0] divisor;
39 wire [7:0] rx_data;
40 wire [7:0] tx_data;
41 wire tx_wr;
42
43 uart_transceiver transceiver(
44         .sys_clk(sys_clk),
45         .sys_rst(sys_rst),
46
47         .uart_rxd(uart_rxd),
48         .uart_txd(uart_txd),
49
50         .divisor(divisor),
51
52         .rx_data(rx_data),
53         .rx_done(rx_irq),
54
55         .tx_data(tx_data),
56         .tx_wr(tx_wr),
57         .tx_done(tx_irq)
58 );
59
60 /* CSR interface */
61 wire csr_selected = csr_a[13:10] == csr_addr;
62
63 assign tx_data = csr_di[7:0];
64 assign tx_wr = csr_selected & csr_we & (csr_a[0] == 1'b0);
65
66 parameter default_divisor = clk_freq/baud/16;
67
68 always @(posedge sys_clk) begin
69         if(sys_rst) begin
70                 divisor <= default_divisor;
71                 csr_do <= 32'd0;
72         end else begin
73                 csr_do <= 32'd0;
74                 if(csr_selected) begin
75                         case(csr_a[0])
76                                 1'b0: csr_do <= rx_data;
77                                 1'b1: csr_do <= divisor;
78                         endcase
79                         if(csr_we) begin
80                                 if(csr_a[0] == 1'b1)
81                                         divisor <= csr_di[15:0];
82                         end
83                 end
84         end
85 end
86
87 endmodule