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