Files
super6502/hw/fpga/uart.sv
Byron Lathi e063e9f6a3 Add basic UART device
So far the device only transmits the ASCII set on repeat, but will
become fully featured later.
2022-03-13 19:42:41 -05:00

110 lines
2.1 KiB
Systemverilog

module uart(
input clk_50,
input clk,
input rst,
input cs,
input rw,
input [7:0] data_in,
input [1:0] addr,
input RXD,
output logic TXD,
output logic [7:0] data_out
);
//Handle reading and writing registers
logic [7:0] _data [3:0];
assign data_out = _data[addr];
always_ff @(posedge clk) begin
if (rst)
_data = '{default:'0};
if (~rw & cs)
_data[addr] <= data_in;
end
// state controller
typedef enum bit [1:0] {START, DATA, PARITY, STOP} 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
logic [14:0] clkdiv;
always_ff @(posedge clk_50) begin
if (rst) begin
clkdiv <= 0;
state.macro <= STOP;
state.count <= 3'b0;
testval <= '0;
end else begin
if (clkdiv == 5207) begin
clkdiv <= 0;
state <= next_state;
testval <= next_testval;
end else begin
clkdiv <= clkdiv + 15'b1;
end
end
end
always_comb begin
next_state = state;
unique case (state.macro)
START: begin
next_state.macro = DATA;
next_state.count = 3'b0;
end
DATA: begin
if (state.count == maxcount) begin
next_state.macro = STOP; // or PARITY
next_state.count = 3'b0;
end else begin
next_state.count = state.count + 3'b1;
next_state.macro = DATA;
end
end
PARITY: begin
end
STOP: begin
next_state.macro = START;
next_state.count = '0;
end
endcase
end
always_comb begin
TXD = '1;
next_testval = testval;
unique case (state.macro)
START: begin
TXD = '0;
end
DATA: begin
TXD = testval[state.count];
end
PARITY: begin
end
STOP: begin
next_testval = testval + 8'b1;
TXD = '1;
end
endcase
end
endmodule