]> rtime.felk.cvut.cz Git - fpga/uart.git/blob - uart.vhd
Resets changed from asynchronous to synchronous.
[fpga/uart.git] / uart.vhd
1 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 uart is
7   generic (
8     output_fifo_width : integer := 2;
9     input_fifo_width  : integer := 2
10   );
11   port (
12     mclk        : in  std_logic;
13     per_addr    : in  std_logic_vector (7 downto 0);
14     per_din     : in  std_logic_vector (15 downto 0);
15     per_en      : in  std_logic;
16     per_wen     : in  std_logic_vector (1 downto 0);
17     puc         : in  std_logic;
18     per_irq_acc : in  std_logic;
19     per_irq     : out std_logic;
20     per_dout    : out std_logic_vector (15 downto 0);
21
22     rxd         : in  std_logic;
23     txd         : out std_logic
24   );
25 end uart;
26
27 --------------------------------------------------------------------------------
28
29 architecture dataflow of uart is
30
31   component tx_control is
32     port (
33       clk        : in  std_logic;
34       reset      : in  std_logic;
35       tx_ready   : in  std_logic;
36       fifo_empty : in  std_logic;
37       tx_we      : out std_logic;
38       fifo_pop   : out std_logic
39     );
40   end component;
41
42   component transmitter is
43     port (
44       clk    : in  std_logic;
45       reset  : in  std_logic;
46       data   : in  std_logic_vector (7 downto 0);
47       we     : in  std_logic;
48       ready  : out std_logic;
49       tx     : out std_logic
50     );
51   end component;
52
53   component rx_control is
54     port (
55       clk           : in  std_logic;
56       reset         : in  std_logic;
57       rx            : in  std_logic;
58       bad_start_bit : in  std_logic;
59       bad_stop_bit  : in  std_logic;
60       rx_ready      : in  std_logic;
61       rx_reset      : out std_logic;
62       rx_en         : out std_logic;
63       fifo_we       : out std_logic;
64       clk_en        : out std_logic
65     );
66   end component rx_control;
67
68   component receiver is
69     port (
70       clk           : in  std_logic;
71       reset         : in  std_logic;
72       en            : in  std_logic;
73       rx            : in  std_logic;
74       ready         : out std_logic;
75       bad_start_bit : out std_logic;
76       bad_stop_bit  : out std_logic;
77       data          : out std_logic_vector (7 downto 0)
78     );
79   end component receiver;
80   
81   component fifo is
82     generic (
83       width : integer := 2
84     );
85     port (
86       clk      : in  std_logic;
87       reset    : in  std_logic;
88       we       : in  std_logic;
89       re       : in  std_logic;
90       clear_ow : in  std_logic;
91       d_in     : in  std_logic_vector (7 downto 0);
92       d_out    : out std_logic_vector (7 downto 0);
93       full     : out std_logic;
94       hfull    : out std_logic;
95       empty    : out std_logic;
96       overflow : out std_logic
97     );
98   end component;
99
100   component baud_gen is
101     port (
102       clk      : in  std_logic;
103       ce       : in  std_logic;
104       reset    : in  std_logic;
105       scale    : in  std_logic_vector (15 downto 0);
106       clk_baud : out std_logic
107     );
108   end component;
109
110 --------------------------------------------------------------------------------
111
112   alias per_din_low  : std_logic_vector (7 downto 0) is per_din (7 downto 0);
113   alias per_din_high : std_logic_vector (7 downto 0) is per_din (15 downto 8);
114   
115   type boolean_vector is array (natural range <>) of boolean;
116
117 --------------------------------------------------------------------------------
118   
119   constant base_addr : integer := 16#0100#;
120   
121   constant UBAUD : integer := base_addr + 00;  -- 2B - Baud rate generator
122   constant UTX   : integer := base_addr + 02;  -- 1B - Transmit data
123   constant URX   : integer := base_addr + 04;  -- 1B - Read data
124   constant USTAT : integer := base_addr + 06;  -- 1B - Rx & Tx status
125   constant UIE   : integer := base_addr + 07;  -- 1B - Interrupt enable
126
127   signal reg_we   : std_logic_vector (511 downto 0);
128   signal reg_re   : std_logic_vector (511 downto 0);
129   signal reg_re_b : boolean_vector (512 downto 0);
130
131   
132   signal reg_baud : std_logic_vector (15 downto 0) := (others => '0');
133   signal reg_stat : std_logic_vector (7 downto 0);
134   signal reg_ie   : std_logic_vector (7 downto 0) := (others => '0');
135
136   
137   signal tx_clk        : std_logic;
138   signal tx_data       : std_logic_vector (7 downto 0);
139   signal tx_we         : std_logic;
140   signal tx_ready      : std_logic;
141   signal tx_fifo_full  : std_logic;
142   signal tx_fifo_hfull : std_logic;
143   signal tx_fifo_empty : std_logic;
144   signal tx_fifo_re    : std_logic;
145
146   signal rx_clk           : std_logic;
147   signal rx_clk_en        : std_logic;
148   signal rx_en            : std_logic;
149   signal rx_ready         : std_logic;
150   signal rx_reset         : std_logic;
151   signal rx_data          : std_logic_vector (7 downto 0);
152   signal rx_bad_start_bit : std_logic;
153   signal rx_bad_stop_bit  : std_logic;
154   signal rx_fifo_we       : std_logic;
155   signal rx_fifo_out      : std_logic_vector (7 downto 0);
156   signal rx_fifo_full     : std_logic;
157   signal rx_fifo_hfull    : std_logic;
158   signal rx_fifo_empty    : std_logic;
159   signal rx_fifo_ow       : std_logic;
160   signal rx_fifo_ow_clear : std_logic;
161   
162 --------------------------------------------------------------------------------
163
164 begin
165
166   -- Address decoder
167   process (per_addr, per_wen, per_en)
168   begin
169     for i in reg_re'range loop
170       reg_re_b (i) <= false;
171       reg_re (i)   <= '0';
172       reg_we (i)   <= '0';
173       
174       if (per_en = '1' and per_addr = i/2) then
175         -- Register of the corresponding address is always read, so
176         -- read-modify-write operation in one cycle is possible.
177         reg_re_b (i) <= true;
178         reg_re (i)   <= '1';
179         
180         if (per_wen (i mod 2) = '1') then
181           reg_we (i) <= '1';
182         end if;
183       end if;
184     end loop;
185   end process;
186   
187 --------------------------------------------------------------------------------
188 -- TX MODULE
189 --------------------------------------------------------------------------------
190
191   tx_control_0 : tx_control port map (
192     clk        => mclk,
193     reset      => puc,
194     tx_ready   => tx_ready,
195     fifo_empty => tx_fifo_empty,
196     tx_we      => tx_we,
197     fifo_pop   => tx_fifo_re
198   );
199
200   tx_transmitter_0 : transmitter port map (
201     clk    => tx_clk,
202     reset  => puc,
203     data   => tx_data,
204     we     => tx_we,
205     ready  => tx_ready,
206     tx     => txd
207   );
208
209   tx_fifo_0 : fifo port map (
210     clk      => mclk,
211     reset    => puc,
212     we       => reg_we (UTX),
213     re       => tx_fifo_re,
214     clear_ow => '0',
215     d_in     => per_din (7 downto 0),
216     d_out    => tx_data,
217     full     => tx_fifo_full,
218     hfull    => tx_fifo_hfull,
219     empty    => tx_fifo_empty,
220     overflow => open
221     );
222
223   tx_baud_gen_0 : baud_gen port map (
224     clk      => mclk,
225     ce       => '1',
226     reset    => puc,
227     scale    => reg_baud,
228     clk_baud => tx_clk
229     );
230
231 --------------------------------------------------------------------------------
232 -- RX MODULE
233 --------------------------------------------------------------------------------
234
235   rx_control_0 : rx_control
236     port map (
237       clk           => mclk,
238       reset         => puc,
239       rx            => rxd,
240       bad_start_bit => rx_bad_start_bit,
241       bad_stop_bit  => rx_bad_stop_bit,
242       rx_ready      => rx_ready,
243       rx_reset      => rx_reset,
244       rx_en         => rx_en,
245       fifo_we       => rx_fifo_we,
246       clk_en        => rx_clk_en);
247
248   rx_receiver_0 : receiver
249     port map (
250       clk           => rx_clk,
251       reset         => puc,
252       en            => rx_en,
253       rx            => rxd,
254       ready         => rx_ready,
255       bad_start_bit => rx_bad_start_bit,
256       bad_stop_bit  => rx_bad_stop_bit,
257       data          => rx_data);
258
259   rx_fifo_0 : fifo
260     port map (
261       clk      => mclk,
262       reset    => puc,
263       we       => rx_fifo_we,
264       re       => reg_re (URX),
265       clear_ow => rx_fifo_ow_clear,
266       d_in     => rx_data,
267       d_out    => rx_fifo_out,
268       full     => rx_fifo_full,
269       hfull    => rx_fifo_hfull,
270       empty    => rx_fifo_empty,
271       overflow => rx_fifo_ow);
272
273   rx_baud_gen_0 : baud_gen
274     port map (
275       clk      => mclk,
276       ce       => rx_clk_en,
277       reset    => puc,
278       scale    => reg_baud,
279       clk_baud => rx_clk);
280   
281 --------------------------------------------------------------------------------
282 -- OTHER LOGIC
283 --------------------------------------------------------------------------------
284   
285   process (mclk, puc) is
286   begin
287     if mclk'event and mclk = '1' then
288       if puc = '1' then
289         reg_baud <= (others => '0');
290         reg_ie   <= (others => '0');
291
292       else
293         if reg_we (UBAUD) = '1' then
294           reg_baud (7 downto 0) <= per_din_low;
295         end if;
296
297         if reg_we (UBAUD+1) = '1' then
298           reg_baud (15 downto 8) <= per_din_high;
299         end if;
300
301         if reg_we (USTAT) = '1' then
302           reg_ie <= per_din_low;
303         end if;
304       end if;
305     end if;
306   end process;
307
308
309   reg_stat <= tx_fifo_empty &
310               tx_fifo_hfull &
311               tx_fifo_full &
312               not rx_fifo_empty &
313               rx_fifo_hfull &
314               rx_fifo_full &
315               rx_fifo_ow &
316               '0';
317
318   
319   per_irq <= '1' when (reg_stat and reg_ie and "10011100") /= "00000000" else '0' ;
320
321   per_dout <= reg_baud                 when reg_re_b (UBAUD) else
322               "00000000" & tx_data     when reg_re_b (UTX) else
323               "00000000" & rx_fifo_out when reg_re_b (URX) else
324               reg_ie & reg_stat        when reg_re_b (USTAT) else
325               (others => '0');
326   
327 --------------------------------------------------------------------------------
328   
329   rx_fifo_ow_clear <= per_din (1) and reg_we (USTAT);
330   
331 end dataflow;
332