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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [acia6850.vhd] - Blame information for rev 118

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

Line No. Rev Author Line
1 100 davidgb
--===========================================================================--
2
--                                                                           --
3
--                  Synthesizable 6850 compatible ACIA                       --
4
--                                                                           --
5
--===========================================================================--
6
--
7
--  File name      : acia6850.vhd
8
--
9
--  Entity name    : acia6850
10
--
11
--  Purpose        : Implements a RS232 6850 compatible 
12
--                   Asynchronous Communications Interface Adapter (ACIA)
13
--                  
14
--  Dependencies   : ieee.std_logic_1164
15 118 dilbert57
--                   ieee.numeric_std
16
--                   ieee.std_logic_unsigned
17 100 davidgb
--
18
--  Author         : John E. Kent
19
--
20
--  Email          : dilbert57@opencores.org      
21
--
22
--  Web            : http://opencores.org/project,system09
23
--
24
--  Origins        : miniUART written by Ovidiu Lupas olupas@opencores.org
25
--
26
--  Registers      :
27
--
28
--  IO address + 0 Read - Status Register
29
--
30
--     Bit[7] - Interrupt Request Flag
31
--     Bit[6] - Receive Parity Error (parity bit does not match)
32
--     Bit[5] - Receive Overrun Error (new character received before last read)
33
--     Bit[4] - Receive Framing Error (bad stop bit)
34
--     Bit[3] - Clear To Send level
35
--     Bit[2] - Data Carrier Detect (lost modem carrier)
36
--     Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
37
--     Bit[0] - Receive Data Ready (character received)
38
-- 
39
--  IO address + 0 Write - Control Register
40
--
41
--     Bit[7]     - Rx Interupt Enable
42
--          0     - disabled
43
--          1     - enabled
44
--     Bits[6..5] - Transmit Control
45
--        0 0     - TX interrupt disabled, RTS asserted
46
--        0 1     - TX interrupt enabled,  RTS asserted
47
--        1 0     - TX interrupt disabled, RTS cleared
48
--        1 1     - TX interrupt disabled, RTS asserted, Send Break
49
--     Bits[4..2] - Word Control
50
--      0 0 0     - 7 data, even parity, 2 stop
51
--      0 0 1     - 7 data, odd  parity, 2 stop
52
--      0 1 0     - 7 data, even parity, 1 stop
53
--      0 1 1     - 7 data, odd  parity, 1 stop
54
--      1 0 0     - 8 data, no   parity, 2 stop
55
--      1 0 1     - 8 data, no   parity, 1 stop
56
--      1 1 0     - 8 data, even parity, 1 stop
57
--      1 1 1     - 8 data, odd  parity, 1 stop
58
--     Bits[1..0] - Baud Control
59
--        0 0     - Baud Clk divide by 1
60
--        0 1     - Baud Clk divide by 16
61
--        1 0     - Baud Clk divide by 64
62
--        1 1     - Reset
63
--
64
--  IO address + 1 Read - Receive Data Register
65
--
66
--     Read when Receive Data Ready bit set
67
--     Read resets Receive Data Ready bit 
68
--
69
--  IO address + 1 Write - Transmit Data Register
70
--
71
--     Write when Transmit Buffer Empty bit set
72
--     Write resets Transmit Buffer Empty Bit
73
--
74
--
75
--  Copyright (C) 2002 - 2010 John Kent
76
--
77
--  This program is free software: you can redistribute it and/or modify
78
--  it under the terms of the GNU General Public License as published by
79
--  the Free Software Foundation, either version 3 of the License, or
80
--  (at your option) any later version.
81
--
82
--  This program is distributed in the hope that it will be useful,
83
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
84
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
85
--  GNU General Public License for more details.
86
--
87
--  You should have received a copy of the GNU General Public License
88
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
89
--
90
--===========================================================================--
91
--                                                                           --
92
--                              Revision  History                            --
93
--                                                                           --
94
--===========================================================================--
95
--
96
-- Version Author        Date         Changes
97
--
98
-- 0.1     Ovidiu Lupas  2000-01-15   New model
99
-- 1.0     Ovidiu Lupas  2000-01      Synthesis optimizations
100
-- 2.0     Ovidiu Lupas  2000-04      Bugs removed - the RSBusCtrl did not
101
--                                    process all possible situations
102
--
103
-- 3.0     John Kent     2002-10      Changed Status bits to match MC6805
104
--                                    Added CTS, RTS, Baud rate control & Software Reset
105
-- 3.1     John Kent     2003-01-05   Added Word Format control a'la mc6850
106
-- 3.2     John Kent     2003-07-19   Latched Data input to UART
107
-- 3.3     John Kent     2004-01-16   Integrated clkunit in rxunit & txunit
108
--                                    TX / RX Baud Clock now external
109
--                                    also supports x1 clock and DCD. 
110
-- 3.4     John Kent     2005-09-13   Removed LoadCS signal. 
111
--                                    Fixed ReadCS and Read 
112
--                                    in miniuart_DCD_Init process
113
-- 3.5     John Kent     2006-11-28   Cleaned up code.
114
--
115
-- 4.0     John Kent     2007-02-03   Renamed ACIA6850
116
-- 4.1     John Kent     2007-02-06   Made software reset synchronous
117
-- 4.2     John Kent     2007-02-25   Changed sensitivity lists
118
--                                    Rearranged Reset process.
119
-- 4.3     John Kent     2010-06-17   Updated header
120
-- 4.4     John Kent     2010-08-27   Combined with ACIA_RX & ACIA_TX
121
--                                    Renamed to acia6850
122
--
123
 
124
library ieee;
125
  use ieee.std_logic_1164.all;
126
  use ieee.numeric_std.all;
127
  use ieee.std_logic_unsigned.all;
128 118 dilbert57
--library unisim;
129
--  use unisim.vcomponents.all;
130 100 davidgb
 
131
-----------------------------------------------------------------------
132
-- Entity for ACIA_6850                                              --
133
-----------------------------------------------------------------------
134
 
135
entity acia6850 is
136
  port (
137
    --
138
    -- CPU Interface signals
139
    --
140
    clk      : in  std_logic;                     -- System Clock
141
    rst      : in  std_logic;                     -- Reset input (active high)
142
    cs       : in  std_logic;                     -- miniUART Chip Select
143
    addr     : in  std_logic;                     -- Register Select
144
    rw       : in  std_logic;                     -- Read / Not Write
145
    data_in  : in  std_logic_vector(7 downto 0);  -- Data Bus In 
146
    data_out : out std_logic_vector(7 downto 0);  -- Data Bus Out
147
    irq      : out std_logic;                     -- Interrupt Request out
148
    --
149
    -- RS232 Interface Signals
150
    --
151
    RxC   : in  std_logic;              -- Receive Baud Clock
152
    TxC   : in  std_logic;              -- Transmit Baud Clock
153
    RxD   : in  std_logic;              -- Receive Data
154
    TxD   : out std_logic;              -- Transmit Data
155
    DCD_n : in  std_logic;              -- Data Carrier Detect
156
    CTS_n : in  std_logic;              -- Clear To Send
157
    RTS_n : out std_logic               -- Request To send
158
    );
159
end acia6850;  --================== End of entity ==============================--
160
 
161
-------------------------------------------------------------------------------
162
-- Architecture for ACIA_6850 Interface registees
163
-------------------------------------------------------------------------------
164
 
165
architecture rtl of acia6850 is
166
 
167
  type DCD_State_Type is (DCD_State_Idle, DCD_State_Int, DCD_State_Reset);
168
 
169
  -----------------------------------------------------------------------------
170
  -- Signals
171
  -----------------------------------------------------------------------------
172
  --
173
  -- Reset signals
174
  --
175
  signal ac_rst   : std_logic;          -- Reset (Software & Hardware)
176
  signal rx_rst   : std_logic;          -- Receive Reset (Software & Hardware)
177
  signal tx_rst   : std_logic;          -- Transmit Reset (Software & Hardware)
178
 
179
  --------------------------------------------------------------------
180
  --  Status Register: StatReg 
181
  ----------------------------------------------------------------------
182
  --
183
  -- IO address + 0 Read
184
  --
185
  -----------+--------+-------+--------+--------+--------+--------+--------+
186
  --  Irq    | PErr   | OErr  | FErr   |  CTS   |  DCD   | TxRdy  | RxRdy  |
187
  -----------+--------+-------+--------+--------+--------+--------+--------+
188
  --
189
  -- Irq   - Bit[7] - Interrupt request
190
  -- PErr  - Bit[6] - Receive Parity error (parity bit does not match)
191
  -- OErr  - Bit[5] - Receive Overrun error (new character received before last read)
192
  -- FErr  - Bit[4] - Receive Framing Error (bad stop bit)
193
  -- CTS   - Bit[3] - Clear To Send level
194
  -- DCD   - Bit[2] - Data Carrier Detect (lost modem carrier)
195
  -- TxRdy - Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
196
  -- RxRdy - Bit[0] - Receive Data Ready (character received)
197
  -- 
198
 
199
  signal StatReg : std_logic_vector(7 downto 0) := (others => '0'); -- status register
200
 
201
  ----------------------------------------------------------------------
202
  --  Control Register: CtrlReg
203
  ----------------------------------------------------------------------
204
  --
205
  -- IO address + 0 Write
206
  --
207
  -----------+--------+--------+--------+--------+--------+--------+--------+
208
  --   RxIE  |TxCtl(1)|TxCtl(0)|WdFmt(2)|WdFmt(1)|WdFmt(0)|BdCtl(1)|BdCtl(0)|
209
  -----------+--------+--------+--------+--------+--------+--------+--------+
210
  -- RxIEnb - Bit[7]
211
  -- 0       - Rx Interrupt disabled
212
  -- 1       - Rx Interrupt enabled
213
  -- TxCtl - Bits[6..5]
214
  -- 0 1     - Tx Interrupt Enable
215
  -- 1 0     - RTS high
216
  -- WdFmt - Bits[4..2]
217
  -- 0 0 0   - 7 data, even parity, 2 stop
218
  -- 0 0 1   - 7 data, odd  parity, 2 stop
219
  -- 0 1 0   - 7 data, even parity, 1 stop
220
  -- 0 1 1   - 7 data, odd  parity, 1 stop
221
  -- 1 0 0   - 8 data, no   parity, 2 stop
222
  -- 1 0 1   - 8 data, no   parity, 1 stop
223
  -- 1 1 0   - 8 data, even parity, 1 stop
224
  -- 1 1 1   - 8 data, odd  parity, 1 stop
225
  -- BdCtl - Bits[1..0]
226
  -- 0 0     - Baud Clk divide by 1
227
  -- 0 1     - Baud Clk divide by 16
228
  -- 1 0     - Baud Clk divide by 64
229
  -- 1 1     - reset
230
  signal CtrlReg : std_logic_vector(7 downto 0) := (others => '0'); -- control register
231
 
232
  ----------------------------------------------------------------------
233
  -- Receive Register
234
  ----------------------------------------------------------------------
235
  --
236
  -- IO address + 1     Read
237
  --
238
  signal RxReg : std_logic_vector(7 downto 0) := (others => '0');
239
 
240
  ----------------------------------------------------------------------
241
  -- Transmit Register
242
  ----------------------------------------------------------------------
243
  --
244
  -- IO address + 1     Write
245
  --
246
  signal TxReg    : std_logic_vector(7 downto 0) := (others => '0');
247
 
248
  signal TxDat    : std_logic := '1';   -- Transmit data bit
249
  signal TxRdy    : std_logic := '0';   -- Transmit buffer empty
250
  signal RxRdy    : std_logic := '0';   -- Receive Data ready
251
 --
252
  signal FErr     : std_logic := '0';   -- Frame error
253
  signal OErr     : std_logic := '0';   -- Output error
254
  signal PErr     : std_logic := '0';   -- Parity Error
255
  --
256
  signal TxIE     : std_logic := '0';   -- Transmit interrupt enable
257
  signal RxIE     : std_logic := '0';   -- Receive interrupt enable
258
  --
259
  signal RxRd     : std_logic := '0';   -- Read receive buffer
260
  signal TxWr     : std_logic := '0';   -- Write Transmit buffer
261
  signal StRd     : std_logic := '0';   -- Read status register
262
  --
263
  signal DCDState : DCD_State_Type;     -- DCD Reset state sequencer
264
  signal DCDDel   : std_logic := '0';   -- Delayed DCD_n
265
  signal DCDEdge  : std_logic := '0';   -- Rising DCD_N Edge Pulse
266
  signal DCDInt   : std_logic := '0';   -- DCD Interrupt
267
 
268
  signal BdFmt    : std_logic_vector(1 downto 0) := "00";   -- Baud Clock Format
269
  signal WdFmt    : std_logic_vector(2 downto 0) := "000";  -- Data Word Format
270
 
271
  -----------------------------------------------------------------------------
272
  -- RX Signals
273
  -----------------------------------------------------------------------------
274
 
275
  type RxStateType is ( RxState_Wait, RxState_Data, RxState_Parity, RxState_Stop );
276
 
277
  signal RxState    : RxStateType;                  -- receive bit state
278
 
279
  signal RxDatDel0  : Std_Logic := '0';             -- Delayed Rx Data
280
  signal RxDatDel1  : Std_Logic := '0';             -- Delayed Rx Data
281
  signal RxDatDel2  : Std_Logic := '0';             -- Delayed Rx Data
282
  signal RxDatEdge  : Std_Logic := '0';             -- Rx Data Edge pulse
283
 
284
  signal RxClkDel   : Std_Logic := '0';             -- Delayed Rx Input Clock
285
  signal RxClkEdge  : Std_Logic := '0';             -- Rx Input Clock Edge pulse
286
  signal RxStart    : Std_Logic := '0';             -- Rx Start request
287
  signal RxEnable   : Std_Logic := '0';             -- Rx Enabled
288
  signal RxClkCnt   : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Rx Baud Clock Counter
289
  signal RxBdClk    : Std_Logic := '0';             -- Rx Baud Clock
290
  signal RxBdDel    : Std_Logic := '0';             -- Delayed Rx Baud Clock
291
 
292
  signal RxReq      : Std_Logic := '0';             -- Rx Data Valid
293
  signal RxAck      : Std_Logic := '0';             -- Rx Data Valid
294
  signal RxParity   : Std_Logic := '0';             -- Calculated RX parity bit
295
  signal RxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0');  -- Rx Bit counter
296
  signal RxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Shift Register
297
 
298
  -----------------------------------------------------------------------------
299
  -- TX Signals
300
  -----------------------------------------------------------------------------
301
  type TxStateType is ( TxState_Idle, TxState_Start, TxState_Data, TxState_Parity, TxState_Stop );
302
 
303
  signal TxState     : TxStateType;                   -- Transmitter state
304
 
305
  signal TxClkDel    : Std_Logic := '0';              -- Delayed Tx Input Clock
306
  signal TxClkEdge   : Std_Logic := '0';              -- Tx Input Clock Edge pulse
307
  signal TxClkCnt    : Std_Logic_Vector(5 downto 0) := (others => '0');  -- Tx Baud Clock Counter
308
  signal TxBdClk     : Std_Logic := '0';              -- Tx Baud Clock
309
  signal TxBdDel     : Std_Logic := '0';              -- Delayed Tx Baud Clock
310
 
311
  signal TxReq       : std_logic := '0';              -- Request transmit start
312
  signal TxAck       : std_logic := '0';              -- Acknowledge transmit start
313
  signal TxParity    : Std_logic := '0';              -- Parity Bit
314
  signal TxBitCount  : Std_Logic_Vector(2 downto 0) := (others => '0');  -- Data Bit Counter
315
  signal TxShiftReg  : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Transmit shift register
316
 
317
begin
318
 
319
---------------------------------------------------------------
320
-- ACIA Reset may be hardware or software
321
---------------------------------------------------------------
322
  acia_reset : process( clk, rst, ac_rst, dcd_n )
323
  begin
324
    --
325
    -- ACIA reset Synchronous 
326
    -- Includes software reset
327
    --
328
    if falling_edge(clk) then
329
      ac_rst <= (CtrlReg(1) and CtrlReg(0)) or rst;
330
    end if;
331
    -- Receiver reset
332
    rx_rst <= ac_rst or DCD_n;
333
    -- Transmitter reset
334
    tx_rst <= ac_rst;
335
 
336
  end process;
337
 
338
 
339
-----------------------------------------------------------------------------
340
-- Generate Read / Write strobes.
341
-----------------------------------------------------------------------------
342
 
343 118 dilbert57
  acia_read_write : process(clk, ac_rst)
344 100 davidgb
  begin
345
    if falling_edge(clk) then
346 118 dilbert57
      if rst = '1' then
347
        CtrlReg(1 downto 0) <= "11";
348
        CtrlReg(7 downto 2) <= (others => '0');
349 100 davidgb
        TxReg   <= (others => '0');
350
        RxRd  <= '0';
351
        TxWr  <= '0';
352
        StRd  <= '0';
353
      else
354
        RxRd  <= '0';
355
        TxWr  <= '0';
356
        StRd  <= '0';
357
        if cs = '1' then
358
          if Addr = '0' then              -- Control / Status register
359
            if rw = '0' then              -- write control register
360
              CtrlReg <= data_in;
361
            else                          -- read status register
362
              StRd <= '1';
363
            end if;
364
          else                            -- Data Register
365
            if rw = '0' then              -- write transmiter register
366
              TxReg <= data_in;
367
              TxWr  <= '1';
368
            else                          -- read receiver register
369
              RxRd <= '1';
370
            end if;
371
          end if;
372
        end if;
373
      end if;
374
    end if;
375
  end process;
376
 
377
  -----------------------------------------------------------------------------
378
  -- ACIA Status Register
379
  -----------------------------------------------------------------------------
380
 
381
  acia_status : process( clk )
382
  begin
383
    if falling_edge( clk ) then
384
      StatReg(0) <= RxRdy;                 -- Receive Data Ready
385
      StatReg(1) <= TxRdy and (not CTS_n); -- Transmit Buffer Empty
386
      StatReg(2) <= DCDInt;                -- Data Carrier Detect
387
      StatReg(3) <= CTS_n;                 -- Clear To Send
388
      StatReg(4) <= FErr;                  -- Framing error
389
      StatReg(5) <= OErr;                  -- Overrun error
390
      StatReg(6) <= PErr;                  -- Parity error
391
      StatReg(7) <= (RxIE and RxRdy) or
392
                    (RxIE and DCDInt) or
393
                    (TxIE and TxRdy);
394
    end if;
395
  end process;
396
 
397
 
398
-----------------------------------------------------------------------------
399
-- ACIA Transmit Control
400
-----------------------------------------------------------------------------
401
 
402
  acia_control : process(CtrlReg, TxDat)
403
  begin
404
    case CtrlReg(6 downto 5) is
405
      when "00" =>                      -- Disable TX Interrupts, Assert RTS
406
        TxD   <= TxDat;
407
        TxIE  <= '0';
408
        RTS_n <= '0';
409
      when "01" =>                      -- Enable TX interrupts, Assert RTS
410
        TxD   <= TxDat;
411
        TxIE  <= '1';
412
        RTS_n <= '0';
413
      when "10" =>                      -- Disable Tx Interrupts, Clear RTS
414
        TxD   <= TxDat;
415
        TxIE  <= '0';
416
        RTS_n <= '1';
417
      when "11" =>                      -- Disable Tx interrupts, Assert RTS, send break
418
        TxD   <= '0';
419
        TxIE  <= '0';
420
        RTS_n <= '0';
421
      when others =>
422
        null;
423
    end case;
424
 
425
    RxIE  <= CtrlReg(7);
426
    WdFmt <= CtrlReg(4 downto 2);
427
    BdFmt <= CtrlReg(1 downto 0);
428
  end process;
429
 
430
---------------------------------------------------------------
431
-- Set Data Output Multiplexer
432
--------------------------------------------------------------
433
 
434
  acia_data_mux : process(Addr, RxReg, StatReg)
435
  begin
436
    if Addr = '1' then
437
      data_out <= RxReg;               -- read receiver register
438
    else
439
      data_out <= StatReg;               -- read status register
440
    end if;
441
  end process;
442
 
443
  irq <= StatReg(7);
444
 
445
---------------------------------------------------------------
446
-- Data Carrier Detect Edge rising edge detect
447
---------------------------------------------------------------
448
  acia_dcd_edge : process( clk, ac_rst )
449
  begin
450
    if falling_edge(clk) then
451
      if ac_rst = '1' then
452
        DCDDel  <= '0';
453
        DCDEdge <= '0';
454
      else
455
        DCDDel  <= DCD_n;
456
        DCDEdge <= DCD_n and (not DCDDel);
457
      end if;
458
    end if;
459
  end process;
460
 
461
 
462
---------------------------------------------------------------
463
-- Data Carrier Detect Interrupt
464
---------------------------------------------------------------
465
-- If Data Carrier is lost, an interrupt is generated
466
-- To clear the interrupt, first read the status register
467
--      then read the data receive register
468
 
469
  acia_dcd_int : process( clk, ac_rst )
470
  begin
471
    if falling_edge(clk) then
472
      if ac_rst = '1' then
473
        DCDInt   <= '0';
474
        DCDState <= DCD_State_Idle;
475
      else
476
        case DCDState is
477
        when DCD_State_Idle =>
478
          -- DCD Edge activates interrupt
479
          if DCDEdge = '1' then
480
            DCDInt   <= '1';
481
            DCDState <= DCD_State_Int;
482
          end if;
483
        when DCD_State_Int =>
484
          -- To reset DCD interrupt, 
485
          -- First read status
486
          if StRd = '1' then
487
            DCDState <= DCD_State_Reset;
488
          end if;
489
        when DCD_State_Reset =>
490
          -- Then read receive register
491
          if RxRd = '1' then
492
            DCDInt   <= '0';
493
            DCDState <= DCD_State_Idle;
494
          end if;
495
        when others =>
496
          null;
497
        end case;
498
      end if;
499
    end if;
500
  end process;
501
 
502
 
503
  ---------------------------------------------------------------------
504
  -- Receiver Clock Edge Detection
505
  ---------------------------------------------------------------------
506
  -- A rising edge will produce a one clock cycle pulse
507
  --
508
  acia_rx_clock_edge : process( clk, rx_rst )
509
  begin
510
    if falling_edge(clk) then
511
      if rx_rst = '1' then
512
        RxClkDel  <= '0';
513
        RxClkEdge <= '0';
514
      else
515
        RxClkDel  <= RxC;
516
        RxClkEdge <= (not RxClkDel) and RxC;
517
      end if;
518
    end if;
519
  end process;
520
 
521
  ---------------------------------------------------------------------
522
  -- Receiver Data Edge Detection
523
  ---------------------------------------------------------------------
524
  -- A falling edge will produce a pulse on RxClk wide
525
  --
526
  acia_rx_data_edge : process( clk, rx_rst )
527
  begin
528
    if falling_edge(clk) then
529
      if rx_rst = '1' then
530
        RxDatDel0 <= '0';
531
        RxDatDel1 <= '0';
532
        RxDatDel2 <= '0';
533
        RxDatEdge <= '0';
534
      else
535
        RxDatDel0 <= RxD;
536
        RxDatDel1 <= RxDatDel0;
537
        RxDatDel2 <= RxDatDel1;
538
        RxDatEdge <= RxDatDel0 and (not RxD);
539
      end if;
540
    end if;
541
  end process;
542
 
543
  ---------------------------------------------------------------------
544
  -- Receiver Start / Stop
545
  ---------------------------------------------------------------------
546
  -- Enable the receive clock on detection of a start bit
547
  -- Disable the receive clock after a byte is received.
548
  -- 
549
  acia_rx_start_stop : process( clk, rx_rst )
550
  begin
551
    if falling_edge(clk) then
552
      if rx_rst = '1' then
553
        RxEnable <= '0';
554
        RxStart  <= '0';
555
      elsif (RxEnable = '0') and (RxDatEdge = '1') then
556
        -- Data Edge detected 
557
        RxStart  <= '1';                    -- Request Start and
558
        RxEnable <= '1';                    -- Enable Receive Clock
559
      elsif (RxStart = '1') and (RxAck = '1') then
560
        -- Data is being received
561
        RxStart <= '0';                     -- Reset Start Request
562
      elsif (RxStart = '0') and (RxAck = '0') then
563
        -- Data has now been received
564
        RxEnable <= '0';                    -- Disable Receiver until next Start Bit
565
      end if;
566
    end if;
567
  end process;
568
 
569
  ---------------------------------------------------------------------
570
  -- Receiver Clock Divider
571
  ---------------------------------------------------------------------
572
  -- Hold the Rx Clock divider in reset when the receiver is disabled
573
  -- Advance the count only on a rising Rx clock edge
574
  --
575
  acia_rx_clock_divide : process( clk, rx_rst )
576
  begin
577
    if falling_edge(clk) then
578
      if rx_rst = '1' then
579
        RxClkCnt  <= (others => '0');
580
      elsif RxDatEdge = '1' then
581
        -- reset on falling data edge
582
        RxClkCnt <= (others => '0');
583
      elsif RxClkEdge = '1' then
584
        -- increment count on Clock edge
585
        RxClkCnt <= RxClkCnt + "000001";
586
      end if;
587
    end if;
588
  end process;
589
 
590
  ---------------------------------------------------------------------
591
  -- Receiver Baud Clock Selector
592
  ---------------------------------------------------------------------
593
  -- BdFmt
594
  -- 0 0     - Baud Clk divide by 1
595
  -- 0 1     - Baud Clk divide by 16
596
  -- 1 0     - Baud Clk divide by 64
597
  -- 1 1     - Reset
598
  --
599
  acia_rx_baud_clock_select : process( BdFmt, RxC, RxClkCnt )
600
  begin
601
    case BdFmt is
602
      when "00" =>                              -- Div by 1
603
        RxBdClk <= RxC;
604
      when "01" =>                              -- Div by 16
605
        RxBdClk <= RxClkCnt(3);
606
      when "10" =>                              -- Div by 64
607
        RxBdClk <= RxClkCnt(5);
608
      when others =>                         -- Software Reset
609
        RxBdClk <= '0';
610
    end case;
611
  end process;
612
 
613
  ---------------------------------------------------------------------
614
  -- Receiver process
615
  ---------------------------------------------------------------------
616
  -- WdFmt - Bits[4..2]
617
  -- 0 0 0   - 7 data, even parity, 2 stop
618
  -- 0 0 1   - 7 data, odd  parity, 2 stop
619
  -- 0 1 0   - 7 data, even parity, 1 stop
620
  -- 0 1 1   - 7 data, odd  parity, 1 stop
621
  -- 1 0 0   - 8 data, no   parity, 2 stop
622
  -- 1 0 1   - 8 data, no   parity, 1 stop
623
  -- 1 1 0   - 8 data, even parity, 1 stop
624
  -- 1 1 1   - 8 data, odd  parity, 1 stop
625
  acia_rx_receive : process( clk, rst )
626
  begin
627
    if falling_edge( clk ) then
628
      if rx_rst = '1' then
629
        FErr       <= '0';
630
        OErr       <= '0';
631
        PErr       <= '0';
632
        RxShiftReg <= (others => '0');       -- Reset Shift register
633
        RxReg      <= (others => '0');
634
        RxParity   <= '0';                   -- reset Parity bit
635
        RxAck      <= '0';                   -- Receiving data
636
        RxBitCount <= (others => '0');
637
        RxState    <= RxState_Wait;
638
      else
639
        RxBdDel      <= RxBdClk;
640
        if RxBdDel = '0' and RxBdClk = '1' then
641
          case RxState is
642
          when RxState_Wait =>
643
            RxShiftReg <= (others => '0');   -- Reset Shift register
644
            RxParity   <= '0';               -- Reset Parity bit
645
            if WdFmt(2) = '0' then           -- WdFmt(2) = '0' => 7 data bits
646
              RxBitCount <= "110";
647
            else                             -- WdFmt(2) = '1' => 8 data bits
648
              RxBitCount <= "111";
649
            end if;
650
            if RxDatDel2 = '0' then          -- look for start bit
651
              RxState <= RxState_Data;       -- if low, start reading data
652
            end if;
653
 
654
          when RxState_Data =>               -- Receiving data bits 
655
            RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1);
656
            RxParity   <= RxParity xor RxDatDel2;
657
            RxAck      <= '1';               -- Flag receive in progress
658
            RxBitCount <= RxBitCount - "001";
659
            if RxBitCount = "000" then
660
              if WdFmt(2) = '0' then         -- WdFmt(2) = '0' => 7 data
661
                RxState <= RxState_Parity;   -- 7 bits always has parity
662
              elsif WdFmt(1) = '0' then      -- WdFmt(2) = '1' => 8 data                          
663
                RxState <= RxState_Stop;     -- WdFmt(1) = '0' => no parity
664
                PErr <= '0';               -- Reset Parity Error
665
              else
666
                RxState <= RxState_Parity;   -- WdFmt(1) = '1' => 8 data + parity
667
              end if;
668
            end if;
669
 
670
          when RxState_Parity =>             -- Receive Parity bit
671
            if WdFmt(2) = '0' then           -- if 7 data bits, shift parity into MSB
672
              RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); -- 7 data + parity
673
            end if;
674
            if RxParity = (RxDatDel2 xor WdFmt(0)) then
675
              PErr <= '1';                 -- If parity not the same flag error
676
            else
677
              PErr <= '0';
678
            end if;
679
            RxState <= RxState_Stop;
680
 
681
          when RxState_Stop =>             -- stop bit (Only one required for RX)
682
            RxAck  <= '0';                 -- Flag Receive Complete
683
            RxReg <= RxShiftReg;
684
            if RxDatDel2 = '1' then        -- stop bit expected
685
              FErr <= '0';                 -- yes, no framing error
686
            else
687
              FErr <= '1';                 -- no, framing error
688
            end if;
689
            if RxRdy = '1' then            -- Has previous data been read ? 
690
              OErr <= '1';                 -- no, overrun error
691
            else
692
              OErr <= '0';                 -- yes, no over run error
693
            end if;
694
            RxState <= RxState_Wait;
695
 
696
          when others =>
697
            RxAck   <= '0';                -- Flag Receive Complete
698
            RxState <= RxState_Wait;
699
          end case;
700
        end if;
701
      end if;
702
    end if;
703
 
704
  end process;
705
 
706
  ---------------------------------------------------------------------
707
  -- Receiver Read process
708
  ---------------------------------------------------------------------
709
  acia_rx_read : process( clk, rst, RxRdy )
710
  begin
711
    if falling_edge(clk) then
712
      if rx_rst = '1' then
713
        RxRdy <= '0';
714
        RxReq <= '0';
715
      elsif RxRd = '1' then
716
        -- Data was read,        
717
        RxRdy <= '0';                        -- Reset receive full
718
        RxReq <= '1';                        -- Request more data
719
      elsif RxReq = '1' and RxAck = '1' then
720
        -- Data is being received
721
        RxReq <= '0';                        -- reset receive request
722
      elsif RxReq = '0' and RxAck = '0' then
723
        -- Data now received
724
        RxRdy <= '1';                        -- Flag RxRdy and read Shift Register
725
      end if;
726
    end if;
727
  end process;
728
 
729
 
730
  ---------------------------------------------------------------------
731
  -- Transmit Clock Edge Detection
732
  -- A falling edge will produce a one clock cycle pulse
733
  ---------------------------------------------------------------------
734
 
735
  acia_tx_clock_edge : process( Clk, tx_rst )
736
  begin
737
    if falling_edge(clk) then
738
      if tx_rst = '1' then
739
        TxClkDel  <= '0';
740
        TxClkEdge <= '0';
741
      else
742
        TxClkDel  <= TxC;
743
        TxClkEdge <= TxClkDel and (not TxC);
744
      end if;
745
    end if;
746
  end process;
747
 
748
  ---------------------------------------------------------------------
749
  -- Transmit Clock Divider
750
  -- Advance the count only on an input clock pulse
751
  ---------------------------------------------------------------------
752
 
753
  acia_tx_clock_divide : process( clk, tx_rst )
754
  begin
755
    if falling_edge(clk) then
756
      if tx_rst = '1' then
757
        TxClkCnt <= (others=>'0');
758
      elsif TxClkEdge = '1' then
759
        TxClkCnt <= TxClkCnt + "000001";
760
      end if;
761
    end if;
762
  end process;
763
 
764
  ---------------------------------------------------------------------
765
  -- Transmit Baud Clock Selector
766
  ---------------------------------------------------------------------
767
  acia_tx_baud_clock_select : process( BdFmt, TxClkCnt, TxC )
768
  begin
769
    -- BdFmt
770
    -- 0 0     - Baud Clk divide by 1
771
    -- 0 1     - Baud Clk divide by 16
772
    -- 1 0     - Baud Clk divide by 64
773
    -- 1 1     - reset
774
    case BdFmt is
775
      when "00" =>                               -- Div by 1
776
        TxBdClk <= TxC;
777
      when "01" =>                               -- Div by 16
778
        TxBdClk <= TxClkCnt(3);
779
      when "10" =>                               -- Div by 64
780
        TxBdClk <= TxClkCnt(5);
781
      when others =>                          -- Software reset
782
        TxBdClk <= '0';
783
    end case;
784
  end process;
785
 
786
  -----------------------------------------------------------------------------
787
  -- Implements the Tx unit
788
  -----------------------------------------------------------------------------
789
  -- WdFmt - Bits[4..2]
790
  -- 0 0 0   - 7 data, even parity, 2 stop
791
  -- 0 0 1   - 7 data, odd  parity, 2 stop
792
  -- 0 1 0   - 7 data, even parity, 1 stop
793
  -- 0 1 1   - 7 data, odd  parity, 1 stop
794
  -- 1 0 0   - 8 data, no   parity, 2 stop
795
  -- 1 0 1   - 8 data, no   parity, 1 stop
796
  -- 1 1 0   - 8 data, even parity, 1 stop
797
  -- 1 1 1   - 8 data, odd  parity, 1 stop
798
  acia_tx_transmit : process( clk, tx_rst)
799
  begin
800
    if falling_edge(clk) then
801
      if tx_rst = '1' then
802
        TxDat      <= '1';
803
        TxShiftReg <= (others=>'0');
804
        TxParity   <= '0';
805
        TxBitCount <= (others=>'0');
806
        TxAck      <= '0';
807
        TxState    <= TxState_Idle;
808
      else
809
 
810
        TxBdDel <= TxBdClk;
811
        -- On rising edge of baud clock, run the state machine
812
        if TxBdDel = '0' and TxBdClk = '1' then
813
 
814
          case TxState is
815
          when TxState_Idle =>
816
            TxDat <= '1';
817
            if TxReq = '1' then
818
              TxShiftReg <= TxReg;              -- Load Shift reg with Tx Data
819
              TxAck      <= '1';
820
              TxState    <= TxState_Start;
821
            end if;
822
 
823
          when TxState_Start =>
824
            TxDat    <= '0';                    -- Start bit
825
            TxParity <= '0';
826
            if WdFmt(2) = '0' then
827
              TxBitCount <= "110";              -- 7 data + parity
828
            else
829
              TxBitCount <= "111";              -- 8 data
830
            end if;
831
            TxState <= TxState_Data;
832
 
833
          when TxState_Data =>
834
            TxDat      <= TxShiftReg(0);
835
            TxShiftReg <= '1' & TxShiftReg(7 downto 1);
836
            TxParity   <= TxParity xor TxShiftReg(0);
837
            TxBitCount <= TxBitCount - "001";
838
            if TxBitCount = "000" then
839
              if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
840
                if WdFmt(0) = '0' then        -- 8 data bits
841
                  TxState <= TxState_Stop;    -- 2 stops
842
                else
843
                  TxAck   <= '0';
844
                  TxState <= TxState_Idle;    -- 1 stop
845
                end if;
846
              else
847
                TxState <= TxState_Parity;    -- parity
848
              end if;
849
            end if;
850
 
851
          when TxState_Parity =>              -- 7/8 data + parity bit
852
            if WdFmt(0) = '0' then
853
              TxDat <= not(TxParity);         -- even parity
854
            else
855
              TxDat <= TxParity;              -- odd parity
856
            end if;
857
            if WdFmt(1) = '0' then
858
              TxState <= TxState_Stop;        -- 2 stops
859
            else
860
              TxAck   <= '0';
861
              TxState <= TxState_Idle;        -- 1 stop
862
            end if;
863
 
864
          when TxState_Stop =>                -- first of two stop bits
865
            TxDat   <= '1';
866
            TxAck   <= '0';
867
            TxState <= TxState_Idle;
868
 
869
          end case;
870
        end if;
871
      end if;
872
    end if;
873
  end process;
874
 
875
  ---------------------------------------------------------------------
876
  -- Transmitter Write process
877
  ---------------------------------------------------------------------
878
 
879
  acia_tx_write : process( clk, tx_rst, TxWr, TxReq, TxAck )
880
  begin
881
    if falling_edge(clk) then
882
      if tx_rst = '1' then
883
        TxRdy <= '0';
884
        TxReq <= '0';
885
      elsif TxWr = '1' then
886
        -- Data was read,        
887
        TxRdy <= '0';                        -- Reset transmit empty
888
        TxReq <= '1';                        -- Request data transmit
889
      elsif TxReq = '1' and TxAck = '1' then -- Data is being transmitted
890
        TxReq <= '0';                        -- reset transmit request
891
      elsif TxReq = '0' and TxAck = '0' then -- Data transmitted
892
        TxRdy <= '1';                        -- Flag TxRdy
893
      end if;
894
    end if;
895
  end process;
896
 
897
end rtl;
898
 

powered by: WebSVN 2.1.0

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