forked from vicharak-in/difflogic
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuart_rx.v
More file actions
121 lines (102 loc) · 3.14 KB
/
uart_rx.v
File metadata and controls
121 lines (102 loc) · 3.14 KB
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module uart_rx (
/* Clock Signals */
input i_Clock,
/* Configuration Control Signals */
input [CONFIG_DATA_WIDTH-1:0] uart_config_data,
/* UART Rx Signals */
input i_Rx_Serial,
output o_Rx_DV,
output [UART_DATA_WIDTH-1:0] o_Rx_Byte
);
/* Global parameters */
parameter UART_DATA_WIDTH = 8;
parameter CONFIG_DATA_WIDTH = 32;
/* Register declaration and Initialization */
reg [CONFIG_DATA_WIDTH-1:0] r_Clock_Count = 0;
reg [2:0] r_Bit_Index = 0;
reg [UART_DATA_WIDTH:0] r_Rx_Byte = 0;
reg r_Rx_DV = 0;
reg [CONFIG_DATA_WIDTH-1:0] r_config_data = 32'd437;
/* State Machine Parameters */
reg [2:0] r_SM_Main = 0;
localparam s_IDLE = 3'b000;
localparam s_RX_START_BIT = 3'b001;
localparam s_RX_DATA_BITS = 3'b010;
localparam s_RX_STOP_BIT = 3'b011;
localparam s_CLEANUP = 3'b100;
/* To avoid metastability */
reg r_Rx_Data_R = 1'b1;
reg r_Rx_Data = 1'b1;
always @(posedge i_Clock) begin
r_Rx_Data_R <= i_Rx_Serial;
r_Rx_Data <= r_Rx_Data_R;
end
/* Main FSM */
always @(posedge i_Clock) begin
r_Rx_Data_R <= i_Rx_Serial;
r_Rx_Data <= r_Rx_Data_R;
case (r_SM_Main)
s_IDLE : begin
r_Rx_DV <= 1'b0;
r_Clock_Count <= 0;
r_Bit_Index <= 0;
//r_config_data <= uart_config_data - 1;
if (r_Rx_Data == 1'b0) begin // Start bit detected
r_SM_Main <= s_RX_START_BIT;
end else begin
r_SM_Main <= s_IDLE;
end
end
s_RX_START_BIT : begin
if (r_Clock_Count == (r_config_data >> 1)) begin
if (r_Rx_Data == 1'b0) begin
r_Clock_Count <= 0; // reset counter, found the middle
r_SM_Main <= s_RX_DATA_BITS;
end else begin
r_SM_Main <= s_IDLE;
end
end else begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_RX_START_BIT;
end
end
s_RX_DATA_BITS : begin
if (r_Clock_Count < r_config_data) begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_RX_DATA_BITS;
end else begin
r_Clock_Count <= 0;
r_Rx_Byte[r_Bit_Index] <= r_Rx_Data;
// Check if we have received all bits
if (r_Bit_Index < 7) begin
r_Bit_Index <= r_Bit_Index + 1;
r_SM_Main <= s_RX_DATA_BITS;
end else begin
r_Bit_Index <= 0;
r_SM_Main <= s_RX_STOP_BIT;
end
end
end
// Receive Stop bit. Stop bit = 1
s_RX_STOP_BIT : begin
// Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
if (r_Clock_Count < r_config_data) begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_RX_STOP_BIT;
end else begin
r_Rx_DV <= 1'b1;
r_Clock_Count <= 0;
r_SM_Main <= s_CLEANUP;
end
end
// Stay here 1 clock
s_CLEANUP : begin
r_SM_Main <= s_IDLE;
r_Rx_DV <= 1'b0;
end
default : r_SM_Main <= s_IDLE;
endcase
end
assign o_Rx_DV = r_Rx_DV;
assign o_Rx_Byte = r_Rx_DV ? r_Rx_Byte : 0;
endmodule