]> Joshua Wise's Git repositories - fpgaboy.git/blob - Uart.v
e5213044f684b88f1812e011800883bebcf2bd69
[fpgaboy.git] / Uart.v
1 `define IN_CLK 8388608
2 `define OUT_CLK 57600
3 `define CLK_DIV `IN_CLK / `OUT_CLK
4 `define DATA_ADDR 16'hFF52
5 `define STAT_ADDR 16'hFF53
6
7 module UART(
8         input clk,
9         input wr,
10         input rd,
11         input [15:0] addr,
12         inout [7:0] data,
13         output reg serial = 1);
14
15         wire data_decode = (addr == `DATA_ADDR);
16         wire stat_decode = (addr == `STAT_ADDR);
17         reg data_latch = 0;
18         reg stat_latch = 0;
19         
20         reg [7:0] tx_data = 0;
21         reg [15:0] tx_clkdiv = 0;
22         reg [3:0] tx_state = 4'b1011;   // 1011 is the not busy state.
23         wire tx_busy = tx_state != 4'b1011;
24         wire tx_newdata = (wr) && (!tx_busy) && data_decode;
25         
26         assign data = (rd && stat_latch) ? (tx_busy ? 8'b1 : 8'b0) :
27                         (rd && data_latch) ? (8'b0) :
28                         8'bzzzzzzzz;
29
30         always @(posedge clk)
31         begin
32                 data_latch <= rd && data_decode;
33                 stat_latch <= rd && stat_decode;
34                 /* deal with diqing */
35                 if(tx_newdata) begin
36                         tx_data <= data;
37                         tx_state <= 4'b0000;
38                 end else if (tx_clkdiv == 0) begin
39                         tx_state <= tx_state + 1;
40                         if (tx_busy)
41                                 case (tx_state)
42                                 4'b0000: serial <= 0;
43                                 4'b0001: serial <= tx_data[0];
44                                 4'b0010: serial <= tx_data[1];
45                                 4'b0011: serial <= tx_data[2];
46                                 4'b0100: serial <= tx_data[3];
47                                 4'b0101: serial <= tx_data[4];
48                                 4'b0110: serial <= tx_data[5];
49                                 4'b0111: serial <= tx_data[6];
50                                 4'b1000: serial <= tx_data[7];
51                                 4'b1001: serial <= 1;
52                                 4'b1010: serial <= 1;
53                                 default: $stop;
54                         endcase
55                 end
56
57                 if((tx_newdata && !tx_busy) || (tx_clkdiv == `CLK_DIV))
58                         tx_clkdiv <= 0;
59                 else
60                         tx_clkdiv <= tx_clkdiv + 1;
61         end
62 endmodule
This page took 0.019048 seconds and 2 git commands to generate.