`define IN_CLK 8388608 `define OUT_CLK 57600 `define CLK_DIV `IN_CLK / `OUT_CLK `define MMAP_ADDR 16'hFF50 module UART( input clk, input wr, 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; reg [7:0] data_stor = 0; reg [15:0] clkdiv = 0; reg have_data = 0; reg [3:0] diqing = 4'b0000; wire new = (wr) && (!have_data) && decode; assign odata = have_data ? 8'b1 : 8'b0; always @ (negedge clk) begin /* deal with diqing */ if(new) begin data_stor <= data; have_data <= 1; diqing <= 4'b0000; end else if (clkdiv == 0) begin diqing <= diqing + 1; if (have_data) case (diqing) 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'b1001: serial <= 1; 4'b1010: have_data <= 0; default: $stop; endcase end /* deal with clkdiv */ if((new && !have_data) || clkdiv == `CLK_DIV) clkdiv <= 0; else clkdiv <= clkdiv + 1; end endmodule