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

Subversion Repositories z80soc

[/] [z80soc/] [trunk/] [V0.7.3/] [DE1/] [vhdl/] [T16450.vhd] - Blame information for rev 46

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 46 rrred
--
2
-- 16450 compatible UART with synchronous bus interface
3
-- RClk/BaudOut is XIn enable instead of actual clock
4
--
5
-- Version : 0249b
6
--
7
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
8
--
9
-- All rights reserved
10
--
11
-- Redistribution and use in source and synthezised forms, with or without
12
-- modification, are permitted provided that the following conditions are met:
13
--
14
-- Redistributions of source code must retain the above copyright notice,
15
-- this list of conditions and the following disclaimer.
16
--
17
-- Redistributions in synthesized form must reproduce the above copyright
18
-- notice, this list of conditions and the following disclaimer in the
19
-- documentation and/or other materials provided with the distribution.
20
--
21
-- Neither the name of the author nor the names of other contributors may
22
-- be used to endorse or promote products derived from this software without
23
-- specific prior written permission.
24
--
25
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
29
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
-- POSSIBILITY OF SUCH DAMAGE.
36
--
37
-- Please report bugs to the author, but before you do so, please
38
-- make sure that this is not a derivative work and that
39
-- you have the latest version of this file.
40
--
41
-- The latest version of this file can be found at:
42
--      http://www.opencores.org/cvsweb.shtml/t80/
43
--
44
-- Limitations :
45
--
46
-- File history :
47
--
48
-- 0208 : First release
49
--
50
-- 0249 : Fixed interrupt and baud rate bugs found by Andy Dyer
51
--        Added modem status and break detection
52
--        Added support for 1.5 and 2 stop bits
53
--
54
-- 0249b : Fixed loopback break generation bugs found by Andy Dyer
55
--
56
 
57
library IEEE;
58
use IEEE.std_logic_1164.all;
59
use IEEE.numeric_std.all;
60
 
61
entity T16450 is
62
        port(
63
                MR_n            : in std_logic;
64
                XIn                     : in std_logic;
65
                RClk            : in std_logic;
66
                CS_n            : in std_logic;
67
                Rd_n            : in std_logic;
68
                Wr_n            : in std_logic;
69
                A                       : in std_logic_vector(2 downto 0);
70
                D_In            : in std_logic_vector(7 downto 0);
71
                D_Out           : out std_logic_vector(7 downto 0);
72
                SIn                     : in std_logic;
73
                CTS_n           : in std_logic;
74
                DSR_n           : in std_logic;
75
                RI_n            : in std_logic;
76
                DCD_n           : in std_logic;
77
                SOut            : out std_logic;
78
                RTS_n           : out std_logic;
79
                DTR_n           : out std_logic;
80
                OUT1_n          : out std_logic;
81
                OUT2_n          : out std_logic;
82
                BaudOut         : out std_logic;
83
                Intr            : out std_logic
84
        );
85
end T16450;
86
 
87
architecture rtl of T16450 is
88
 
89
        signal  RBR                             : std_logic_vector(7 downto 0);  -- Reciever Buffer Register
90
        signal  THR                             : std_logic_vector(7 downto 0);  -- Transmitter Holding Register
91
        signal  IER                             : std_logic_vector(7 downto 0);  -- Interrupt Enable Register
92
        signal  IIR                             : std_logic_vector(7 downto 0);  -- Interrupt Ident. Register
93
        signal  LCR                             : std_logic_vector(7 downto 0);  -- Line Control Register
94
        signal  MCR                             : std_logic_vector(7 downto 0);  -- MODEM Control Register
95
        signal  LSR                             : std_logic_vector(7 downto 0);  -- Line Status Register
96
        signal  MSR                             : std_logic_vector(7 downto 0);  -- MODEM Status Register
97
        signal  SCR                             : std_logic_vector(7 downto 0);  -- Scratch Register
98
        signal  DLL                             : std_logic_vector(7 downto 0);  -- Divisor Latch (LS)
99
        signal  DLM                             : std_logic_vector(7 downto 0);  -- Divisor Latch (MS)
100
 
101
        signal  DM0                             : std_logic_vector(7 downto 0);
102
        signal  DM1                             : std_logic_vector(7 downto 0);
103
 
104
        signal  MSR_In                  : std_logic_vector(3 downto 0);
105
 
106
        signal  Bit_Phase               : unsigned(3 downto 0);
107
        signal  Brk_Cnt                 : unsigned(3 downto 0);
108
        signal  RX_Filtered             : std_logic;
109
        signal  RX_ShiftReg             : std_logic_vector(7 downto 0);
110
        signal  RX_Bit_Cnt              : integer range 0 to 11;
111
        signal  RX_Parity               : std_logic;
112
        signal  RXD                             : std_logic;
113
 
114
        signal  TX_Tick                 : std_logic;
115
        signal  TX_ShiftReg             : std_logic_vector(7 downto 0);
116
        signal  TX_Bit_Cnt              : integer range 0 to 11;
117
        signal  TX_Parity               : std_logic;
118
        signal  TX_Next_Is_Stop : std_logic;
119
        signal  TX_Stop_Bit             : std_logic;
120
        signal  TXD                             : std_logic;
121
 
122
begin
123
 
124
        DTR_n <= MCR(4) or not MCR(0);
125
        RTS_n <= MCR(4) or not MCR(1);
126
        OUT1_n <= MCR(4) or not MCR(2);
127
        OUT2_n <= MCR(4) or not MCR(3);
128
        SOut <= MCR(4) or (TXD and not LCR(6));
129
        RXD <= SIn when MCR(4) = '0' else (TXD and not LCR(6));
130
 
131
        Intr <= not IIR(0);
132
 
133
        -- Registers
134
        DM0 <= DLL when LCR(7) = '1' else RBR;
135
        DM1 <= DLM when LCR(7) = '1' else IER;
136
        with A select
137
                D_Out <=
138
                        DM0 when "000",
139
                        DM1 when "001",
140
                        IIR when "010",
141
                        LCR when "011",
142
                        MCR when "100",
143
                        LSR when "101",
144
                        MSR when "110",
145
                        SCR when others;
146
        process (MR_n, XIn)
147
        begin
148
                if MR_n = '0' then
149
                        THR <= "00000000";
150
                        IER <= "00000000";
151
                        LCR <= "00000000";
152
                        MCR <= "00000000";
153
                        MSR(3 downto 0) <= "0000";
154
                        SCR <= "00000000"; -- ??
155
                        DLL <= "00000000"; -- ??
156
                        DLM <= "00000000"; -- ??
157
                elsif XIn'event and XIn = '1' then
158
                        if Wr_n = '0' and CS_n = '0' then
159
                                case A is
160
                                when "000" =>
161
                                        if LCR(7) = '1' then
162
                                                DLL <= D_In;
163
                                        else
164
                                                THR <= D_In;
165
                                        end if;
166
                                when "001" =>
167
                                        if LCR(7) = '1' then
168
                                                DLM <= D_In;
169
                                        else
170
                                                IER(3 downto 0) <= D_In(3 downto 0);
171
                                        end if;
172
                                when "011" =>
173
                                        LCR <= D_In;
174
                                when "100" =>
175
                                        MCR <= D_In;
176
                                when "111" =>
177
                                        SCR <= D_In;
178
                                when others =>
179
                                end case;
180
                        end if;
181
                        if Rd_n = '0' and CS_n = '0' and A = "110" then
182
                                MSR(3 downto 0) <= "0000";
183
                        end if;
184
                        if MSR(4) /= MSR_In(0) then
185
                                MSR(0) <= '1';
186
                        end if;
187
                        if MSR(5) /= MSR_In(1) then
188
                                MSR(1) <= '1';
189
                        end if;
190
                        if MSR(6) = '0' and MSR_In(2) = '1' then
191
                                MSR(2) <= '1';
192
                        end if;
193
                        if MSR(7) /= MSR_In(3) then
194
                                MSR(3) <= '1';
195
                        end if;
196
                end if;
197
        end process;
198
        process (XIn)
199
        begin
200
                if XIn'event and XIn = '1' then
201
                        if MCR(4) = '0' then
202
                                MSR(4) <= MSR_In(0);
203
                                MSR(5) <= MSR_In(1);
204
                                MSR(6) <= MSR_In(2);
205
                                MSR(7) <= MSR_In(3);
206
                        else
207
                                MSR(4) <= MCR(1);
208
                                MSR(5) <= MCR(0);
209
                                MSR(6) <= MCR(2);
210
                                MSR(7) <= MCR(3);
211
                        end if;
212
                        MSR_In(0) <= CTS_n;
213
                        MSR_In(1) <= DSR_n;
214
                        MSR_In(2) <= RI_n;
215
                        MSR_In(3) <= DCD_n;
216
                end if;
217
        end process;
218
 
219
        IIR(7 downto 3) <= "00000";
220
        IIR(2 downto 0) <=
221
                "110" when IER(2) = '1' and LSR(4 downto 1) /= "0000" else
222
                "100" when (IER(0) and LSR(0)) = '1' else
223
                "010" when (IER(1) and LSR(5)) = '1' else
224
                "000" when IER(3) = '1' and ((MCR(4) = '0' and MSR(3 downto 0) /= "0000") or
225
                                                                        (MCR(4) = '1' and MCR(3 downto 0) /= "0000")) else
226
                "001";
227
 
228
        -- Baud x 16 clock generator
229
        process (MR_n, XIn)
230
                variable Baud_Cnt : unsigned(15 downto 0);
231
        begin
232
                if MR_n = '0' then
233
                        Baud_Cnt := "0000000000000000";
234
                        BaudOut <= '0';
235
                elsif XIn'event and XIn = '1' then
236
                        if Baud_Cnt(15 downto 1) = "000000000000000" or (Wr_n = '0' and CS_n = '0' and A(2 downto 1) = "00" and LCR(7) = '1') then
237
                                Baud_Cnt(15 downto 8) := unsigned(DLM);
238
                                Baud_Cnt(7 downto 0) := unsigned(DLL);
239
                                BaudOut <= '1';
240
                        else
241
                                Baud_Cnt := Baud_Cnt - 1;
242
                                BaudOut <= '0';
243
                        end if;
244
                end if;
245
        end process;
246
 
247
        -- Input filter
248
        process (MR_n, XIn)
249
                variable Samples : std_logic_vector(1 downto 0);
250
        begin
251
                if MR_n = '0' then
252
                        Samples := "11";
253
                        RX_Filtered <= '1';
254
                elsif XIn'event and XIn = '1' then
255
                        if RClk = '1' then
256
                                Samples(1) := Samples(0);
257
                                Samples(0) := RXD;
258
                        end if;
259
                        if Samples = "00" then
260
                                RX_Filtered <= '0';
261
                        end if;
262
                        if Samples = "11" then
263
                                RX_Filtered <= '1';
264
                        end if;
265
                end if;
266
        end process;
267
 
268
        -- Receive state machine
269
        process (MR_n, XIn)
270
        begin
271
                if MR_n = '0' then
272
                        RBR <= "00000000";
273
                        LSR(4 downto 0) <= "00000";
274
                        Bit_Phase <= "0000";
275
                        Brk_Cnt <= "0000";
276
                        RX_ShiftReg(7 downto 0) <= "00000000";
277
                        RX_Bit_Cnt <= 0;
278
                        RX_Parity <= '0';
279
                elsif XIn'event and XIn = '1' then
280
                        if A = "000" and LCR(7) = '0' and Rd_n = '0' and CS_n = '0' then
281
                                LSR(0) <= '0';    -- DR
282
                        end if;
283
                        if A = "101" and Rd_n = '0' and CS_n = '0' then
284
                                LSR(4) <= '0';   -- BI
285
                                LSR(3) <= '0';   -- FE
286
                                LSR(2) <= '0';   -- PE
287
                                LSR(1) <= '0';   -- OE
288
                        end if;
289
                        if RClk = '1' then
290
                                if RX_Bit_Cnt = 0 and (RX_Filtered = '1' or Bit_Phase = "0111") then
291
                                        Bit_Phase <= "0000";
292
                                else
293
                                        Bit_Phase <= Bit_Phase + 1;
294
                                end if;
295
                                if Bit_Phase = "1111" then
296
                                        if RX_Filtered = '1' then
297
                                                Brk_Cnt <= "0000";
298
                                        else
299
                                                Brk_Cnt <= Brk_Cnt + 1;
300
                                        end if;
301
                                        if Brk_Cnt = "1100" then
302
                                                LSR(4) <= '1';  -- BI
303
                                        end if;
304
                                end if;
305
                                if RX_Bit_Cnt = 0 then
306
                                        if Bit_Phase = "0111" then
307
                                                RX_Bit_Cnt <= RX_Bit_Cnt + 1;
308
                                                RX_Parity <= not LCR(4);        -- EPS
309
                                        end if;
310
                                elsif Bit_Phase = "1111" then
311
                                        RX_Bit_Cnt <= RX_Bit_Cnt + 1;
312
                                        if RX_Bit_Cnt = 10 then -- Parity stop bit
313
                                                RX_Bit_Cnt <= 0;
314
                                                LSR(0) <= '1'; -- UART Receive complete
315
                                                LSR(3) <= not RX_Filtered; -- Framing error
316
                                        elsif (RX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
317
                                                (RX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
318
                                                (RX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
319
                                                (RX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then -- Stop bit/Parity
320
                                                RX_Bit_Cnt <= 0;
321
                                                if LCR(3) = '1' then    -- PEN
322
                                                        RX_Bit_Cnt <= 10;
323
                                                        if LCR(5) = '1' then    -- Stick parity
324
                                                                if RX_Filtered = LCR(4) then
325
                                                                        LSR(2) <= '1';
326
                                                                end if;
327
                                                        else
328
                                                                if RX_Filtered /= RX_Parity then
329
                                                                        LSR(2) <= '1';
330
                                                                end if;
331
                                                        end if;
332
                                                else
333
                                                        LSR(0) <= '1'; -- UART Receive complete
334
                                                        LSR(3) <= not RX_Filtered; -- Framing error
335
                                                end if;
336
                                                RBR <= RX_ShiftReg(7 downto 0);
337
                                                LSR(1) <= LSR(0);
338
                                                if A = "101" and Rd_n = '0' and CS_n = '0' then
339
                                                        LSR(1) <= '0';
340
                                                end if;
341
                                        else
342
                                                RX_ShiftReg(6 downto 0) <= RX_ShiftReg(7 downto 1);
343
                                                RX_ShiftReg(7) <= RX_Filtered;
344
                                                if LCR(1 downto 0) = "10" then
345
                                                        RX_ShiftReg(7) <= '0';
346
                                                        RX_ShiftReg(6) <= RX_Filtered;
347
                                                end if;
348
                                                if LCR(1 downto 0) = "01" then
349
                                                        RX_ShiftReg(7) <= '0';
350
                                                        RX_ShiftReg(6) <= '0';
351
                                                        RX_ShiftReg(5) <= RX_Filtered;
352
                                                end if;
353
                                                if LCR(1 downto 0) = "00" then
354
                                                        RX_ShiftReg(7) <= '0';
355
                                                        RX_ShiftReg(6) <= '0';
356
                                                        RX_ShiftReg(5) <= '0';
357
                                                        RX_ShiftReg(4) <= RX_Filtered;
358
                                                end if;
359
                                                RX_Parity <= RX_Filtered xor RX_Parity;
360
                                        end if;
361
                                end if;
362
                        end if;
363
                end if;
364
        end process;
365
 
366
        -- Transmit bit tick
367
        process (MR_n, XIn)
368
                variable TX_Cnt : unsigned(4 downto 0);
369
        begin
370
                if MR_n = '0' then
371
                        TX_Cnt := "00000";
372
                        TX_Tick <= '0';
373
                elsif XIn'event and XIn = '1' then
374
                        TX_Tick <= '0';
375
                        if RClk = '1' then
376
                                TX_Cnt := TX_Cnt + 1;
377
                                if LCR(2) = '1' and TX_Stop_Bit = '1' then
378
                                        if LCR(1 downto 0) = "00" then
379
                                                if TX_Cnt = "10111" then
380
                                                        TX_Tick <= '1';
381
                                                        TX_Cnt(3 downto 0) := "0000";
382
                                                end if;
383
                                        else
384
                                                if TX_Cnt = "11111" then
385
                                                        TX_Tick <= '1';
386
                                                        TX_Cnt(3 downto 0) := "0000";
387
                                                end if;
388
                                        end if;
389
                                else
390
                                        TX_Cnt(4) := '1';
391
                                        if TX_Cnt(3 downto 0) = "1111" then
392
                                                TX_Tick <= '1';
393
                                        end if;
394
                                end if;
395
                        end if;
396
                end if;
397
        end process;
398
 
399
        -- Transmit state machine
400
        process (MR_n, XIn)
401
        begin
402
                if MR_n = '0' then
403
                        LSR(7 downto 5) <= "011";
404
                        TX_Bit_Cnt <= 0;
405
                        TX_ShiftReg <= (others => '0');
406
                        TXD <= '1';
407
                        TX_Parity <= '0';
408
                        TX_Next_Is_Stop <= '0';
409
                        TX_Stop_Bit <= '0';
410
                elsif XIn'event and XIn = '1' then
411
                        if TX_Tick = '1' then
412
                                TX_Next_Is_Stop <= '0';
413
                                TX_Stop_Bit <= TX_Next_Is_Stop;
414
                                case TX_Bit_Cnt is
415
                                when 0 =>
416
                                        if LSR(5) <= '0' then    -- THRE
417
                                                TX_Bit_Cnt <= 1;
418
                                        end if;
419
                                        TXD <= '1';
420
                                when 1 => -- Start bit
421
                                        TX_ShiftReg(7 downto 0) <= THR;
422
                                        LSR(5) <= '1';  -- THRE
423
                                        TXD <= '0';
424
                                        TX_Parity <= not LCR(4);        -- EPS
425
                                        TX_Bit_Cnt <= TX_Bit_Cnt + 1;
426
                                when 10 => -- Parity bit
427
                                        TXD <= TX_Parity;
428
                                        if LCR(5) = '1' then    -- Stick parity
429
                                                TXD <= not LCR(4);
430
                                        end if;
431
                                        TX_Bit_Cnt <= 0;
432
                                        TX_Next_Is_Stop <= '1';
433
                                when others =>
434
                                        TX_Bit_Cnt <= TX_Bit_Cnt + 1;
435
                                        if (TX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
436
                                                (TX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
437
                                                (TX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
438
                                                (TX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then
439
                                                TX_Bit_Cnt <= 0;
440
                                                if LCR(3) = '1' then    -- PEN
441
                                                        TX_Bit_Cnt <= 10;
442
                                                else
443
                                                        TX_Next_Is_Stop <= '1';
444
                                                end if;
445
                                                LSR(6) <= '1';  -- TEMT
446
                                        end if;
447
                                        TXD <= TX_ShiftReg(0);
448
                                        TX_ShiftReg(6 downto 0) <= TX_ShiftReg(7 downto 1);
449
                                        TX_Parity <= TX_ShiftReg(0) xor TX_Parity;
450
                                end case;
451
                        end if;
452
                        if Wr_n = '0' and CS_n = '0' and A = "000" and LCR(7) = '0' then
453
                                LSR(5) <= '0';   -- THRE
454
                                LSR(6) <= '0';   -- TEMT
455
                        end if;
456
                end if;
457
        end process;
458
 
459
end;

powered by: WebSVN 2.1.0

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