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