X-Git-Url: http://git.joshuawise.com/fpgaboy.git/blobdiff_plain/e7fb589a21ee26ad897e03cbd0d7a647d9cd97e5..3db3fc270d517ca76518b47950f5240990e84cc5:/Uart.v?ds=inline diff --git a/Uart.v b/Uart.v index 1f0ae7d..03db0e1 100644 --- a/Uart.v +++ b/Uart.v @@ -1,7 +1,8 @@ `define IN_CLK 8388608 -`define OUT_CLK 57600 +`define OUT_CLK 19200 `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, @@ -9,52 +10,93 @@ module UART( 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 - /* 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'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'b1010: have_data <= 0; + 4'b1010: tx_busy <= 0; 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 + + 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 - clkdiv <= clkdiv + 1; + rx_clkdiv <= rx_clkdiv + 1; end endmodule