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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_uart_tal.vhd] - Blame information for rev 29

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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