148 lines
3.9 KiB
Systemverilog
148 lines
3.9 KiB
Systemverilog
|
|
`ifndef UART
|
||
|
|
`define UART
|
||
|
|
|
||
|
|
localparam UART_STATE_IDLE = 2'b00;
|
||
|
|
localparam UART_STATE_START = 2'b01;
|
||
|
|
localparam UART_STATE_DATA = 2'b10;
|
||
|
|
localparam UART_STATE_STOP = 2'b11;
|
||
|
|
|
||
|
|
module uart #(
|
||
|
|
parameter CLK_FREQ = 36000000,
|
||
|
|
parameter BAUD_RATE = 9600
|
||
|
|
) (
|
||
|
|
input clk,
|
||
|
|
input reset,
|
||
|
|
|
||
|
|
/* serial port */
|
||
|
|
input rx_in,
|
||
|
|
output tx_out,
|
||
|
|
|
||
|
|
/* control in */
|
||
|
|
input tx_transmit_in,
|
||
|
|
|
||
|
|
/* data in */
|
||
|
|
input [7:0] tx_byte_in,
|
||
|
|
|
||
|
|
/* control out */
|
||
|
|
output rx_received_out,
|
||
|
|
output tx_ready_out,
|
||
|
|
|
||
|
|
/* data out */
|
||
|
|
output [7:0] rx_byte_out
|
||
|
|
);
|
||
|
|
localparam CLK_DIV = CLK_FREQ / BAUD_RATE;
|
||
|
|
|
||
|
|
logic [11:0] rx_clk_div;
|
||
|
|
logic [11:0] tx_clk_div;
|
||
|
|
|
||
|
|
logic [1:0] rx_state;
|
||
|
|
logic [1:0] tx_state;
|
||
|
|
|
||
|
|
logic [2:0] rx_bit;
|
||
|
|
logic [2:0] tx_bit;
|
||
|
|
|
||
|
|
logic [7:0] rx_pending_byte;
|
||
|
|
logic [7:0] tx_byte;
|
||
|
|
|
||
|
|
initial begin
|
||
|
|
rx_state <= UART_STATE_IDLE;
|
||
|
|
tx_state <= UART_STATE_IDLE;
|
||
|
|
rx_received_out <= 0;
|
||
|
|
tx_out <= 1;
|
||
|
|
tx_ready_out <= 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
always @(posedge clk) begin
|
||
|
|
rx_received_out <= 0;
|
||
|
|
|
||
|
|
if (rx_clk_div)
|
||
|
|
rx_clk_div <= rx_clk_div - 1;
|
||
|
|
|
||
|
|
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
|
||
|
|
UART_STATE_START: begin
|
||
|
|
if (!rx_clk_div) begin
|
||
|
|
if (!rx_in) begin
|
||
|
|
rx_state <= UART_STATE_DATA;
|
||
|
|
rx_clk_div <= CLK_DIV;
|
||
|
|
rx_bit <= 7;
|
||
|
|
end else begin
|
||
|
|
rx_state <= UART_STATE_IDLE;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
UART_STATE_DATA: begin
|
||
|
|
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)
|
||
|
|
UART_STATE_IDLE: begin
|
||
|
|
if (tx_transmit_in) begin
|
||
|
|
tx_state <= UART_STATE_START;
|
||
|
|
tx_clk_div <= CLK_DIV;
|
||
|
|
tx_byte <= tx_byte_in;
|
||
|
|
tx_out <= 0;
|
||
|
|
tx_ready_out <= 0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
UART_STATE_START: begin
|
||
|
|
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
|
||
|
|
rx_state <= UART_STATE_IDLE;
|
||
|
|
tx_state <= UART_STATE_IDLE;
|
||
|
|
rx_received_out <= 0;
|
||
|
|
tx_out <= 1;
|
||
|
|
tx_ready_out <= 1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
endmodule
|
||
|
|
|
||
|
|
`endif
|