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.
This commit is contained in:
Byron Lathi
2022-03-14 00:00:55 -05:00
parent e063e9f6a3
commit f8da9206d9

View File

@@ -17,42 +17,71 @@ module uart(
//Handle reading and writing registers //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 always_ff @(posedge clk) begin
if (rst) if (rst) begin
_data = '{default:'0}; tx_flag_set <= '0;
if (~rw & cs) tx_buf <= '0;
_data[addr] <= data_in; 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 end
// state controller // 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 { struct packed {
macro_t macro; macro_t macro;
logic [3:0] count; logic [3:0] count;
} state, next_state; } state, next_state;
localparam logic [3:0] maxcount = 4'h7; localparam logic [3:0] maxcount = 4'h7;
logic [7:0] testval, next_testval;
// baud rate: 9600 // baud rate: 9600
localparam baud = 9600;
localparam count = (50000000/baud)-1;
logic [14:0] clkdiv; logic [14:0] clkdiv;
always_ff @(posedge clk_50) begin always_ff @(posedge clk_50) begin
if (rst) begin if (rst) begin
clkdiv <= 0; clkdiv <= 0;
state.macro <= STOP; state.macro <= IDLE;
state.count <= 3'b0; state.count <= 3'b0;
testval <= '0; tx_flag <= '0;
end else begin 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; clkdiv <= 0;
state <= next_state; state <= next_state;
testval <= next_testval;
end else begin end else begin
clkdiv <= clkdiv + 15'b1; clkdiv <= clkdiv + 15'b1;
end end
@@ -79,30 +108,43 @@ always_comb begin
PARITY: begin PARITY: begin
end end
STOP: begin STOP: begin
next_state.macro = START; next_state.macro = IDLE;
next_state.count = '0; next_state.count = '0;
end end
IDLE: begin
if (tx_flag)
next_state.macro = START;
else
next_state.macro = IDLE;
end
default:;
endcase endcase
end end
always_comb begin always_comb begin
TXD = '1; TXD = '1;
next_testval = testval; tx_flag_clear = '0;
unique case (state.macro) unique case (state.macro)
START: begin START: begin
TXD = '0; TXD = '0;
end end
DATA: begin DATA: begin
TXD = testval[state.count]; TXD = tx_buf[state.count];
end end
PARITY: begin PARITY: begin
end end
STOP: begin STOP: begin
next_testval = testval + 8'b1; tx_flag_clear = '1;
TXD = '1; TXD = '1;
end end
IDLE: begin
TXD = '1;
end
default:;
endcase endcase
end end