File size: 1,658 Bytes
0ba037b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | // 8N1 UART receiver. cpb = clocks per bit = clock frequency / baud rate (>= 4).
// valid pulses for one cycle with the received byte in data.
module uart_rx #(
parameter int CW = 10 // width of cpb
)(
input logic clk,
input logic reset,
input logic [CW-1:0] cpb,
input logic rx,
output logic valid,
output logic [7:0] data
);
logic [CW-1:0] FULL, HALF;
assign FULL = cpb - 1'b1;
assign HALF = cpb >> 1;
logic rx_m, rx_s; // two-flop synchronizer
logic [1:0] state; // 0 idle, 1 start, 2 data, 3 stop
logic [CW-1:0] cnt;
logic [2:0] bitn;
always_ff @(posedge clk) begin
rx_m <= rx;
rx_s <= rx_m;
valid <= 1'b0;
if (reset) begin
state <= 2'd0; cnt <= '0; bitn <= '0; data <= '0;
rx_m <= 1'b1; rx_s <= 1'b1;
end else begin
case (state)
2'd0: if (!rx_s) begin state <= 2'd1; cnt <= HALF; end
2'd1: if (cnt == 0) begin
if (!rx_s) begin state <= 2'd2; cnt <= FULL; bitn <= '0; end
else state <= 2'd0; // glitch, not a start bit
end else cnt <= cnt - 1'b1;
2'd2: if (cnt == 0) begin
data <= {rx_s, data[7:1]};
cnt <= FULL;
if (bitn == 3'd7) state <= 2'd3;
bitn <= bitn + 1'b1;
end else cnt <= cnt - 1'b1;
default: if (cnt == 0) begin
state <= 2'd0;
valid <= rx_s; // drop bytes with a bad stop bit
end else cnt <= cnt - 1'b1;
endcase
end
end
endmodule
|