Add receive logic to UART

The UART has a receive buffer which will fill up when it receives bytes.
Once the buffer is full, it raises the RX flag until the value is read
by the cpu.
This commit is contained in:
Byron Lathi
2022-03-14 16:40:04 -05:00
parent ed18b381f3
commit 59d2d4f601

View File

@@ -16,9 +16,6 @@ module uart(
output logic [7:0] data_out
);
//Temporary!
assign irq = ~RXD;
//Handle reading and writing registers
logic [7:0] tx_buf;
@@ -26,18 +23,24 @@ logic [7:0] rx_buf;
logic [7:0] status;
logic tx_flag;
logic rx_flag;
logic tx_flag_set;
logic tx_flag_clear;
logic rx_flag_set;
logic rx_flag_clear;
assign status[0] = tx_flag | tx_flag_clear;
assign status[1] = rx_flag | rx_flag_set;
assign irq = status[1];
always_ff @(posedge clk) begin
if (rst) begin
tx_flag_set <= '0;
rx_flag_clear <= '0;
tx_buf <= '0;
rx_buf <= '0;
status[7:1] <= '0;
status[7:2] <= '0;
end
if (cs) begin
@@ -56,6 +59,11 @@ always_ff @(posedge clk) begin
tx_flag_set <= '1;
else
tx_flag_set <= '0;
if (rw & cs && addr == 0)
rx_flag_clear <= '1;
else
rx_flag_clear <= '0;
end
// tx state controller
@@ -152,4 +160,69 @@ always_comb begin
endcase
end
//basically in idle state we need to sample RXD very fast,
//then as soon as we detect that RXD is low, we start clkdiv
//going and then go into the start state.
logic [14:0] rx_clkdiv;
always_ff @(posedge clk_50) begin
if (rst) begin
rx_buf <= '0;
rx_clkdiv <= 0;
rx_state.macro <= IDLE;
rx_state.count <= 3'b0;
end else begin
if (rx_flag_set)
rx_flag <= '1;
else if (rx_flag_clear)
rx_flag <= '0;
if (rx_state.macro == IDLE) begin // Sample constantly in idle state
rx_state <= rx_next_state;
rx_clkdiv <= count/15'h2; // offset rx clock by 1/2 phase
end else begin
if (rx_clkdiv == count) begin // other states are as usual
rx_clkdiv <= 0;
rx_state <= rx_next_state;
if (rx_state.macro == DATA)
rx_buf[rx_state.count] = RXD;
end else begin
rx_clkdiv <= rx_clkdiv + 15'b1;
end
end
end
end
always_comb begin
rx_next_state = rx_state;
rx_flag_set = '0;
unique case (rx_state.macro)
IDLE: begin
if (~RXD)
rx_next_state.macro = START;
end
START: begin
rx_next_state.macro = DATA;
rx_next_state.count = 3'b0;
end
DATA: begin
if (rx_state.count == maxcount) begin
rx_next_state.macro = STOP;
rx_next_state.count = 3'b0;
end else begin
rx_next_state.count = rx_state.count + 3'b1;
rx_next_state.macro = DATA;
end
end
PARITY: begin
end
STOP: begin
rx_flag_set = '1;
rx_next_state.macro = IDLE;
end
endcase
end
endmodule