1 |
6 |
TobiasJ |
library IEEE;
|
2 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
3 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
4 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
5 |
|
|
|
6 |
|
|
entity rx_func is
|
7 |
|
|
port( clk, reset, rx_enable : in std_logic;
|
8 |
|
|
rx : in std_logic;
|
9 |
|
|
|
10 |
|
|
word_width : in std_logic_vector(3 downto 0);
|
11 |
11 |
TobiasJ |
baud_period : in std_logic_vector(15 downto 0);
|
12 |
6 |
TobiasJ |
use_parity_bit, parity_type : in std_logic;
|
13 |
|
|
stop_bits : in std_logic_vector(1 downto 0);
|
14 |
|
|
idle_line_lvl : in std_logic;
|
15 |
|
|
|
16 |
|
|
start_samples : in std_logic_vector(3 downto 0); --How many correct samples should give a start bit
|
17 |
|
|
line_samples : in std_logic_vector(3 downto 0); --How many samples should tip the internal rx value
|
18 |
|
|
|
19 |
|
|
data : out std_logic_vector(7 downto 0);
|
20 |
|
|
data_ready : out std_logic;
|
21 |
|
|
parity_error : out std_logic;
|
22 |
|
|
stop_bit_error : out std_logic);
|
23 |
|
|
end entity rx_func;
|
24 |
|
|
|
25 |
|
|
architecture behaviour of rx_func is
|
26 |
11 |
TobiasJ |
type state_type is (idle, data_bit0, data_bit1, data_bit2, data_bit3, data_bit4, data_bit5, data_bit6, data_bit7, parity_bit, stop_bit1, stop_bit2, data_check, data_rdy);
|
27 |
|
|
signal current_state : state_type := idle;
|
28 |
27 |
TobiasJ |
signal next_state, next_state_rst : state_type;
|
29 |
11 |
TobiasJ |
signal next_state_from_data_bit4 : state_type;
|
30 |
|
|
signal next_state_from_data_bit5 : state_type;
|
31 |
|
|
signal next_state_from_data_bit6 : state_type;
|
32 |
|
|
signal next_state_from_data_bit7 : state_type;
|
33 |
|
|
signal next_state_from_stop_bit1 : state_type;
|
34 |
|
|
|
35 |
27 |
TobiasJ |
signal sampled_data : std_logic_vector(9 downto 0);-- := "0000000000";
|
36 |
6 |
TobiasJ |
|
37 |
11 |
TobiasJ |
signal period_count_enable : std_logic;
|
38 |
27 |
TobiasJ |
signal period_count_q : std_logic_vector(15 downto 0);-- := "0000000000000000";
|
39 |
11 |
TobiasJ |
signal period_count_d : std_logic_vector(15 downto 0);
|
40 |
6 |
TobiasJ |
signal baud_tick : std_logic;
|
41 |
27 |
TobiasJ |
signal period16_count_q : std_logic_vector(11 downto 0);-- := "000000000000";
|
42 |
11 |
TobiasJ |
signal period16_count_d : std_logic_vector(11 downto 0);
|
43 |
6 |
TobiasJ |
signal sample_tick : std_logic;
|
44 |
27 |
TobiasJ |
signal sample_reg_q, sample_reg_start_bit_q : std_logic_vector(3 downto 0);-- := "0000";
|
45 |
11 |
TobiasJ |
signal sample_reg_start_bit_d, sample_reg_d : std_logic_vector(3 downto 0);
|
46 |
27 |
TobiasJ |
signal rx_sampled_q : std_logic;-- := '0';
|
47 |
11 |
TobiasJ |
signal rx_sampled_d : std_logic;
|
48 |
27 |
TobiasJ |
signal xored_sampled_data_bit_q : std_logic;-- := '0';
|
49 |
11 |
TobiasJ |
signal xored_sampled_data_bit_d : std_logic;
|
50 |
6 |
TobiasJ |
|
51 |
|
|
begin
|
52 |
11 |
TobiasJ |
-------------------------
|
53 |
|
|
-- Combinational logic --
|
54 |
|
|
-------------------------
|
55 |
|
|
|
56 |
|
|
--State Logic
|
57 |
27 |
TobiasJ |
next_state <= idle when reset = '1' else
|
58 |
|
|
next_state_rst;
|
59 |
11 |
TobiasJ |
with current_state select
|
60 |
27 |
TobiasJ |
next_state_rst <= data_bit0 when idle, --Identifying start bit
|
61 |
|
|
data_bit1 when data_bit0,
|
62 |
|
|
data_bit2 when data_bit1,
|
63 |
|
|
data_bit3 when data_bit2,
|
64 |
|
|
data_bit4 when data_bit3,
|
65 |
|
|
next_state_from_data_bit4 when data_bit4,
|
66 |
|
|
next_state_from_data_bit5 when data_bit5,
|
67 |
|
|
next_state_from_data_bit6 when data_bit6,
|
68 |
|
|
next_state_from_data_bit7 when data_bit7,
|
69 |
|
|
stop_bit1 when parity_bit,
|
70 |
|
|
next_state_from_stop_bit1 when stop_bit1,
|
71 |
|
|
data_check when stop_bit2,
|
72 |
|
|
data_rdy when data_check,
|
73 |
|
|
idle when data_rdy,
|
74 |
|
|
idle when others;
|
75 |
11 |
TobiasJ |
|
76 |
|
|
next_state_from_data_bit4 <= parity_bit when word_width = "0101" and use_parity_bit = '1' else
|
77 |
|
|
stop_bit1 when word_width = "0101" and use_parity_bit = '0' else
|
78 |
|
|
data_bit5;
|
79 |
|
|
|
80 |
|
|
next_state_from_data_bit5 <= parity_bit when word_width = "0110" and use_parity_bit = '1' else
|
81 |
|
|
stop_bit1 when word_width = "0110" and use_parity_bit = '0' else
|
82 |
|
|
data_bit6;
|
83 |
6 |
TobiasJ |
|
84 |
11 |
TobiasJ |
next_state_from_data_bit6 <= parity_bit when word_width = "0111" and use_parity_bit = '1' else
|
85 |
|
|
stop_bit1 when word_width = "0111" and use_parity_bit = '0' else
|
86 |
|
|
data_bit7;
|
87 |
|
|
|
88 |
|
|
next_state_from_data_bit7 <= parity_bit when use_parity_bit = '1' else
|
89 |
|
|
stop_bit1;
|
90 |
|
|
|
91 |
|
|
next_state_from_stop_bit1 <= stop_bit2 when stop_bits = "10" else
|
92 |
|
|
data_check;
|
93 |
6 |
TobiasJ |
|
94 |
|
|
|
95 |
11 |
TobiasJ |
--Sample logic
|
96 |
|
|
period16_count_d <= period16_count_q + 1 when reset = '0' and period16_count_q /= baud_period(15 downto 4) else
|
97 |
|
|
"000000000001";
|
98 |
|
|
sample_tick <= '1' when period16_count_q = baud_period(15 downto 4) else
|
99 |
|
|
'0';
|
100 |
6 |
TobiasJ |
|
101 |
11 |
TobiasJ |
--Baud logic
|
102 |
|
|
with current_state select
|
103 |
|
|
period_count_enable <= '0' when idle,
|
104 |
|
|
'0' when data_check,
|
105 |
|
|
'0' when data_rdy,
|
106 |
|
|
'1' when others;
|
107 |
|
|
period_count_d <= period_count_q + 1 when reset = '0' and period_count_q /= baud_period else
|
108 |
|
|
"0000000000000001";
|
109 |
|
|
baud_tick <= '1' when period_count_q = baud_period else
|
110 |
|
|
'0';
|
111 |
|
|
|
112 |
|
|
--RX sampled, by saturation counter
|
113 |
|
|
sample_reg_d <= sample_reg_q + 1 when reset = '0' and rx = '1' and sample_reg_q /= line_samples else
|
114 |
|
|
sample_reg_q - 1 when reset = '0' and rx = '0' and sample_reg_q /= "0000" else
|
115 |
|
|
sample_reg_q when reset = '0' else
|
116 |
|
|
"0000";
|
117 |
|
|
|
118 |
|
|
rx_sampled_d <= '1' when reset = '0' and sample_reg_q = line_samples else
|
119 |
|
|
'0' when reset = '0' and sample_reg_q = "0000" else
|
120 |
|
|
rx_sampled_q;
|
121 |
6 |
TobiasJ |
|
122 |
11 |
TobiasJ |
sample_reg_start_bit_d <= sample_reg_start_bit_q + 1 when reset = '0' and rx /= idle_line_lvl and sample_reg_start_bit_q /= start_samples else
|
123 |
|
|
sample_reg_start_bit_q - 1 when reset = '0' and rx = idle_line_lvl and sample_reg_start_bit_q /= "0000" else
|
124 |
|
|
sample_reg_start_bit_q when reset = '0' else
|
125 |
|
|
"0000";
|
126 |
|
|
|
127 |
14 |
TobiasJ |
--Parity bit
|
128 |
11 |
TobiasJ |
with current_state select
|
129 |
|
|
xored_sampled_data_bit_d <= '0' when idle,
|
130 |
|
|
xored_sampled_data_bit_q when stop_bit1,
|
131 |
|
|
xored_sampled_data_bit_q when stop_bit2,
|
132 |
|
|
xored_sampled_data_bit_q when data_check,
|
133 |
|
|
xored_sampled_data_bit_q xor rx_sampled_q when others;
|
134 |
|
|
|
135 |
|
|
--Reciving status signals
|
136 |
|
|
data_ready <= '1' when current_state = data_rdy else
|
137 |
|
|
'0';
|
138 |
|
|
parity_error <= '1' when xored_sampled_data_bit_q /= parity_type and current_state = data_check else
|
139 |
|
|
'0';
|
140 |
|
|
stop_bit_error <= '1' when current_state = data_check and (sampled_data(8) /= idle_line_lvl or (sampled_data(9) /= idle_line_lvl and stop_bits = "10")) else
|
141 |
|
|
'0';
|
142 |
|
|
|
143 |
|
|
|
144 |
|
|
--------------------
|
145 |
|
|
-- Register logic --
|
146 |
|
|
--------------------
|
147 |
27 |
TobiasJ |
register_logic : process(clk, reset, rx_enable, period_count_enable, sample_tick, baud_tick, current_state, use_parity_bit)
|
148 |
6 |
TobiasJ |
begin
|
149 |
11 |
TobiasJ |
if rising_edge(clk) then
|
150 |
|
|
--sample counter
|
151 |
27 |
TobiasJ |
if rx_enable = '1' or reset = '1' then
|
152 |
11 |
TobiasJ |
period16_count_q <= period16_count_d;
|
153 |
6 |
TobiasJ |
end if;
|
154 |
11 |
TobiasJ |
|
155 |
|
|
--baud counter
|
156 |
|
|
if period_count_enable = '1' or reset = '1' then
|
157 |
|
|
period_count_q <= period_count_d;
|
158 |
6 |
TobiasJ |
end if;
|
159 |
|
|
|
160 |
11 |
TobiasJ |
if sample_tick = '1' then
|
161 |
|
|
sample_reg_q <= sample_reg_d;
|
162 |
|
|
rx_sampled_q <= rx_sampled_d;
|
163 |
|
|
sample_reg_start_bit_q <= sample_reg_start_bit_d;
|
164 |
|
|
end if;
|
165 |
6 |
TobiasJ |
|
166 |
11 |
TobiasJ |
if baud_tick = '1' or (current_state = idle and sample_reg_start_bit_q = start_samples) or current_state = data_check or current_state = data_rdy then
|
167 |
6 |
TobiasJ |
current_state <= next_state;
|
168 |
11 |
TobiasJ |
end if;
|
169 |
|
|
|
170 |
|
|
if baud_tick = '1' and current_state = data_bit0 then
|
171 |
|
|
sampled_data(0) <= rx_sampled_q;
|
172 |
|
|
end if;
|
173 |
|
|
if baud_tick = '1' and current_state = data_bit1 then
|
174 |
|
|
sampled_data(1) <= rx_sampled_q;
|
175 |
|
|
end if;
|
176 |
|
|
if baud_tick = '1' and current_state = data_bit2 then
|
177 |
|
|
sampled_data(2) <= rx_sampled_q;
|
178 |
|
|
end if;
|
179 |
|
|
if baud_tick = '1' and current_state = data_bit3 then
|
180 |
|
|
sampled_data(3) <= rx_sampled_q;
|
181 |
|
|
end if;
|
182 |
|
|
if baud_tick = '1' and current_state = data_bit4 then
|
183 |
|
|
sampled_data(4) <= rx_sampled_q;
|
184 |
|
|
end if;
|
185 |
|
|
if baud_tick = '1' and current_state = data_bit5 then
|
186 |
|
|
sampled_data(5) <= rx_sampled_q;
|
187 |
|
|
end if;
|
188 |
|
|
if baud_tick = '1' and current_state = data_bit6 then
|
189 |
|
|
sampled_data(6) <= rx_sampled_q;
|
190 |
|
|
end if;
|
191 |
|
|
if baud_tick = '1' and current_state = data_bit7 then
|
192 |
|
|
sampled_data(7) <= rx_sampled_q;
|
193 |
|
|
end if;
|
194 |
|
|
if baud_tick = '1' and current_state = stop_bit1 then
|
195 |
|
|
sampled_data(8) <= rx_sampled_q;
|
196 |
|
|
end if;
|
197 |
|
|
if baud_tick = '1' and current_state = stop_bit2 then
|
198 |
|
|
sampled_data(9) <= rx_sampled_q;
|
199 |
|
|
end if;
|
200 |
|
|
|
201 |
|
|
if current_state = data_check then
|
202 |
|
|
data <= sampled_data(7 downto 0);
|
203 |
|
|
end if;
|
204 |
|
|
|
205 |
|
|
if baud_tick = '1' and use_parity_bit = '1' then
|
206 |
|
|
xored_sampled_data_bit_q <= xored_sampled_data_bit_d;
|
207 |
|
|
end if;
|
208 |
6 |
TobiasJ |
end if;
|
209 |
11 |
TobiasJ |
end process register_logic;
|
210 |
|
|
|
211 |
27 |
TobiasJ |
end architecture behaviour;
|