|
| 1 | +`default_nettype none |
| 2 | + |
| 3 | +module uart_rx_des |
| 4 | + #( parameter WORD_WIDTH = 8, |
| 5 | + parameter OVERSAMPLING = 16) ( |
| 6 | + input wire clk, |
| 7 | + input wire rst_n, |
| 8 | + input wire tick, |
| 9 | + input wire din, |
| 10 | + input wire parity_en, |
| 11 | + output wire ready_tick, |
| 12 | + output wire [DATA_WIDTH-1:0] dout |
| 13 | +); |
| 14 | + |
| 15 | +localparam TICK_MID_VAL = OVERSAMPLING / 2 - 1; |
| 16 | +localparam DATA_WIDTH = WORD_WIDTH + 1; // parity bit |
| 17 | + |
| 18 | +localparam [2:0] |
| 19 | + IDLE = 3'b000, |
| 20 | + START_BIT = 3'b001, |
| 21 | + DATA = 3'b010, |
| 22 | + STOP_BIT = 3'b011; |
| 23 | + |
| 24 | +reg [2:0 ] state, state_nxt; |
| 25 | + |
| 26 | +// config |
| 27 | +reg parity, parity_nxt; |
| 28 | + |
| 29 | +// internal |
| 30 | +reg [$clog2(OVERSAMPLING)-1:0] tick_ctr, tick_ctr_nxt; |
| 31 | +reg [$clog2(DATA_WIDTH)-1:0 ] bit_ctr, bit_ctr_nxt; |
| 32 | +wire [$clog2(DATA_WIDTH)-1:0] N = parity ? DATA_WIDTH : WORD_WIDTH; |
| 33 | + |
| 34 | +// outputs |
| 35 | +reg [DATA_WIDTH-1:0 ] d, d_nxt; |
| 36 | +reg ready; |
| 37 | + |
| 38 | +always @(posedge clk or negedge rst_n) begin |
| 39 | + if (~rst_n) begin |
| 40 | + state <= IDLE; |
| 41 | + tick_ctr <= 0; |
| 42 | + bit_ctr <= 0; |
| 43 | + d <= 0; |
| 44 | + parity <= 0; |
| 45 | + end else begin |
| 46 | + state <= state_nxt; |
| 47 | + tick_ctr <= tick_ctr_nxt; |
| 48 | + bit_ctr <= bit_ctr_nxt; |
| 49 | + d <= d_nxt; |
| 50 | + parity <= parity_nxt; |
| 51 | + end |
| 52 | +end |
| 53 | + |
| 54 | +always @(*) begin |
| 55 | + state_nxt = state; |
| 56 | + tick_ctr_nxt = tick_ctr; |
| 57 | + bit_ctr_nxt = bit_ctr; |
| 58 | + d_nxt = d; |
| 59 | + parity_nxt = parity; |
| 60 | + ready = 1'b0; |
| 61 | + |
| 62 | + case (state) |
| 63 | + IDLE: begin |
| 64 | + if (~din) begin |
| 65 | + state_nxt = START_BIT; |
| 66 | + tick_ctr_nxt = TICK_MID_VAL; |
| 67 | + parity_nxt = parity_en; |
| 68 | + end |
| 69 | + end |
| 70 | + START_BIT: begin |
| 71 | + if (tick) begin |
| 72 | + tick_ctr_nxt = tick_ctr - 1; |
| 73 | + if (tick_ctr == 0) begin |
| 74 | + state_nxt = DATA; |
| 75 | + tick_ctr_nxt = OVERSAMPLING - 1; |
| 76 | + end |
| 77 | + end |
| 78 | + end |
| 79 | + DATA: begin |
| 80 | + if (tick) begin |
| 81 | + tick_ctr_nxt = tick_ctr - 1; |
| 82 | + if (tick_ctr == 0) begin |
| 83 | + d_nxt = {din, d[DATA_WIDTH - 1 : 1]}; |
| 84 | + if (bit_ctr == N) |
| 85 | + state_nxt = STOP_BIT; |
| 86 | + else |
| 87 | + bit_ctr_nxt = bit_ctr + 1; |
| 88 | + tick_ctr_nxt = OVERSAMPLING - 1; |
| 89 | + end |
| 90 | + end |
| 91 | + end |
| 92 | + STOP_BIT: begin |
| 93 | + if (tick) begin |
| 94 | + if (tick_ctr == 0) begin |
| 95 | + state_nxt = IDLE; |
| 96 | + if (din) // check data line deasserted |
| 97 | + ready = 1'b1; |
| 98 | + end else |
| 99 | + tick_ctr_nxt = tick_ctr - 1; |
| 100 | + end |
| 101 | + end |
| 102 | + endcase |
| 103 | +end |
| 104 | + |
| 105 | +assign ready_tick = ready; |
| 106 | +assign dout = d; |
| 107 | + |
| 108 | +endmodule |
0 commit comments