From f8da9206d960de13d50014b36df00260e2972641 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 00:00:55 -0500 Subject: [PATCH] Refactor uart.sv to better allow cpu control Added new signal tx_flag, which indicates whether the transmitter is ready for new data. Added status register, which when read will return the tx_flag bit, as well as others that can be implemented. Added new state IDLE, which resets the TX flag and allows new data to be written. Added code to allow for different baud rates, though it is still fixed currently. --- hw/fpga/uart.sv | 78 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/hw/fpga/uart.sv b/hw/fpga/uart.sv index 2ad48f9..9c86ffb 100644 --- a/hw/fpga/uart.sv +++ b/hw/fpga/uart.sv @@ -17,42 +17,71 @@ module uart( //Handle reading and writing registers -logic [7:0] _data [3:0]; +logic [7:0] tx_buf; +logic [7:0] rx_buf; +logic [7:0] status; -assign data_out = _data[addr]; +logic tx_flag; + +logic tx_flag_set; +logic tx_flag_clear; + +assign status[0] = tx_flag | tx_flag_clear; always_ff @(posedge clk) begin - if (rst) - _data = '{default:'0}; - if (~rw & cs) - _data[addr] <= data_in; + if (rst) begin + tx_flag_set <= '0; + tx_buf <= '0; + rx_buf <= '0; + status[7:1] <= '0; + end + + if (cs) begin + if (~rw) begin + if (addr == 0) + tx_buf <= data_in; + end else begin + if (addr == 0) + data_out <= rx_buf; + if (addr == 1) + data_out <= status; + end + end + + if (~rw & cs && addr == 0) + tx_flag_set <= '1; + else + tx_flag_set <= '0; end // state controller -typedef enum bit [1:0] {START, DATA, PARITY, STOP} macro_t; +typedef enum bit [2:0] {START, DATA, PARITY, STOP, IDLE} macro_t; struct packed { macro_t macro; logic [3:0] count; } state, next_state; localparam logic [3:0] maxcount = 4'h7; -logic [7:0] testval, next_testval; - - // baud rate: 9600 +localparam baud = 9600; +localparam count = (50000000/baud)-1; logic [14:0] clkdiv; always_ff @(posedge clk_50) begin if (rst) begin clkdiv <= 0; - state.macro <= STOP; + state.macro <= IDLE; state.count <= 3'b0; - testval <= '0; + tx_flag <= '0; end else begin - if (clkdiv == 5207) begin + if (tx_flag_set) + tx_flag <= '1; + else if (tx_flag_clear) + tx_flag <= '0; + + if (clkdiv == count) begin clkdiv <= 0; state <= next_state; - testval <= next_testval; end else begin clkdiv <= clkdiv + 15'b1; end @@ -79,30 +108,43 @@ always_comb begin PARITY: begin end STOP: begin - next_state.macro = START; + next_state.macro = IDLE; next_state.count = '0; end + IDLE: begin + if (tx_flag) + next_state.macro = START; + else + next_state.macro = IDLE; + end + + default:; endcase end always_comb begin TXD = '1; - next_testval = testval; + tx_flag_clear = '0; unique case (state.macro) START: begin TXD = '0; end DATA: begin - TXD = testval[state.count]; + TXD = tx_buf[state.count]; end PARITY: begin end STOP: begin - next_testval = testval + 8'b1; + tx_flag_clear = '1; TXD = '1; end + IDLE: begin + TXD = '1; + end + + default:; endcase end