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

Subversion Repositories System09

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

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

Line No. Rev Author Line
1 138 davidgb
--===========================================================================--
2
--                                                                           --
3
--                  Synthesizable 6850 compatible ACIA                       --
4
--                                                                           --
5
--===========================================================================--
6 100 davidgb
--
7
--  File name      : acia6850.vhd
8 138 davidgb
--
9 100 davidgb
--  Entity name    : acia6850
10
--
11 138 davidgb
--  Purpose        : Implements a RS232 6850 compatible 
12 100 davidgb
--                   Asynchronous Communications Interface Adapter (ACIA)
13
--                  
14
--  Dependencies   : ieee.std_logic_1164
15 138 davidgb
--                   ieee.numeric_std
16 118 dilbert57
--                   ieee.std_logic_unsigned
17 138 davidgb
--
18
--  Author         : John E. Kent
19
--
20
--  Email          : dilbert57@opencores.org      
21
--
22
--  Web            : http://opencores.org/project,system09
23
--
24 100 davidgb
--  Origins        : miniUART written by Ovidiu Lupas olupas@opencores.org
25 138 davidgb
--
26
--  Registers      :
27
--
28
--  IO address + 0 Read - Status Register
29
--
30 100 davidgb
--     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 138 davidgb
--
41 100 davidgb
--     Bit[7]     - Rx Interupt Enable
42
--          0     - disabled
43
--          1     - enabled
44 138 davidgb
--     Bits[6..5] - Transmit Control
45 100 davidgb
--        0 0     - TX interrupt disabled, RTS asserted
46 138 davidgb
--        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 100 davidgb
--     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 138 davidgb
--
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 100 davidgb
--                                                                           --
92 138 davidgb
--                              Revision  History                            --
93 100 davidgb
--                                                                           --
94 138 davidgb
--===========================================================================--
95
--
96 100 davidgb
-- 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 138 davidgb
-- 2.0     Ovidiu Lupas  2000-04      Bugs removed - the RSBusCtrl did not
101 100 davidgb
--                                    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 138 davidgb
--                                    Fixed ReadCS and Read 
112 100 davidgb
--                                    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 138 davidgb
-- 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 100 davidgb
library ieee;
125
  use ieee.std_logic_1164.all;
126 138 davidgb
  use ieee.numeric_std.all;
127 100 davidgb
  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 138 davidgb
    data_out : out std_logic_vector(7 downto 0);  -- Data Bus Out
147
    irq      : out std_logic;                     -- Interrupt Request out
148 100 davidgb
    --
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 138 davidgb
  --
173
  -- Reset signals
174
  --
175 100 davidgb
  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 138 davidgb
  --
185 100 davidgb
  -----------+--------+-------+--------+--------+--------+--------+--------+
186
  --  Irq    | PErr   | OErr  | FErr   |  CTS   |  DCD   | TxRdy  | RxRdy  |
187 138 davidgb
  -----------+--------+-------+--------+--------+--------+--------+--------+
188 100 davidgb
  --
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 138 davidgb
 
199 100 davidgb
  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 138 davidgb
  --
207 100 davidgb
  -----------+--------+--------+--------+--------+--------+--------+--------+
208 139 davidgb
  --  RXIEnb |TxCtl(1)|TxCtl(0)|WdFmt(2)|WdFmt(1)|WdFmt(0)|BdCtl(1)|BdCtl(0)|
209 100 davidgb
  -----------+--------+--------+--------+--------+--------+--------+--------+
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 138 davidgb
 
240 100 davidgb
  ----------------------------------------------------------------------
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 139 davidgb
  --
252 100 davidgb
  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 138 davidgb
  signal TxWr     : std_logic := '0';   -- Write Transmit buffer
261 100 davidgb
  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 138 davidgb
 
277 100 davidgb
  signal RxState    : RxStateType;                  -- receive bit state
278 138 davidgb
 
279 100 davidgb
  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 138 davidgb
 
284 100 davidgb
  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 138 davidgb
 
305 100 davidgb
  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 138 davidgb
 
311 100 davidgb
  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 139 davidgb
  ---------------------------------------------------------------
320
  -- ACIA Reset may be hardware or software
321
  ---------------------------------------------------------------
322
 
323 100 davidgb
  acia_reset : process( clk, rst, ac_rst, dcd_n )
324 138 davidgb
  begin
325 100 davidgb
    --
326 138 davidgb
    -- ACIA reset Synchronous 
327
    -- Includes software reset
328 100 davidgb
    --
329
    if falling_edge(clk) then
330
      ac_rst <= (CtrlReg(1) and CtrlReg(0)) or rst;
331
    end if;
332
    -- Receiver reset
333 138 davidgb
    rx_rst <= ac_rst or DCD_n;
334 100 davidgb
    -- Transmitter reset
335
    tx_rst <= ac_rst;
336
 
337
  end process;
338
 
339 139 davidgb
  -----------------------------------------------------------------------------
340
  -- Generate Read / Write strobes.
341
  -----------------------------------------------------------------------------
342 100 davidgb
 
343 138 davidgb
  acia_read_write : process(clk, ac_rst)
344
  begin
345
    if falling_edge(clk) then
346
      if rst = '1' then
347
        CtrlReg(1 downto 0) <= "11";
348
        CtrlReg(7 downto 2) <= (others => '0');
349
        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 100 davidgb
  -----------------------------------------------------------------------------
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 138 davidgb
                    (TxIE and TxRdy);
394
    end if;
395 100 davidgb
  end process;
396
 
397 139 davidgb
  -----------------------------------------------------------------------------
398
  -- ACIA Transmit Control
399
  -----------------------------------------------------------------------------
400 100 davidgb
 
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 138 davidgb
        TxIE  <= '0';
419 100 davidgb
        RTS_n <= '0';
420
      when others =>
421
        null;
422
    end case;
423
 
424 138 davidgb
    RxIE  <= CtrlReg(7);
425 100 davidgb
    WdFmt <= CtrlReg(4 downto 2);
426 138 davidgb
    BdFmt <= CtrlReg(1 downto 0);
427 100 davidgb
  end process;
428
 
429 139 davidgb
  ---------------------------------------------------------------
430
  -- Set Data Output Multiplexer
431
  --------------------------------------------------------------
432 100 davidgb
 
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 139 davidgb
  ---------------------------------------------------------------
445
  -- Data Carrier Detect Edge rising edge detect
446
  ---------------------------------------------------------------
447
 
448 100 davidgb
  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 138 davidgb
      else
455 100 davidgb
        DCDDel  <= DCD_n;
456 138 davidgb
        DCDEdge <= DCD_n and (not DCDDel);
457 100 davidgb
      end if;
458
    end if;
459
  end process;
460
 
461 139 davidgb
  ---------------------------------------------------------------
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 100 davidgb
 
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 138 davidgb
      else
475 100 davidgb
        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 138 davidgb
        end case;
497 100 davidgb
      end if;
498
    end if;
499
  end process;
500
 
501
  ---------------------------------------------------------------------
502
  -- Receiver Clock Edge Detection
503
  ---------------------------------------------------------------------
504
  -- A rising edge will produce a one clock cycle pulse
505 139 davidgb
 
506 100 davidgb
  acia_rx_clock_edge : process( clk, rx_rst )
507
  begin
508
    if falling_edge(clk) then
509
      if rx_rst = '1' then
510
        RxClkDel  <= '0';
511 138 davidgb
        RxClkEdge <= '0';
512 100 davidgb
      else
513
        RxClkDel  <= RxC;
514 138 davidgb
        RxClkEdge <= (not RxClkDel) and RxC;
515 100 davidgb
      end if;
516
    end if;
517
  end process;
518
 
519
  ---------------------------------------------------------------------
520
  -- Receiver Data Edge Detection
521
  ---------------------------------------------------------------------
522
  -- A falling edge will produce a pulse on RxClk wide
523 139 davidgb
 
524 100 davidgb
  acia_rx_data_edge : process( clk, rx_rst )
525
  begin
526 138 davidgb
    if falling_edge(clk) then
527 100 davidgb
      if rx_rst = '1' then
528
        RxDatDel0 <= '0';
529
        RxDatDel1 <= '0';
530
        RxDatDel2 <= '0';
531
        RxDatEdge <= '0';
532
      else
533
        RxDatDel0 <= RxD;
534
        RxDatDel1 <= RxDatDel0;
535
        RxDatDel2 <= RxDatDel1;
536 138 davidgb
        RxDatEdge <= RxDatDel0 and (not RxD);
537 100 davidgb
      end if;
538
    end if;
539
  end process;
540
 
541
  ---------------------------------------------------------------------
542
  -- Receiver Start / Stop
543
  ---------------------------------------------------------------------
544
  -- Enable the receive clock on detection of a start bit
545
  -- Disable the receive clock after a byte is received.
546 139 davidgb
 
547 100 davidgb
  acia_rx_start_stop : process( clk, rx_rst )
548
  begin
549 138 davidgb
    if falling_edge(clk) then
550 100 davidgb
      if rx_rst = '1' then
551
        RxEnable <= '0';
552
        RxStart  <= '0';
553
      elsif (RxEnable = '0') and (RxDatEdge = '1') then
554
        -- Data Edge detected 
555 138 davidgb
        RxStart  <= '1';                    -- Request Start and
556 100 davidgb
        RxEnable <= '1';                    -- Enable Receive Clock
557
      elsif (RxStart = '1') and (RxAck = '1') then
558
        -- Data is being received
559
        RxStart <= '0';                     -- Reset Start Request
560
      elsif (RxStart = '0') and (RxAck = '0') then
561
        -- Data has now been received
562
        RxEnable <= '0';                    -- Disable Receiver until next Start Bit
563
      end if;
564
    end if;
565
  end process;
566
 
567
  ---------------------------------------------------------------------
568
  -- Receiver Clock Divider
569
  ---------------------------------------------------------------------
570
  -- Hold the Rx Clock divider in reset when the receiver is disabled
571
  -- Advance the count only on a rising Rx clock edge
572 139 davidgb
 
573 100 davidgb
  acia_rx_clock_divide : process( clk, rx_rst )
574
  begin
575
    if falling_edge(clk) then
576
      if rx_rst = '1' then
577
        RxClkCnt  <= (others => '0');
578
      elsif RxDatEdge = '1' then
579
        -- reset on falling data edge
580 138 davidgb
        RxClkCnt <= (others => '0');
581
      elsif RxClkEdge = '1' then
582 100 davidgb
        -- increment count on Clock edge
583 138 davidgb
        RxClkCnt <= RxClkCnt + "000001";
584 100 davidgb
      end if;
585
    end if;
586
  end process;
587
 
588
  ---------------------------------------------------------------------
589
  -- Receiver Baud Clock Selector
590
  ---------------------------------------------------------------------
591
  -- BdFmt
592
  -- 0 0     - Baud Clk divide by 1
593
  -- 0 1     - Baud Clk divide by 16
594
  -- 1 0     - Baud Clk divide by 64
595
  -- 1 1     - Reset
596
  --
597
  acia_rx_baud_clock_select : process( BdFmt, RxC, RxClkCnt )
598
  begin
599
    case BdFmt is
600
      when "00" =>                              -- Div by 1
601
        RxBdClk <= RxC;
602
      when "01" =>                              -- Div by 16
603
        RxBdClk <= RxClkCnt(3);
604
      when "10" =>                              -- Div by 64
605
        RxBdClk <= RxClkCnt(5);
606
      when others =>                         -- Software Reset
607
        RxBdClk <= '0';
608
    end case;
609
  end process;
610
 
611
  ---------------------------------------------------------------------
612
  -- Receiver process
613
  ---------------------------------------------------------------------
614
  -- WdFmt - Bits[4..2]
615
  -- 0 0 0   - 7 data, even parity, 2 stop
616
  -- 0 0 1   - 7 data, odd  parity, 2 stop
617
  -- 0 1 0   - 7 data, even parity, 1 stop
618
  -- 0 1 1   - 7 data, odd  parity, 1 stop
619
  -- 1 0 0   - 8 data, no   parity, 2 stop
620
  -- 1 0 1   - 8 data, no   parity, 1 stop
621
  -- 1 1 0   - 8 data, even parity, 1 stop
622
  -- 1 1 1   - 8 data, odd  parity, 1 stop
623 139 davidgb
 
624 100 davidgb
  acia_rx_receive : process( clk, rst )
625
  begin
626 138 davidgb
    if falling_edge( clk ) then
627 100 davidgb
      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 138 davidgb
        RxState    <= RxState_Wait;
637 100 davidgb
      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 138 davidgb
            if RxParity = (RxDatDel2 xor WdFmt(0)) then
674 100 davidgb
              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 139 davidgb
 
709 100 davidgb
  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 138 davidgb
        RxReq <= '0';
715
      elsif RxRd = '1' then
716 100 davidgb
        -- 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 138 davidgb
    end if;
727 100 davidgb
  end process;
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 138 davidgb
        TxClkEdge <= '0';
740 100 davidgb
      else
741
        TxClkDel  <= TxC;
742 138 davidgb
        TxClkEdge <= TxClkDel and (not TxC);
743 100 davidgb
      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 139 davidgb
 
767 100 davidgb
  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 139 davidgb
 
799 100 davidgb
  acia_tx_transmit : process( clk, tx_rst)
800
  begin
801
    if falling_edge(clk) then
802
      if tx_rst = '1' then
803
        TxDat      <= '1';
804
        TxShiftReg <= (others=>'0');
805
        TxParity   <= '0';
806
        TxBitCount <= (others=>'0');
807
        TxAck      <= '0';
808 138 davidgb
        TxState    <= TxState_Idle;
809 100 davidgb
      else
810
 
811
        TxBdDel <= TxBdClk;
812
        -- On rising edge of baud clock, run the state machine
813
        if TxBdDel = '0' and TxBdClk = '1' then
814
 
815
          case TxState is
816
          when TxState_Idle =>
817
            TxDat <= '1';
818 138 davidgb
            if TxReq = '1' then
819 100 davidgb
              TxShiftReg <= TxReg;              -- Load Shift reg with Tx Data
820
              TxAck      <= '1';
821
              TxState    <= TxState_Start;
822
            end if;
823
 
824
          when TxState_Start =>
825
            TxDat    <= '0';                    -- Start bit
826
            TxParity <= '0';
827
            if WdFmt(2) = '0' then
828
              TxBitCount <= "110";              -- 7 data + parity
829
            else
830
              TxBitCount <= "111";              -- 8 data
831
            end if;
832
            TxState <= TxState_Data;
833
 
834
          when TxState_Data =>
835
            TxDat      <= TxShiftReg(0);
836
            TxShiftReg <= '1' & TxShiftReg(7 downto 1);
837
            TxParity   <= TxParity xor TxShiftReg(0);
838
            TxBitCount <= TxBitCount - "001";
839
            if TxBitCount = "000" then
840
              if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
841
                if WdFmt(0) = '0' then        -- 8 data bits
842
                  TxState <= TxState_Stop;    -- 2 stops
843
                else
844
                  TxAck   <= '0';
845
                  TxState <= TxState_Idle;    -- 1 stop
846
                end if;
847
              else
848
                TxState <= TxState_Parity;    -- parity
849 138 davidgb
              end if;
850 100 davidgb
            end if;
851
 
852
          when TxState_Parity =>              -- 7/8 data + parity bit
853
            if WdFmt(0) = '0' then
854
              TxDat <= not(TxParity);         -- even parity
855
            else
856
              TxDat <= TxParity;              -- odd parity
857
            end if;
858
            if WdFmt(1) = '0' then
859
              TxState <= TxState_Stop;        -- 2 stops
860 138 davidgb
            else
861 100 davidgb
              TxAck   <= '0';
862
              TxState <= TxState_Idle;        -- 1 stop
863
            end if;
864
 
865
          when TxState_Stop =>                -- first of two stop bits
866 138 davidgb
            TxDat   <= '1';
867 100 davidgb
            TxAck   <= '0';
868
            TxState <= TxState_Idle;
869
 
870 138 davidgb
          end case;
871 100 davidgb
        end if;
872
      end if;
873
    end if;
874
  end process;
875 138 davidgb
 
876 100 davidgb
  ---------------------------------------------------------------------
877
  -- Transmitter Write process
878
  ---------------------------------------------------------------------
879
 
880
  acia_tx_write : process( clk, tx_rst, TxWr, TxReq, TxAck )
881
  begin
882
    if falling_edge(clk) then
883
      if tx_rst = '1' then
884
        TxRdy <= '0';
885 138 davidgb
        TxReq <= '0';
886
      elsif TxWr = '1' then
887 100 davidgb
        -- Data was read,        
888
        TxRdy <= '0';                        -- Reset transmit empty
889
        TxReq <= '1';                        -- Request data transmit
890
      elsif TxReq = '1' and TxAck = '1' then -- Data is being transmitted
891
        TxReq <= '0';                        -- reset transmit request
892
      elsif TxReq = '0' and TxAck = '0' then -- Data transmitted
893
        TxRdy <= '1';                        -- Flag TxRdy
894
      end if;
895 138 davidgb
    end if;
896 100 davidgb
  end process;
897
 
898
end rtl;
899
 

powered by: WebSVN 2.1.0

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