Add new memory-mapped UART
This implementation uses a simpler state machine than the previous version. The receiver still needs to be implemented.
This commit is contained in:
parent
bb5f2c8d8c
commit
6d638404f1
2 changed files with 72 additions and 122 deletions
22
top.sv
22
top.sv
|
|
@ -77,16 +77,18 @@ module top (
|
||||||
|
|
||||||
/* memory bus data */
|
/* memory bus data */
|
||||||
logic [31:0] mem_address;
|
logic [31:0] mem_address;
|
||||||
logic [31:0] mem_read_value = ram_read_value | leds_read_value;
|
logic [31:0] mem_read_value = ram_read_value | leds_read_value | uart_read_value;
|
||||||
logic [31:0] mem_write_value;
|
logic [31:0] mem_write_value;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
ram_sel = 0;
|
ram_sel = 0;
|
||||||
leds_sel = 0;
|
leds_sel = 0;
|
||||||
|
uart_sel = 0;
|
||||||
|
|
||||||
casez (mem_address)
|
casez (mem_address)
|
||||||
32'b00000000_00000000_????????_????????: ram_sel = 1;
|
32'b00000000_00000000_????????_????????: ram_sel = 1;
|
||||||
32'b00000000_00000001_00000000_000000??: leds_sel = 1;
|
32'b00000000_00000001_00000000_000000??: leds_sel = 1;
|
||||||
|
32'b00000000_00000010_00000000_0000????: uart_sel = 1;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -116,9 +118,8 @@ module top (
|
||||||
leds <= mem_write_value[7:0];
|
leds <= mem_write_value[7:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
logic uart_rx_received;
|
logic uart_sel;
|
||||||
logic uart_tx_ready;
|
logic [31:0] uart_read_value;
|
||||||
logic [7:0] uart_rx_byte;
|
|
||||||
|
|
||||||
uart uart (
|
uart uart (
|
||||||
.clk(pll_clk),
|
.clk(pll_clk),
|
||||||
|
|
@ -129,16 +130,15 @@ module top (
|
||||||
.tx_out(uart_tx),
|
.tx_out(uart_tx),
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
.tx_transmit_in(uart_rx_received),
|
.sel_in(uart_sel),
|
||||||
|
.read_in(mem_read),
|
||||||
|
.write_mask_in(mem_write_mask),
|
||||||
|
|
||||||
/* data in */
|
/* data in */
|
||||||
.tx_byte_in(uart_rx_byte),
|
.address_in(mem_address),
|
||||||
|
.write_value_in(mem_write_value),
|
||||||
/* control out */
|
|
||||||
.rx_received_out(uart_rx_received),
|
|
||||||
.tx_ready_out(uart_tx_ready),
|
|
||||||
|
|
||||||
/* data out */
|
/* data out */
|
||||||
.rx_byte_out(uart_rx_byte)
|
.read_value_out(uart_read_value)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
172
uart.sv
172
uart.sv
|
|
@ -1,15 +1,11 @@
|
||||||
`ifndef UART
|
`ifndef UART
|
||||||
`define UART
|
`define UART
|
||||||
|
|
||||||
localparam UART_STATE_IDLE = 2'b00;
|
localparam UART_REG_CLK_DIV = 2'b00;
|
||||||
localparam UART_STATE_START = 2'b01;
|
localparam UART_REG_STATUS = 2'b01;
|
||||||
localparam UART_STATE_DATA = 2'b10;
|
localparam UART_REG_DATA = 2'b10;
|
||||||
localparam UART_STATE_STOP = 2'b11;
|
|
||||||
|
|
||||||
module uart #(
|
module uart (
|
||||||
parameter CLK_FREQ = 36000000,
|
|
||||||
parameter BAUD_RATE = 9600
|
|
||||||
) (
|
|
||||||
input clk,
|
input clk,
|
||||||
input reset,
|
input reset,
|
||||||
|
|
||||||
|
|
@ -18,128 +14,82 @@ module uart #(
|
||||||
output tx_out,
|
output tx_out,
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
input tx_transmit_in,
|
input sel_in,
|
||||||
|
input read_in,
|
||||||
|
input [3:0] write_mask_in,
|
||||||
|
|
||||||
/* data in */
|
/* data in */
|
||||||
input [7:0] tx_byte_in,
|
input [31:0] address_in,
|
||||||
|
input [31:0] write_value_in,
|
||||||
/* control out */
|
|
||||||
output rx_received_out,
|
|
||||||
output tx_ready_out,
|
|
||||||
|
|
||||||
/* data out */
|
/* data out */
|
||||||
output [7:0] rx_byte_out
|
output [31:0] read_value_out
|
||||||
);
|
);
|
||||||
localparam CLK_DIV = CLK_FREQ / BAUD_RATE;
|
logic [15:0] clk_div;
|
||||||
|
|
||||||
logic [11:0] rx_clk_div;
|
logic [15:0] tx_clks;
|
||||||
logic [11:0] tx_clk_div;
|
logic [3:0] tx_bits;
|
||||||
|
logic [9:0] tx_buf;
|
||||||
|
|
||||||
logic [1:0] rx_state;
|
initial
|
||||||
logic [1:0] tx_state;
|
tx_buf[0] = 1;
|
||||||
|
|
||||||
logic [2:0] rx_bit;
|
assign tx_out = tx_buf[0];
|
||||||
logic [2:0] tx_bit;
|
|
||||||
|
|
||||||
logic [7:0] rx_pending_byte;
|
always_comb begin
|
||||||
logic [7:0] tx_byte;
|
if (sel_in) begin
|
||||||
|
case (address_in[3:2])
|
||||||
initial begin
|
UART_REG_CLK_DIV: begin
|
||||||
rx_state <= UART_STATE_IDLE;
|
read_value_out = {16'b0, clk_div};
|
||||||
tx_state <= UART_STATE_IDLE;
|
end
|
||||||
rx_received_out <= 0;
|
UART_REG_STATUS: begin
|
||||||
tx_out <= 1;
|
read_value_out = {31'b0, |tx_bits};
|
||||||
tx_ready_out <= 1;
|
end
|
||||||
|
UART_REG_DATA: begin
|
||||||
|
read_value_out = 0;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
read_value_out = 32'bx;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end else begin
|
||||||
|
read_value_out = 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
rx_received_out <= 0;
|
if (sel_in) begin
|
||||||
|
case (address_in[3:2])
|
||||||
|
UART_REG_CLK_DIV: begin
|
||||||
|
if (write_mask_in[1])
|
||||||
|
clk_div[15:8] <= write_value_in[15:8];
|
||||||
|
|
||||||
if (rx_clk_div)
|
if (write_mask_in[0])
|
||||||
rx_clk_div <= rx_clk_div - 1;
|
clk_div[7:0] <= write_value_in[7:0];
|
||||||
|
|
||||||
if (tx_clk_div)
|
|
||||||
tx_clk_div <= tx_clk_div - 1;
|
|
||||||
|
|
||||||
case (rx_state)
|
|
||||||
UART_STATE_IDLE: begin
|
|
||||||
if (!rx_in) begin
|
|
||||||
rx_state <= UART_STATE_START;
|
|
||||||
rx_clk_div <= CLK_DIV / 2;
|
|
||||||
end
|
end
|
||||||
end
|
UART_REG_DATA: begin
|
||||||
UART_STATE_START: begin
|
if (write_mask_in[0] && !tx_bits) begin
|
||||||
if (!rx_clk_div) begin
|
tx_clks <= clk_div;
|
||||||
if (!rx_in) begin
|
tx_bits <= 10;
|
||||||
rx_state <= UART_STATE_DATA;
|
tx_buf <= {1'b1, write_value_in[7:0], 1'b0};
|
||||||
rx_clk_div <= CLK_DIV;
|
|
||||||
rx_bit <= 7;
|
|
||||||
end else begin
|
|
||||||
rx_state <= UART_STATE_IDLE;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
endcase
|
||||||
UART_STATE_DATA: begin
|
end
|
||||||
if (!rx_clk_div) begin
|
|
||||||
rx_state <= rx_bit ? UART_STATE_DATA : UART_STATE_STOP;
|
|
||||||
rx_clk_div <= CLK_DIV;
|
|
||||||
rx_bit <= rx_bit - 1;
|
|
||||||
rx_pending_byte <= {rx_in, rx_pending_byte[7:1]};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
UART_STATE_STOP: begin
|
|
||||||
if (!rx_clk_div) begin
|
|
||||||
rx_state <= UART_STATE_IDLE;
|
|
||||||
if (rx_in) begin
|
|
||||||
rx_received_out <= 1;
|
|
||||||
rx_byte_out <= rx_pending_byte;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
|
|
||||||
case (tx_state)
|
if (tx_bits) begin
|
||||||
UART_STATE_IDLE: begin
|
if (tx_clks) begin
|
||||||
if (tx_transmit_in) begin
|
tx_clks <= tx_clks - 1;
|
||||||
tx_state <= UART_STATE_START;
|
end else begin
|
||||||
tx_clk_div <= CLK_DIV;
|
tx_clks <= clk_div;
|
||||||
tx_byte <= tx_byte_in;
|
tx_bits <= tx_bits - 1;
|
||||||
tx_out <= 0;
|
tx_buf <= {1'b1, tx_buf[9:1]};
|
||||||
tx_ready_out <= 0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
UART_STATE_START: begin
|
end
|
||||||
if (!tx_clk_div) begin
|
|
||||||
tx_state <= UART_STATE_DATA;
|
|
||||||
tx_clk_div <= CLK_DIV;
|
|
||||||
tx_bit <= 7;
|
|
||||||
tx_byte <= {1'b0, tx_byte[7:1]};
|
|
||||||
tx_out <= tx_byte[0];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
UART_STATE_DATA: begin
|
|
||||||
if (!tx_clk_div) begin
|
|
||||||
tx_state <= tx_bit ? UART_STATE_DATA : UART_STATE_STOP;
|
|
||||||
tx_clk_div <= CLK_DIV;
|
|
||||||
tx_bit <= tx_bit - 1;
|
|
||||||
tx_byte <= {1'b0, tx_byte[7:1]};
|
|
||||||
tx_out <= tx_bit ? tx_byte[0] : 1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
UART_STATE_STOP: begin
|
|
||||||
if (!tx_clk_div) begin
|
|
||||||
tx_state <= UART_STATE_IDLE;
|
|
||||||
tx_ready_out <= 1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
rx_state <= UART_STATE_IDLE;
|
tx_bits <= 0;
|
||||||
tx_state <= UART_STATE_IDLE;
|
tx_buf[0] <= 1;
|
||||||
rx_received_out <= 0;
|
|
||||||
tx_out <= 1;
|
|
||||||
tx_ready_out <= 1;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue