1
1
module uart_rx # (
2
+ parameter Parity = 1'b0 ,
3
+ parameter StopBit = 1'b1 ,
4
+ parameter OverSample = 8
2
5
// params
3
6
)(
4
7
// i/o
@@ -11,19 +14,28 @@ module uart_rx #(
11
14
/* Sample Timing */
12
15
input logic i_strobe,
13
16
input logic i_half,
14
- output logic o_prescaler_en
17
+ output logic o_prescaler_en,
18
+ output logic o_parity_error,
19
+ output logic o_stop_bit_error
15
20
);
16
21
22
+ localparam counter_width = $clog2 (OverSample);
23
+
17
24
typedef enum logic [2 : 0 ] {
18
- RESET = 3'b000 ,
19
- WAIT = 2'b001 ,
20
- LOAD = 3'b010 ,
21
- STOP = 3'b011 ,
22
- READY = 3'b100
25
+ RESET = 3'b000 ,
26
+ WAIT = 2'b001 ,
27
+ LOAD = 3'b010 ,
28
+ PARITY = 3'b011 ,
29
+ STOP = 3'b100 ,
30
+ READY = 3'b101
23
31
} states_t ;
24
32
25
33
states_t curr_state, next_state;
26
- logic [2 : 0 ] counter;
34
+
35
+ logic [counter_width: 0 ] counter;
36
+ logic counter_rst_n;
37
+
38
+ logic parity_bit;
27
39
28
40
// State controller
29
41
always_ff @ (posedge i_clk) begin
@@ -33,45 +45,59 @@ module uart_rx #(
33
45
34
46
// Next State Logic Controller
35
47
always_comb begin
36
- unique case (state )
48
+ unique case (curr_state )
37
49
RESET :
38
50
next_state = WAIT ;
39
51
WAIT :
40
- if (serial_in == '0 )
52
+ if (i_rx == '0 )
41
53
next_state = LOAD ;
42
54
else
43
55
next_state = WAIT ;
44
56
LOAD :
45
57
if (counter == '0 )
46
- next_state = STOP ;
58
+ generate
59
+ case (Parity)
60
+ 0 : next_state = STOP ;
61
+ 1 : next_state = PARITY ;
62
+ endcase
63
+ endgenerate
47
64
else
48
65
next_state = LOAD ;
66
+ PARITY :
67
+ if (i_half)
68
+ next_state = STOP ;
69
+ else
70
+ next_state = PARITY ;
49
71
STOP :
50
- // wait for stop bit
72
+ if (i_half && i_rx) // halfway strobe AND rx == 1 (stop bit)
73
+ next_state = READY ;
74
+ else
75
+ next_state = STOP ;
51
76
READY :
52
77
next_state = WAIT ;
53
78
endcase
54
79
end
55
80
56
81
always_comb begin
57
- unique case (state)
58
- RESET :
59
- WAIT :
60
- LOAD :
61
- STOP :
62
- READY :
82
+ unique case (curr_state)
83
+ RESET : { o_prescaler_en, counter_rst_n} = 2'b00 ;
84
+ WAIT : { o_prescaler_en, counter_rst_n} = 2'b00 ;
85
+ LOAD : { o_prescaler_en, counter_rst_n} = 2'b11 ;
86
+ PARITY : { o_prescaler_en, counter_rst_n} = 2'b10 ;
87
+ STOP : { o_prescaler_en, counter_rst_n} = 2'b10 ;
88
+ READY : { o_prescaler_en, counter_rst_n} = 2'b00 ;
63
89
endcase
64
90
end
65
91
66
92
always_ff @ (posedge i_clk)
67
93
if (! i_rst_n)
68
94
o_rx_data <= 0 ;
69
95
else if (i_half)
70
- o_rx_data <= { rx , o_rx_data[7 : 1 ]} ;
96
+ o_rx_data <= { i_rx , o_rx_data[7 : 1 ]} ;
71
97
72
98
always_ff @ (posedge i_clk)
73
- if (! i_rst_n )
74
- counter <= '0 ;
99
+ if (! counter_rst_n )
100
+ counter <= '1 ;
75
101
else if (i_half)
76
102
counter <= counter - 3'b1 ;
77
103
0 commit comments