Fix the UART, and set it to 19k2 for more stable operation. Make the downloader a...
[fpgaboy.git] / Uart.v
diff --git a/Uart.v b/Uart.v
index 1f0ae7d..03db0e1 100644 (file)
--- a/Uart.v
+++ b/Uart.v
@@ -1,7 +1,8 @@
 `define IN_CLK 8388608
 `define IN_CLK 8388608
-`define OUT_CLK 57600
+`define OUT_CLK 19200
 `define CLK_DIV `IN_CLK / `OUT_CLK
 `define CLK_DIV `IN_CLK / `OUT_CLK
-`define MMAP_ADDR 16'hFF50
+`define DATA_ADDR 16'hFF52
+`define STAT_ADDR 16'hFF53
 
 module UART(
        input clk,
 
 module UART(
        input clk,
@@ -9,52 +10,93 @@ module UART(
        input rd,
        input [15:0] addr,
        inout [7:0] data,
        input rd,
        input [15:0] addr,
        inout [7:0] data,
-       output reg serial = 1);
-       
-       wire decode = (addr == `MMAP_ADDR);
-       
-       wire [7:0] odata;
-       assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
+       output reg serial = 1,
+       input serialrx);
 
 
-       reg [7:0] data_stor = 0;
-       reg [15:0] clkdiv = 0;
-       reg have_data = 0;
-       reg [3:0] diqing = 4'b0000;
+       wire data_decode = (addr == `DATA_ADDR);
+       wire stat_decode = (addr == `STAT_ADDR);
+       reg data_latch = 0;
+       reg stat_latch = 0;
+       
+       reg [7:0] tx_data = 0;
+       reg [15:0] tx_clkdiv = 0;
+       reg [3:0] tx_state = 4'b0000;
+       reg tx_busy = 0;
+       wire tx_newdata = (wr) && (!tx_busy) && data_decode;
        
        
-       wire newdata = (wr) && (!have_data) && decode;
+       reg rx_hasdata = 0;
+       reg [15:0] rx_clkdiv = 0;
+       reg [3:0] rx_state = 4'b0000;
+       reg [7:0] rx_data, rx_data_tmp;
        
        
-       assign odata = have_data ? 8'b1 : 8'b0;
+       assign data = (stat_latch) ? {6'b0, rx_hasdata, tx_busy} :
+                       (data_latch) ? rx_data :
+                       8'bzzzzzzzz;
 
 
-       always @ (negedge clk)
+       always @(posedge clk)
        begin
        begin
-               /* deal with diqing */
-               if(newdata) begin
-                       data_stor <= data;
-                       have_data <= 1;
-                       diqing <= 4'b0000;
-               end else if (clkdiv == 0) begin
-                       diqing <= diqing + 1;
-                       if (have_data)
-                               case (diqing)
+               data_latch <= rd && data_decode;
+               stat_latch <= rd && stat_decode;
+               if(tx_newdata) begin
+                       tx_data <= data;
+                       tx_state <= 4'b0000;
+                       tx_busy <= 1;
+               end else if (tx_clkdiv == 0) begin
+                       tx_state <= tx_state + 1;
+                       if (tx_busy)
+                               case (tx_state)
                                4'b0000: serial <= 0;
                                4'b0000: serial <= 0;
-                               4'b0001: serial <= data_stor[0];
-                               4'b0010: serial <= data_stor[1];
-                               4'b0011: serial <= data_stor[2];
-                               4'b0100: serial <= data_stor[3];
-                               4'b0101: serial <= data_stor[4];
-                               4'b0110: serial <= data_stor[5];
-                               4'b0111: serial <= data_stor[6];
-                               4'b1000: serial <= data_stor[7];
+                               4'b0001: serial <= tx_data[0];
+                               4'b0010: serial <= tx_data[1];
+                               4'b0011: serial <= tx_data[2];
+                               4'b0100: serial <= tx_data[3];
+                               4'b0101: serial <= tx_data[4];
+                               4'b0110: serial <= tx_data[5];
+                               4'b0111: serial <= tx_data[6];
+                               4'b1000: serial <= tx_data[7];
                                4'b1001: serial <= 1;
                                4'b1001: serial <= 1;
-                               4'b1010: have_data <= 0;
+                               4'b1010: tx_busy <= 0;
                                default: $stop;
                                default: $stop;
+                               endcase
+               end
+               
+               if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Kick off. */
+                       rx_state <= 4'b0001;
+               else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
+                       if (rx_state != 4'b1010)
+                               rx_state <= rx_state + 1;
+                       else
+                               rx_state <= 0;
+                       case (rx_state)
+                       4'b0001:        begin end /* Twiddle thumbs -- this is the end of the half bit. */
+                       4'b0010:        rx_data_tmp[0] <= serialrx;
+                       4'b0011:        rx_data_tmp[1] <= serialrx;
+                       4'b0100:        rx_data_tmp[2] <= serialrx;
+                       4'b0101:        rx_data_tmp[3] <= serialrx;
+                       4'b0110:        rx_data_tmp[4] <= serialrx;
+                       4'b0111:        rx_data_tmp[5] <= serialrx;
+                       4'b1000:        rx_data_tmp[6] <= serialrx;
+                       4'b1001:        rx_data_tmp[7] <= serialrx;
+                       4'b1010:        if (serialrx == 1) begin
+                                               rx_data <= rx_data_tmp; /* Expect a 1 */
+                                               rx_hasdata <= 1;
+                                       end
                        endcase
                end
                        endcase
                end
+               
+               if (rd && data_decode)
+                       rx_hasdata <= 0;
 
 
-               /* deal with clkdiv */
-               if((newdata && !have_data) || clkdiv == `CLK_DIV)
-                       clkdiv <= 0;
+               if(tx_newdata || (tx_clkdiv == `CLK_DIV))
+                       tx_clkdiv <= 0;
+               else
+                       tx_clkdiv <= tx_clkdiv + 1;
+               
+               if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Wait half a period before advancing. */
+                       rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
+               else if (rx_clkdiv == `CLK_DIV)
+                       rx_clkdiv <= 0;
                else
                else
-                       clkdiv <= clkdiv + 1;
+                       rx_clkdiv <= rx_clkdiv + 1;
        end
 endmodule
        end
 endmodule
This page took 0.022689 seconds and 4 git commands to generate.