--===========================================================================--
|
--===========================================================================--
|
--
|
--
|
-- S Y N T H E Z I A B L E ACIA 6850 C O R E
|
-- S Y N T H E Z I A B L E ACIA 6850 C O R E
|
--
|
--
|
-- www.OpenCores.Org - January 2007
|
-- www.OpenCores.Org - January 2007
|
-- This core adheres to the GNU public license
|
-- This core adheres to the GNU public license
|
--
|
--
|
-- Design units : 6850 ACIA core for the System68/09
|
-- Design units : 6850 ACIA core for the System68/09
|
--
|
--
|
-- File name : ACIA_TX.vhd
|
-- File name : ACIA_TX.vhd
|
--
|
--
|
-- Purpose : Implements an ACIA device for communication purposes
|
-- Purpose : Implements an ACIA device for communication purposes
|
-- between the FPGA processor and the Host computer through
|
-- between the FPGA processor and the Host computer through
|
-- a RS-232 communication protocol.
|
-- a RS-232 communication protocol.
|
--
|
--
|
-- Dependencies : ieee.std_logic_1164
|
-- Dependencies : ieee.std_logic_1164
|
-- ieee.numeric_std
|
-- ieee.numeric_std
|
-- ieee.std_logic_unsigned
|
-- ieee.std_logic_unsigned
|
--
|
--
|
--===========================================================================--
|
--===========================================================================--
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Revision list
|
-- Revision list
|
-- Version Author Date Changes
|
-- Version Author Date Changes
|
--
|
--
|
-- 0.1 Ovidiu Lupas 15 January 2000 New model
|
-- 0.1 Ovidiu Lupas 15 January 2000 New model
|
-- 2.0 Ovidiu Lupas 17 April 2000 unnecessary variable removed
|
-- 2.0 Ovidiu Lupas 17 April 2000 unnecessary variable removed
|
--
|
--
|
-- 3.0 John Kent 5 January 2003 added 6850 word format control
|
-- 3.0 John Kent 5 January 2003 added 6850 word format control
|
-- 3.1 John Kent 12 January 2003 Rearranged state machine code
|
-- 3.1 John Kent 12 January 2003 Rearranged state machine code
|
-- 3.2 John Kent 30 March 2003 Revamped State machine
|
-- 3.2 John Kent 30 March 2003 Revamped State machine
|
-- 3.3 John Kent 16 January 2004 Major re-write - added baud rate gen
|
-- 3.3 John Kent 16 January 2004 Major re-write - added baud rate gen
|
-- 4.0 John Kent 3 February 2007 renamed txunit to ACIA_TX
|
-- 4.0 John Kent 3 February 2007 renamed txunit to ACIA_TX
|
-- 4.1 John Kent 4 February 2007 Cleaned up transmiter
|
-- 4.1 John Kent 4 February 2007 Cleaned up transmiter
|
-- 4.2 John Kent 25 Februauy 2007 Modify sensitivity lists and
|
-- 4.2 John Kent 25 Februauy 2007 Modify sensitivity lists and
|
-- split Tx Baud Clock select
|
-- split Tx Baud Clock select
|
-- and edge detection.
|
-- and edge detection.
|
-- dilbert57@opencores.org
|
-- dilbert57@opencores.org
|
--
|
--
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
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;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Entity for the ACIA Transmitter
|
-- Entity for the ACIA Transmitter
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
entity ACIA_TX is
|
entity ACIA_TX is
|
port (
|
port (
|
Clk : in Std_Logic; -- CPU Clock signal
|
Clk : in Std_Logic; -- CPU Clock signal
|
TxRst : in Std_Logic; -- Reset input
|
TxRst : in Std_Logic; -- Reset input
|
TxWr : in Std_Logic; -- Load transmit data
|
TxWr : in Std_Logic; -- Load transmit data
|
TxDin : in Std_Logic_Vector(7 downto 0); -- Transmit data input.
|
TxDin : in Std_Logic_Vector(7 downto 0); -- Transmit data input.
|
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format
|
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format
|
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format
|
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format
|
TxClk : in Std_Logic; -- Enable input
|
TxClk : in Std_Logic; -- Enable input
|
TxDat : out Std_Logic; -- RS-232 data bit output
|
TxDat : out Std_Logic; -- RS-232 data bit output
|
TxEmp : out Std_Logic ); -- Tx buffer empty
|
TxEmp : out Std_Logic ); -- Tx buffer empty
|
end ACIA_TX; --================== End of entity ==============================--
|
end ACIA_TX; --================== End of entity ==============================--
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Architecture for ACIA_TX
|
-- Architecture for ACIA_TX
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
architecture rtl of ACIA_TX is
|
architecture rtl of ACIA_TX is
|
|
|
type TxStateType is ( Tx1Stop_State, TxStart_State,
|
type TxStateType is ( Tx1Stop_State, TxStart_State,
|
TxData_State, TxParity_State, Tx2Stop_State );
|
TxData_State, TxParity_State, Tx2Stop_State );
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Signals
|
-- Signals
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
signal TxClkDel : Std_Logic := '0'; -- Delayed Tx Input Clock
|
signal TxClkDel : Std_Logic := '0'; -- Delayed Tx Input Clock
|
signal TxClkEdge : Std_Logic := '0'; -- Tx Input Clock Edge pulse
|
signal TxClkEdge : Std_Logic := '0'; -- Tx Input Clock 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 TxBdDel : Std_Logic := '0'; -- Delayed Tx Baud Clock
|
signal TxBdDel : Std_Logic := '0'; -- Delayed Tx Baud Clock
|
signal TxBdEdge : Std_Logic := '0'; -- Tx Baud Clock Edge pulse
|
signal TxBdEdge : Std_Logic := '0'; -- Tx Baud Clock Edge pulse
|
signal TxBdClk : Std_Logic := '0'; -- Tx Baud Clock
|
signal TxBdClk : Std_Logic := '0'; -- Tx Baud Clock
|
signal TxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Transmit shift register
|
signal TxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Transmit shift register
|
signal TxParity : Std_logic := '0'; -- Parity Bit
|
signal TxParity : Std_logic := '0'; -- Parity Bit
|
signal TxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Data Bit Counter
|
signal TxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Data Bit Counter
|
signal TxReq : Std_Logic := '0'; -- Request Transmit
|
signal TxReq : Std_Logic := '0'; -- Request Transmit
|
signal TxAck : Std_Logic := '0'; -- Transmit Commenced
|
signal TxAck : Std_Logic := '0'; -- Transmit Commenced
|
signal TxState : TxStateType; -- Transmitter state
|
signal TxState : TxStateType; -- Transmitter state
|
|
|
begin
|
begin
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Transmit Clock Edge Detection
|
-- Transmit Clock Edge Detection
|
-- A falling edge will produce a one clock cycle pulse
|
-- A falling edge will produce a one clock cycle pulse
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
-- acia_tx_clock_edge : process(Clk, TxRst, TxClk, TxClkDel )
|
-- acia_tx_clock_edge : process(Clk, TxRst, TxClk, TxClkDel )
|
acia_tx_clock_edge : process( TxRst, Clk )
|
acia_tx_clock_edge : process( TxRst, Clk )
|
begin
|
begin
|
if TxRst = '1' then
|
if TxRst = '1' then
|
TxClkDel <= '0';
|
TxClkDel <= '0';
|
TxClkEdge <= '0';
|
TxClkEdge <= '0';
|
elsif Clk'event and Clk = '0' then
|
elsif Clk'event and Clk = '0' then
|
TxClkDel <= TxClk;
|
TxClkDel <= TxClk;
|
TxClkEdge <= TxClkDel and (not TxClk);
|
TxClkEdge <= TxClkDel and (not TxClk);
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Transmit Clock Divider
|
-- Transmit Clock Divider
|
-- Advance the count only on an input clock pulse
|
-- Advance the count only on an input clock pulse
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
-- acia_tx_clock_divide : process( Clk, TxRst, TxClkEdge, TxClkCnt )
|
-- acia_tx_clock_divide : process( Clk, TxRst, TxClkEdge, TxClkCnt )
|
acia_tx_clock_divide : process( TxRst, Clk )
|
acia_tx_clock_divide : process( TxRst, Clk )
|
begin
|
begin
|
if TxRst = '1' then
|
if TxRst = '1' then
|
TxClkCnt <= "000000";
|
TxClkCnt <= "000000";
|
elsif Clk'event and Clk = '0' then
|
elsif Clk'event and Clk = '0' then
|
if TxClkEdge = '1' then
|
if TxClkEdge = '1' then
|
TxClkCnt <= TxClkCnt + "000001";
|
TxClkCnt <= TxClkCnt + "000001";
|
end if; -- TxClkEdge
|
end if; -- TxClkEdge
|
end if; -- reset / clk
|
end if; -- reset / clk
|
end process;
|
end process;
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Transmit Baud Clock Selector
|
-- Transmit Baud Clock Selector
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
acia_tx_baud_clock_select : process( BdFmt, TxClk, TxClkCnt )
|
acia_tx_baud_clock_select : process( BdFmt, TxClk, TxClkCnt )
|
begin
|
begin
|
-- BdFmt
|
-- 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
|
case BdFmt is
|
when "00" => -- Div by 1
|
when "00" => -- Div by 1
|
TxBdClk <= TxClk;
|
TxBdClk <= TxClk;
|
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 => -- reset
|
when others => -- reset
|
TxBdClk <= '0';
|
TxBdClk <= '0';
|
end case;
|
end case;
|
end process;
|
end process;
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Transmit Baud Clock Edge Detector
|
-- Transmit Baud Clock Edge Detector
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
--
|
--
|
-- Generate one clock pulse strobe on falling edge of Tx Baud Clock
|
-- Generate one clock pulse strobe on falling edge of Tx Baud Clock
|
--
|
--
|
-- acia_tx_baud_clock_edge : process(Clk, TxRst, TxBdClk, TxBdDel )
|
-- acia_tx_baud_clock_edge : process(Clk, TxRst, TxBdClk, TxBdDel )
|
acia_tx_baud_clock_edge : process( TxRst, Clk )
|
acia_tx_baud_clock_edge : process( TxRst, Clk )
|
begin
|
begin
|
if TxRst = '1' then
|
if TxRst = '1' then
|
TxBdDel <= '0';
|
TxBdDel <= '0';
|
TxBdEdge <= '0';
|
TxBdEdge <= '0';
|
elsif Clk'event and Clk = '0' then
|
elsif Clk'event and Clk = '0' then
|
TxBdDel <= TxBdClk;
|
TxBdDel <= TxBdClk;
|
TxBdEdge <= (not TxBdClk) and TxBdDel;
|
TxBdEdge <= (not TxBdClk) and TxBdDel;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Transmitter activation process
|
-- Transmitter activation process
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- acia_tx_write : process(Clk, TxRst, TxWr, TxReq, TxAck )
|
-- acia_tx_write : process(Clk, TxRst, TxWr, TxReq, TxAck )
|
acia_tx_write : process( TxRst, Clk )
|
acia_tx_write : process( TxRst, Clk )
|
begin
|
begin
|
if TxRst = '1' then
|
if TxRst = '1' then
|
TxReq <= '0';
|
TxReq <= '0';
|
TxEmp <= '1';
|
TxEmp <= '1';
|
elsif Clk'event and Clk = '0' then
|
elsif Clk'event and Clk = '0' then
|
if TxWr = '1' then
|
if TxWr = '1' then
|
-- Write requests transmit
|
-- Write requests transmit
|
-- and clears the Empty Flag
|
-- and clears the Empty Flag
|
TxReq <= '1';
|
TxReq <= '1';
|
TxEmp <= '0';
|
TxEmp <= '0';
|
else
|
else
|
if (TxReq = '1') and (TxAck = '1') then
|
if (TxReq = '1') and (TxAck = '1') then
|
-- Once the transmitter is started
|
-- Once the transmitter is started
|
-- We can clear request.
|
-- We can clear request.
|
TxReq <= '0';
|
TxReq <= '0';
|
elsif (TxReq = '0') and (TxAck = '0') then
|
elsif (TxReq = '0') and (TxAck = '0') then
|
-- When the transmitter is finished
|
-- When the transmitter is finished
|
-- We can flag transmit empty
|
-- We can flag transmit empty
|
TxEmp <= '1';
|
TxEmp <= '1';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if; -- clk / reset
|
end if; -- clk / reset
|
end process;
|
end process;
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Implements the Tx unit
|
-- Implements the Tx unit
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- WdFmt - Bits[4..2]
|
-- WdFmt - Bits[4..2]
|
-- 0 0 0 - 7 data, even parity, 2 stop
|
-- 0 0 0 - 7 data, even parity, 2 stop
|
-- 0 0 1 - 7 data, odd parity, 2 stop
|
-- 0 0 1 - 7 data, odd parity, 2 stop
|
-- 0 1 0 - 7 data, even parity, 1 stop
|
-- 0 1 0 - 7 data, even parity, 1 stop
|
-- 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(TxRst, Clk, TxState, TxDin, WdFmt,
|
-- acia_tx_transmit : process(TxRst, Clk, TxState, TxDin, WdFmt,
|
-- TxShiftReg, TxBdEdge, TxParity, TxBitCount,
|
-- TxShiftReg, TxBdEdge, TxParity, TxBitCount,
|
-- TxReq, TxAck )
|
-- TxReq, TxAck )
|
acia_tx_transmit : process( TxRst, Clk )
|
acia_tx_transmit : process( TxRst, Clk )
|
begin
|
begin
|
if TxRst = '1' then
|
if TxRst = '1' then
|
TxDat <= '1';
|
TxDat <= '1';
|
TxShiftReg <= "00000000";
|
TxShiftReg <= "00000000";
|
TxParity <= '0';
|
TxParity <= '0';
|
TxBitCount <= "000";
|
TxBitCount <= "000";
|
TxAck <= '0';
|
TxAck <= '0';
|
TxState <= Tx1Stop_State;
|
TxState <= Tx1Stop_State;
|
elsif Clk'event and Clk = '0' then
|
elsif Clk'event and Clk = '0' then
|
if TxBdEdge = '1' then
|
if TxBdEdge = '1' then
|
case TxState is
|
case TxState is
|
when Tx1Stop_State => -- Last Stop bit state
|
when Tx1Stop_State => -- Last Stop bit state
|
TxDat <= '1';
|
TxDat <= '1';
|
TxAck <= '0'; -- Transmitter halted
|
TxAck <= '0'; -- Transmitter halted
|
if TxReq = '1' then
|
if TxReq = '1' then
|
TxState <= TxStart_State;
|
TxState <= TxStart_State;
|
end if;
|
end if;
|
|
|
when TxStart_State =>
|
when TxStart_State =>
|
TxDat <= '0'; -- Start bit
|
TxDat <= '0'; -- Start bit
|
TxShiftReg <= TxDin; -- Load Shift reg with Tx Data
|
TxShiftReg <= TxDin; -- Load Shift reg with Tx Data
|
TxParity <= '0';
|
TxParity <= '0';
|
if WdFmt(2) = '0' then
|
if WdFmt(2) = '0' then
|
TxBitCount <= "110"; -- 7 data + parity
|
TxBitCount <= "110"; -- 7 data + parity
|
else
|
else
|
TxBitCount <= "111"; -- 8 data
|
TxBitCount <= "111"; -- 8 data
|
end if;
|
end if;
|
TxAck <= '1'; -- Flag transmit started
|
TxAck <= '1'; -- Flag transmit started
|
TxState <= TxData_State;
|
TxState <= TxData_State;
|
|
|
when TxData_State =>
|
when TxData_State =>
|
TxDat <= TxShiftReg(0);
|
TxDat <= TxShiftReg(0);
|
TxShiftReg <= '1' & TxShiftReg(7 downto 1);
|
TxShiftReg <= '1' & TxShiftReg(7 downto 1);
|
TxParity <= TxParity xor TxShiftReg(0);
|
TxParity <= TxParity xor TxShiftReg(0);
|
TxBitCount <= TxBitCount - "001";
|
TxBitCount <= TxBitCount - "001";
|
if TxBitCount = "000" then
|
if TxBitCount = "000" then
|
if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
|
if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
|
if WdFmt(0) = '0' then -- 8 data bits
|
if WdFmt(0) = '0' then -- 8 data bits
|
TxState <= Tx2Stop_State; -- 2 stops
|
TxState <= Tx2Stop_State; -- 2 stops
|
else
|
else
|
TxState <= Tx1Stop_State; -- 1 stop
|
TxState <= Tx1Stop_State; -- 1 stop
|
end if;
|
end if;
|
else
|
else
|
TxState <= TxParity_State; -- parity
|
TxState <= TxParity_State; -- parity
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
when TxParity_State => -- 7/8 data + parity bit
|
when TxParity_State => -- 7/8 data + parity bit
|
if WdFmt(0) = '0' then
|
if WdFmt(0) = '0' then
|
TxDat <= not( TxParity ); -- even parity
|
TxDat <= not( TxParity ); -- even parity
|
else
|
else
|
TxDat <= TxParity; -- odd parity
|
TxDat <= TxParity; -- odd parity
|
end if;
|
end if;
|
if WdFmt(1) = '0' then
|
if WdFmt(1) = '0' then
|
TxState <= Tx2Stop_State; -- 2 stops
|
TxState <= Tx2Stop_State; -- 2 stops
|
else
|
else
|
TxState <= Tx1Stop_State; -- 1 stop
|
TxState <= Tx1Stop_State; -- 1 stop
|
end if;
|
end if;
|
|
|
when Tx2Stop_State => -- first of two stop bits
|
when Tx2Stop_State => -- first of two stop bits
|
TxDat <= '1';
|
TxDat <= '1';
|
TxState <= Tx1Stop_State;
|
TxState <= Tx1Stop_State;
|
|
|
when others => -- Undefined
|
when others => -- Undefined
|
TxDat <= '1';
|
TxDat <= '1';
|
TxState <= Tx1Stop_State;
|
TxState <= Tx1Stop_State;
|
|
|
end case; -- TxState
|
end case; -- TxState
|
|
|
end if; -- TxBdEdge
|
end if; -- TxBdEdge
|
end if; -- clk / reset
|
end if; -- clk / reset
|
|
|
end process;
|
end process;
|
|
|
|
|