module uartmm(input clk,
              input             rst,

              input             RX,
              output            TX,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   reg [7:0]                uart_din_r;
   reg                      uart_valid_r;
   reg                      uart_ready_r;
   
   reg [7:0]                input_axis_tdata;
   reg                      input_axis_tvalid;
   wire                     input_axis_tready;
   
   
   wire [7:0]               output_axis_tdata;
   wire                     output_axis_tvalid;
   reg                      output_axis_tready;
   
   uart _uart (
               .clk(clk),
               .rst(~rst),
               
               .rxd(RX),
               .txd(TX),

               .input_axis_tdata(input_axis_tdata),
               .input_axis_tvalid(input_axis_tvalid),
               .input_axis_tready(input_axis_tready),

               .output_axis_tdata(output_axis_tdata),
               .output_axis_tvalid(output_axis_tvalid),
               .output_axis_tready(output_axis_tready),
               
               //  100MHz
               .prescale(100000000/(115200*8)));
   
   assign strobe_b_next = (addr_b == 65537) | (addr_b == 65538) | (addr_b == 65539);
   assign data_b_next = (addr_b == 65537)?uart_valid_r:
                        (addr_b == 65538)?uart_ready_r:
                        (addr_b == 65539)?uart_din_r:0;

   always @(posedge clk)
     if (~rst) begin
        uart_din_r <= 0;
        uart_valid_r <= 0;
        uart_ready_r <= 0;
        input_axis_tdata <= 0;
        input_axis_tvalid <= 0;
        output_axis_tready <= 0;
     end else begin

        data_b <= data_b_next;
        strobe_b <= strobe_b_next;
        
        if (input_axis_tvalid) begin
           input_axis_tvalid <= 0;
        end
        
        if (output_axis_tvalid & ~output_axis_tready) begin
           output_axis_tready <= 1;
        end

        uart_ready_r <= input_axis_tready; // delay

        if (output_axis_tvalid) begin
           output_axis_tready <= 0;
           uart_din_r <= output_axis_tdata;
           uart_valid_r <= 1;
        end else if ((addr_b == 65539) & ~data_b_we & uart_valid_r) begin
           uart_valid_r <= 0;
        end else if ((addr_b == 65539) & data_b_we & input_axis_tready & ~input_axis_tvalid) begin
           input_axis_tdata <= data_b[7:0];
           input_axis_tvalid <= 1;
        end
     end
   

endmodule