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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [acia6850.vhd] - Diff between revs 139 and 197

Show entire file | Details | Blame | View Log

Rev 139 Rev 197
Line 45... Line 45...
--        0 0     - TX interrupt disabled, RTS asserted
--        0 0     - TX interrupt disabled, RTS asserted
--        0 1     - TX interrupt enabled,  RTS asserted
--        0 1     - TX interrupt enabled,  RTS asserted
--        1 0     - TX interrupt disabled, RTS cleared
--        1 0     - TX interrupt disabled, RTS cleared
--        1 1     - TX interrupt disabled, RTS asserted, Send Break
--        1 1     - TX interrupt disabled, RTS asserted, Send Break
--     Bits[4..2] - Word Control
--     Bits[4..2] - Word Control
--      0 0 0     - 7 data, even parity, 2 stop
--      0 0 0     - 7 data, 2 stop, even parity 
--      0 0 1     - 7 data, odd  parity, 2 stop
--      0 0 1     - 7 data, 2 stop, odd  parity
--      0 1 0     - 7 data, even parity, 1 stop
--      0 1 0     - 7 data, 1 stop, even parity
--      0 1 1     - 7 data, odd  parity, 1 stop
--      0 1 1     - 7 data, 1 stop, odd  parity
--      1 0 0     - 8 data, no   parity, 2 stop
--      1 0 0     - 8 data, 2 stop, no   parity
--      1 0 1     - 8 data, no   parity, 1 stop
--      1 0 1     - 8 data, 1 stop, no   parity
--      1 1 0     - 8 data, even parity, 1 stop
--      1 1 0     - 8 data, 1 stop, even parity
--      1 1 1     - 8 data, odd  parity, 1 stop
--      1 1 1     - 8 data, 1 stop, odd  parity
--     Bits[1..0] - Baud Control
--     Bits[1..0] - Baud Control
--        0 0     - Baud Clk divide by 1
--        0 0     - Baud Clk divide by 1
--        0 1     - Baud Clk divide by 16
--        0 1     - Baud Clk divide by 16
--        1 0     - Baud Clk divide by 64
--        1 0     - Baud Clk divide by 64
--        1 1     - Reset
--        1 1     - Reset
Line 70... Line 70...
--
--
--     Write when Transmit Buffer Empty bit set
--     Write when Transmit Buffer Empty bit set
--     Write resets Transmit Buffer Empty Bit
--     Write resets Transmit Buffer Empty Bit
--
--
--
--
--  Copyright (C) 2002 - 2010 John Kent
--  Copyright (C) 2002 - 2012 John Kent
--
--
--  This program is free software: you can redistribute it and/or modify
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 3 of the License, or
--  the Free Software Foundation, either version 3 of the License, or
--  (at your option) any later version.
--  (at your option) any later version.
Line 117... Line 117...
-- 4.2     John Kent     2007-02-25   Changed sensitivity lists
-- 4.2     John Kent     2007-02-25   Changed sensitivity lists
--                                    Rearranged Reset process.
--                                    Rearranged Reset process.
-- 4.3     John Kent     2010-06-17   Updated header
-- 4.3     John Kent     2010-06-17   Updated header
-- 4.4     John Kent     2010-08-27   Combined with ACIA_RX & ACIA_TX
-- 4.4     John Kent     2010-08-27   Combined with ACIA_RX & ACIA_TX
--                                    Renamed to acia6850
--                                    Renamed to acia6850
 
-- 4.5     John Kent     2012-02-04   Re-arranged Rx & Tx Baud clock edge detect.
 
-- 4.6     John Kent     3021-01-30   Double sample RxC, TxC, and RxD with cpu_clk
 
--                                    for 125MHz Clock on Zybo Z7 board.
--
--
 
 
library ieee;
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;
  use ieee.numeric_std.all;
Line 135... Line 138...
entity acia6850 is
entity acia6850 is
  port (
  port (
    --
    --
    -- CPU Interface signals
    -- CPU Interface signals
    --
    --
    clk      : in  std_logic;                     -- System Clock
    clk      : in  std_logic;                     -- CPU Clock
    rst      : in  std_logic;                     -- Reset input (active high)
    rst      : in  std_logic;                     -- Reset input (active high)
    cs       : in  std_logic;                     -- miniUART Chip Select
    cs       : in  std_logic;                     -- miniUART Chip Select
    addr     : in  std_logic;                     -- Register Select
    addr     : in  std_logic;                     -- Register Select
    rw       : in  std_logic;                     -- Read / Not Write
    rw       : in  std_logic;                     -- Read / Not Write
    data_in  : in  std_logic_vector(7 downto 0);  -- Data Bus In 
    data_in  : in  std_logic_vector(7 downto 0);  -- Data Bus In 
Line 162... Line 165...
-- Architecture for ACIA_6850 Interface registees
-- Architecture for ACIA_6850 Interface registees
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
 
architecture rtl of acia6850 is
architecture rtl of acia6850 is
 
 
  type DCD_State_Type is (DCD_State_Idle, DCD_State_Int, DCD_State_Reset);
 
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- Signals
  -- Reset Signals
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  --
 
  -- Reset signals
 
  --
 
  signal ac_rst   : std_logic;          -- Reset (Software & Hardware)
  signal ac_rst   : std_logic;          -- Reset (Software & Hardware)
  signal rx_rst   : std_logic;          -- Receive Reset (Software & Hardware)
  signal rx_rst   : std_logic;          -- Receive Reset (Software & Hardware)
  signal tx_rst   : std_logic;          -- Transmit Reset (Software & Hardware)
  signal tx_rst   : std_logic;          -- Transmit Reset (Software & Hardware)
 
 
  --------------------------------------------------------------------
  --------------------------------------------------------------------
  --  Status Register: StatReg 
  --  Status Register: status_reg 
  ----------------------------------------------------------------------
  ----------------------------------------------------------------------
  --
  --
  -- IO address + 0 Read
 
  --
 
  -----------+--------+-------+--------+--------+--------+--------+--------+
  -----------+--------+-------+--------+--------+--------+--------+--------+
  --  Irq    | PErr   | OErr  | FErr   |  CTS   |  DCD   | TxRdy  | RxRdy  |
  --  Irq    | PErr   | OErr  | FErr   |  CTS   |  DCD   | TxRdy  | RxRdy  |
  -----------+--------+-------+--------+--------+--------+--------+--------+
  -----------+--------+-------+--------+--------+--------+--------+--------+
  --
  --
  -- Irq   - Bit[7] - Interrupt request
  -- Irq   - Bit[7] - Interrupt request
Line 193... Line 189...
  -- CTS   - Bit[3] - Clear To Send level
  -- CTS   - Bit[3] - Clear To Send level
  -- DCD   - Bit[2] - Data Carrier Detect (lost modem carrier)
  -- DCD   - Bit[2] - Data Carrier Detect (lost modem carrier)
  -- TxRdy - Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
  -- TxRdy - Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
  -- RxRdy - Bit[0] - Receive Data Ready (character received)
  -- RxRdy - Bit[0] - Receive Data Ready (character received)
  -- 
  -- 
 
  constant RXRBIT       : integer := 0; -- Receive Data Ready
 
  constant TXRBIT       : integer := 1; -- Transmir Data Ready
 
  constant DCDBIT       : integer := 2; -- Data Carrier Detect
 
  constant CTSBIT       : integer := 3; -- Clear To Send (inverted)
 
  constant FERBIT       : integer := 4; -- Framing Error
 
  constant OERBIT       : integer := 5; -- Over Run Error
 
  constant PERBIT       : integer := 6; -- Parity error
 
  constant IRQBIT       : integer := 7; -- Interrupt Request Flag
 
 
  signal StatReg : std_logic_vector(7 downto 0) := (others => '0'); -- status register
 
 
 
  ----------------------------------------------------------------------
  ----------------------------------------------------------------------
  --  Control Register: CtrlReg
  --  Control Register: control_reg
  ----------------------------------------------------------------------
  ----------------------------------------------------------------------
  --
  --
  -- IO address + 0 Write
 
  --
 
  -----------+--------+--------+--------+--------+--------+--------+--------+
  -----------+--------+--------+--------+--------+--------+--------+--------+
  --  RXIEnb |TxCtl(1)|TxCtl(0)|WdFmt(2)|WdFmt(1)|WdFmt(0)|BdCtl(1)|BdCtl(0)|
  --  RIEBIT | TX1BIT | TX0BIT | DATBIT | STPBIT | POEBIT | BD1BIT | BD0BIT |
  -----------+--------+--------+--------+--------+--------+--------+--------+
  -----------+--------+--------+--------+--------+--------+--------+--------+
  -- RxIEnb - Bit[7]
  -- RIEBIT - Bit[7]
  -- 0       - Rx Interrupt disabled
  -- 0       - Rx Interrupt disabled
  -- 1       - Rx Interrupt enabled
  -- 1       - Rx Interrupt enabled
  -- TxCtl - Bits[6..5]
  --
  -- 0 1     - Tx Interrupt Enable
  -- TXnBIT - Bits[6..5]
  -- 1 0     - RTS high
  -- 0 0     - RTS low,  Tx Interrupt Disabled
  -- WdFmt - Bits[4..2]
  -- 0 1     - RTS low,  Tx Interrupt Enable
  -- 0 0 0   - 7 data, even parity, 2 stop
  -- 1 0     - RTS high, Tx interrupt Disabled
  -- 0 0 1   - 7 data, odd  parity, 2 stop
  -- 1 1     - RTS low,  Tx interrupt Disabled, send break
  -- 0 1 0   - 7 data, even parity, 1 stop
  --
  -- 0 1 1   - 7 data, odd  parity, 1 stop
  -- DATBIT, STPBIT, POEBIT - Bits[4..2]
  -- 1 0 0   - 8 data, no   parity, 2 stop
  -- 0 0 0   - 7 data, 2 stop, even parity
  -- 1 0 1   - 8 data, no   parity, 1 stop
  -- 0 0 1   - 7 data, 2 stop, odd  parity
  -- 1 1 0   - 8 data, even parity, 1 stop
  -- 0 1 0   - 7 data, 1 stop, even parity
  -- 1 1 1   - 8 data, odd  parity, 1 stop
  -- 0 1 1   - 7 data, 1 stop, odd  parity
  -- BdCtl - Bits[1..0]
  -- 1 0 0   - 8 data, 2 stop, no   parity
 
  -- 1 0 1   - 8 data, 1 stop, no   parity
 
  -- 1 1 0   - 8 data, 1 stop, even parity
 
  -- 1 1 1   - 8 data, 1 stop, odd  parity
 
  -- BDnBIT - Bits[1..0]
  -- 0 0     - Baud Clk divide by 1
  -- 0 0     - Baud Clk divide by 1
  -- 0 1     - Baud Clk divide by 16
  -- 0 1     - Baud Clk divide by 16
  -- 1 0     - Baud Clk divide by 64
  -- 1 0     - Baud Clk divide by 64
  -- 1 1     - reset
  -- 1 1     - reset
  signal CtrlReg : std_logic_vector(7 downto 0) := (others => '0'); -- control register
 
 
 
  ----------------------------------------------------------------------
 
  -- Receive Register
 
  ----------------------------------------------------------------------
 
  --
 
  -- IO address + 1     Read
 
  --
 
  signal RxReg : std_logic_vector(7 downto 0) := (others => '0');
 
 
 
  ----------------------------------------------------------------------
  constant BD0BIT       : integer := 0; -- Baud clock divider 0=>1/64 1=>16/RESET
  -- Transmit Register
  constant BD1BIT       : integer := 1; -- Baud clock divider 0=>1/16 1=>64/RESET
  ----------------------------------------------------------------------
  constant POEBIT       : integer := 2; -- parity 0=>even 1=>odd            (ctrl(DATBIT)=1 & ctrl(STPBIT)=0 => no parity)
  --
  constant STPBIT       : integer := 3; -- stop bits 0=>2 stop 1=>1 stop    (ctrl(DATBIT)=1 & ctrl(STPBIT)=0 & ctrl(POEBIT)=1 => 1 stop bit)
  -- IO address + 1     Write
  constant DATBIT       : integer := 4; -- data bits 0=>7 data bits 1=>8 data bits
  --
  constant TX0BIT       : integer := 5; -- Transmit control 0=>TX IRQ disabled 1=>RTS_N low
  signal TxReg    : std_logic_vector(7 downto 0) := (others => '0');
  constant TX1BIT       : integer := 6; -- Transmit control 1=>TX IRQ disabled 0=>RTS_N low (ctrl(TX0BIT)=1 & ctrl(TX1BIT)=1 => break)
 
  constant RIEBIT       : integer := 7; -- receive interrupt enable
 
 
 
  signal status_reg     : std_logic_vector(7 downto 0) := (others => '0'); -- status register        IO+0 RW=1
 
  signal control_reg    : std_logic_vector(7 downto 0) := (others => '0'); -- control register       IO+0 RW=0
 
  signal rx_data_reg    : std_logic_vector(7 downto 0) := (others => '0'); -- receive data register  IO+1 RW=1
 
  signal tx_data_reg    : std_logic_vector(7 downto 0) := (others => '0'); -- transmit data registet IO+1 RW=0
 
 
 
  signal status_read    : std_logic := '0';   -- Read status register
 
  signal rx_data_read   : std_logic := '0';   -- Read receive buffer
 
  signal tx_data_write  : std_logic := '0';   -- Write Transmit buffer
 
 
  signal TxDat    : std_logic := '1';   -- Transmit data bit
 
  signal TxRdy    : std_logic := '0';   -- Transmit buffer empty
 
  signal RxRdy    : std_logic := '0';   -- Receive Data ready
  signal RxRdy    : std_logic := '0';   -- Receive Data ready
  --
  signal TxRdy          : std_logic := '1';   -- Transmit buffer empty
  signal FErr     : std_logic := '0';   -- Frame error
  signal DCDInt         : std_logic := '0';   -- DCD Interrupt
  signal OErr     : std_logic := '0';   -- Output error
  signal FErr           : std_logic := '0';   -- Receive Data ready
  signal PErr     : std_logic := '0';   -- Parity Error
  signal OErr           : std_logic := '0';   -- Receive Data ready
  --
  signal PErr           : std_logic := '0';   -- Receive Data ready
  signal TxIE     : std_logic := '0';   -- Transmit interrupt enable
  signal TxIE     : std_logic := '0';   -- Transmit interrupt enable
  signal RxIE     : std_logic := '0';   -- Receive interrupt enable
  signal RxIE     : std_logic := '0';   -- Receive interrupt enable
 
 
  --
  --
  signal RxRd     : std_logic := '0';   -- Read receive buffer
  -- status register error bit controls
  signal TxWr     : std_logic := '0';   -- Write Transmit buffer
 
  signal StRd     : std_logic := '0';   -- Read status register
 
  --
  --
 
  signal status_rxr_set : std_logic := '0';
 
  signal status_txr_set : std_logic := '0';
 
  signal status_fer_set : std_logic := '0';
 
  signal status_fer_clr : std_logic := '0';
 
  signal status_oer_set : std_logic := '0';
 
  signal status_oer_clr : std_logic := '0';
 
  signal status_per_set : std_logic := '0';
 
  signal status_per_clr : std_logic := '0';
 
 
 
 
 
  type dcd_state_type is (DCD_State_Idle, DCD_State_Int, DCD_State_Reset);
 
 
  signal DCDState : DCD_State_Type;     -- DCD Reset state sequencer
  signal DCDState : DCD_State_Type;     -- DCD Reset state sequencer
  signal DCDDel   : std_logic := '0';   -- Delayed DCD_n
  signal DCDDel   : std_logic := '0';   -- Delayed DCD_n
  signal DCDEdge  : std_logic := '0';   -- Rising DCD_N Edge Pulse
  signal DCDEdge  : std_logic := '0';   -- Rising DCD_N Edge Pulse
  signal DCDInt   : std_logic := '0';   -- DCD Interrupt
 
 
 
  signal BdFmt    : std_logic_vector(1 downto 0) := "00";   -- Baud Clock Format
  -----------------------------------------------------------------------------
  signal WdFmt    : std_logic_vector(2 downto 0) := "000";  -- Data Word Format
  -- RX & TX state machine types
 
  -----------------------------------------------------------------------------
 
 
 
  type state_type is ( start_state, data_state, parity_state, stop_state,  idle_state );
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- RX Signals
  -- RX Signals
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 
 
  type RxStateType is ( RxState_Wait, RxState_Data, RxState_Parity, RxState_Stop );
  signal rx_current_state : state_type;                 -- receive bit current state
 
  signal rx_next_state    : state_type;                 -- receive bit next state
 
 
  signal RxState    : RxStateType;                  -- receive bit state
  signal RxDat          : std_logic := '1';                     -- Resampled RxD bit
 
  signal RxDDel         : Std_Logic_Vector(1 downto 0) := "11"; -- Delayed RxD Input
  signal RxDatDel0  : Std_Logic := '0';             -- Delayed Rx Data
  signal RxDEdge        : Std_Logic := '0';                     -- RxD Edge pulse
  signal RxDatDel1  : Std_Logic := '0';             -- Delayed Rx Data
  signal RxCDel         : Std_Logic_Vector(1 downto 0) := "00"; -- Delayed RxC Input
  signal RxDatDel2  : Std_Logic := '0';             -- Delayed Rx Data
  signal RxCEdge        : Std_Logic := '0';                     -- RxC Edge pulse
  signal RxDatEdge  : Std_Logic := '0';             -- Rx Data Edge pulse
 
 
 
  signal RxClkDel   : Std_Logic := '0';             -- Delayed Rx Input Clock
 
  signal RxClkEdge  : Std_Logic := '0';             -- Rx Input Clock Edge pulse
 
  signal RxStart    : Std_Logic := '0';             -- Rx Start request
 
  signal RxEnable   : Std_Logic := '0';             -- Rx Enabled
 
  signal RxClkCnt   : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Rx Baud Clock Counter
  signal RxClkCnt   : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Rx Baud Clock Counter
  signal RxBdClk    : Std_Logic := '0';             -- Rx Baud Clock
  signal RxBdClk    : Std_Logic := '0';             -- Rx Baud Clock
  signal RxBdDel    : Std_Logic := '0';             -- Delayed Rx Baud Clock
  signal RxBdDel    : Std_Logic := '0';             -- Delayed Rx Baud Clock
 
  signal RxBdEdgeRise   : Std_Logic := '0';             -- Rx Baud Clock rising edge
 
  signal RxBdEdgeFall   : Std_Logic := '0';             -- Rx Baud Clock falling edge
 
 
  signal RxReq      : Std_Logic := '0';             -- Rx Data Valid
  signal rx_parity      : Std_Logic := '0';             -- Calculated RX parity bit
  signal RxAck      : Std_Logic := '0';             -- Rx Data Valid
  signal rx_bit_count   : Std_Logic_Vector(3 downto 0) := (others => '0');  -- Rx Bit counter
  signal RxParity   : Std_Logic := '0';             -- Calculated RX parity bit
  signal rx_shift_reg   : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Shift Register
  signal RxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0');  -- Rx Bit counter
 
  signal RxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Shift Register
 
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- TX Signals
  -- TX Signals
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  type TxStateType is ( TxState_Idle, TxState_Start, TxState_Data, TxState_Parity, TxState_Stop );
 
 
 
  signal TxState     : TxStateType;                   -- Transmitter state
  signal tx_current_state : state_type;                 -- Transmitter current state
 
  signal tx_next_state    : state_type;                 -- Transmitter next state
 
 
  signal TxClkDel    : Std_Logic := '0';              -- Delayed Tx Input Clock
  signal TxOut          : std_logic := '1';             -- Transmit data bit
  signal TxClkEdge   : Std_Logic := '0';              -- Tx Input Clock Edge pulse
  signal TxDat          : std_logic := '1';             -- Transmit data bit
 
  signal TxCDel         : Std_Logic_Vector(1 downto 0) := "00";             -- Delayed TxC Input
 
  signal TxCEdge        : Std_Logic := '0';             -- TxC Edge pulse
  signal TxClkCnt    : Std_Logic_Vector(5 downto 0) := (others => '0');  -- Tx Baud Clock Counter
  signal TxClkCnt    : Std_Logic_Vector(5 downto 0) := (others => '0');  -- Tx Baud Clock Counter
  signal TxBdClk     : Std_Logic := '0';              -- Tx Baud Clock
  signal TxBdClk     : Std_Logic := '0';              -- Tx Baud Clock
  signal TxBdDel     : Std_Logic := '0';              -- Delayed Tx Baud Clock
  signal TxBdDel     : Std_Logic := '0';              -- Delayed Tx Baud Clock
 
  signal TxBdEdgeRise   : Std_Logic := '0';             -- Tx Baud Clock rising edge
 
  signal TxBdEdgeFall   : Std_Logic := '0';             -- Tx Baud Clock falling edge
 
 
  signal TxReq       : std_logic := '0';              -- Request transmit start
  signal tx_parity      : Std_logic := '0';              -- Parity Bit
  signal TxAck       : std_logic := '0';              -- Acknowledge transmit start
  signal tx_bit_count   : Std_Logic_Vector(3 downto 0) := (others => '0');  -- Data Bit Counter
  signal TxParity    : Std_logic := '0';              -- Parity Bit
  signal tx_shift_reg   : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Transmit shift register
  signal TxBitCount  : Std_Logic_Vector(2 downto 0) := (others => '0');  -- Data Bit Counter
  --
  signal TxShiftReg  : Std_Logic_Vector(7 downto 0) := (others => '0');  -- Transmit shift register
  -- Data register controls
 
  --
 
  type data_reg_type   is (data_reg_rst,  data_reg_load,   data_reg_idle);
 
  signal rx_data_ctrl   : data_reg_type;
 
 
 
  --
 
  -- Shift register controls
 
  --
 
  type shift_reg_type  is (shift_reg_rst, shift_reg_load, shift_reg_shift, shift_reg_idle);
 
  signal rx_shift_ctrl  : shift_reg_type;
 
  signal tx_shift_ctrl  : shift_reg_type;
 
 
 
  --
 
  -- Count register controls
 
  --  
 
  type count_reg_type  is (count_reg_rst, count_reg_decr,  count_reg_idle);
 
  signal rx_count_ctrl  : count_reg_type;
 
  signal tx_count_ctrl  : count_reg_type;
 
 
begin
begin
 
 
  ---------------------------------------------------------------
  ---------------------------------------------------------------
  -- ACIA Reset may be hardware or software
  -- ACIA Reset may be hardware or software
  ---------------------------------------------------------------
  ---------------------------------------------------------------
 
 
  acia_reset : process( clk, rst, ac_rst, dcd_n )
  acia_reset : process( clk, rst, ac_rst, dcd_n )
  begin
  begin
    --
    --
    -- ACIA reset Synchronous 
    -- ACIA reset Synchronous 
    -- Includes software reset
    -- Includes software reset
    --
    --
    if falling_edge(clk) then
    if falling_edge(clk) then
      ac_rst <= (CtrlReg(1) and CtrlReg(0)) or rst;
      ac_rst <= (control_reg(1) and control_reg(0)) or rst;
    end if;
    end if;
    -- Receiver reset
    -- Receiver reset
    rx_rst <= ac_rst or DCD_n;
    rx_rst <= ac_rst or DCD_n;
    -- Transmitter reset
    -- Transmitter reset
    tx_rst <= ac_rst;
    tx_rst <= ac_rst;
 
 
  end process;
  end process;
 
 
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- Generate Read / Write strobes.
  -- Generate Read / Write strobes.
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 
 
  acia_read_write : process(clk, ac_rst)
  acia_read_write : process(clk, rst)
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
 
      status_read   <= '0';
 
      tx_data_write <= '0';
 
      rx_data_read  <= '0';
      if rst = '1' then
      if rst = '1' then
        CtrlReg(1 downto 0) <= "11";
        control_reg(1 downto 0) <= "11";
        CtrlReg(7 downto 2) <= (others => '0');
        control_reg(7 downto 2) <= (others => '0');
        TxReg   <= (others => '0');
        tx_data_reg   <= (others => '0');
        RxRd  <= '0';
      else
        TxWr  <= '0';
 
        StRd  <= '0';
 
      else
 
        RxRd  <= '0';
 
        TxWr  <= '0';
 
        StRd  <= '0';
 
        if cs = '1' then
        if cs = '1' then
          if Addr = '0' then              -- Control / Status register
          if addr = '0' then              -- Control / Status register
            if rw = '0' then              -- write control register
            if rw = '0' then              -- write control register
              CtrlReg <= data_in;
              control_reg   <= data_in;
            else                          -- read status register
            else                          -- read status register
              StRd <= '1';
              status_read   <= '1';
            end if;
            end if;
          else                            -- Data Register
          else                            -- Data Register
            if rw = '0' then              -- write transmiter register
            if rw = '0' then              -- write transmiter register
              TxReg <= data_in;
              tx_data_reg <= data_in;
              TxWr  <= '1';
              tx_data_write <= '1';
            else                          -- read receiver register
            else                          -- read receiver register
              RxRd <= '1';
              rx_data_read  <= '1';
            end if;
            end if;
          end if;
          end if;
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
Line 376... Line 406...
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- ACIA Status Register
  -- ACIA Status Register
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 
 
  acia_status : process( clk )
  acia_status : process( RxRdy, TxRdy, DCDInt, CTS_n, FErr, OErr, PErr, RxIE, TxIE,  status_reg, control_reg )
  begin
  begin
    if falling_edge( clk ) then
    TxIE <= (not control_reg(TX1BIT)) and control_reg(TX0BIT);
      StatReg(0) <= RxRdy;                 -- Receive Data Ready
    RxIE <= control_reg(RIEBIT);
      StatReg(1) <= TxRdy and (not CTS_n); -- Transmit Buffer Empty
    status_reg(RXRBIT) <= RxRdy;
      StatReg(2) <= DCDInt;                -- Data Carrier Detect
    status_reg(TXRBIT) <= TxRdy and (not CTS_n);
      StatReg(3) <= CTS_n;                 -- Clear To Send
    status_reg(DCDBIT) <= DCDInt;                -- Data Carrier Detect
      StatReg(4) <= FErr;                  -- Framing error
    status_reg(CTSBIT) <= CTS_n;                 -- Clear To Send
      StatReg(5) <= OErr;                  -- Overrun error
    status_reg(FERBIT) <= FErr;
      StatReg(6) <= PErr;                  -- Parity error
    status_reg(OERBIT) <= OErr;
      StatReg(7) <= (RxIE and RxRdy) or
    status_reg(PERBIT) <= PErr;
 
    status_reg(IRQBIT) <= (RxIE and RxRdy) or
                    (RxIE and DCDInt) or
                    (RxIE and DCDInt) or
                    (TxIE and TxRdy);
                    (TxIE and TxRdy);
 
    irq <= status_reg(IRQBIT);
 
  end process;
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA Rx data ready status
 
  -----------------------------------------------------------------------------
 
 
 
  acia_rx_data_ready : process( clk, rx_rst, RxBdEdgeFall, status_rxr_set )
 
  begin
 
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        RxRdy <= '0';
 
      else
 
        if RxBdEdgeFall = '1' and status_rxr_set = '1' then
 
          RxRdy <= '1';
 
        elsif rx_data_read  = '1' then
 
          RxRdy <= '0';
 
        end if;
 
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- ACIA Transmit Control
  -- ACIA Tx data ready status
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 
 
  acia_control : process(CtrlReg, TxDat)
  acia_tx_data_ready : process( clk, tx_rst, TxBdEdgeRise, status_txr_set )
  begin
  begin
    case CtrlReg(6 downto 5) is
    if falling_edge( clk ) then
      when "00" =>                      -- Disable TX Interrupts, Assert RTS
      if tx_rst = '1' then
        TxD   <= TxDat;
         TxRdy <= '1';
        TxIE  <= '0';
      else
        RTS_n <= '0';
        if TxBdEdgeRise = '1' and status_txr_set = '1' then
      when "01" =>                      -- Enable TX interrupts, Assert RTS
          TxRdy <= '1';
        TxD   <= TxDat;
        elsif  tx_data_write  = '1' then
        TxIE  <= '1';
          TxRdy <= '0';
        RTS_n <= '0';
        end if;
      when "10" =>                      -- Disable Tx Interrupts, Clear RTS
      end if;
        TxD   <= TxDat;
    end if;
        TxIE  <= '0';
  end process;
        RTS_n <= '1';
 
      when "11" =>                      -- Disable Tx interrupts, Assert RTS, send break
 
        TxD   <= '0';
  -----------------------------------------------------------------------------
        TxIE  <= '0';
  -- ACIA Framing Error
        RTS_n <= '0';
  -----------------------------------------------------------------------------
      when others =>
 
        null;
 
    end case;
 
 
 
    RxIE  <= CtrlReg(7);
  acia_fer_status : process( clk )
    WdFmt <= CtrlReg(4 downto 2);
  begin
    BdFmt <= CtrlReg(1 downto 0);
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        FErr <= '0';
 
      elsif RxBdEdgeFall = '1' then
 
        if status_fer_clr = '1' then
 
          FErr <= '0';
 
        end if;
 
        if status_fer_set = '1' then
 
          FErr <= '1';
 
        end if;
 
      end if;
 
    end if;
 
  end process;
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA Over-run Error
 
  -----------------------------------------------------------------------------
 
 
 
  acia_oer_status : process( clk )
 
  begin
 
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        OErr <= '0';
 
      elsif RxBdEdgeFall = '1' then
 
        if status_oer_set = '1' then
 
          OErr <= '1';
 
        end if;
 
        if status_oer_clr = '1' or rx_data_read = '1' then
 
          OErr <= '0';
 
        end if;
 
      end if;
 
    end if;
 
  end process;
 
 
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA Parity Error
 
  -----------------------------------------------------------------------------
 
 
 
  acia_per_status : process( clk )
 
  begin
 
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        PErr <= '0';
 
      elsif RxBdEdgeFall = '1' and status_per_set = '1' then
 
        PErr <= '1';
 
      elsif RxBdEdgeFall = '1' and status_per_clr = '1' then
 
        PErr <= '0';
 
      elsif rx_data_read = '1' then
 
        PErr <= '0';
 
      end if;
 
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------
  ---------------------------------------------------------------
  -- Set Data Output Multiplexer
  -- Set Data Output Multiplexer
  --------------------------------------------------------------
  --------------------------------------------------------------
 
 
  acia_data_mux : process(Addr, RxReg, StatReg)
  acia_data_mux : process(addr, rx_data_reg, status_reg)
  begin
  begin
    if Addr = '1' then
    if addr = '1' then
      data_out <= RxReg;               -- read receiver register
      data_out <= rx_data_reg;               -- read receiver register
    else
    else
      data_out <= StatReg;               -- read status register
      data_out <= status_reg;               -- read status register
    end if;
    end if;
  end process;
  end process;
 
 
  irq <= StatReg(7);
 
 
 
  ---------------------------------------------------------------
  ---------------------------------------------------------------
  -- Data Carrier Detect Edge rising edge detect
  -- Data Carrier Detect Edge rising edge detect
  ---------------------------------------------------------------
  ---------------------------------------------------------------
 
 
  acia_dcd_edge : process( clk, ac_rst )
  acia_dcd_edge : process( clk, ac_rst )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if ac_rst = '1' then
      if ac_rst = '1' then
        DCDDel  <= '0';
        DCDDel  <= '0';
Line 456... Line 552...
        DCDEdge <= DCD_n and (not DCDDel);
        DCDEdge <= DCD_n and (not DCDDel);
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
  ---------------------------------------------------------------
  ---------------------------------------------------------------
  -- Data Carrier Detect Interrupt
  -- Data Carrier Detect Interrupt
  ---------------------------------------------------------------
  ---------------------------------------------------------------
  -- If Data Carrier is lost, an interrupt is generated
  -- If Data Carrier is lost, an interrupt is generated
  -- To clear the interrupt, first read the status register
  -- To clear the interrupt, first read the status register
Line 480... Line 577...
            DCDState <= DCD_State_Int;
            DCDState <= DCD_State_Int;
          end if;
          end if;
        when DCD_State_Int =>
        when DCD_State_Int =>
          -- To reset DCD interrupt, 
          -- To reset DCD interrupt, 
          -- First read status
          -- First read status
          if StRd = '1' then
          if status_read = '1' then
            DCDState <= DCD_State_Reset;
            DCDState <= DCD_State_Reset;
          end if;
          end if;
        when DCD_State_Reset =>
        when DCD_State_Reset =>
          -- Then read receive register
          -- Then read receive register
          if RxRd = '1' then
          if rx_data_read = '1' then
            DCDInt   <= '0';
            DCDInt   <= '0';
            DCDState <= DCD_State_Idle;
            DCDState <= DCD_State_Idle;
          end if;
          end if;
        when others =>
        when others =>
          null;
          null;
        end case;
        end case;
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver Clock Edge Detection
  -- Receiver Clock Edge Detection
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- A rising edge will produce a one clock cycle pulse
  -- A rising edge will produce a one CPU clock cycle pulse
 
  --
  acia_rx_clock_edge : process( clk, rx_rst )
  acia_rx_clock_edge : process( clk, rx_rst )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if rx_rst = '1' then
      if rx_rst = '1' then
        RxClkDel  <= '0';
        RxCDel  <= "00";
        RxClkEdge <= '0';
        RxCEdge <= '0';
      else
      else
        RxClkDel  <= RxC;
        --
        RxClkEdge <= (not RxClkDel) and RxC;
        -- RxClkEdge is one CPU clock cycle wide
 
        --
 
        RxCDel(0) <= RxC;
 
        RxCDel(1) <= RxCDel(0);
 
        RxCEdge <= (not RxCDel(1)) and RxCDel(0);
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver Data Edge Detection
  -- Receiver Data Edge Detection
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- A falling edge will produce a pulse on RxClk wide
  --
 
  -- If there is a falling edge on the RxD line
  acia_rx_data_edge : process( clk, rx_rst )
  -- and the ACIA receiver is in the start, stop or idle state 
 
  -- RxDatEdge is generated to reset the Baud Clock divide
 
  -- so that it is synchronized to the edge of the data
 
  -- 2021-01-30 JEK Double clock RxD
 
  acia_rx_data_edge : process( clk, rx_rst, RxD, RxDDel )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if rx_rst = '1' then
      if (rx_rst = '1') then
        RxDatDel0 <= '0';
        RxDDel(0) <= RxD;
        RxDatDel1 <= '0';
                  RxDDel(1) <= RxDDel(0);
        RxDatDel2 <= '0';
        RxDEdge <= '0';
        RxDatEdge <= '0';
 
      else
      else
        RxDatDel0 <= RxD;
        RxDDel(0) <= RxD;
        RxDatDel1 <= RxDatDel0;
                  RxDDel(1) <= RxDDel(0);
        RxDatDel2 <= RxDatDel1;
        RxDEdge <= not(RxDDel(0)) and RxDDel(1);
        RxDatEdge <= RxDatDel0 and (not RxD);
 
      end if;
 
    end if;
 
  end process;
 
 
 
  ---------------------------------------------------------------------
 
  -- Receiver Start / Stop
 
  ---------------------------------------------------------------------
 
  -- Enable the receive clock on detection of a start bit
 
  -- Disable the receive clock after a byte is received.
 
 
 
  acia_rx_start_stop : process( clk, rx_rst )
 
  begin
 
    if falling_edge(clk) then
 
      if rx_rst = '1' then
 
        RxEnable <= '0';
 
        RxStart  <= '0';
 
      elsif (RxEnable = '0') and (RxDatEdge = '1') then
 
        -- Data Edge detected 
 
        RxStart  <= '1';                    -- Request Start and
 
        RxEnable <= '1';                    -- Enable Receive Clock
 
      elsif (RxStart = '1') and (RxAck = '1') then
 
        -- Data is being received
 
        RxStart <= '0';                     -- Reset Start Request
 
      elsif (RxStart = '0') and (RxAck = '0') then
 
        -- Data has now been received
 
        RxEnable <= '0';                    -- Disable Receiver until next Start Bit
 
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver Clock Divider
  -- Receiver Clock Divider
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Hold the Rx Clock divider in reset when the receiver is disabled
  -- Hold the Rx Clock divider in reset when the receiver is disabled
  -- Advance the count only on a rising Rx clock edge
  -- Advance the count only on a rising Rx clock edge
 
  --
  acia_rx_clock_divide : process( clk, rx_rst )
  acia_rx_clock_divide : process( clk, rx_rst, RxDEdge, RxCEdge )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if rx_rst = '1' then
      if (rx_rst = '1') or (RxDEdge = '1') then
        RxClkCnt  <= (others => '0');
        --
      elsif RxDatEdge = '1' then
        -- Reset counter on rx_rst or falling data edge
        -- reset on falling data edge
        --
        RxClkCnt <= (others => '0');
        RxClkCnt <= (others => '0');
      elsif RxClkEdge = '1' then
      elsif RxCEdge = '1' then
        -- increment count on Clock edge
        --         
 
        -- increment count on Rx Clock edge
 
        --
        RxClkCnt <= RxClkCnt + "000001";
        RxClkCnt <= RxClkCnt + "000001";
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
 
-----------------------------------------------------------------------------
 
-- ACIA RX Baud select
 
-----------------------------------------------------------------------------
 
-- 2021-01-30 JEK change RxC to RxCDel(0)
 
  acia_rx_baud_control : process(clk, control_reg, RxC, RxClkCnt )
 
  begin
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver Baud Clock Selector
    -- Receive Baud Clock Selector
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- BdFmt
    -- control_reg(BD1BIT downto BD0BIT)
  -- 0 0     - Baud Clk divide by 1
  -- 0 0     - Baud Clk divide by 1
  -- 0 1     - Baud Clk divide by 16
  -- 0 1     - Baud Clk divide by 16
  -- 1 0     - Baud Clk divide by 64
  -- 1 0     - Baud Clk divide by 64
  -- 1 1     - Reset
    -- 1 1     - reset
  --
    if falling_edge(clk) then
  acia_rx_baud_clock_select : process( BdFmt, RxC, RxClkCnt )
      case control_reg(BD1BIT downto BD0BIT) is
  begin
 
    case BdFmt is
 
      when "00" =>                              -- Div by 1
      when "00" =>                              -- Div by 1
        RxBdClk <= RxC;
        RxBdClk <= RxCDel(0);
      when "01" =>                              -- Div by 16
      when "01" =>                              -- Div by 16
        RxBdClk <= RxClkCnt(3);
        RxBdClk <= RxClkCnt(3);
      when "10" =>                              -- Div by 64
      when "10" =>                              -- Div by 64
        RxBdClk <= RxClkCnt(5);
        RxBdClk <= RxClkCnt(5);
      when others =>                         -- Software Reset
      when others =>                          -- Software reset
        RxBdClk <= '0';
        RxBdClk <= '0';
    end case;
    end case;
 
    end if;
 
 
 
  end process;
 
 
 
 
 
  ---------------------------------------------------------------------
 
  -- Receiver Baud Clock Edge Detection
 
  ---------------------------------------------------------------------
 
  -- A Rising Baud Clock edge will produce a single CPU clock pulse
 
  --
 
  acia_rx_baud_edge : process( clk, rx_rst, RxBdClk, RxBdDel )
 
  begin
 
    if falling_edge(clk) then
 
      if rx_rst = '1' then
 
        RxBdDel      <= '0';
 
        RxBdEdgeRise <= '0';
 
        RxBdEdgeFall <= '0';
 
      else
 
        RxBdDel      <= RxBdClk;
 
        RxBdEdgeRise <= not(RxBdDel) and     RxBdClk;
 
        RxBdEdgeFall <=     RxBdDel  and not(RxBdClk);
 
      end if;
 
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver process
  -- Receiver process
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
Line 618... Line 726...
  -- 0 1 1   - 7 data, odd  parity, 1 stop
  -- 0 1 1   - 7 data, odd  parity, 1 stop
  -- 1 0 0   - 8 data, no   parity, 2 stop
  -- 1 0 0   - 8 data, no   parity, 2 stop
  -- 1 0 1   - 8 data, no   parity, 1 stop
  -- 1 0 1   - 8 data, no   parity, 1 stop
  -- 1 1 0   - 8 data, even parity, 1 stop
  -- 1 1 0   - 8 data, even parity, 1 stop
  -- 1 1 1   - 8 data, odd  parity, 1 stop
  -- 1 1 1   - 8 data, odd  parity, 1 stop
 
  --
  acia_rx_receive : process( clk, rst )
  -- Registers activated on rising bit clock edge
 
  -- State transitions on falling bit clock edge
 
  --
 
  acia_rx_receive : process( rx_current_state, control_reg, rx_bit_count, RxDDel, RxDat, rx_parity, RxRdy )
  begin
  begin
    if falling_edge( clk ) then
          rx_data_ctrl   <= data_reg_idle;
      if rx_rst = '1' then
          rx_shift_ctrl  <= shift_reg_idle;
        FErr       <= '0';
          rx_next_state  <= start_state;
        OErr       <= '0';
 
        PErr       <= '0';
          status_rxr_set <= '0';                       -- receive data ready
        RxShiftReg <= (others => '0');       -- Reset Shift register
          status_fer_clr <= '0';                       -- framing error status
        RxReg      <= (others => '0');
          status_fer_set <= '0';                       -- framing error status
        RxParity   <= '0';                   -- reset Parity bit
          status_oer_clr <= '0';                       -- over-run error status
        RxAck      <= '0';                   -- Receiving data
          status_oer_set <= '0';                       -- over-run error status
        RxBitCount <= (others => '0');
          status_per_clr <= '0';                       -- parity  error status
        RxState    <= RxState_Wait;
          status_per_set <= '0';                       -- parity  error status
 
 
 
          case rx_current_state is
 
          when start_state =>
 
            rx_shift_ctrl <= shift_reg_rst;            -- Reset Shift register on rising baud clock
 
            if RxDat = '0' then                        -- RxDat = '0' => start bit
 
              rx_next_state <= data_state;             -- if low, start shifting in data
 
            end if;
 
 
 
          when data_state =>                           -- Receiving data bits
 
            --  on rising baud clock edge 
 
            rx_shift_ctrl <= shift_reg_shift;          -- shift in data bit
 
 
 
            -- on falling baud clock edge transition state
 
            if rx_bit_count = "0000" then               -- All bits shifted in ?
 
              --                                       -- yes, transition to parity or stop state
 
              -- if control_reg(DATBIT) = '1' and control_reg(STPBIT) = '0'
 
              -- then 8 data bit, no parity
 
              --
 
              if control_reg(DATBIT)='1' and control_reg(STPBIT)='0' then
 
                rx_next_state  <= stop_state;          -- 8 data, 1 or 2 stops, no parity => stop_state
      else
      else
        RxBdDel      <= RxBdClk;
                rx_next_state <= parity_state;         -- control_reg(DATBIT) = '0' => 7 data + parity or
        if RxBdDel = '0' and RxBdClk = '1' then
              end if;                                  -- control_reg(STPBIT) = '1' => 8 data + parity => parity_state
          case RxState is
            else
          when RxState_Wait =>
              rx_next_state <= data_state;             -- bit count none zero => remain in data state
            RxShiftReg <= (others => '0');   -- Reset Shift register
 
            RxParity   <= '0';               -- Reset Parity bit
 
            if WdFmt(2) = '0' then           -- WdFmt(2) = '0' => 7 data bits
 
              RxBitCount <= "110";
 
            else                             -- WdFmt(2) = '1' => 8 data bits
 
              RxBitCount <= "111";
 
            end if;
 
            if RxDatDel2 = '0' then          -- look for start bit
 
              RxState <= RxState_Data;       -- if low, start reading data
 
            end if;
 
 
 
          when RxState_Data =>               -- Receiving data bits 
 
            RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1);
 
            RxParity   <= RxParity xor RxDatDel2;
 
            RxAck      <= '1';               -- Flag receive in progress
 
            RxBitCount <= RxBitCount - "001";
 
            if RxBitCount = "000" then
 
              if WdFmt(2) = '0' then         -- WdFmt(2) = '0' => 7 data
 
                RxState <= RxState_Parity;   -- 7 bits always has parity
 
              elsif WdFmt(1) = '0' then      -- WdFmt(2) = '1' => 8 data                          
 
                RxState <= RxState_Stop;     -- WdFmt(1) = '0' => no parity
 
                PErr <= '0';               -- Reset Parity Error
 
              else
 
                RxState <= RxState_Parity;   -- WdFmt(1) = '1' => 8 data + parity
 
              end if;
 
            end if;
            end if;
 
 
          when RxState_Parity =>             -- Receive Parity bit
          when parity_state =>                         -- Receive Parity bit
            if WdFmt(2) = '0' then           -- if 7 data bits, shift parity into MSB
            -- on rising baud clock edge:
              RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); -- 7 data + parity
            if control_reg(DATBIT) = '0' then          -- if 7 data bits, shift parity into MSB
 
              rx_shift_ctrl <= shift_reg_shift;        -- 7 data + parity
            end if;
            end if;
            if RxParity = (RxDatDel2 xor WdFmt(0)) then
 
              PErr <= '1';                 -- If parity not the same flag error
            -- on falling baud clock edge, set parity
 
            if rx_parity = (RxDat xor control_reg(POEBIT)) then
 
              status_per_set <= '1';                   -- set parity  error status
            else
            else
              PErr <= '0';
              status_per_clr <= '1';                   -- resetset parity  error status
            end if;
            end if;
            RxState <= RxState_Stop;
            rx_next_state <= stop_state;
 
 
          when RxState_Stop =>             -- stop bit (Only one required for RX)
          when stop_state =>                           -- stop bit (Only one required for RX)
            RxAck  <= '0';                 -- Flag Receive Complete
            -- on falling baud clock edge
            RxReg <= RxShiftReg;
            rx_data_ctrl   <= data_reg_load;             -- load receive data reg with shift register
            if RxDatDel2 = '1' then        -- stop bit expected
            status_rxr_set <= '1';                       -- flag receive data ready
              FErr <= '0';                 -- yes, no framing error
 
            else
            -- on falling baud clock edge
              FErr <= '1';                 -- no, framing error
            if control_reg(DATBIT)='1' and control_reg(STPBIT)='0' then
 
                status_per_clr <= '1';                 -- reset parity  error status if no parity
            end if;
            end if;
 
 
 
            -- on falling baud clock edge
            if RxRdy = '1' then            -- Has previous data been read ? 
            if RxRdy = '1' then            -- Has previous data been read ? 
              OErr <= '1';                 -- no, overrun error
              status_oer_set <= '1';                   -- no, set over-run  error status
            else
            else
              OErr <= '0';                 -- yes, no over run error
              status_oer_clr <= '1';                   -- yes, reset over-run  error status
            end if;
            end if;
            RxState <= RxState_Wait;
 
 
 
          when others =>
            -- on falling baud clock edge
            RxAck   <= '0';                -- Flag Receive Complete
            if RxDat = '1' then                          -- stop bit received ?
            RxState <= RxState_Wait;
              status_fer_clr <= '1';                   -- yes, reset framing error status
          end case;
            else
 
              status_fer_set <= '1';                   -- no, set framing error status
        end if;
        end if;
 
 
 
            -- on falling baud clock edge
 
            if RxDat = '0' then                        -- wait until RxDat returns high
 
              rx_next_state  <= idle_state;
      end if;
      end if;
 
 
 
          when idle_state =>
 
            if RxDat = '0' then                        -- wait until RxD returns high
 
              rx_next_state <= idle_state;
    end if;
    end if;
 
 
 
          when others =>
 
            null;
 
          end case;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Receiver Read process
  -- Rx State machine
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
 
  --
 
  -- State machine transitions on the falling edge of the Rx Baud clock
 
  --
 
  acia_rx_state : process(clk, rst )
 
  begin
 
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        rx_current_state <= start_state;
 
      else
 
        if RxBdEdgeFall = '1' then
 
          rx_current_state <= rx_next_state;
 
        end if;
 
      end if;
 
    end if;
 
 
  acia_rx_read : process( clk, rst, RxRdy )
  end process;
 
 
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA Rx Shift Register
 
  -----------------------------------------------------------------------------
 
  -- 2021-01-30 JEK change RxD to RxDDel(0)
 
  --
 
  acia_rx_shift_reg : process( clk, rx_rst, RxBdEdgeRise, rx_shift_reg, RxDDel, rx_parity )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if rx_rst = '1' then
      if rx_rst = '1' then
        RxRdy <= '0';
        RxDat <= '1';
        RxReq <= '0';
        rx_bit_count <= (others=>'0');
      elsif RxRd = '1' then
        rx_shift_reg <= (others=>'0');
        -- Data was read,        
        rx_parity    <= '0';
        RxRdy <= '0';                        -- Reset receive full
      elsif RxBdEdgeRise = '1' then
        RxReq <= '1';                        -- Request more data
        RxDat <= RxDDel(0);
      elsif RxReq = '1' and RxAck = '1' then
        case rx_shift_ctrl is
        -- Data is being received
        when shift_reg_rst =>
        RxReq <= '0';                        -- reset receive request
          if control_reg(DATBIT) = '0' then  -- control_reg(DATBIT) = '0' => 7 data bits
      elsif RxReq = '0' and RxAck = '0' then
            rx_bit_count <= "0111";
        -- Data now received
          else                               -- control_reg(DATBIT) = '1' => 8 data bits
        RxRdy <= '1';                        -- Flag RxRdy and read Shift Register
            rx_bit_count <= "1000";
 
          end if;
 
          rx_shift_reg <= (others=>'0');
 
          rx_parity    <= '0';
 
        when shift_reg_shift =>
 
          rx_bit_count <= rx_bit_count - "0001";
 
          rx_shift_reg <= RxDDel(0) & rx_shift_reg(7 downto 1);
 
          rx_parity    <= rx_parity xor RxDDel(0);
 
        when others =>
 
          null;
 
        end case;
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA Rx Data Register
 
  -----------------------------------------------------------------------------
 
 
 
  acia_rx_data_reg : process( clk, rx_rst, rx_shift_reg )
 
  begin
 
    if falling_edge( clk ) then
 
      if rx_rst = '1' then
 
        rx_data_reg <= (others=>'0');
 
      elsif RxBdEdgeFall = '1' then
 
        case rx_data_ctrl is
 
        when data_reg_rst =>
 
          rx_data_reg <= (others=>'0');
 
        when data_reg_load =>
 
          rx_data_reg  <= rx_shift_reg;
 
        when others =>
 
          null;
 
        end case;
 
      end if;
 
    end if;
 
  end process;
 
 
 
  -----------------------------------------------------------------------------
 
  -- ACIA TX control
 
  -----------------------------------------------------------------------------
 
 
 
  acia_tx_control : process(control_reg, TxDat )
 
  begin
 
    case control_reg(TX1BIT downto TX0BIT) is
 
      when "00" =>                      -- Disable TX Interrupts, Assert RTS
 
        TxD   <= TxDat;
 
        RTS_n <= '0';
 
      when "01" =>                      -- Enable TX interrupts, Assert RTS
 
        TxD   <= TxDat;
 
        RTS_n <= '0';
 
      when "10" =>                      -- Disable Tx Interrupts, Clear RTS
 
        TxD   <= TxDat;
 
        RTS_n <= '1';
 
      when "11" =>                      -- Disable Tx interrupts, Assert RTS, send break
 
        TxD   <= '0';
 
        RTS_n <= '0';
 
      when others =>
 
        null;
 
    end case;
 
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Transmit Clock Edge Detection
  -- Transmit Clock Edge Detection
  -- A falling edge will produce a one clock cycle pulse
  -- A rising edge will produce a one clock cycle pulse
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
 
  -- 2021-01-30 JEK add one more bit to TxCDel. Double sample TxC
  acia_tx_clock_edge : process( Clk, tx_rst )
  acia_tx_clock_edge : process( Clk, tx_rst )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if tx_rst = '1' then
      if tx_rst = '1' then
        TxClkDel  <= '0';
        TxCDel(1 downto 0) <= "00";
        TxClkEdge <= '0';
        TxCEdge <= '0';
      else
      else
        TxClkDel  <= TxC;
        TxCDel(0) <= TxC;
        TxClkEdge <= TxClkDel and (not TxC);
                  TxCDel(1) <= RxCDel(0);
 
        TxCEdge <= (not TxCDel(1)) and TxCDel(0);
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
Line 752... Line 954...
  acia_tx_clock_divide : process( clk, tx_rst )
  acia_tx_clock_divide : process( clk, tx_rst )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if tx_rst = '1' then
      if tx_rst = '1' then
        TxClkCnt <= (others=>'0');
        TxClkCnt <= (others=>'0');
      elsif TxClkEdge = '1' then
      elsif TxCEdge = '1' then
        TxClkCnt <= TxClkCnt + "000001";
        TxClkCnt <= TxClkCnt + "000001";
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
 
-----------------------------------------------------------------------------
 
-- ACIA TX Baud select
 
-----------------------------------------------------------------------------
 
-- 2021-01-30 JEK change TxC to TxCDel(0)
 
  acia_tx_baud_select : process(clk, control_reg, TxDat, TxCDel, TxClkCnt )
 
  begin
 
 
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
  -- Transmit Baud Clock Selector
  -- Transmit Baud Clock Selector
  ---------------------------------------------------------------------
  ---------------------------------------------------------------------
 
    -- control_reg(BD1BIT downto BD0BIT)
  acia_tx_baud_clock_select : process( BdFmt, TxClkCnt, TxC )
 
  begin
 
    -- BdFmt
 
    -- 0 0     - Baud Clk divide by 1
    -- 0 0     - Baud Clk divide by 1
    -- 0 1     - Baud Clk divide by 16
    -- 0 1     - Baud Clk divide by 16
    -- 1 0     - Baud Clk divide by 64
    -- 1 0     - Baud Clk divide by 64
    -- 1 1     - reset
    -- 1 1     - reset
    case BdFmt is
    if falling_edge(clk) then
 
      case control_reg(BD1BIT downto BD0BIT) is
      when "00" =>                               -- Div by 1
      when "00" =>                               -- Div by 1
        TxBdClk <= TxC;
        TxBdClk <= TxCDel(0);
      when "01" =>                               -- Div by 16
      when "01" =>                               -- Div by 16
        TxBdClk <= TxClkCnt(3);
        TxBdClk <= TxClkCnt(3);
      when "10" =>                               -- Div by 64
      when "10" =>                               -- Div by 64
        TxBdClk <= TxClkCnt(5);
        TxBdClk <= TxClkCnt(5);
      when others =>                          -- Software reset
      when others =>                          -- Software reset
        TxBdClk <= '0';
        TxBdClk <= '0';
    end case;
    end case;
 
    end if;
 
 
 
  end process;
 
 
 
 
 
  ---------------------------------------------------------------------
 
  -- Transmit Baud Clock Edge Detection
 
  ---------------------------------------------------------------------
 
  -- A Falling edge will produce a single pulse on TxBdEdgeFall
 
  --
 
  acia_tx_baud_edge : process( clk, tx_rst )
 
  begin
 
    if falling_edge(clk) then
 
      if tx_rst = '1' then
 
        TxBdDel      <= '0';
 
        TxBdEdgeRise <= '0';
 
        TxBdEdgeFall <= '0';
 
      else
 
        TxBdDel  <= TxBdClk;
 
        TxBdEdgeRise <= (not TxBdDel) and TxBdClk;
 
        TxBdEdgeFall <= TxBdDel and (not TxBdClk);
 
      end if;
 
    end if;
  end process;
  end process;
 
 
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- Implements the Tx unit
  -- Implements the Tx unit
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
Line 793... Line 1024...
  -- 0 1 1   - 7 data, odd  parity, 1 stop
  -- 0 1 1   - 7 data, odd  parity, 1 stop
  -- 1 0 0   - 8 data, no   parity, 2 stop
  -- 1 0 0   - 8 data, no   parity, 2 stop
  -- 1 0 1   - 8 data, no   parity, 1 stop
  -- 1 0 1   - 8 data, no   parity, 1 stop
  -- 1 1 0   - 8 data, even parity, 1 stop
  -- 1 1 0   - 8 data, even parity, 1 stop
  -- 1 1 1   - 8 data, odd  parity, 1 stop
  -- 1 1 1   - 8 data, odd  parity, 1 stop
 
  acia_tx_transmit : process( tx_current_state, TxRdy, tx_bit_count, tx_shift_reg, control_reg, tx_parity )
  acia_tx_transmit : process( clk, tx_rst)
 
  begin
  begin
    if falling_edge(clk) then
          status_txr_set <= '0';
      if tx_rst = '1' then
          case tx_current_state is
        TxDat      <= '1';
          when idle_state =>
        TxShiftReg <= (others=>'0');
            TxOut <= '1';
        TxParity   <= '0';
            tx_shift_ctrl <= shift_reg_idle;
        TxBitCount <= (others=>'0');
            if TxRdy = '0' then
        TxAck      <= '0';
              tx_next_state <= start_state;
        TxState    <= TxState_Idle;
 
      else
      else
 
              tx_next_state <= idle_state;
        TxBdDel <= TxBdClk;
 
        -- On rising edge of baud clock, run the state machine
 
        if TxBdDel = '0' and TxBdClk = '1' then
 
 
 
          case TxState is
 
          when TxState_Idle =>
 
            TxDat <= '1';
 
            if TxReq = '1' then
 
              TxShiftReg <= TxReg;              -- Load Shift reg with Tx Data
 
              TxAck      <= '1';
 
              TxState    <= TxState_Start;
 
            end if;
            end if;
 
 
          when TxState_Start =>
          when start_state =>
            TxDat    <= '0';                    -- Start bit
            TxOut         <= '0';                    -- Start bit
            TxParity <= '0';
            tx_shift_ctrl <= shift_reg_load;         -- Load Shift reg with Tx Data
            if WdFmt(2) = '0' then
            tx_next_state <= data_state;
              TxBitCount <= "110";              -- 7 data + parity
 
 
          when data_state =>
 
            TxOut <= tx_shift_reg(0);
 
            tx_shift_ctrl <= shift_reg_shift;        -- shift tx shift reg
 
            if tx_bit_count = "000" then
 
              if (control_reg(DATBIT) = '1') and (control_reg(STPBIT) = '0') then
 
                if control_reg(POEBIT) = '0' then    -- 8 data bits
 
                  tx_next_state <= stop_state;       -- 2 stops
            else
            else
              TxBitCount <= "111";              -- 8 data
                  tx_next_state <= idle_state;       -- 1 stop
            end if;
            end if;
            TxState <= TxState_Data;
 
 
 
          when TxState_Data =>
 
            TxDat      <= TxShiftReg(0);
 
            TxShiftReg <= '1' & TxShiftReg(7 downto 1);
 
            TxParity   <= TxParity xor TxShiftReg(0);
 
            TxBitCount <= TxBitCount - "001";
 
            if TxBitCount = "000" then
 
              if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
 
                if WdFmt(0) = '0' then        -- 8 data bits
 
                  TxState <= TxState_Stop;    -- 2 stops
 
                else
                else
                  TxAck   <= '0';
                tx_next_state <= parity_state;        -- parity
                  TxState <= TxState_Idle;    -- 1 stop
 
                end if;
                end if;
              else
              else
                TxState <= TxState_Parity;    -- parity
              tx_next_state <= data_state;
              end if;
 
            end if;
            end if;
 
 
          when TxState_Parity =>              -- 7/8 data + parity bit
          when parity_state =>                        -- 7/8 data + parity bit
            if WdFmt(0) = '0' then
            if control_reg(POEBIT) = '0' then
              TxDat <= not(TxParity);         -- even parity
              TxOut <= not(tx_parity);                -- even parity
            else
            else
              TxDat <= TxParity;              -- odd parity
              TxOut <= tx_parity;                     -- odd parity
            end if;
            end if;
            if WdFmt(1) = '0' then
            tx_shift_ctrl <= shift_reg_idle;
              TxState <= TxState_Stop;        -- 2 stops
            if control_reg(STPBIT) = '0' then
 
              tx_next_state <= stop_state;            -- 2 stops
            else
            else
              TxAck   <= '0';
              tx_next_state <= idle_state;            -- 1 stop
              TxState <= TxState_Idle;        -- 1 stop
 
            end if;
            end if;
 
 
          when TxState_Stop =>                -- first of two stop bits
          when stop_state =>                          -- first of two stop bits
            TxDat   <= '1';
            TxOut          <= '1';
            TxAck   <= '0';
            tx_shift_ctrl  <= shift_reg_idle;
            TxState <= TxState_Idle;
            status_txr_set <= '1';
 
            tx_next_state  <= idle_state;
 
 
 
 --         when others =>
 
 --           null;
 
 
          end case;
          end case;
 
  end process;
 
 
 
  ---------------------------------------------------------------------
 
  -- Tx State machine
 
  ---------------------------------------------------------------------
 
  --
 
  -- State machine transitions on the rising edge of the Tx Baud clock
 
  --
 
  acia_tx_state : process(clk, tx_rst )
 
  begin
 
     if falling_edge( clk ) then
 
      if tx_rst = '1' then
 
        tx_current_state <= idle_state;
 
      else
 
        if TxBdEdgeRise = '1' then
 
          tx_current_state <= tx_next_state;
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
  ---------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- Transmitter Write process
  -- ACIA tx Shift Register
  ---------------------------------------------------------------------
  -----------------------------------------------------------------------------
 
 
  acia_tx_write : process( clk, tx_rst, TxWr, TxReq, TxAck )
  acia_tx_shift_reg : process( clk, TxBdEdgeFall, tx_shift_ctrl, tx_data_reg, tx_shift_reg, tx_parity )
  begin
  begin
    if falling_edge(clk) then
    if falling_edge(clk) then
      if tx_rst = '1' then
      if tx_rst = '1' then
        TxRdy <= '0';
        tx_bit_count <= (others=>'0');
        TxReq <= '0';
        tx_shift_reg <= (others=>'1');
      elsif TxWr = '1' then
        tx_parity    <= '0';
        -- Data was read,        
        TxDat        <= '1';
        TxRdy <= '0';                        -- Reset transmit empty
      elsif TxBdEdgeFall = '1' then
        TxReq <= '1';                        -- Request data transmit
        TxDat <= TxOut;
      elsif TxReq = '1' and TxAck = '1' then -- Data is being transmitted
        case tx_shift_ctrl is
        TxReq <= '0';                        -- reset transmit request
        when shift_reg_load =>
      elsif TxReq = '0' and TxAck = '0' then -- Data transmitted
          if control_reg(DATBIT) = '0' then  -- control_reg(DATBIT) = '0' => 7 data bits
        TxRdy <= '1';                        -- Flag TxRdy
            tx_bit_count <= "0111";
 
          else                               -- control_reg(DATBIT) = '1' => 8 data bits
 
            tx_bit_count <= "1000";
 
          end if;
 
          tx_shift_reg  <= tx_data_reg;
 
          tx_parity     <= '0';
 
        when shift_reg_shift =>
 
          tx_bit_count <= tx_bit_count - "0001";
 
          tx_shift_reg <= '1' & tx_shift_reg(7 downto 1);
 
          tx_parity    <= tx_parity xor tx_shift_reg(0);
 
        when others =>
 
          null;
 
        end case;
      end if;
      end if;
    end if;
    end if;
  end process;
  end process;
 
 
 
 
end rtl;
end rtl;
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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