From b2827b2fb42b2d2b9749daffbb4411ae132f0dc8 Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Mon, 6 Apr 2020 19:54:40 +0800 Subject: [PATCH] uart: update Signed-off-by: liangkangnan --- rtl/perips/uart_tx.v | 183 +++++++++++++------------------------------ 1 file changed, 54 insertions(+), 129 deletions(-) diff --git a/rtl/perips/uart_tx.v b/rtl/perips/uart_tx.v index 26958fb..ef371a6 100644 --- a/rtl/perips/uart_tx.v +++ b/rtl/perips/uart_tx.v @@ -32,23 +32,19 @@ module uart_tx( ); - localparam BAUD_115200 = 32'h1B3; + localparam BAUD_115200 = 32'h1B8; localparam S_IDLE = 4'b0001; localparam S_START = 4'b0010; localparam S_SEND_BYTE = 4'b0100; localparam S_STOP = 4'b1000; - reg[31:0] fifo_data[31:0]; reg tx_data_valid; reg tx_data_ready; - reg[8:0] fifo_index; - reg[8:0] fifo_count; reg[3:0] state; - reg[3:0] next_state; reg[15:0] cycle_cnt; - reg[2:0] bit_cnt; + reg[3:0] bit_cnt; reg[7:0] tx_data; reg tx_reg; @@ -57,8 +53,17 @@ module uart_tx( localparam UART_BAUD = 4'h8; localparam UART_TXDATA = 4'hc; + // addr: 0x00 + // rw. bit[0]: tx enable, 1 = enable, 0 = disable reg[31:0] uart_ctrl; + + // addr: 0x04 + // ro. bit[0]: tx busy, 1 = busy, 0 = idle + // must check this bit before tx data reg[31:0] uart_status; + + // addr: 0x08 + // rw. clk div reg[31:0] uart_baud; @@ -69,44 +74,29 @@ module uart_tx( if (rst == 1'b0) begin uart_ctrl <= 32'h0; uart_status <= 32'h0; - fifo_count <= 8'h0; - fifo_index <= 8'h0; uart_baud <= BAUD_115200; + tx_data_valid <= 1'b0; end else begin if (we_i == 1'b1) begin case (addr_i[3:0]) UART_CTRL: begin uart_ctrl <= data_i; - if (data_i[1] == 1'b1) begin - fifo_count <= 8'h0; - end - if (uart_ctrl[0] == 1'b0 && data_i[0] == 1'b1) begin - if (fifo_count > 8'h0) begin - tx_data_valid <= 1'b1; - fifo_index <= 8'h0; - uart_status <= 32'h1; - end - end end UART_BAUD: begin uart_baud <= data_i; end UART_TXDATA: begin - if (fifo_count <= 8'd31) begin - fifo_data[fifo_count] <= data_i; - fifo_count <= fifo_count + 1'b1; + if (uart_ctrl[0] == 1'b1 && uart_status[0] == 1'b0) begin + tx_data <= data_i[7:0]; + uart_status <= 32'h1; + tx_data_valid <= 1'b1; end end endcase end else begin - if (tx_data_ready == 1'b1 && tx_data_valid == 1'b1) begin - fifo_count <= 8'h0; - tx_data_valid <= 1'b0; - fifo_index <= 8'h0; + tx_data_valid <= 1'b0; + if (tx_data_ready == 1'b1) begin uart_status <= 32'h0; - uart_ctrl[0] <= 1'b0; - end else if (cycle_cnt == uart_baud[15:0] && bit_cnt == 3'd7) begin - fifo_index <= fifo_index + 1'b1; end end end @@ -136,112 +126,47 @@ module uart_tx( always @ (posedge clk) begin if (rst == 1'b0) begin state <= S_IDLE; + cycle_cnt <= 16'd0; + tx_reg <= 1'b0; + bit_cnt <= 4'd0; + tx_data_ready <= 1'b0; end else begin - state <= next_state; - end - end - - always @ (*) begin - case (state) - S_IDLE: begin + if (state == S_IDLE) begin + tx_reg <= 1'b1; + tx_data_ready <= 1'b0; if (tx_data_valid == 1'b1) begin - next_state <= S_START; - end else begin - next_state <= S_IDLE; - end - end - S_START: begin - if (cycle_cnt == uart_baud[15:0]) begin - next_state <= S_SEND_BYTE; - end else begin - next_state <= S_START; - end - end - S_SEND_BYTE: begin - if (cycle_cnt == uart_baud[15:0] && bit_cnt == 3'd7) begin - next_state <= S_STOP; - end else begin - next_state <= S_SEND_BYTE; - end - end - S_STOP: begin - if (cycle_cnt == uart_baud[15:0]) begin - next_state <= S_IDLE; - end else begin - next_state <= S_STOP; - end - end - default: begin - next_state <= S_IDLE; - end - endcase - end - - always @ (posedge clk) begin - if (rst == 1'b0) begin - tx_data_ready <= 1'b0; - end else if (state == S_STOP && cycle_cnt == uart_baud[15:0]) begin - if (fifo_index == (fifo_count - 1'b1)) begin - tx_data_ready <= 1'b1; - end - end else begin - tx_data_ready <= 1'b0; - end - end - - always @ (posedge clk) begin - if (rst == 1'b0) begin - tx_data <= 8'd0; - end else if (state == S_IDLE && tx_data_valid == 1'b1) begin - tx_data <= fifo_data[fifo_index]; - end - end - - always @ (posedge clk) begin - if (rst == 1'b0) begin - bit_cnt <= 3'd0; - end else if (state == S_SEND_BYTE) begin - if (cycle_cnt == uart_baud[15:0]) begin - bit_cnt <= bit_cnt + 3'd1; - end else begin - bit_cnt <= bit_cnt; - end - end else begin - bit_cnt <= 3'd0; - end - end - - always @ (posedge clk) begin - if (rst == 1'b0) begin - cycle_cnt <= 16'd0; - end else if ((state == S_SEND_BYTE && cycle_cnt == uart_baud[15:0]) || next_state != state) begin - cycle_cnt <= 16'd0; - end else begin - cycle_cnt <= cycle_cnt + 16'd1; - end - end - - always @ (posedge clk) begin - if (rst == 1'b0) begin - tx_reg <= 1'b1; - end else begin - case (state) - S_IDLE: begin - tx_reg <= 1'b1; - end - S_START: begin + state <= S_START; + cycle_cnt <= 16'd0; + bit_cnt <= 4'd0; tx_reg <= 1'b0; end - S_SEND_BYTE: begin - tx_reg <= tx_data[bit_cnt]; + end else begin + cycle_cnt <= cycle_cnt + 16'd1; + if (cycle_cnt == uart_baud[15:0]) begin + cycle_cnt <= 16'd0; + case (state) + S_START: begin + tx_reg <= tx_data[bit_cnt]; + state <= S_SEND_BYTE; + bit_cnt <= bit_cnt + 4'd1; + end + S_SEND_BYTE: begin + bit_cnt <= bit_cnt + 4'd1; + if (bit_cnt == 4'd8) begin + state <= S_STOP; + tx_reg <= 1'b1; + end else begin + tx_reg <= tx_data[bit_cnt]; + end + end + S_STOP: begin + tx_reg <= 1'b1; + state <= S_IDLE; + tx_data_ready <= 1'b1; + end + endcase end - S_STOP: begin - tx_reg <= 1'b1; - end - default: begin - tx_reg <= 1'b1; - end - endcase + end end end