]> Joshua Wise's Git repositories - fpgaboy.git/blame - Uart.v
IP
[fpgaboy.git] / Uart.v
CommitLineData
7d9d69c7 1`define IN_CLK 8388608
6d070aee 2`define OUT_CLK 57600
a0267255 3`define CLK_DIV `IN_CLK / `OUT_CLK
1eefdc8e
JW
4`define DATA_ADDR 16'hFF52
5`define STAT_ADDR 16'hFF53
a0267255
JW
6
7module UART(
8 input clk,
9 input wr,
10 input rd,
11 input [15:0] addr,
a85b19a7 12 inout [7:0] data,
298e8085
JW
13 output reg serial = 1,
14 input serialrx);
a8f4468d 15
1eefdc8e
JW
16 wire data_decode = (addr == `DATA_ADDR);
17 wire stat_decode = (addr == `STAT_ADDR);
18 reg data_latch = 0;
19 reg stat_latch = 0;
a85b19a7 20
1eefdc8e
JW
21 reg [7:0] tx_data = 0;
22 reg [15:0] tx_clkdiv = 0;
298e8085
JW
23 reg [3:0] tx_state = 4'b0000;
24 reg tx_busy = 0;
1eefdc8e 25 wire tx_newdata = (wr) && (!tx_busy) && data_decode;
a85b19a7 26
298e8085
JW
27 reg rx_hasdata = 0;
28 reg [15:0] rx_clkdiv = 0;
29 reg [3:0] rx_state = 4'b0000;
bf3f2c5f 30 reg [7:0] rx_data, rx_data_tmp;
298e8085
JW
31
32 assign data = (stat_latch) ? {6'b0, rx_hasdata, tx_busy} :
33 (data_latch) ? rx_data :
1eefdc8e 34 8'bzzzzzzzz;
a0267255 35
1eefdc8e 36 always @(posedge clk)
a0267255 37 begin
1eefdc8e
JW
38 data_latch <= rd && data_decode;
39 stat_latch <= rd && stat_decode;
1eefdc8e
JW
40 if(tx_newdata) begin
41 tx_data <= data;
42 tx_state <= 4'b0000;
298e8085 43 tx_busy <= 1;
1eefdc8e
JW
44 end else if (tx_clkdiv == 0) begin
45 tx_state <= tx_state + 1;
46 if (tx_busy)
47 case (tx_state)
7d9d69c7 48 4'b0000: serial <= 0;
1eefdc8e
JW
49 4'b0001: serial <= tx_data[0];
50 4'b0010: serial <= tx_data[1];
51 4'b0011: serial <= tx_data[2];
52 4'b0100: serial <= tx_data[3];
53 4'b0101: serial <= tx_data[4];
54 4'b0110: serial <= tx_data[5];
55 4'b0111: serial <= tx_data[6];
56 4'b1000: serial <= tx_data[7];
7d9d69c7 57 4'b1001: serial <= 1;
298e8085 58 4'b1010: tx_busy <= 0;
a0267255 59 default: $stop;
298e8085
JW
60 endcase
61 end
62
63 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Kick off. */
64 rx_state <= 4'b0001;
65 else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
66 if (rx_state != 4'b1010)
67 rx_state <= rx_state + 1;
68 else
69 rx_state <= 0;
70 case (rx_state)
71 4'b0001: begin end /* Twiddle thumbs -- this is the end of the half bit. */
bf3f2c5f
JW
72 4'b0010: rx_data_tmp[0] <= serialrx;
73 4'b0011: rx_data_tmp[1] <= serialrx;
74 4'b0100: rx_data_tmp[2] <= serialrx;
75 4'b0101: rx_data_tmp[3] <= serialrx;
76 4'b0110: rx_data_tmp[4] <= serialrx;
77 4'b0111: rx_data_tmp[5] <= serialrx;
78 4'b1000: rx_data_tmp[6] <= serialrx;
79 4'b1001: rx_data_tmp[7] <= serialrx;
80 4'b1010: if (serialrx == 1) begin
81 rx_data <= rx_data_tmp; /* Expect a 1 */
82 rx_hasdata <= 1;
83 end
a0267255
JW
84 endcase
85 end
298e8085 86
bf3f2c5f
JW
87 if (rd && data_decode)
88 rx_hasdata <= 0;
a0267255 89
298e8085 90 if(tx_newdata || (tx_clkdiv == `CLK_DIV))
1eefdc8e 91 tx_clkdiv <= 0;
a0267255 92 else
1eefdc8e 93 tx_clkdiv <= tx_clkdiv + 1;
298e8085
JW
94
95 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Wait half a period before advancing. */
96 rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
97 else if (rx_clkdiv == `CLK_DIV)
98 rx_clkdiv <= 0;
99 else
100 rx_clkdiv <= rx_clkdiv + 1;
a0267255
JW
101 end
102endmodule
This page took 0.058976 seconds and 5 git commands to generate.