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

Subversion Repositories System09

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

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
--                   ieee.numeric_std
16
--                   unisim.vcomponents
17
--
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
library unisim;
129
  use unisim.vcomponents.all;
130
 
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
  ACIA_Read_Write : process(clk, ac_rst)
344
  begin
345
    if falling_edge(clk) then
346
      if ac_rst = '1' then
347
        CtrlReg <= (others => '0');
348
        TxReg   <= (others => '0');
349
        RxRd  <= '0';
350
        TxWr  <= '0';
351
        StRd  <= '0';
352
      else
353
        RxRd  <= '0';
354
        TxWr  <= '0';
355
        StRd  <= '0';
356
        if cs = '1' then
357
          if Addr = '0' then              -- Control / Status register
358
            if rw = '0' then              -- write control register
359
              CtrlReg <= data_in;
360
            else                          -- read status register
361
              StRd <= '1';
362
            end if;
363
          else                            -- Data Register
364
            if rw = '0' then              -- write transmiter register
365
              TxReg <= data_in;
366
              TxWr  <= '1';
367
            else                          -- read receiver register
368
              RxRd <= '1';
369
            end if;
370
          end if;
371
        end if;
372
      end if;
373
    end if;
374
  end process;
375
 
376
  -----------------------------------------------------------------------------
377
  -- ACIA Status Register
378
  -----------------------------------------------------------------------------
379
 
380
  acia_status : process( clk )
381
  begin
382
    if falling_edge( clk ) then
383
      StatReg(0) <= RxRdy;                 -- Receive Data Ready
384
      StatReg(1) <= TxRdy and (not CTS_n); -- Transmit Buffer Empty
385
      StatReg(2) <= DCDInt;                -- Data Carrier Detect
386
      StatReg(3) <= CTS_n;                 -- Clear To Send
387
      StatReg(4) <= FErr;                  -- Framing error
388
      StatReg(5) <= OErr;                  -- Overrun error
389
      StatReg(6) <= PErr;                  -- Parity error
390
      StatReg(7) <= (RxIE and RxRdy) or
391
                    (RxIE and DCDInt) or
392
                    (TxIE and TxRdy);
393
    end if;
394
  end process;
395
 
396
 
397
-----------------------------------------------------------------------------
398
-- ACIA Transmit Control
399
-----------------------------------------------------------------------------
400
 
401
  acia_control : process(CtrlReg, TxDat)
402
  begin
403
    case CtrlReg(6 downto 5) is
404
      when "00" =>                      -- Disable TX Interrupts, Assert RTS
405
        TxD   <= TxDat;
406
        TxIE  <= '0';
407
        RTS_n <= '0';
408
      when "01" =>                      -- Enable TX interrupts, Assert RTS
409
        TxD   <= TxDat;
410
        TxIE  <= '1';
411
        RTS_n <= '0';
412
      when "10" =>                      -- Disable Tx Interrupts, Clear RTS
413
        TxD   <= TxDat;
414
        TxIE  <= '0';
415
        RTS_n <= '1';
416
      when "11" =>                      -- Disable Tx interrupts, Assert RTS, send break
417
        TxD   <= '0';
418
        TxIE  <= '0';
419
        RTS_n <= '0';
420
      when others =>
421
        null;
422
    end case;
423
 
424
    RxIE  <= CtrlReg(7);
425
    WdFmt <= CtrlReg(4 downto 2);
426
    BdFmt <= CtrlReg(1 downto 0);
427
  end process;
428
 
429
---------------------------------------------------------------
430
-- Set Data Output Multiplexer
431
--------------------------------------------------------------
432
 
433
  acia_data_mux : process(Addr, RxReg, StatReg)
434
  begin
435
    if Addr = '1' then
436
      data_out <= RxReg;               -- read receiver register
437
    else
438
      data_out <= StatReg;               -- read status register
439
    end if;
440
  end process;
441
 
442
  irq <= StatReg(7);
443
 
444
---------------------------------------------------------------
445
-- Data Carrier Detect Edge rising edge detect
446
---------------------------------------------------------------
447
  acia_dcd_edge : process( clk, ac_rst )
448
  begin
449
    if falling_edge(clk) then
450
      if ac_rst = '1' then
451
        DCDDel  <= '0';
452
        DCDEdge <= '0';
453
      else
454
        DCDDel  <= DCD_n;
455
        DCDEdge <= DCD_n and (not DCDDel);
456
      end if;
457
    end if;
458
  end process;
459
 
460
 
461
---------------------------------------------------------------
462
-- Data Carrier Detect Interrupt
463
---------------------------------------------------------------
464
-- If Data Carrier is lost, an interrupt is generated
465
-- To clear the interrupt, first read the status register
466
--      then read the data receive register
467
 
468
  acia_dcd_int : process( clk, ac_rst )
469
  begin
470
    if falling_edge(clk) then
471
      if ac_rst = '1' then
472
        DCDInt   <= '0';
473
        DCDState <= DCD_State_Idle;
474
      else
475
        case DCDState is
476
        when DCD_State_Idle =>
477
          -- DCD Edge activates interrupt
478
          if DCDEdge = '1' then
479
            DCDInt   <= '1';
480
            DCDState <= DCD_State_Int;
481
          end if;
482
        when DCD_State_Int =>
483
          -- To reset DCD interrupt, 
484
          -- First read status
485
          if StRd = '1' then
486
            DCDState <= DCD_State_Reset;
487
          end if;
488
        when DCD_State_Reset =>
489
          -- Then read receive register
490
          if RxRd = '1' then
491
            DCDInt   <= '0';
492
            DCDState <= DCD_State_Idle;
493
          end if;
494
        when others =>
495
          null;
496
        end case;
497
      end if;
498
    end if;
499
  end process;
500
 
501
 
502
  ---------------------------------------------------------------------
503
  -- Receiver Clock Edge Detection
504
  ---------------------------------------------------------------------
505
  -- A rising edge will produce a one clock cycle pulse
506
  --
507
  acia_rx_clock_edge : process( clk, rx_rst )
508
  begin
509
    if falling_edge(clk) then
510
      if rx_rst = '1' then
511
        RxClkDel  <= '0';
512
        RxClkEdge <= '0';
513
      else
514
        RxClkDel  <= RxC;
515
        RxClkEdge <= (not RxClkDel) and RxC;
516
      end if;
517
    end if;
518
  end process;
519
 
520
  ---------------------------------------------------------------------
521
  -- Receiver Data Edge Detection
522
  ---------------------------------------------------------------------
523
  -- A falling edge will produce a pulse on RxClk wide
524
  --
525
  acia_rx_data_edge : process( clk, rx_rst )
526
  begin
527
    if falling_edge(clk) then
528
      if rx_rst = '1' then
529
        RxDatDel0 <= '0';
530
        RxDatDel1 <= '0';
531
        RxDatDel2 <= '0';
532
        RxDatEdge <= '0';
533
      else
534
        RxDatDel0 <= RxD;
535
        RxDatDel1 <= RxDatDel0;
536
        RxDatDel2 <= RxDatDel1;
537
        RxDatEdge <= RxDatDel0 and (not RxD);
538
      end if;
539
    end if;
540
  end process;
541
 
542
  ---------------------------------------------------------------------
543
  -- Receiver Start / Stop
544
  ---------------------------------------------------------------------
545
  -- Enable the receive clock on detection of a start bit
546
  -- Disable the receive clock after a byte is received.
547
  -- 
548
  acia_rx_start_stop : process( clk, rx_rst )
549
  begin
550
    if falling_edge(clk) then
551
      if rx_rst = '1' then
552
        RxEnable <= '0';
553
        RxStart  <= '0';
554
      elsif (RxEnable = '0') and (RxDatEdge = '1') then
555
        -- Data Edge detected 
556
        RxStart  <= '1';                    -- Request Start and
557
        RxEnable <= '1';                    -- Enable Receive Clock
558
      elsif (RxStart = '1') and (RxAck = '1') then
559
        -- Data is being received
560
        RxStart <= '0';                     -- Reset Start Request
561
      elsif (RxStart = '0') and (RxAck = '0') then
562
        -- Data has now been received
563
        RxEnable <= '0';                    -- Disable Receiver until next Start Bit
564
      end if;
565
    end if;
566
  end process;
567
 
568
  ---------------------------------------------------------------------
569
  -- Receiver Clock Divider
570
  ---------------------------------------------------------------------
571
  -- Hold the Rx Clock divider in reset when the receiver is disabled
572
  -- Advance the count only on a rising Rx clock edge
573
  --
574
  acia_rx_clock_divide : process( clk, rx_rst )
575
  begin
576
    if falling_edge(clk) then
577
      if rx_rst = '1' then
578
        RxClkCnt  <= (others => '0');
579
      elsif RxDatEdge = '1' then
580
        -- reset on falling data edge
581
        RxClkCnt <= (others => '0');
582
      elsif RxClkEdge = '1' then
583
        -- increment count on Clock edge
584
        RxClkCnt <= RxClkCnt + "000001";
585
      end if;
586
    end if;
587
  end process;
588
 
589
  ---------------------------------------------------------------------
590
  -- Receiver Baud Clock Selector
591
  ---------------------------------------------------------------------
592
  -- BdFmt
593
  -- 0 0     - Baud Clk divide by 1
594
  -- 0 1     - Baud Clk divide by 16
595
  -- 1 0     - Baud Clk divide by 64
596
  -- 1 1     - Reset
597
  --
598
  acia_rx_baud_clock_select : process( BdFmt, RxC, RxClkCnt )
599
  begin
600
    case BdFmt is
601
      when "00" =>                              -- Div by 1
602
        RxBdClk <= RxC;
603
      when "01" =>                              -- Div by 16
604
        RxBdClk <= RxClkCnt(3);
605
      when "10" =>                              -- Div by 64
606
        RxBdClk <= RxClkCnt(5);
607
      when others =>                         -- Software Reset
608
        RxBdClk <= '0';
609
    end case;
610
  end process;
611
 
612
  ---------------------------------------------------------------------
613
  -- Receiver process
614
  ---------------------------------------------------------------------
615
  -- WdFmt - Bits[4..2]
616
  -- 0 0 0   - 7 data, even parity, 2 stop
617
  -- 0 0 1   - 7 data, odd  parity, 2 stop
618
  -- 0 1 0   - 7 data, even parity, 1 stop
619
  -- 0 1 1   - 7 data, odd  parity, 1 stop
620
  -- 1 0 0   - 8 data, no   parity, 2 stop
621
  -- 1 0 1   - 8 data, no   parity, 1 stop
622
  -- 1 1 0   - 8 data, even parity, 1 stop
623
  -- 1 1 1   - 8 data, odd  parity, 1 stop
624
  acia_rx_receive : process( clk, rst )
625
  begin
626
    if falling_edge( clk ) then
627
      if rx_rst = '1' then
628
        FErr       <= '0';
629
        OErr       <= '0';
630
        PErr       <= '0';
631
        RxShiftReg <= (others => '0');       -- Reset Shift register
632
        RxReg      <= (others => '0');
633
        RxParity   <= '0';                   -- reset Parity bit
634
        RxAck      <= '0';                   -- Receiving data
635
        RxBitCount <= (others => '0');
636
        RxState    <= RxState_Wait;
637
      else
638
        RxBdDel      <= RxBdClk;
639
        if RxBdDel = '0' and RxBdClk = '1' then
640
          case RxState is
641
          when RxState_Wait =>
642
            RxShiftReg <= (others => '0');   -- Reset Shift register
643
            RxParity   <= '0';               -- Reset Parity bit
644
            if WdFmt(2) = '0' then           -- WdFmt(2) = '0' => 7 data bits
645
              RxBitCount <= "110";
646
            else                             -- WdFmt(2) = '1' => 8 data bits
647
              RxBitCount <= "111";
648
            end if;
649
            if RxDatDel2 = '0' then          -- look for start bit
650
              RxState <= RxState_Data;       -- if low, start reading data
651
            end if;
652
 
653
          when RxState_Data =>               -- Receiving data bits 
654
            RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1);
655
            RxParity   <= RxParity xor RxDatDel2;
656
            RxAck      <= '1';               -- Flag receive in progress
657
            RxBitCount <= RxBitCount - "001";
658
            if RxBitCount = "000" then
659
              if WdFmt(2) = '0' then         -- WdFmt(2) = '0' => 7 data
660
                RxState <= RxState_Parity;   -- 7 bits always has parity
661
              elsif WdFmt(1) = '0' then      -- WdFmt(2) = '1' => 8 data                          
662
                RxState <= RxState_Stop;     -- WdFmt(1) = '0' => no parity
663
                PErr <= '0';               -- Reset Parity Error
664
              else
665
                RxState <= RxState_Parity;   -- WdFmt(1) = '1' => 8 data + parity
666
              end if;
667
            end if;
668
 
669
          when RxState_Parity =>             -- Receive Parity bit
670
            if WdFmt(2) = '0' then           -- if 7 data bits, shift parity into MSB
671
              RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); -- 7 data + parity
672
            end if;
673
            if RxParity = (RxDatDel2 xor WdFmt(0)) then
674
              PErr <= '1';                 -- If parity not the same flag error
675
            else
676
              PErr <= '0';
677
            end if;
678
            RxState <= RxState_Stop;
679
 
680
          when RxState_Stop =>             -- stop bit (Only one required for RX)
681
            RxAck  <= '0';                 -- Flag Receive Complete
682
            RxReg <= RxShiftReg;
683
            if RxDatDel2 = '1' then        -- stop bit expected
684
              FErr <= '0';                 -- yes, no framing error
685
            else
686
              FErr <= '1';                 -- no, framing error
687
            end if;
688
            if RxRdy = '1' then            -- Has previous data been read ? 
689
              OErr <= '1';                 -- no, overrun error
690
            else
691
              OErr <= '0';                 -- yes, no over run error
692
            end if;
693
            RxState <= RxState_Wait;
694
 
695
          when others =>
696
            RxAck   <= '0';                -- Flag Receive Complete
697
            RxState <= RxState_Wait;
698
          end case;
699
        end if;
700
      end if;
701
    end if;
702
 
703
  end process;
704
 
705
  ---------------------------------------------------------------------
706
  -- Receiver Read process
707
  ---------------------------------------------------------------------
708
  acia_rx_read : process( clk, rst, RxRdy )
709
  begin
710
    if falling_edge(clk) then
711
      if rx_rst = '1' then
712
        RxRdy <= '0';
713
        RxReq <= '0';
714
      elsif RxRd = '1' then
715
        -- Data was read,        
716
        RxRdy <= '0';                        -- Reset receive full
717
        RxReq <= '1';                        -- Request more data
718
      elsif RxReq = '1' and RxAck = '1' then
719
        -- Data is being received
720
        RxReq <= '0';                        -- reset receive request
721
      elsif RxReq = '0' and RxAck = '0' then
722
        -- Data now received
723
        RxRdy <= '1';                        -- Flag RxRdy and read Shift Register
724
      end if;
725
    end if;
726
  end process;
727
 
728
 
729
  ---------------------------------------------------------------------
730
  -- Transmit Clock Edge Detection
731
  -- A falling edge will produce a one clock cycle pulse
732
  ---------------------------------------------------------------------
733
 
734
  acia_tx_clock_edge : process( Clk, tx_rst )
735
  begin
736
    if falling_edge(clk) then
737
      if tx_rst = '1' then
738
        TxClkDel  <= '0';
739
        TxClkEdge <= '0';
740
      else
741
        TxClkDel  <= TxC;
742
        TxClkEdge <= TxClkDel and (not TxC);
743
      end if;
744
    end if;
745
  end process;
746
 
747
  ---------------------------------------------------------------------
748
  -- Transmit Clock Divider
749
  -- Advance the count only on an input clock pulse
750
  ---------------------------------------------------------------------
751
 
752
  acia_tx_clock_divide : process( clk, tx_rst )
753
  begin
754
    if falling_edge(clk) then
755
      if tx_rst = '1' then
756
        TxClkCnt <= (others=>'0');
757
      elsif TxClkEdge = '1' then
758
        TxClkCnt <= TxClkCnt + "000001";
759
      end if;
760
    end if;
761
  end process;
762
 
763
  ---------------------------------------------------------------------
764
  -- Transmit Baud Clock Selector
765
  ---------------------------------------------------------------------
766
  acia_tx_baud_clock_select : process( BdFmt, TxClkCnt, TxC )
767
  begin
768
    -- BdFmt
769
    -- 0 0     - Baud Clk divide by 1
770
    -- 0 1     - Baud Clk divide by 16
771
    -- 1 0     - Baud Clk divide by 64
772
    -- 1 1     - reset
773
    case BdFmt is
774
      when "00" =>                               -- Div by 1
775
        TxBdClk <= TxC;
776
      when "01" =>                               -- Div by 16
777
        TxBdClk <= TxClkCnt(3);
778
      when "10" =>                               -- Div by 64
779
        TxBdClk <= TxClkCnt(5);
780
      when others =>                          -- Software reset
781
        TxBdClk <= '0';
782
    end case;
783
  end process;
784
 
785
  -----------------------------------------------------------------------------
786
  -- Implements the Tx unit
787
  -----------------------------------------------------------------------------
788
  -- WdFmt - Bits[4..2]
789
  -- 0 0 0   - 7 data, even parity, 2 stop
790
  -- 0 0 1   - 7 data, odd  parity, 2 stop
791
  -- 0 1 0   - 7 data, even parity, 1 stop
792
  -- 0 1 1   - 7 data, odd  parity, 1 stop
793
  -- 1 0 0   - 8 data, no   parity, 2 stop
794
  -- 1 0 1   - 8 data, no   parity, 1 stop
795
  -- 1 1 0   - 8 data, even parity, 1 stop
796
  -- 1 1 1   - 8 data, odd  parity, 1 stop
797
  acia_tx_transmit : process( clk, tx_rst)
798
  begin
799
    if falling_edge(clk) then
800
      if tx_rst = '1' then
801
        TxDat      <= '1';
802
        TxShiftReg <= (others=>'0');
803
        TxParity   <= '0';
804
        TxBitCount <= (others=>'0');
805
        TxAck      <= '0';
806
        TxState    <= TxState_Idle;
807
      else
808
 
809
        TxBdDel <= TxBdClk;
810
        -- On rising edge of baud clock, run the state machine
811
        if TxBdDel = '0' and TxBdClk = '1' then
812
 
813
          case TxState is
814
          when TxState_Idle =>
815
            TxDat <= '1';
816
            if TxReq = '1' then
817
              TxShiftReg <= TxReg;              -- Load Shift reg with Tx Data
818
              TxAck      <= '1';
819
              TxState    <= TxState_Start;
820
            end if;
821
 
822
          when TxState_Start =>
823
            TxDat    <= '0';                    -- Start bit
824
            TxParity <= '0';
825
            if WdFmt(2) = '0' then
826
              TxBitCount <= "110";              -- 7 data + parity
827
            else
828
              TxBitCount <= "111";              -- 8 data
829
            end if;
830
            TxState <= TxState_Data;
831
 
832
          when TxState_Data =>
833
            TxDat      <= TxShiftReg(0);
834
            TxShiftReg <= '1' & TxShiftReg(7 downto 1);
835
            TxParity   <= TxParity xor TxShiftReg(0);
836
            TxBitCount <= TxBitCount - "001";
837
            if TxBitCount = "000" then
838
              if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
839
                if WdFmt(0) = '0' then        -- 8 data bits
840
                  TxState <= TxState_Stop;    -- 2 stops
841
                else
842
                  TxAck   <= '0';
843
                  TxState <= TxState_Idle;    -- 1 stop
844
                end if;
845
              else
846
                TxState <= TxState_Parity;    -- parity
847
              end if;
848
            end if;
849
 
850
          when TxState_Parity =>              -- 7/8 data + parity bit
851
            if WdFmt(0) = '0' then
852
              TxDat <= not(TxParity);         -- even parity
853
            else
854
              TxDat <= TxParity;              -- odd parity
855
            end if;
856
            if WdFmt(1) = '0' then
857
              TxState <= TxState_Stop;        -- 2 stops
858
            else
859
              TxAck   <= '0';
860
              TxState <= TxState_Idle;        -- 1 stop
861
            end if;
862
 
863
          when TxState_Stop =>                -- first of two stop bits
864
            TxDat   <= '1';
865
            TxAck   <= '0';
866
            TxState <= TxState_Idle;
867
 
868
          end case;
869
        end if;
870
      end if;
871
    end if;
872
  end process;
873
 
874
  ---------------------------------------------------------------------
875
  -- Transmitter Write process
876
  ---------------------------------------------------------------------
877
 
878
  acia_tx_write : process( clk, tx_rst, TxWr, TxReq, TxAck )
879
  begin
880
    if falling_edge(clk) then
881
      if tx_rst = '1' then
882
        TxRdy <= '0';
883
        TxReq <= '0';
884
      elsif TxWr = '1' then
885
        -- Data was read,        
886
        TxRdy <= '0';                        -- Reset transmit empty
887
        TxReq <= '1';                        -- Request data transmit
888
      elsif TxReq = '1' and TxAck = '1' then -- Data is being transmitted
889
        TxReq <= '0';                        -- reset transmit request
890
      elsif TxReq = '0' and TxAck = '0' then -- Data transmitted
891
        TxRdy <= '1';                        -- Flag TxRdy
892
      end if;
893
    end if;
894
  end process;
895
 
896
end rtl;
897
 

powered by: WebSVN 2.1.0

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