../src/lowrisc_ip_uart_0.1/rtl/uart_rx.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Description: UART Receive Module
6: //
7:
8: module uart_rx (
9: input clk_i,
10: input rst_ni,
11:
12: input rx_enable,
13: input tick_baud_x16,
14: input parity_enable,
15: input parity_odd,
16:
17: output logic tick_baud,
18: output logic rx_valid,
19: output [7:0] rx_data,
20: output logic idle,
21: output frame_err,
22: output rx_parity_err,
23:
24: input rx
25: );
26:
27: logic rx_valid_q;
28: logic [10:0] sreg_q, sreg_d;
29: logic [3:0] bit_cnt_q, bit_cnt_d;
30: logic [3:0] baud_div_q, baud_div_d;
31: logic tick_baud_d, tick_baud_q;
32: logic idle_d, idle_q;
33:
34: assign tick_baud = tick_baud_q;
35: assign idle = idle_q;
36:
37: always_ff @(posedge clk_i or negedge rst_ni) begin
38: if (!rst_ni) begin
39: sreg_q <= 11'h0;
40: bit_cnt_q <= 4'h0;
41: baud_div_q <= 4'h0;
42: tick_baud_q <= 1'b0;
43: idle_q <= 1'b1;
44: end else begin
45: sreg_q <= sreg_d;
46: bit_cnt_q <= bit_cnt_d;
47: baud_div_q <= baud_div_d;
48: tick_baud_q <= tick_baud_d;
49: idle_q <= idle_d;
50: end
51: end
52:
53: always_comb begin
54: if (!rx_enable) begin
55: sreg_d = 11'h0;
56: bit_cnt_d = 4'h0;
57: baud_div_d = 4'h0;
58: tick_baud_d = 1'b0;
59: idle_d = 1'b1;
60: end else begin
61: tick_baud_d = 1'b0;
62: sreg_d = sreg_q;
63: bit_cnt_d = bit_cnt_q;
64: baud_div_d = baud_div_q;
65: idle_d = idle_q;
66: if (tick_baud_x16) begin
67: {tick_baud_d, baud_div_d} = {1'b0,baud_div_q} + 5'h1;
68: end
69:
70: if (idle_q && !rx) begin
71: // start of char, sample in the middle of the bit time
72: baud_div_d = 4'd8;
73: tick_baud_d = 1'b0;
74: bit_cnt_d = (parity_enable ? 4'd11 : 4'd10);
75: sreg_d = 11'h0;
76: idle_d = 1'b0;
77: end else if (!idle_q && tick_baud_q) begin
78: if ((bit_cnt_q == (parity_enable ? 4'd11 : 4'd10)) && rx) begin
79: // must have been a glitch on the input, start bit is not set
80: // in the middle of the bit time, abort
81: idle_d = 1'b1;
82: bit_cnt_d = 4'h0;
83: end else begin
84: sreg_d = {rx, sreg_q[10:1]};
85: bit_cnt_d = bit_cnt_q - 4'h1;
86: idle_d = (bit_cnt_q == 4'h1);
87: end
88: end
89: end
90: end
91:
92: always_ff @(posedge clk_i or negedge rst_ni) begin
93: if (!rst_ni) rx_valid_q <= 1'b0;
94: else rx_valid_q <= tick_baud_q & (bit_cnt_q == 4'h1);
95:
96: end
97:
98: assign rx_valid = rx_valid_q;
99: assign rx_data = parity_enable ? sreg_q[8:1] : sreg_q[9:2];
100: // (rx_parity = sreg_q[9])
101: assign frame_err = rx_valid_q & ~sreg_q[10];
102: assign rx_parity_err = parity_enable & rx_valid_q &
103: (^{sreg_q[9:1],parity_odd});
104:
105: endmodule
106: