| 1 |
19 |
dilbert57 |
--===========================================================================--
|
| 2 |
|
|
--
|
| 3 |
|
|
-- S Y N T H E Z I A B L E ACIA 6850 C O R E
|
| 4 |
|
|
--
|
| 5 |
|
|
-- www.OpenCores.Org - January 2007
|
| 6 |
|
|
-- This core adheres to the GNU public license
|
| 7 |
|
|
--
|
| 8 |
|
|
-- Design units : 6850 ACIA core for the System68/09
|
| 9 |
|
|
--
|
| 10 |
|
|
-- File name : ACIA_TX.vhd
|
| 11 |
|
|
--
|
| 12 |
|
|
-- Purpose : Implements an ACIA device for communication purposes
|
| 13 |
|
|
-- between the FPGA processor and the Host computer through
|
| 14 |
|
|
-- a RS-232 communication protocol.
|
| 15 |
|
|
--
|
| 16 |
|
|
-- Dependencies : ieee.std_logic_1164
|
| 17 |
|
|
-- ieee.numeric_std
|
| 18 |
|
|
-- ieee.std_logic_unsigned
|
| 19 |
|
|
--
|
| 20 |
|
|
--===========================================================================--
|
| 21 |
|
|
-------------------------------------------------------------------------------
|
| 22 |
|
|
-- Revision list
|
| 23 |
|
|
-- Version Author Date Changes
|
| 24 |
|
|
--
|
| 25 |
|
|
-- 0.1 Ovidiu Lupas 15 January 2000 New model
|
| 26 |
|
|
-- 2.0 Ovidiu Lupas 17 April 2000 unnecessary variable removed
|
| 27 |
|
|
--
|
| 28 |
|
|
-- 3.0 John Kent 5 January 2003 added 6850 word format control
|
| 29 |
|
|
-- 3.1 John Kent 12 January 2003 Rearranged state machine code
|
| 30 |
|
|
-- 3.2 John Kent 30 March 2003 Revamped State machine
|
| 31 |
|
|
-- 3.3 John Kent 16 January 2004 Major re-write - added baud rate gen
|
| 32 |
|
|
-- 4.0 John Kent 3 February 2007 renamed txunit to ACIA_TX
|
| 33 |
|
|
-- 4.1 John Kent 4 February 2007 Cleaned up transmiter
|
| 34 |
|
|
-- 4.2 John Kent 25 Februauy 2007 Modify sensitivity lists and
|
| 35 |
|
|
-- split Tx Baud Clock select
|
| 36 |
|
|
-- and edge detection.
|
| 37 |
|
|
-- dilbert57@opencores.org
|
| 38 |
|
|
--
|
| 39 |
|
|
-------------------------------------------------------------------------------
|
| 40 |
|
|
library ieee;
|
| 41 |
|
|
use ieee.std_logic_1164.all;
|
| 42 |
|
|
use ieee.numeric_std.all;
|
| 43 |
|
|
use ieee.std_logic_unsigned.all;
|
| 44 |
|
|
|
| 45 |
|
|
-------------------------------------------------------------------------------
|
| 46 |
|
|
-- Entity for the ACIA Transmitter
|
| 47 |
|
|
-------------------------------------------------------------------------------
|
| 48 |
|
|
entity ACIA_TX is
|
| 49 |
|
|
port (
|
| 50 |
|
|
Clk : in Std_Logic; -- CPU Clock signal
|
| 51 |
|
|
TxRst : in Std_Logic; -- Reset input
|
| 52 |
|
|
TxWr : in Std_Logic; -- Load transmit data
|
| 53 |
|
|
TxDin : in Std_Logic_Vector(7 downto 0); -- Transmit data input.
|
| 54 |
|
|
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format
|
| 55 |
|
|
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format
|
| 56 |
|
|
TxClk : in Std_Logic; -- Enable input
|
| 57 |
|
|
TxDat : out Std_Logic; -- RS-232 data bit output
|
| 58 |
|
|
TxEmp : out Std_Logic ); -- Tx buffer empty
|
| 59 |
|
|
end ACIA_TX; --================== End of entity ==============================--
|
| 60 |
|
|
|
| 61 |
|
|
-------------------------------------------------------------------------------
|
| 62 |
|
|
-- Architecture for ACIA_TX
|
| 63 |
|
|
-------------------------------------------------------------------------------
|
| 64 |
|
|
|
| 65 |
|
|
architecture rtl of ACIA_TX is
|
| 66 |
|
|
|
| 67 |
|
|
type TxStateType is ( Tx1Stop_State, TxStart_State,
|
| 68 |
|
|
TxData_State, TxParity_State, Tx2Stop_State );
|
| 69 |
|
|
|
| 70 |
|
|
-----------------------------------------------------------------------------
|
| 71 |
|
|
-- Signals
|
| 72 |
|
|
-----------------------------------------------------------------------------
|
| 73 |
|
|
|
| 74 |
|
|
signal TxClkDel : Std_Logic := '0'; -- Delayed Tx Input Clock
|
| 75 |
|
|
signal TxClkEdge : Std_Logic := '0'; -- Tx Input Clock Edge pulse
|
| 76 |
|
|
signal TxClkCnt : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Tx Baud Clock Counter
|
| 77 |
|
|
signal TxBdDel : Std_Logic := '0'; -- Delayed Tx Baud Clock
|
| 78 |
|
|
signal TxBdEdge : Std_Logic := '0'; -- Tx Baud Clock Edge pulse
|
| 79 |
|
|
signal TxBdClk : Std_Logic := '0'; -- Tx Baud Clock
|
| 80 |
|
|
signal TxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Transmit shift register
|
| 81 |
|
|
signal TxParity : Std_logic := '0'; -- Parity Bit
|
| 82 |
|
|
signal TxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Data Bit Counter
|
| 83 |
|
|
signal TxReq : Std_Logic := '0'; -- Request Transmit
|
| 84 |
|
|
signal TxAck : Std_Logic := '0'; -- Transmit Commenced
|
| 85 |
|
|
signal TxState : TxStateType; -- Transmitter state
|
| 86 |
|
|
|
| 87 |
|
|
begin
|
| 88 |
|
|
|
| 89 |
|
|
---------------------------------------------------------------------
|
| 90 |
|
|
-- Transmit Clock Edge Detection
|
| 91 |
|
|
-- A falling edge will produce a one clock cycle pulse
|
| 92 |
|
|
---------------------------------------------------------------------
|
| 93 |
|
|
|
| 94 |
|
|
-- acia_tx_clock_edge : process(Clk, TxRst, TxClk, TxClkDel )
|
| 95 |
|
|
acia_tx_clock_edge : process( TxRst, Clk )
|
| 96 |
|
|
begin
|
| 97 |
|
|
if TxRst = '1' then
|
| 98 |
|
|
TxClkDel <= '0';
|
| 99 |
|
|
TxClkEdge <= '0';
|
| 100 |
|
|
elsif Clk'event and Clk = '0' then
|
| 101 |
|
|
TxClkDel <= TxClk;
|
| 102 |
|
|
TxClkEdge <= TxClkDel and (not TxClk);
|
| 103 |
|
|
end if;
|
| 104 |
|
|
end process;
|
| 105 |
|
|
|
| 106 |
|
|
|
| 107 |
|
|
---------------------------------------------------------------------
|
| 108 |
|
|
-- Transmit Clock Divider
|
| 109 |
|
|
-- Advance the count only on an input clock pulse
|
| 110 |
|
|
---------------------------------------------------------------------
|
| 111 |
|
|
|
| 112 |
|
|
-- acia_tx_clock_divide : process( Clk, TxRst, TxClkEdge, TxClkCnt )
|
| 113 |
|
|
acia_tx_clock_divide : process( TxRst, Clk )
|
| 114 |
|
|
begin
|
| 115 |
|
|
if TxRst = '1' then
|
| 116 |
|
|
TxClkCnt <= "000000";
|
| 117 |
|
|
elsif Clk'event and Clk = '0' then
|
| 118 |
|
|
if TxClkEdge = '1' then
|
| 119 |
|
|
TxClkCnt <= TxClkCnt + "000001";
|
| 120 |
|
|
end if; -- TxClkEdge
|
| 121 |
|
|
end if; -- reset / clk
|
| 122 |
|
|
end process;
|
| 123 |
|
|
|
| 124 |
|
|
---------------------------------------------------------------------
|
| 125 |
|
|
-- Transmit Baud Clock Selector
|
| 126 |
|
|
---------------------------------------------------------------------
|
| 127 |
|
|
acia_tx_baud_clock_select : process( BdFmt, TxClk, TxClkCnt )
|
| 128 |
|
|
begin
|
| 129 |
|
|
-- BdFmt
|
| 130 |
|
|
-- 0 0 - Baud Clk divide by 1
|
| 131 |
|
|
-- 0 1 - Baud Clk divide by 16
|
| 132 |
|
|
-- 1 0 - Baud Clk divide by 64
|
| 133 |
|
|
-- 1 1 - reset
|
| 134 |
|
|
case BdFmt is
|
| 135 |
|
|
when "00" => -- Div by 1
|
| 136 |
|
|
TxBdClk <= TxClk;
|
| 137 |
|
|
when "01" => -- Div by 16
|
| 138 |
|
|
TxBdClk <= TxClkCnt(3);
|
| 139 |
|
|
when "10" => -- Div by 64
|
| 140 |
|
|
TxBdClk <= TxClkCnt(5);
|
| 141 |
|
|
when others => -- reset
|
| 142 |
|
|
TxBdClk <= '0';
|
| 143 |
|
|
end case;
|
| 144 |
|
|
end process;
|
| 145 |
|
|
|
| 146 |
|
|
---------------------------------------------------------------------
|
| 147 |
|
|
-- Transmit Baud Clock Edge Detector
|
| 148 |
|
|
---------------------------------------------------------------------
|
| 149 |
|
|
--
|
| 150 |
|
|
-- Generate one clock pulse strobe on falling edge of Tx Baud Clock
|
| 151 |
|
|
--
|
| 152 |
|
|
-- acia_tx_baud_clock_edge : process(Clk, TxRst, TxBdClk, TxBdDel )
|
| 153 |
|
|
acia_tx_baud_clock_edge : process( TxRst, Clk )
|
| 154 |
|
|
begin
|
| 155 |
|
|
if TxRst = '1' then
|
| 156 |
|
|
TxBdDel <= '0';
|
| 157 |
|
|
TxBdEdge <= '0';
|
| 158 |
|
|
elsif Clk'event and Clk = '0' then
|
| 159 |
|
|
TxBdDel <= TxBdClk;
|
| 160 |
|
|
TxBdEdge <= (not TxBdClk) and TxBdDel;
|
| 161 |
|
|
end if;
|
| 162 |
|
|
end process;
|
| 163 |
|
|
|
| 164 |
|
|
|
| 165 |
|
|
---------------------------------------------------------------------
|
| 166 |
|
|
-- Transmitter activation process
|
| 167 |
|
|
---------------------------------------------------------------------
|
| 168 |
|
|
-- acia_tx_write : process(Clk, TxRst, TxWr, TxReq, TxAck )
|
| 169 |
|
|
acia_tx_write : process( TxRst, Clk )
|
| 170 |
|
|
begin
|
| 171 |
|
|
if TxRst = '1' then
|
| 172 |
|
|
TxReq <= '0';
|
| 173 |
|
|
TxEmp <= '1';
|
| 174 |
|
|
elsif Clk'event and Clk = '0' then
|
| 175 |
|
|
if TxWr = '1' then
|
| 176 |
|
|
-- Write requests transmit
|
| 177 |
|
|
-- and clears the Empty Flag
|
| 178 |
|
|
TxReq <= '1';
|
| 179 |
|
|
TxEmp <= '0';
|
| 180 |
|
|
else
|
| 181 |
|
|
if (TxReq = '1') and (TxAck = '1') then
|
| 182 |
|
|
-- Once the transmitter is started
|
| 183 |
|
|
-- We can clear request.
|
| 184 |
|
|
TxReq <= '0';
|
| 185 |
|
|
elsif (TxReq = '0') and (TxAck = '0') then
|
| 186 |
|
|
-- When the transmitter is finished
|
| 187 |
|
|
-- We can flag transmit empty
|
| 188 |
|
|
TxEmp <= '1';
|
| 189 |
|
|
end if;
|
| 190 |
|
|
end if;
|
| 191 |
|
|
end if; -- clk / reset
|
| 192 |
|
|
end process;
|
| 193 |
|
|
|
| 194 |
|
|
-----------------------------------------------------------------------------
|
| 195 |
|
|
-- Implements the Tx unit
|
| 196 |
|
|
-----------------------------------------------------------------------------
|
| 197 |
|
|
-- WdFmt - Bits[4..2]
|
| 198 |
|
|
-- 0 0 0 - 7 data, even parity, 2 stop
|
| 199 |
|
|
-- 0 0 1 - 7 data, odd parity, 2 stop
|
| 200 |
|
|
-- 0 1 0 - 7 data, even parity, 1 stop
|
| 201 |
|
|
-- 0 1 1 - 7 data, odd parity, 1 stop
|
| 202 |
|
|
-- 1 0 0 - 8 data, no parity, 2 stop
|
| 203 |
|
|
-- 1 0 1 - 8 data, no parity, 1 stop
|
| 204 |
|
|
-- 1 1 0 - 8 data, even parity, 1 stop
|
| 205 |
|
|
-- 1 1 1 - 8 data, odd parity, 1 stop
|
| 206 |
|
|
-- acia_tx_transmit : process(TxRst, Clk, TxState, TxDin, WdFmt,
|
| 207 |
|
|
-- TxShiftReg, TxBdEdge, TxParity, TxBitCount,
|
| 208 |
|
|
-- TxReq, TxAck )
|
| 209 |
|
|
acia_tx_transmit : process( TxRst, Clk )
|
| 210 |
|
|
begin
|
| 211 |
|
|
if TxRst = '1' then
|
| 212 |
|
|
TxDat <= '1';
|
| 213 |
|
|
TxShiftReg <= "00000000";
|
| 214 |
|
|
TxParity <= '0';
|
| 215 |
|
|
TxBitCount <= "000";
|
| 216 |
|
|
TxAck <= '0';
|
| 217 |
|
|
TxState <= Tx1Stop_State;
|
| 218 |
|
|
elsif Clk'event and Clk = '0' then
|
| 219 |
|
|
if TxBdEdge = '1' then
|
| 220 |
|
|
case TxState is
|
| 221 |
|
|
when Tx1Stop_State => -- Last Stop bit state
|
| 222 |
|
|
TxDat <= '1';
|
| 223 |
|
|
TxAck <= '0'; -- Transmitter halted
|
| 224 |
|
|
if TxReq = '1' then
|
| 225 |
|
|
TxState <= TxStart_State;
|
| 226 |
|
|
end if;
|
| 227 |
|
|
|
| 228 |
|
|
when TxStart_State =>
|
| 229 |
|
|
TxDat <= '0'; -- Start bit
|
| 230 |
|
|
TxShiftReg <= TxDin; -- Load Shift reg with Tx Data
|
| 231 |
|
|
TxParity <= '0';
|
| 232 |
|
|
if WdFmt(2) = '0' then
|
| 233 |
|
|
TxBitCount <= "110"; -- 7 data + parity
|
| 234 |
|
|
else
|
| 235 |
|
|
TxBitCount <= "111"; -- 8 data
|
| 236 |
|
|
end if;
|
| 237 |
|
|
TxAck <= '1'; -- Flag transmit started
|
| 238 |
|
|
TxState <= TxData_State;
|
| 239 |
|
|
|
| 240 |
|
|
when TxData_State =>
|
| 241 |
|
|
TxDat <= TxShiftReg(0);
|
| 242 |
|
|
TxShiftReg <= '1' & TxShiftReg(7 downto 1);
|
| 243 |
|
|
TxParity <= TxParity xor TxShiftReg(0);
|
| 244 |
|
|
TxBitCount <= TxBitCount - "001";
|
| 245 |
|
|
if TxBitCount = "000" then
|
| 246 |
|
|
if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
|
| 247 |
|
|
if WdFmt(0) = '0' then -- 8 data bits
|
| 248 |
|
|
TxState <= Tx2Stop_State; -- 2 stops
|
| 249 |
|
|
else
|
| 250 |
|
|
TxState <= Tx1Stop_State; -- 1 stop
|
| 251 |
|
|
end if;
|
| 252 |
|
|
else
|
| 253 |
|
|
TxState <= TxParity_State; -- parity
|
| 254 |
|
|
end if;
|
| 255 |
|
|
end if;
|
| 256 |
|
|
|
| 257 |
|
|
when TxParity_State => -- 7/8 data + parity bit
|
| 258 |
|
|
if WdFmt(0) = '0' then
|
| 259 |
|
|
TxDat <= not( TxParity ); -- even parity
|
| 260 |
|
|
else
|
| 261 |
|
|
TxDat <= TxParity; -- odd parity
|
| 262 |
|
|
end if;
|
| 263 |
|
|
if WdFmt(1) = '0' then
|
| 264 |
|
|
TxState <= Tx2Stop_State; -- 2 stops
|
| 265 |
|
|
else
|
| 266 |
|
|
TxState <= Tx1Stop_State; -- 1 stop
|
| 267 |
|
|
end if;
|
| 268 |
|
|
|
| 269 |
|
|
when Tx2Stop_State => -- first of two stop bits
|
| 270 |
|
|
TxDat <= '1';
|
| 271 |
|
|
TxState <= Tx1Stop_State;
|
| 272 |
|
|
|
| 273 |
|
|
when others => -- Undefined
|
| 274 |
|
|
TxDat <= '1';
|
| 275 |
|
|
TxState <= Tx1Stop_State;
|
| 276 |
|
|
|
| 277 |
|
|
end case; -- TxState
|
| 278 |
|
|
|
| 279 |
|
|
end if; -- TxBdEdge
|
| 280 |
|
|
end if; -- clk / reset
|
| 281 |
|
|
|
| 282 |
|
|
end process;
|
| 283 |
|
|
|
| 284 |
|
|
end rtl; --=================== End of architecture ====================--
|