51e7135a11c2076e3c4c39795320ce26359e31de
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

1) LIBRARY IEEE;
2) USE IEEE.STD_LOGIC_1164.ALL;
3) USE IEEE.NUMERIC_STD.ALL;
4) 
5) ENTITY e_io_uart IS
6)     PORT (
7)         rst:       IN  std_logic;
8)         clk:       IN  std_logic;
9)         i_addr:    IN  std_logic_vector( 1 DOWNTO 0);
10)         o_rd_data: OUT std_logic_vector(31 DOWNTO 0);
11)         i_wr_data: IN  std_logic_vector(31 DOWNTO 0);
12)         i_wr_en:   IN  std_logic_vector( 3 DOWNTO 0);
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

13)         pin_i_rx:  IN  std_logic;
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

14)         pin_o_tx:  OUT std_logic
15)     );
16) END ENTITY e_io_uart;
17) 
18) ARCHITECTURE a_io_uart OF e_io_uart IS
19) 
20)     TYPE t_state IS (inactive, start, data, stop);
21) 
22)     SIGNAL n_cfg_scale: std_logic_vector(15 DOWNTO 0);
23)     SIGNAL r_cfg_scale: std_logic_vector(15 DOWNTO 0) := X"0001";
24)     SIGNAL n_cfg_bits:  std_logic_vector( 3 DOWNTO 0);
25)     SIGNAL r_cfg_bits:  std_logic_vector( 3 DOWNTO 0) := X"1";
26)     SIGNAL n_cfg_stop:  std_logic_vector( 1 DOWNTO 0);
27)     SIGNAL r_cfg_stop:  std_logic_vector( 1 DOWNTO 0) := "01";
28) 
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

29)     SIGNAL n_rx_scale:   natural RANGE 2**16 - 1 DOWNTO 0;
30)     SIGNAL r_rx_scale:   natural RANGE 2**16 - 1 DOWNTO 0 := 1;
31)     SIGNAL n_rx_bits:    natural RANGE 15        DOWNTO 0;
32)     SIGNAL r_rx_bits:    natural RANGE 15        DOWNTO 0 := 1;
33)     SIGNAL n_rx_stop:    natural RANGE 3         DOWNTO 0;
34)     SIGNAL r_rx_stop:    natural RANGE 3         DOWNTO 0 := 1;
35)     SIGNAL n_rx_state:   t_state;
36)     SIGNAL r_rx_state:   t_state                          := inactive;
37)     SIGNAL n_rx_cnt:     natural RANGE 2**16 - 1 DOWNTO 0;
38)     SIGNAL r_rx_cnt:     natural RANGE 2**16 - 1 DOWNTO 0 := 0;
39)     SIGNAL n_rx_sample:  natural RANGE 6         DOWNTO 0;
40)     SIGNAL r_rx_sample:  natural RANGE 6         DOWNTO 0 := 0;
41)     SIGNAL n_rx_bit:     natural RANGE 15        DOWNTO 0;
42)     SIGNAL r_rx_bit:     natural RANGE 15        DOWNTO 0 := 0;
43)     SIGNAL n_rx_samples: std_logic_vector( 1 DOWNTO 0);
44)     SIGNAL r_rx_samples: std_logic_vector( 1 DOWNTO 0)    := "00";
45)     SIGNAL n_rx_data:    std_logic_vector(15 DOWNTO 0);
46)     SIGNAL r_rx_data:    std_logic_vector(15 DOWNTO 0)    := X"0000";
47) 
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

48)     SIGNAL s_tx_wr_rdy:  std_logic;
49)     SIGNAL s_tx_wr_en:   std_logic;
50)     SIGNAL s_tx_rd_rdy:  std_logic;
51)     SIGNAL s_tx_rd_data: std_logic_vector(15 DOWNTO 0);
52)     SIGNAL s_tx_rd_en:   std_logic;
53) 
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

54)     SIGNAL n_tx_scale:  natural RANGE 2**16 - 1 DOWNTO 0;
55)     SIGNAL r_tx_scale:  natural RANGE 2**16 - 1 DOWNTO 0 := 1;
56)     SIGNAL n_tx_bits:   natural RANGE 15        DOWNTO 0;
57)     SIGNAL r_tx_bits:   natural RANGE 15        DOWNTO 0 := 1;
58)     SIGNAL n_tx_stop:   natural RANGE 3         DOWNTO 0;
59)     SIGNAL r_tx_stop:   natural RANGE 3         DOWNTO 0 := 1;
60)     SIGNAL n_tx_state:  t_state;
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

61)     SIGNAL r_tx_state:  t_state                          := inactive;
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

62)     SIGNAL n_tx_cnt:    natural RANGE 2**16 - 1 DOWNTO 0;
63)     SIGNAL r_tx_cnt:    natural RANGE 2**16 - 1 DOWNTO 0 := 0;
64)     SIGNAL n_tx_sample: natural RANGE 6         DOWNTO 0;
65)     SIGNAL r_tx_sample: natural RANGE 6         DOWNTO 0 := 0;
66)     SIGNAL n_tx_bit:    natural RANGE 15        DOWNTO 0;
67)     SIGNAL r_tx_bit:    natural RANGE 15        DOWNTO 0 := 0;
68)     SIGNAL n_tx_data:   std_logic_vector(15 DOWNTO 0);
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

69)     SIGNAL r_tx_data:   std_logic_vector(15 DOWNTO 0)    := X"0000";
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

70) 
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

71)     COMPONENT e_block_fifo IS
72)         GENERIC (
73)             addr_width: natural;
74)             data_width: natural
75)         );
76)         PORT (
77)             rst:       IN  std_logic;
78)             clk:       IN  std_logic;
79)             o_wr_rdy:  OUT std_logic;
80)             i_wr_data: IN  std_logic_vector(data_width - 1 DOWNTO 0);
81)             i_wr_en:   IN  std_logic;
82)             o_rd_rdy:  OUT std_logic;
83)             o_rd_data: OUT std_logic_vector(data_width - 1 DOWNTO 0);
84)             i_rd_en:   IN  std_logic
85)         );
86)     END COMPONENT e_block_fifo;
87) 
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

88) BEGIN
89) 
90)     p_cfg_next: PROCESS(r_cfg_scale, r_cfg_bits, r_cfg_stop,
91)                         i_addr, i_wr_data, i_wr_en)
92)     BEGIN
93)         n_cfg_scale <= r_cfg_scale;
94)         n_cfg_bits  <= r_cfg_bits;
95)         n_cfg_stop  <= r_cfg_stop;
96)         IF i_addr = "00" THEN
97)             IF i_wr_en(1 DOWNTO 0) = "11" AND
98)                i_wr_data(15 DOWNTO 0) /= X"0000" THEN
99)                 n_cfg_scale <= i_wr_data(15 DOWNTO 0);
100)             END IF;
101)             IF i_wr_en(2) = '1' AND
102)                i_wr_data(23 DOWNTO 20) = X"0" AND
103)                i_wr_data(19 DOWNTO 16) /= X"0" THEN
104)                 n_cfg_bits <= i_wr_data(19 DOWNTO 16);
105)             END IF;
106)             IF i_wr_en(3) = '1' AND
107)                i_wr_data(31 DOWNTO 26) = "000000" AND
108)                i_wr_data(25 DOWNTO 24) /= "00" THEN
109)                 n_cfg_stop <= i_wr_data(25 DOWNTO 24);
110)             END IF;
111)         END IF;
112)     END PROCESS p_cfg_next;
113) 
114)     p_cfg_sync: PROCESS(rst, clk)
115)     BEGIN
116)         IF rst = '1' THEN
117)             r_cfg_scale <= X"0001";
118)             r_cfg_bits  <= X"1";
119)             r_cfg_stop  <= "01";
120)         ELSIF rising_edge(clk) THEN
121)             r_cfg_scale <= n_cfg_scale;
122)             r_cfg_bits  <= n_cfg_bits;
123)             r_cfg_stop  <= n_cfg_stop;
124)         END IF;
125)     END PROCESS p_cfg_sync;
126) 
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

127)     p_rx_next: PROCESS(r_cfg_scale, r_cfg_bits, r_cfg_stop,
128)                        r_rx_scale, r_rx_bits, r_rx_stop,
129)                        r_rx_state, r_rx_cnt, r_rx_sample, r_rx_bit,
130)                        r_rx_samples, r_rx_data,
131)                        pin_i_rx)
132)         VARIABLE v_next_cnt:    boolean;
133)         VARIABLE v_next_sample: boolean;
134)         VARIABLE v_next_bit:    boolean;
135)         VARIABLE v_next_state:  boolean;
136)         VARIABLE v_bits:        natural RANGE 15 DOWNTO 0;
137)         VARIABLE v_samples:     std_logic_vector(2 DOWNTO 0);
138)         VARIABLE v_bit_val:     std_logic;
139)         VARIABLE v_err:         boolean;
140)     BEGIN
141)         n_rx_scale   <= r_rx_scale;
142)         n_rx_bits    <= r_rx_bits;
143)         n_rx_stop    <= r_rx_stop;
144)         n_rx_state   <= r_rx_state;
145)         n_rx_cnt     <= r_rx_cnt;
146)         n_rx_sample  <= r_rx_sample;
147)         n_rx_bit     <= r_rx_bit;
148)         n_rx_samples <= r_rx_samples;
149)         n_rx_data    <= r_rx_data;
150)         v_next_cnt    := false;
151)         v_next_sample := false;
152)         v_next_bit    := false;
153)         v_next_state  := false;
154)         v_bits        := 0;
155)         v_samples     := "000";
156)         v_bit_val     := '0';
157)         v_err         := false;
158)         IF r_rx_state = inactive THEN
159)             IF pin_i_rx = '0' THEN
160)                 n_rx_scale   <= to_integer(unsigned(r_cfg_scale));
161)                 n_rx_bits    <= to_integer(unsigned(r_cfg_bits));
162)                 n_rx_stop    <= to_integer(unsigned(r_cfg_stop));
163)                 n_rx_state   <= start;
164)                 n_rx_cnt     <= 0;
165)                 n_rx_sample  <= 3; -- sample in middle of received bits
166)                 n_rx_bit     <= 0;
167)                 n_rx_samples <= "00";
168)                 n_rx_data    <= X"0000";
169)             END IF;
170)         ELSE
171)             v_next_cnt := true;
172)         END IF;
173)         IF v_next_cnt THEN
174)             IF r_rx_cnt + 1 /= r_rx_scale THEN
175)                 n_rx_cnt <= r_rx_cnt + 1;
176)             ELSE
177)                 n_rx_cnt <= 0;
178)                 v_next_sample := true;
179)             END IF;
180)         END IF;
181)         IF v_next_sample THEN
182)             IF r_rx_sample = 4 THEN
183)                 n_rx_samples(0) <= pin_i_rx;
184)             ELSIF r_rx_sample = 5 THEN
185)                 n_rx_samples(1) <= pin_i_rx;
186)             ELSIF r_rx_sample = 6 THEN
187)                 v_samples := pin_i_rx & r_rx_samples;
188)                 CASE v_samples IS
189)                    WHEN "000" | "001" | "010" | "100" => v_bit_val := '0';
190)                    WHEN "011" | "101" | "110" | "111" => v_bit_val := '1';
191)                    WHEN OTHERS => NULL;
192)                 END CASE;
193)                 IF r_rx_state = data THEN
194)                     n_rx_data(r_rx_bit) <= v_bit_val;
195)                 END IF;
196)                 CASE r_rx_state IS
197)                     WHEN start => v_err := v_bit_val /= '0';
198)                     WHEN data  => v_err := false;
199)                     WHEN stop  => v_err := v_bit_val /= '1';
200)                     WHEN OTHERS => NULL;
201)                 END CASE;
202)                 IF v_err THEN
203)                     n_rx_data(15) <= '1';
204)                 END IF;
205)             END IF;
206)             IF r_rx_sample /= 6 THEN
207)                 n_rx_sample <= r_rx_sample + 1;
208)             ELSE
209)                 n_rx_sample <= 0;
210)                 v_next_bit := true;
211)             END IF;
212)         END IF;
213)         IF v_next_bit THEN
214)             CASE r_rx_state IS
215)                 WHEN start => v_bits := 1;
216)                 WHEN data  => v_bits := r_rx_bits;
217)                 WHEN stop  => v_bits := r_rx_stop;
218)                 WHEN OTHERS => NULL;
219)             END CASE;
220)             IF r_rx_bit + 1 /= v_bits THEN
221)                 n_rx_bit <= r_rx_bit + 1;
222)             ELSE
223)                 n_rx_bit <= 0;
224)                 v_next_state := true;
225)             END IF;
226)         END IF;
227)         IF v_next_state THEN
228)             CASE r_rx_state IS
229)                 WHEN start => n_rx_state <= data;
230)                 WHEN data  => n_rx_state <= stop;
231)                 WHEN stop  => n_rx_state <= inactive;
232)                 WHEN OTHERS => NULL;
233)             END CASE;
234)         END IF;
235)     END PROCESS p_rx_next;
236) 
237)     p_rx_sync: PROCESS(rst, clk)
238)     BEGIN
239)         IF rst = '1' THEN
240)             r_rx_scale   <= 1;
241)             r_rx_bits    <= 1;
242)             r_rx_stop    <= 1;
243)             r_rx_state   <= inactive;
244)             r_rx_cnt     <= 0;
245)             r_rx_sample  <= 0;
246)             r_rx_bit     <= 0;
247)             r_rx_samples <= "00";
248)             r_rx_data    <= X"0000";
249)         ELSIF rising_edge(clk) THEN
250)             r_rx_scale   <= n_rx_scale;
251)             r_rx_bits    <= n_rx_bits;
252)             r_rx_stop    <= n_rx_stop;
253)             r_rx_state   <= n_rx_state;
254)             r_rx_cnt     <= n_rx_cnt;
255)             r_rx_sample  <= n_rx_sample;
256)             r_rx_bit     <= n_rx_bit;
257)             r_rx_samples <= n_rx_samples;
258)             r_rx_data    <= n_rx_data;
259)         END IF;
260)     END PROCESS p_rx_sync;
261) 
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

262)     s_tx_wr_en <= '1' WHEN i_addr = "10" AND i_wr_en(1 DOWNTO 0) = "11"
263)                   ELSE '0';
264) 
265)     tx_fifo: e_block_fifo
266)         GENERIC MAP (
267)             addr_width => 4,
268)             data_width => 16
269)         )
270)         PORT MAP (
271)             rst       => rst,
272)             clk       => clk,
273)             o_wr_rdy  => s_tx_wr_rdy,
274)             i_wr_data => i_wr_data(15 DOWNTO 0),
275)             i_wr_en   => s_tx_wr_en,
276)             o_rd_rdy  => s_tx_rd_rdy,
277)             o_rd_data => s_tx_rd_data,
278)             i_rd_en   => s_tx_rd_en
279)         );
280) 
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

281)     p_tx_next: PROCESS(r_cfg_scale, r_cfg_bits, r_cfg_stop,
282)                        r_tx_scale, r_tx_bits, r_tx_stop,
283)                        r_tx_state, r_tx_cnt, r_tx_sample, r_tx_bit, r_tx_data,
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

284)                        s_tx_rd_rdy, s_tx_rd_data)
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

285)         VARIABLE v_next_cnt:    boolean;
286)         VARIABLE v_next_sample: boolean;
287)         VARIABLE v_next_bit:    boolean;
288)         VARIABLE v_next_state:  boolean;
289)         VARIABLE v_bits:        natural RANGE 15 DOWNTO 0;
290)     BEGIN
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

291)         s_tx_rd_en  <= '0';
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

292)         n_tx_scale  <= r_tx_scale;
293)         n_tx_bits   <= r_tx_bits;
294)         n_tx_stop   <= r_tx_stop;
295)         n_tx_state  <= r_tx_state;
296)         n_tx_cnt    <= r_tx_cnt;
297)         n_tx_sample <= r_tx_sample;
298)         n_tx_bit    <= r_tx_bit;
299)         n_tx_data   <= r_tx_data;
300)         v_next_cnt    := false;
301)         v_next_sample := false;
302)         v_next_bit    := false;
303)         v_next_state  := false;
304)         v_bits        := 0;
305)         IF r_tx_state = inactive THEN
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

306)             IF s_tx_rd_rdy = '1' THEN
307)                 s_tx_rd_en  <= '1';
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

308)                 n_tx_scale  <= to_integer(unsigned(r_cfg_scale));
309)                 n_tx_bits   <= to_integer(unsigned(r_cfg_bits));
310)                 n_tx_stop   <= to_integer(unsigned(r_cfg_stop));
311)                 n_tx_state  <= start;
312)                 n_tx_cnt    <= 0;
313)                 n_tx_sample <= 0;
314)                 n_tx_bit    <= 0;
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

315)                 n_tx_data   <= s_tx_rd_data;
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

316)             END IF;
317)         ELSE
318)             v_next_cnt := true;
319)         END IF;
320)         IF v_next_cnt THEN
321)             IF r_tx_cnt + 1 /= r_tx_scale THEN
322)                 n_tx_cnt <= r_tx_cnt + 1;
323)             ELSE
324)                 n_tx_cnt <= 0;
325)                 v_next_sample := true;
326)             END IF;
327)         END IF;
328)         IF v_next_sample THEN
Stefan Schuermans implemented RX part of UART...

Stefan Schuermans authored 12 years ago

329)             IF r_tx_sample /= 6 THEN
Stefan Schuermans implemented TX part of UART...

Stefan Schuermans authored 12 years ago

330)                 n_tx_sample <= r_tx_sample + 1;
331)             ELSE
332)                 n_tx_sample <= 0;
333)                 v_next_bit := true;
334)             END IF;
335)         END IF;
336)         IF v_next_bit THEN
337)             CASE r_tx_state IS
338)                 WHEN start => v_bits := 1;
339)                 WHEN data  => v_bits := r_tx_bits;
340)                 WHEN stop  => v_bits := r_tx_stop;
341)                 WHEN OTHERS => NULL;
342)             END CASE;
343)             IF r_tx_bit + 1 /= v_bits THEN
344)                 n_tx_bit <= r_tx_bit + 1;
345)             ELSE
346)                 n_tx_bit <= 0;
347)                 v_next_state := true;
348)             END IF;
349)         END IF;
350)         IF v_next_state THEN
351)             CASE r_tx_state IS
352)                 WHEN start => n_tx_state <= data;
353)                 WHEN data  => n_tx_state <= stop;
354)                 WHEN stop  => n_tx_state <= inactive;
355)                 WHEN OTHERS => NULL;
356)             END CASE;
357)         END IF;
358)     END PROCESS p_tx_next;
359) 
360)     p_tx_sync: PROCESS(rst, clk)
361)     BEGIN
362)         IF rst = '1' THEN
363)             r_tx_scale  <= 1;
364)             r_tx_bits   <= 1;
365)             r_tx_stop   <= 1;
366)             r_tx_state  <= inactive;
367)             r_tx_cnt    <= 0;
368)             r_tx_sample <= 0;
369)             r_tx_bit    <= 0;
370)             r_tx_data   <= X"0000";
371)         ELSIF rising_edge(clk) THEN
372)             r_tx_scale  <= n_tx_scale;
373)             r_tx_bits   <= n_tx_bits;
374)             r_tx_stop   <= n_tx_stop;
375)             r_tx_state  <= n_tx_state;
376)             r_tx_cnt    <= n_tx_cnt;
377)             r_tx_sample <= n_tx_sample;
378)             r_tx_bit    <= n_tx_bit;
379)             r_tx_data   <= n_tx_data;
380)         END IF;
381)     END PROCESS p_tx_sync;
382) 
383)     p_tx_out: PROCESS(r_tx_bit, r_tx_state, r_tx_data)
384)     BEGIN
385)         pin_o_tx <= '1';
386)         CASE r_tx_state IS
387)             WHEN start => pin_o_tx <= '0';
388)             WHEN data  => pin_o_tx <= r_tx_data(r_tx_bit);
389)             WHEN stop  => pin_o_tx <= '1';
390)             WHEN OTHERS => NULL;
391)         END CASE;
392)     END PROCESS p_tx_out;
393) 
394)     p_read: PROCESS(rst, clk)
395)     BEGIN
396)         IF rst = '1' THEN
397)             o_rd_data <= (OTHERS => '0');
398)         ELSIF rising_edge(clk) THEN
399)             o_rd_data <= (OTHERS => '0');
400)             CASE i_addr IS
401)                 WHEN "00" =>
402)                     o_rd_data(15 DOWNTO  0) <= r_cfg_scale;
403)                     o_rd_data(19 DOWNTO 16) <= r_cfg_bits;
404)                     o_rd_data(25 DOWNTO 24) <= r_cfg_stop;
405)                 WHEN "01" =>
Stefan Schuermans added FIFO to UART TX

Stefan Schuermans authored 12 years ago

406)                     o_rd_data(0) <= s_tx_wr_rdy;