2017-12-06 14:45:08 +00:00
|
|
|
`ifndef UART
|
|
|
|
|
`define UART
|
|
|
|
|
|
2017-12-09 10:44:39 +00:00
|
|
|
`define UART_REG_CLK_DIV 2'b00
|
|
|
|
|
`define UART_REG_STATUS 2'b01
|
|
|
|
|
`define UART_REG_DATA 2'b10
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
module uart (
|
2017-12-06 14:45:08 +00:00
|
|
|
input clk,
|
|
|
|
|
input reset,
|
|
|
|
|
|
|
|
|
|
/* serial port */
|
|
|
|
|
input rx_in,
|
2017-12-09 21:03:45 +00:00
|
|
|
output logic tx_out,
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-12 21:15:11 +00:00
|
|
|
/* memory bus */
|
|
|
|
|
input [31:0] address_in,
|
2017-12-06 22:29:18 +00:00
|
|
|
input sel_in,
|
|
|
|
|
input read_in,
|
2017-12-12 21:15:11 +00:00
|
|
|
output logic [31:0] read_value_out,
|
2017-12-06 22:29:18 +00:00
|
|
|
input [3:0] write_mask_in,
|
2017-12-12 21:15:11 +00:00
|
|
|
input [31:0] write_value_in
|
2017-12-06 14:45:08 +00:00
|
|
|
);
|
2017-12-06 22:29:18 +00:00
|
|
|
logic [15:0] clk_div;
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-07 21:29:58 +00:00
|
|
|
logic [15:0] rx_clks;
|
|
|
|
|
logic [3:0] rx_bits;
|
|
|
|
|
logic [7:0] rx_buf;
|
|
|
|
|
|
|
|
|
|
logic [7:0] rx_read_buf;
|
|
|
|
|
logic rx_read_ready;
|
|
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
logic [15:0] tx_clks;
|
|
|
|
|
logic [3:0] tx_bits;
|
|
|
|
|
logic [9:0] tx_buf;
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-09 21:03:45 +00:00
|
|
|
logic tx_write_ready;
|
2017-12-07 21:32:25 +00:00
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
initial
|
|
|
|
|
tx_buf[0] = 1;
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
assign tx_out = tx_buf[0];
|
2017-12-09 21:03:45 +00:00
|
|
|
assign tx_write_ready = ~|tx_bits;
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
always_comb begin
|
|
|
|
|
if (sel_in) begin
|
|
|
|
|
case (address_in[3:2])
|
2017-12-09 10:44:39 +00:00
|
|
|
`UART_REG_CLK_DIV: begin
|
2017-12-06 22:29:18 +00:00
|
|
|
read_value_out = {16'b0, clk_div};
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-09 10:44:39 +00:00
|
|
|
`UART_REG_STATUS: begin
|
2017-12-07 21:32:25 +00:00
|
|
|
read_value_out = {30'b0, rx_read_ready, tx_write_ready};
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-09 10:44:39 +00:00
|
|
|
`UART_REG_DATA: begin
|
2017-12-07 21:29:58 +00:00
|
|
|
read_value_out = {{24{~rx_read_ready}}, rx_read_ready ? rx_read_buf : 8'b0};
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-06 22:29:18 +00:00
|
|
|
default: begin
|
|
|
|
|
read_value_out = 32'bx;
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-06 22:29:18 +00:00
|
|
|
endcase
|
|
|
|
|
end else begin
|
|
|
|
|
read_value_out = 0;
|
|
|
|
|
end
|
|
|
|
|
end
|
2017-12-06 14:45:08 +00:00
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
always_ff @(posedge clk) begin
|
|
|
|
|
if (sel_in) begin
|
|
|
|
|
case (address_in[3:2])
|
2017-12-09 10:44:39 +00:00
|
|
|
`UART_REG_CLK_DIV: begin
|
2017-12-06 22:29:18 +00:00
|
|
|
if (write_mask_in[1])
|
|
|
|
|
clk_div[15:8] <= write_value_in[15:8];
|
|
|
|
|
|
|
|
|
|
if (write_mask_in[0])
|
|
|
|
|
clk_div[7:0] <= write_value_in[7:0];
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-09 10:44:39 +00:00
|
|
|
`UART_REG_DATA: begin
|
2017-12-07 21:29:58 +00:00
|
|
|
if (read_in)
|
|
|
|
|
rx_read_ready <= 0;
|
|
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
if (write_mask_in[0] && !tx_bits) begin
|
|
|
|
|
tx_clks <= clk_div;
|
|
|
|
|
tx_bits <= 10;
|
|
|
|
|
tx_buf <= {1'b1, write_value_in[7:0], 1'b0};
|
|
|
|
|
end
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-06 22:29:18 +00:00
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
|
2017-12-07 21:29:58 +00:00
|
|
|
if (rx_bits) begin
|
|
|
|
|
if (rx_clks) begin
|
|
|
|
|
rx_clks <= rx_clks - 1;
|
|
|
|
|
end else begin
|
|
|
|
|
rx_clks <= clk_div;
|
|
|
|
|
rx_bits <= rx_bits - 1;
|
|
|
|
|
|
|
|
|
|
case (rx_bits)
|
|
|
|
|
10: begin
|
|
|
|
|
if (rx_in)
|
|
|
|
|
rx_bits <= 0;
|
|
|
|
|
end
|
|
|
|
|
1: begin
|
|
|
|
|
if (rx_in) begin
|
|
|
|
|
rx_read_ready <= 1;
|
|
|
|
|
rx_read_buf <= rx_buf;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
default: begin
|
|
|
|
|
rx_buf <= {rx_in, rx_buf[7:1]};
|
|
|
|
|
end
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
end else if (!rx_in) begin
|
|
|
|
|
rx_clks <= clk_div[15:1];
|
|
|
|
|
rx_bits <= 10;
|
|
|
|
|
end
|
|
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
if (tx_bits) begin
|
|
|
|
|
if (tx_clks) begin
|
|
|
|
|
tx_clks <= tx_clks - 1;
|
|
|
|
|
end else begin
|
|
|
|
|
tx_clks <= clk_div;
|
|
|
|
|
tx_bits <= tx_bits - 1;
|
|
|
|
|
tx_buf <= {1'b1, tx_buf[9:1]};
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
2017-12-06 22:29:18 +00:00
|
|
|
end
|
2017-12-06 14:45:08 +00:00
|
|
|
|
|
|
|
|
if (reset) begin
|
2017-12-07 21:29:58 +00:00
|
|
|
rx_bits <= 0;
|
|
|
|
|
|
2017-12-06 22:29:18 +00:00
|
|
|
tx_bits <= 0;
|
|
|
|
|
tx_buf[0] <= 1;
|
2017-12-06 14:45:08 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
`endif
|