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

Subversion Repositories rise

[/] [rise/] [trunk/] [vhdl/] [sc_uart.vhd] - Blame information for rev 149

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 115 trinklhar
--
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
generic (addr_bits : integer;
46
        clk_freq : integer;
47
        baud_rate : integer;
48
        txf_depth : integer; txf_thres : integer;
49
        rxf_depth : integer; rxf_thres : integer);
50
port (
51
        clk             : in std_logic;
52
        reset   : in std_logic;
53
 
54
-- SimpCon interface
55
 
56
        address         : in std_logic_vector(addr_bits-1 downto 0);
57
        wr_data         : in std_logic_vector(15 downto 0);
58
        rd, wr          : in std_logic;
59
        rd_data         : out std_logic_vector(15 downto 0);
60
        rdy_cnt         : out unsigned(1 downto 0);
61
 
62
        txd             : out std_logic;
63
        rxd             : in std_logic;
64
        ncts    : in std_logic;
65
        nrts    : out std_logic
66
);
67
end sc_uart;
68
 
69
architecture rtl of sc_uart is
70
 
71
component fifo is
72
 
73
generic (width : integer; depth : integer; thres : integer);
74
port (
75
        clk             : in std_logic;
76
        reset   : in std_logic;
77
 
78
        din             : in std_logic_vector(width-1 downto 0);
79
        dout    : out std_logic_vector(width-1 downto 0);
80
 
81
        rd              : in std_logic;
82
        wr              : in std_logic;
83
 
84
        empty   : out std_logic;
85
        full    : out std_logic;
86
        half    : out std_logic
87
);
88
end component;
89
 
90
--
91
--      signals for uart connection
92
--
93
        signal ua_dout                  : std_logic_vector(7 downto 0);
94
        signal ua_wr, tdre              : std_logic;
95
        signal ua_rd, rdrf              : std_logic;
96
 
97
        type uart_tx_state_type         is (s0, s1);
98
        signal uart_tx_state            : uart_tx_state_type;
99
 
100
        signal tf_dout          : std_logic_vector(7 downto 0); -- fifo out
101
        signal tf_rd            : std_logic;
102
        signal tf_empty         : std_logic;
103
        signal tf_full          : std_logic;
104
        signal tf_half          : std_logic;
105
 
106
        signal ncts_buf         : std_logic_vector(2 downto 0);  -- sync in
107
 
108
        signal tsr                      : std_logic_vector(9 downto 0); -- tx shift register
109
 
110
        signal tx_clk           : std_logic;
111
 
112
 
113
        type uart_rx_state_type         is (s0, s1, s2);
114
        signal uart_rx_state            : uart_rx_state_type;
115
 
116
        signal rf_wr            : std_logic;
117
        signal rf_empty         : std_logic;
118
        signal rf_full          : std_logic;
119
        signal rf_half          : std_logic;
120
 
121
        signal rxd_reg          : std_logic_vector(2 downto 0);
122
        signal rx_buf           : std_logic_vector(2 downto 0);  -- sync in, filter
123
        signal rx_d                     : std_logic;                                    -- rx serial data
124
 
125
        signal rsr                      : std_logic_vector(9 downto 0); -- rx shift register
126
 
127
        signal rx_clk           : std_logic;
128
        signal rx_clk_ena       : std_logic;
129
 
130
        constant clk16_cnt      : integer := (clk_freq/baud_rate+8)/16-1;
131
 
132
 
133
begin
134
 
135
        rdy_cnt <= "00";        -- no wait states
136
        rd_data(15 downto 8) <= ( others => '0' );
137
--
138
--      The registered MUX is all we need for a SimpCon read.
139
--      The read data is stored in registered rd_data.
140
--
141
process(clk, reset)
142
begin
143
 
144 127 jlechner
        if (reset='0') then
145 115 trinklhar
                rd_data(7 downto 0) <= (others => '0');
146
        elsif rising_edge(clk) then
147
 
148
                ua_rd <= '0';
149
                if rd='1' then
150
                        -- that's our very simple address decoder
151
                        if address(0)='0' then
152
                                rd_data(7 downto 0) <= "000000" & rdrf & tdre;
153
                        else
154
                                rd_data(7 downto 0) <= ua_dout;
155
                                ua_rd <= rd;
156
                        end if;
157
                end if;
158
        end if;
159
 
160
end process;
161
 
162
        -- write is on address offest 1
163
        ua_wr <= wr and address(0);
164
 
165
--
166
--      serial clock
167
--
168
process(clk, reset)
169
 
170
        variable clk16          : integer range 0 to clk16_cnt;
171
        variable clktx          : unsigned(3 downto 0);
172
        variable clkrx          : unsigned(3 downto 0);
173
 
174
begin
175 127 jlechner
        if (reset='0') then
176 115 trinklhar
                clk16 := 0;
177
                clktx := "0000";
178
                clkrx := "0000";
179
                tx_clk <= '0';
180
                rx_clk <= '0';
181
                rx_buf <= "111";
182
 
183
        elsif rising_edge(clk) then
184
 
185
                rxd_reg(0) <= rxd;                       -- to avoid setup timing error in Quartus
186
                rxd_reg(1) <= rxd_reg(0);
187
                rxd_reg(2) <= rxd_reg(1);
188
 
189
                if (clk16=clk16_cnt) then               -- 16 x serial clock
190
                        clk16 := 0;
191
--
192
--      tx clock
193
--
194
                        clktx := clktx + 1;
195
                        if (clktx="0000") then
196
                                tx_clk <= '1';
197
                        else
198
                                tx_clk <= '0';
199
                        end if;
200
--
201
--      rx clock
202
--
203
                        if (rx_clk_ena='1') then
204
                                clkrx := clkrx + 1;
205
                                if (clkrx="1000") then
206
                                        rx_clk <= '1';
207
                                else
208
                                        rx_clk <= '0';
209
                                end if;
210
                        else
211
                                clkrx := "0000";
212
                        end if;
213
--
214
--      sync in filter buffer
215
--
216
                        rx_buf(0) <= rxd_reg(2);
217
                        rx_buf(2 downto 1) <= rx_buf(1 downto 0);
218
                else
219
                        clk16 := clk16 + 1;
220
                        tx_clk <= '0';
221
                        rx_clk <= '0';
222
                end if;
223
 
224
 
225
        end if;
226
 
227
end process;
228
 
229
--
230
--      transmit fifo
231
--
232
        cmp_tf: fifo generic map (8, txf_depth, txf_thres)
233
                        port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
234
 
235
--
236
--      state machine for actual shift out
237
--
238
process(clk, reset)
239
 
240
        variable i : integer range 0 to 11;
241
 
242
begin
243
 
244 127 jlechner
        if (reset='0') then
245 115 trinklhar
                uart_tx_state <= s0;
246
                tsr <= "1111111111";
247
                tf_rd <= '0';
248
                ncts_buf <= "111";
249
 
250
        elsif rising_edge(clk) then
251
 
252
                ncts_buf(0) <= ncts;
253
                ncts_buf(2 downto 1) <= ncts_buf(1 downto 0);
254
 
255
                case uart_tx_state is
256
 
257
                        when s0 =>
258
                                i := 0;
259
                                if (tf_empty='0' and ncts_buf(2)='0') then
260
                                        uart_tx_state <= s1;
261
                                        tsr <= tf_dout & '0' & '1';
262
                                        tf_rd <= '1';
263
                                end if;
264
 
265
                        when s1 =>
266
                                tf_rd <= '0';
267
                                if (tx_clk='1') then
268
                                        tsr(9) <= '1';
269
                                        tsr(8 downto 0) <= tsr(9 downto 1);
270
                                        i := i+1;
271
                                        if (i=11) then                          -- two stop bits
272
                                                uart_tx_state <= s0;
273
                                        end if;
274
                                end if;
275
 
276
                end case;
277
        end if;
278
 
279
end process;
280
 
281
        txd <= tsr(0);
282
        tdre <= not tf_full;
283
 
284
 
285
--
286
--      receive fifo
287
--
288
        cmp_rf: fifo generic map (8, rxf_depth, rxf_thres)
289
                        port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half);
290
 
291
        rdrf <= not rf_empty;
292
        nrts <= rf_half;                        -- glitches even on empty fifo!
293
 
294
--
295
--      filter rxd
296
--
297
        with rx_buf select
298
                rx_d <= '0' when "000",
299
                                '0' when "001",
300
                                '0' when "010",
301
                                '1' when "011",
302
                                '0' when "100",
303
                                '1' when "101",
304
                                '1' when "110",
305
                                '1' when "111",
306
                                'X' when others;
307
 
308
--
309
--      state machine for actual shift in
310
--
311
process(clk, reset)
312
 
313
        variable i : integer range 0 to 10;
314
 
315
begin
316
 
317 127 jlechner
        if (reset='0') then
318 115 trinklhar
                uart_rx_state <= s0;
319
                rsr <= "0000000000";
320
                rf_wr <= '0';
321
                rx_clk_ena <= '0';
322
 
323
        elsif rising_edge(clk) then
324
 
325
                case uart_rx_state is
326
 
327
 
328
                        when s0 =>
329
                                i := 0;
330
                                rf_wr <= '0';
331
                                if (rx_d='0') then
332
                                        rx_clk_ena <= '1';
333
                                        uart_rx_state <= s1;
334
                                else
335
                                        rx_clk_ena <= '0';
336
                                end if;
337
 
338
                        when s1 =>
339
                                if (rx_clk='1') then
340
                                        rsr(9) <= rx_d;
341
                                        rsr(8 downto 0) <= rsr(9 downto 1);
342
                                        i := i+1;
343
                                        if (i=10) then
344
                                                uart_rx_state <= s2;
345
                                        end if;
346
                                end if;
347
 
348
                        when s2 =>
349
                                rx_clk_ena <= '0';
350
                                if rsr(0)='0' and rsr(9)='1' then
351
                                        if rf_full='0' then                              -- if full just drop it
352
                                                rf_wr <= '1';
353
                                        end if;
354
                                end if;
355
                                uart_rx_state <= s0;
356
 
357
                end case;
358
        end if;
359
 
360
end process;
361
 
362
end rtl;

powered by: WebSVN 2.1.0

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