OpenCores
URL https://opencores.org/ocsvn/diogenes/diogenes/trunk

Subversion Repositories diogenes

[/] [diogenes/] [tags/] [initial/] [vhdl/] [sc_uart.vhd] - Blame information for rev 236

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 154 fellnhofer
--
2
--      sc_uart.vhd
3
--
4
--      8-N-1 serial interface
5
--      
6
--      wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later
7
--
8
--      Author: Martin Schoeberl        martin@jopdesign.com
9
--
10
--
11
--      resources on ACEX1K30-3
12
--
13
--              100 LCs, max 90 MHz
14
--
15
--      resetting rts with fifo_full-1 works with C program on pc
16
--      but not with javax.comm: sends some more bytes after deassert
17
--      of rts (16 byte blocks regardless of rts).
18
--      Try to stop with half full fifo.
19
--
20
--      todo:
21
--
22
--
23
--      2000-12-02      first working version
24
--      2002-01-06      changed tdr and rdr to fifos.
25
--      2002-05-15      changed clkdiv calculation
26
--      2002-11-01      don't wait if read fifo is full, just drop the byte
27
--      2002-11-03      use threshold in fifo to reset rts 
28
--                              don't send if cts is '0'
29
--      2002-11-08      rx fifo to 20 characters and stop after 4
30
--      2003-07-05      new IO standard, change cts/rts to neg logic
31
--      2003-09-19      sync ncts in!
32
--      2004-03-23      two stop bits
33
--      2005-11-30      change interface to SimpCon
34
--      2006-08-07      rxd input register with clk to avoid Quartus tsu violation
35
--      2006-08-13      use 3 FFs for the rxd input at clk
36
--
37
 
38
 
39
library ieee;
40
use ieee.std_logic_1164.all;
41
use ieee.numeric_std.all;
42
 
43
entity sc_uart is
44
 
45
 
46
generic (addr_bits : integer;
47
        clk_freq : integer;
48
        baud_rate : integer;
49
        txf_depth : integer; txf_thres : integer;
50
        rxf_depth : integer; rxf_thres : integer);
51
port (
52
        clk             : in std_logic;
53
        reset   : in std_logic;
54
 
55
-- SimpCon interface
56
 
57
        address         : in std_logic_vector(addr_bits-1 downto 0);
58
        wr_data         : in std_logic_vector(31 downto 0);
59
        rd, wr          : in std_logic;
60
        rd_data         : out std_logic_vector(31 downto 0);
61
--      rdy_cnt         : out unsigned(1 downto 0);
62
 
63
        txd             : out std_logic;
64
        rxd             : in std_logic;
65
        ncts    : in std_logic;
66
        nrts    : out std_logic
67
);
68
end sc_uart;
69
 
70
architecture rtl of sc_uart is
71
 
72
component fifo is
73
 
74
generic (width : integer; depth : integer; thres : integer);
75
port (
76
        clk             : in std_logic;
77
        reset   : in std_logic;
78
 
79
        din             : in std_logic_vector(width-1 downto 0);
80
        dout    : out std_logic_vector(width-1 downto 0);
81
 
82
        rd              : in std_logic;
83
        wr              : in std_logic;
84
 
85
        empty   : out std_logic;
86
        full    : out std_logic;
87
        half    : out std_logic
88
);
89
end component;
90
 
91
--
92
--      signals for uart connection
93
--
94
        signal ua_dout                  : std_logic_vector(7 downto 0);
95
        signal ua_wr, tdre              : std_logic;
96
        signal ua_rd, rdrf              : std_logic;
97
 
98
        type uart_tx_state_type         is (s0, s1);
99
        signal uart_tx_state            : uart_tx_state_type;
100
 
101
        signal tf_dout          : std_logic_vector(7 downto 0); -- fifo out
102
        signal tf_rd            : std_logic;
103
        signal tf_empty         : std_logic;
104
        signal tf_full          : std_logic;
105
        signal tf_half          : std_logic;
106
 
107
        signal ncts_buf         : std_logic_vector(2 downto 0);  -- sync in
108
 
109
        signal tsr                      : std_logic_vector(9 downto 0); -- tx shift register
110
 
111
        signal tx_clk           : std_logic;
112
 
113
 
114
        type uart_rx_state_type         is (s0, s1, s2);
115
        signal uart_rx_state            : uart_rx_state_type;
116
 
117
        signal rf_wr            : std_logic;
118
        signal rf_empty         : std_logic;
119
        signal rf_full          : std_logic;
120
        signal rf_half          : std_logic;
121
 
122
        signal rxd_reg          : std_logic_vector(2 downto 0);
123
        signal rx_buf           : std_logic_vector(2 downto 0);  -- sync in, filter
124
        signal rx_d                     : std_logic;                                    -- rx serial data
125
 
126
        signal rsr                      : std_logic_vector(9 downto 0); -- rx shift register
127
 
128
        signal rx_clk           : std_logic;
129
        signal rx_clk_ena       : std_logic;
130
 
131
        constant clk16_cnt      : integer := (clk_freq/baud_rate+8)/16-1;
132
 
133
 
134
begin
135
 
136
--      rdy_cnt <= "00";        -- no wait states
137
        rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24));
138
--
139
--      The registered MUX is all we need for a SimpCon read.
140
--      The read data is stored in registered rd_data.
141
--
142
 
143
-- 
144
process(clk, reset, rdrf, tdre, ua_dout, rd, address)
145
begin
146
 
147
--      if (reset='1') then
148
--              rd_data(7 downto 0) <= (others => '0');
149
--      elsif rising_edge(clk) then
150
                ua_rd <= '0';
151
                if rd='1' then
152
                        -- that's our very simple address decoder
153
                        if address(0)='0' then
154
                                rd_data(7 downto 0) <= "000000" & rdrf & tdre;
155
                        else
156
                                rd_data(7 downto 0) <= ua_dout;
157
                                ua_rd <= rd;
158
                        end if;
159
                end if;
160
--      end if;
161
 
162
end process;
163
 
164
        -- write is on address offest 1
165
        ua_wr <= wr and address(0);
166
 
167
--
168
--      serial clock
169
--
170
process(clk, reset)
171
 
172
        variable clk16          : integer;-- range 0 to clk16_cnt;
173
        variable clktx          : unsigned(3 downto 0);
174
        variable clkrx          : unsigned(3 downto 0);
175
 
176
begin
177
        if (reset='1') then
178
                clk16 := 0;
179
                clktx := "0000";
180
                clkrx := "0000";
181
                tx_clk <= '0';
182
                rx_clk <= '0';
183
                rx_buf <= "111";
184
 
185
        elsif rising_edge(clk) then
186
 
187
                rxd_reg(0) <= rxd;                       -- to avoid setup timing error in Quartus
188
                rxd_reg(1) <= rxd_reg(0);
189
                rxd_reg(2) <= rxd_reg(1);
190
 
191
                if (clk16=clk16_cnt) then               -- 16 x serial clock
192
                        clk16 := 0;
193
--
194
--      tx clock
195
--
196
                        clktx := clktx + 1;
197
                        if (clktx="0000") then
198
                                tx_clk <= '1';
199
                        else
200
                                tx_clk <= '0';
201
                        end if;
202
--
203
--      rx clock
204
--
205
                        if (rx_clk_ena='1') then
206
                                clkrx := clkrx + 1;
207
                                if (clkrx="1000") then
208
                                        rx_clk <= '1';
209
                                else
210
                                        rx_clk <= '0';
211
                                end if;
212
                        else
213
                                clkrx := "0000";
214
                        end if;
215
--
216
--      sync in filter buffer
217
--
218
                        rx_buf(0) <= rxd_reg(2);
219
                        rx_buf(2 downto 1) <= rx_buf(1 downto 0);
220
                else
221
                        clk16 := clk16 + 1;
222
                        tx_clk <= '0';
223
                        rx_clk <= '0';
224
                end if;
225
 
226
 
227
        end if;
228
 
229
end process;
230
 
231
--
232
--      transmit fifo
233
--
234
        cmp_tf: fifo generic map (8, txf_depth, txf_thres)
235
                        port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
236
 
237
--
238
--      state machine for actual shift out
239
--
240
process(clk, reset)
241
 
242
        variable i : integer range 0 to 11;
243
 
244
begin
245
 
246
        if (reset='1') then
247
                uart_tx_state <= s0;
248
                tsr <= "1111111111";
249
                tf_rd <= '0';
250
                ncts_buf <= "111";
251
 
252
        elsif rising_edge(clk) then
253
 
254
                ncts_buf(0) <= ncts;
255
                ncts_buf(2 downto 1) <= ncts_buf(1 downto 0);
256
 
257
                case uart_tx_state is
258
 
259
                        when s0 =>
260
                                i := 0;
261
                                if (tf_empty='0' and ncts_buf(2)='0') then
262
                                        uart_tx_state <= s1;
263
                                        tsr <= tf_dout & '0' & '1';
264
                                        tf_rd <= '1';
265
                                end if;
266
 
267
                        when s1 =>
268
                                tf_rd <= '0';
269
                                if (tx_clk='1') then
270
                                        tsr(9) <= '1';
271
                                        tsr(8 downto 0) <= tsr(9 downto 1);
272
                                        i := i+1;
273
                                        if (i=11) then                          -- two stop bits
274
                                                uart_tx_state <= s0;
275
                                        end if;
276
                                end if;
277
 
278
                end case;
279
        end if;
280
 
281
end process;
282
 
283
        txd <= tsr(0);
284
        tdre <= not tf_full;
285
 
286
 
287
--
288
--      receive fifo
289
--
290
        cmp_rf: fifo generic map (8, rxf_depth, rxf_thres)
291
                        port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half);
292
 
293
        rdrf <= not rf_empty;
294
        nrts <= rf_half;                        -- glitches even on empty fifo!
295
 
296
--
297
--      filter rxd
298
--
299
        with rx_buf select
300
                rx_d <= '0' when "000",
301
                                '0' when "001",
302
                                '0' when "010",
303
                                '1' when "011",
304
                                '0' when "100",
305
                                '1' when "101",
306
                                '1' when "110",
307
                                '1' when "111",
308
                                'X' when others;
309
 
310
--
311
--      state machine for actual shift in
312
--
313
process(clk, reset)
314
 
315
        variable i : integer range 0 to 10;
316
 
317
begin
318
 
319
        if (reset='1') then
320
                uart_rx_state <= s0;
321
                rsr <= "0000000000";
322
                rf_wr <= '0';
323
                rx_clk_ena <= '0';
324
 
325
        elsif rising_edge(clk) then
326
 
327
                case uart_rx_state is
328
 
329
 
330
                        when s0 =>
331
                                i := 0;
332
                                rf_wr <= '0';
333
                                if (rx_d='0') then
334
                                        rx_clk_ena <= '1';
335
                                        uart_rx_state <= s1;
336
                                else
337
                                        rx_clk_ena <= '0';
338
                                end if;
339
 
340
                        when s1 =>
341
                                if (rx_clk='1') then
342
                                        rsr(9) <= rx_d;
343
                                        rsr(8 downto 0) <= rsr(9 downto 1);
344
                                        i := i+1;
345
                                        if (i=10) then
346
                                                uart_rx_state <= s2;
347
                                        end if;
348
                                end if;
349
 
350
                        when s2 =>
351
                                rx_clk_ena <= '0';
352
                                if rsr(0)='0' and rsr(9)='1' then
353
                                        if rf_full='0' then                              -- if full just drop it
354
                                                rf_wr <= '1';
355
                                        end if;
356
                                end if;
357
                                uart_rx_state <= s0;
358
 
359
                end case;
360
        end if;
361
 
362
end process;
363
 
364
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.