1 |
8 |
federico.a |
--
|
2 |
|
|
-- UART 16750
|
3 |
|
|
--
|
4 |
|
|
-- Author: Federico Aglietti, www.ipdesign.eu
|
5 |
|
|
-- Version: 2.0
|
6 |
|
|
-- Date: 30.08.2009
|
7 |
|
|
-- WishBone 8-bit bus compliant
|
8 |
|
|
--
|
9 |
|
|
-- Author: Sebastian Witt
|
10 |
|
|
-- Date: 29.01.2008
|
11 |
|
|
-- Version: 1.4
|
12 |
|
|
--
|
13 |
|
|
-- History: 1.0 - Initial version
|
14 |
|
|
-- 1.1 - THR empty interrupt register connected to RST
|
15 |
|
|
-- 1.2 - Registered outputs
|
16 |
|
|
-- 1.3 - Automatic flow control
|
17 |
|
|
-- 1.4 - De-assert IIR FIFO64 when FIFO is disabled
|
18 |
|
|
--
|
19 |
|
|
--
|
20 |
|
|
-- This code is free software; you can redistribute it and/or
|
21 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
22 |
|
|
-- License as published by the Free Software Foundation; either
|
23 |
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
24 |
|
|
--
|
25 |
|
|
-- This code is distributed in the hope that it will be useful,
|
26 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
27 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
28 |
|
|
-- Lesser General Public License for more details.
|
29 |
|
|
--
|
30 |
|
|
-- You should have received a copy of the GNU Lesser General Public
|
31 |
|
|
-- License along with this library; if not, write to the
|
32 |
|
|
-- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
33 |
|
|
-- Boston, MA 02111-1307 USA
|
34 |
|
|
--
|
35 |
|
|
|
36 |
|
|
LIBRARY IEEE;
|
37 |
|
|
USE IEEE.std_logic_1164.all;
|
38 |
|
|
USE IEEE.numeric_std.all;
|
39 |
|
|
|
40 |
|
|
-- Serial UART
|
41 |
|
|
entity uart_16750 is
|
42 |
|
|
port (
|
43 |
|
|
CLK : in std_logic; -- Clock
|
44 |
|
|
RST : in std_logic; -- Reset
|
45 |
|
|
BAUDCE : in std_logic; -- Baudrate generator clock enable
|
46 |
|
|
WB_CYC : in std_logic; -- Chip select
|
47 |
|
|
WB_STB : in std_logic; -- Chip select
|
48 |
|
|
WB_WE : in std_logic; -- Write/NotRead to/from UART
|
49 |
|
|
WB_ADR : in std_logic_vector(31 downto 0); -- Address input
|
50 |
|
|
WB_DIN : in std_logic_vector(7 downto 0); -- Data bus input
|
51 |
|
|
WB_DOUT : out std_logic_vector(7 downto 0); -- Data bus output
|
52 |
|
|
WB_ACK : out std_logic; -- Transaction ACK
|
53 |
|
|
INT : out std_logic; -- Interrupt output
|
54 |
|
|
OUT1N : out std_logic; -- Output 1
|
55 |
|
|
OUT2N : out std_logic; -- Output 2
|
56 |
|
|
RCLK : in std_logic; -- Receiver clock (16x baudrate)
|
57 |
|
|
BAUDOUTN : out std_logic; -- Baudrate generator output (16x baudrate)
|
58 |
|
|
RTSN : out std_logic; -- RTS output
|
59 |
|
|
DTRN : out std_logic; -- DTR output
|
60 |
|
|
CTSN : in std_logic; -- CTS input
|
61 |
|
|
DSRN : in std_logic; -- DSR input
|
62 |
|
|
DCDN : in std_logic; -- DCD input
|
63 |
|
|
RIN : in std_logic; -- RI input
|
64 |
|
|
SIN : in std_logic; -- Receiver input
|
65 |
|
|
SOUT : out std_logic -- Transmitter output
|
66 |
|
|
);
|
67 |
|
|
end uart_16750;
|
68 |
|
|
|
69 |
|
|
architecture rtl of uart_16750 is
|
70 |
|
|
-- UART transmitter
|
71 |
|
|
component uart_transmitter is
|
72 |
|
|
port (
|
73 |
|
|
CLK : in std_logic; -- Clock
|
74 |
|
|
RST : in std_logic; -- Reset
|
75 |
|
|
TXCLK : in std_logic; -- Transmitter clock (2x baudrate)
|
76 |
|
|
TXSTART : in std_logic; -- Start transmitter
|
77 |
|
|
CLEAR : in std_logic; -- Clear transmitter state
|
78 |
|
|
WLS : in std_logic_vector(1 downto 0); -- Word length select
|
79 |
|
|
STB : in std_logic; -- Number of stop bits
|
80 |
|
|
PEN : in std_logic; -- Parity enable
|
81 |
|
|
EPS : in std_logic; -- Even parity select
|
82 |
|
|
SP : in std_logic; -- Stick parity
|
83 |
|
|
BC : in std_logic; -- Break control
|
84 |
|
|
DIN : in std_logic_vector(7 downto 0); -- Input data
|
85 |
|
|
TXFINISHED : out std_logic; -- Transmitter operation finished
|
86 |
|
|
SOUT : out std_logic -- Transmitter output
|
87 |
|
|
);
|
88 |
|
|
end component;
|
89 |
|
|
-- UART receiver
|
90 |
|
|
component uart_receiver is
|
91 |
|
|
port (
|
92 |
|
|
CLK : in std_logic; -- Clock
|
93 |
|
|
RST : in std_logic; -- Reset
|
94 |
|
|
RXCLK : in std_logic; -- Receiver clock (16x baudrate)
|
95 |
|
|
RXCLEAR : in std_logic; -- Reset receiver state
|
96 |
|
|
WLS : in std_logic_vector(1 downto 0); -- Word length select
|
97 |
|
|
STB : in std_logic; -- Number of stop bits
|
98 |
|
|
PEN : in std_logic; -- Parity enable
|
99 |
|
|
EPS : in std_logic; -- Even parity select
|
100 |
|
|
SP : in std_logic; -- Stick parity
|
101 |
|
|
SIN : in std_logic; -- Receiver input
|
102 |
|
|
PE : out std_logic; -- Parity error
|
103 |
|
|
FE : out std_logic; -- Framing error
|
104 |
|
|
BI : out std_logic; -- Break interrupt
|
105 |
|
|
DOUT : out std_logic_vector(7 downto 0); -- Output data
|
106 |
|
|
RXFINISHED : out std_logic -- Receiver operation finished
|
107 |
|
|
);
|
108 |
|
|
end component;
|
109 |
|
|
-- UART interrupt control
|
110 |
|
|
component uart_interrupt is
|
111 |
|
|
port (
|
112 |
|
|
CLK : in std_logic; -- Clock
|
113 |
|
|
RST : in std_logic; -- Reset
|
114 |
|
|
IER : in std_logic_vector(3 downto 0); -- IER 3:0
|
115 |
|
|
LSR : in std_logic_vector(4 downto 0); -- LSR 4:0
|
116 |
|
|
THI : in std_logic; -- Transmitter holding register empty interrupt
|
117 |
|
|
RDA : in std_logic; -- Receiver data available
|
118 |
|
|
CTI : in std_logic; -- Character timeout indication
|
119 |
|
|
AFE : in std_logic; -- Automatic flow control enable
|
120 |
|
|
MSR : in std_logic_vector(3 downto 0); -- MSR 3:0
|
121 |
|
|
IIR : out std_logic_vector(3 downto 0); -- IIR 3:0
|
122 |
|
|
INT : out std_logic -- Interrupt
|
123 |
|
|
);
|
124 |
|
|
end component;
|
125 |
|
|
-- UART baudrate generator
|
126 |
|
|
component uart_baudgen is
|
127 |
|
|
port (
|
128 |
|
|
CLK : in std_logic; -- Clock
|
129 |
|
|
RST : in std_logic; -- Reset
|
130 |
|
|
CE : in std_logic; -- Clock enable
|
131 |
|
|
CLEAR : in std_logic; -- Reset generator (synchronization)
|
132 |
|
|
DIVIDER : in std_logic_vector(15 downto 0); -- Clock divider
|
133 |
|
|
BAUDTICK : out std_logic -- 16xBaudrate tick
|
134 |
|
|
);
|
135 |
|
|
end component;
|
136 |
|
|
-- UART FIFO
|
137 |
|
|
component slib_fifo is
|
138 |
|
|
generic (
|
139 |
|
|
WIDTH : integer := 8; -- FIFO width
|
140 |
|
|
SIZE_E : integer := 6 -- FIFO size (2^SIZE_E)
|
141 |
|
|
);
|
142 |
|
|
port (
|
143 |
|
|
CLK : in std_logic; -- Clock
|
144 |
|
|
RST : in std_logic; -- Reset
|
145 |
|
|
CLEAR : in std_logic; -- Clear FIFO
|
146 |
|
|
WRITE : in std_logic; -- Write to FIFO
|
147 |
|
|
READ : in std_logic; -- Read from FIFO
|
148 |
|
|
D : in std_logic_vector(WIDTH-1 downto 0); -- FIFO input
|
149 |
|
|
Q : out std_logic_vector(WIDTH-1 downto 0); -- FIFO output
|
150 |
|
|
EMPTY : out std_logic; -- FIFO is empty
|
151 |
|
|
FULL : out std_logic; -- FIFO is full
|
152 |
|
|
USAGE : out std_logic_vector(SIZE_E-1 downto 0) -- FIFO usage
|
153 |
|
|
);
|
154 |
|
|
end component;
|
155 |
|
|
-- Edge detect
|
156 |
|
|
component slib_edge_detect is
|
157 |
|
|
port (
|
158 |
|
|
CLK : in std_logic; -- Clock
|
159 |
|
|
RST : in std_logic; -- Reset
|
160 |
|
|
D : in std_logic; -- Signal input
|
161 |
|
|
RE : out std_logic; -- Rising edge detected
|
162 |
|
|
FE : out std_logic -- Falling edge detected
|
163 |
|
|
);
|
164 |
|
|
end component;
|
165 |
|
|
-- Input synchronization
|
166 |
|
|
component slib_input_sync is
|
167 |
|
|
port (
|
168 |
|
|
CLK : in std_logic; -- Clock
|
169 |
|
|
RST : in std_logic; -- Reset
|
170 |
|
|
D : in std_logic; -- Signal input
|
171 |
|
|
Q : out std_logic -- Signal output
|
172 |
|
|
);
|
173 |
|
|
end component;
|
174 |
|
|
-- Input filter
|
175 |
|
|
component slib_input_filter is
|
176 |
|
|
generic (
|
177 |
|
|
SIZE : natural := 4 -- Filter width
|
178 |
|
|
);
|
179 |
|
|
port (
|
180 |
|
|
CLK : in std_logic; -- Clock
|
181 |
|
|
RST : in std_logic; -- Reset
|
182 |
|
|
CE : in std_logic; -- Clock enable
|
183 |
|
|
D : in std_logic; -- Signal input
|
184 |
|
|
Q : out std_logic -- Signal output
|
185 |
|
|
);
|
186 |
|
|
end component;
|
187 |
|
|
-- Clock enable generation
|
188 |
|
|
component slib_clock_div is
|
189 |
|
|
generic (
|
190 |
|
|
RATIO : integer := 8 -- Clock divider ratio
|
191 |
|
|
);
|
192 |
|
|
port (
|
193 |
|
|
CLK : in std_logic; -- Clock
|
194 |
|
|
RST : in std_logic; -- Reset
|
195 |
|
|
CE : in std_logic; -- Clock enable input
|
196 |
|
|
Q : out std_logic -- New clock enable output
|
197 |
|
|
);
|
198 |
|
|
end component;
|
199 |
|
|
|
200 |
|
|
-- Global device signals
|
201 |
|
|
signal iWriteFE : std_logic; -- Write falling edge
|
202 |
|
|
signal iReadFE : std_logic; -- Read falling edge
|
203 |
|
|
signal iWrite : std_logic; -- Write to UART
|
204 |
|
|
signal iRead : std_logic; -- Read from UART
|
205 |
|
|
signal iA : std_logic_vector(2 downto 0); -- UART register address
|
206 |
|
|
signal iDIN : std_logic_vector(7 downto 0); -- UART data input
|
207 |
|
|
|
208 |
|
|
-- UART registers read/write signals
|
209 |
|
|
signal iRBRRead : std_logic; -- Read from RBR
|
210 |
|
|
signal iTHRWrite : std_logic; -- Write to THR
|
211 |
|
|
signal iDLLWrite : std_logic; -- Write to DLL
|
212 |
|
|
signal iDLMWrite : std_logic; -- Write to DLM
|
213 |
|
|
signal iIERWrite : std_logic; -- Write to IER
|
214 |
|
|
signal iIIRRead : std_logic; -- Read from IIR
|
215 |
|
|
signal iFCRWrite : std_logic; -- Write to FCR
|
216 |
|
|
signal iLCRWrite : std_logic; -- Write to LCR
|
217 |
|
|
signal iMCRWrite : std_logic; -- Write to MCR
|
218 |
|
|
signal iLSRRead : std_logic; -- Read from LSR
|
219 |
|
|
signal iMSRRead : std_logic; -- Read from MSR
|
220 |
|
|
signal iSCRWrite : std_logic; -- Write to SCR
|
221 |
|
|
|
222 |
|
|
-- UART registers
|
223 |
|
|
signal iTSR : std_logic_vector(7 downto 0); -- Transmitter holding register
|
224 |
|
|
signal iRBR : std_logic_vector(7 downto 0); -- Receiver buffer register
|
225 |
|
|
signal iDLL : std_logic_vector(7 downto 0); -- Divisor latch LSB
|
226 |
|
|
signal iDLM : std_logic_vector(7 downto 0); -- Divisor latch MSB
|
227 |
|
|
signal iIER : std_logic_vector(7 downto 0); -- Interrupt enable register
|
228 |
|
|
signal iIIR : std_logic_vector(7 downto 0); -- Interrupt identification register
|
229 |
|
|
signal iFCR : std_logic_vector(7 downto 0); -- FIFO control register
|
230 |
|
|
signal iLCR : std_logic_vector(7 downto 0); -- Line control register
|
231 |
|
|
signal iMCR : std_logic_vector(7 downto 0); -- Modem control register
|
232 |
|
|
signal iLSR : std_logic_vector(7 downto 0); -- Line status register
|
233 |
|
|
signal iMSR : std_logic_vector(7 downto 0); -- Modem status register
|
234 |
|
|
signal iSCR : std_logic_vector(7 downto 0); -- Scratch register
|
235 |
|
|
|
236 |
|
|
-- IER register signals
|
237 |
|
|
signal iIER_ERBI : std_logic; -- IER: Enable received data available interrupt
|
238 |
|
|
signal iIER_ETBEI : std_logic; -- IER: Enable transmitter holding register empty interrupt
|
239 |
|
|
signal iIER_ELSI : std_logic; -- IER: Enable receiver line status interrupt
|
240 |
|
|
signal iIER_EDSSI : std_logic; -- IER: Enable modem status interrupt
|
241 |
|
|
|
242 |
|
|
-- IIR register signals
|
243 |
|
|
signal iIIR_PI : std_logic; -- IIR: Pending interrupt
|
244 |
|
|
signal iIIR_ID0 : std_logic; -- IIR: Interrupt ID0
|
245 |
|
|
signal iIIR_ID1 : std_logic; -- IIR: Interrupt ID1
|
246 |
|
|
signal iIIR_ID2 : std_logic; -- IIR: Interrupt ID2
|
247 |
|
|
signal iIIR_FIFO64 : std_logic; -- IIR: 64 byte FIFO enabled
|
248 |
|
|
|
249 |
|
|
-- FCR register signals
|
250 |
|
|
signal iFCR_FIFOEnable : std_logic; -- FCR: FIFO enable
|
251 |
|
|
signal iFCR_RXFIFOReset : std_logic; -- FCR: Receiver FIFO reset
|
252 |
|
|
signal iFCR_TXFIFOReset : std_logic; -- FCR: Transmitter FIFO reset
|
253 |
|
|
signal iFCR_DMAMode : std_logic; -- FCR: DMA mode select
|
254 |
|
|
signal iFCR_FIFO64E : std_logic; -- FCR: 64 byte FIFO enable
|
255 |
|
|
signal iFCR_RXTrigger : std_logic_vector(1 downto 0); -- FCR: Receiver trigger
|
256 |
|
|
|
257 |
|
|
-- LCR register signals
|
258 |
|
|
signal iLCR_WLS : std_logic_vector(1 downto 0); -- LCR: Word length select
|
259 |
|
|
signal iLCR_STB : std_logic; -- LCR: Number of stop bits
|
260 |
|
|
signal iLCR_PEN : std_logic; -- LCR: Parity enable
|
261 |
|
|
signal iLCR_EPS : std_logic; -- LCR: Even parity select
|
262 |
|
|
signal iLCR_SP : std_logic; -- LCR: Sticky parity
|
263 |
|
|
signal iLCR_BC : std_logic; -- LCR: Break control
|
264 |
|
|
signal iLCR_DLAB : std_logic; -- LCR: Divisor latch access bit
|
265 |
|
|
|
266 |
|
|
-- MCR register signals
|
267 |
|
|
signal iMCR_DTR : std_logic; -- MCR: Data terminal ready
|
268 |
|
|
signal iMCR_RTS : std_logic; -- MCR: Request to send
|
269 |
|
|
signal iMCR_OUT1 : std_logic; -- MCR: OUT1
|
270 |
|
|
signal iMCR_OUT2 : std_logic; -- MCR: OUT2
|
271 |
|
|
signal iMCR_LOOP : std_logic; -- MCR: Loop
|
272 |
|
|
signal iMCR_AFE : std_logic; -- MCR: Auto flow control enable
|
273 |
|
|
|
274 |
|
|
-- LSR register signals
|
275 |
|
|
signal iLSR_DR : std_logic; -- LSR: Data ready
|
276 |
|
|
signal iLSR_OE : std_logic; -- LSR: Overrun error
|
277 |
|
|
signal iLSR_PE : std_logic; -- LSR: Parity error
|
278 |
|
|
signal iLSR_FE : std_logic; -- LSR: Framing error
|
279 |
|
|
signal iLSR_BI : std_logic; -- LSR: Break Interrupt
|
280 |
|
|
signal iLSR_THRE : std_logic; -- LSR: Transmitter holding register empty
|
281 |
|
|
signal iLSR_TEMT : std_logic; -- LSR: Transmitter empty
|
282 |
|
|
signal iLSR_FIFOERR : std_logic; -- LSR: Error in receiver FIFO
|
283 |
|
|
|
284 |
|
|
-- MSR register signals
|
285 |
|
|
signal iMSR_dCTS : std_logic; -- MSR: Delta CTS
|
286 |
|
|
signal iMSR_dDSR : std_logic; -- MSR: Delta DSR
|
287 |
|
|
signal iMSR_TERI : std_logic; -- MSR: Trailing edge ring indicator
|
288 |
|
|
signal iMSR_dDCD : std_logic; -- MSR: Delta DCD
|
289 |
|
|
signal iMSR_CTS : std_logic; -- MSR: CTS
|
290 |
|
|
signal iMSR_DSR : std_logic; -- MSR: DSR
|
291 |
|
|
signal iMSR_RI : std_logic; -- MSR: RI
|
292 |
|
|
signal iMSR_DCD : std_logic; -- MSR: DCD
|
293 |
|
|
|
294 |
|
|
-- UART MSR signals
|
295 |
|
|
signal iCTSNs : std_logic; -- Synchronized CTSN input
|
296 |
|
|
signal iDSRNs : std_logic; -- Synchronized DSRN input
|
297 |
|
|
signal iDCDNs : std_logic; -- Synchronized DCDN input
|
298 |
|
|
signal iRINs : std_logic; -- Synchronized RIN input
|
299 |
|
|
signal iCTSn : std_logic; -- Filtered CTSN input
|
300 |
|
|
signal iDSRn : std_logic; -- Filtered DSRN input
|
301 |
|
|
signal iDCDn : std_logic; -- Filtered DCDN input
|
302 |
|
|
signal iRIn : std_logic; -- Filtered RIN input
|
303 |
|
|
signal iCTSnRE : std_logic; -- CTSn rising edge
|
304 |
|
|
signal iCTSnFE : std_logic; -- CTSn falling edge
|
305 |
|
|
signal iDSRnRE : std_logic; -- DSRn rising edge
|
306 |
|
|
signal iDSRnFE : std_logic; -- DSRn falling edge
|
307 |
|
|
signal iDCDnRE : std_logic; -- DCDn rising edge
|
308 |
|
|
signal iDCDnFE : std_logic; -- DCDn falling edge
|
309 |
|
|
signal iRInRE : std_logic; -- RIn rising edge
|
310 |
|
|
signal iRInFE : std_logic; -- RIn falling edge
|
311 |
|
|
|
312 |
|
|
-- UART baudrate generation signals
|
313 |
|
|
signal iBaudgenDiv : std_logic_vector(15 downto 0); -- Baudrate divider
|
314 |
|
|
signal iBaudtick16x : std_logic; -- 16x Baudrate output from baudrate generator
|
315 |
|
|
signal iBaudtick2x : std_logic; -- 2x Baudrate for transmitter
|
316 |
|
|
signal iRCLK : std_logic; -- 16x Baudrate for receiver
|
317 |
|
|
|
318 |
|
|
-- UART FIFO signals
|
319 |
|
|
signal iTXFIFOClear : std_logic; -- Clear TX FIFO
|
320 |
|
|
signal iTXFIFOWrite : std_logic; -- Write to TX FIFO
|
321 |
|
|
signal iTXFIFORead : std_logic; -- Read from TX FIFO
|
322 |
|
|
signal iTXFIFOEmpty : std_logic; -- TX FIFO is empty
|
323 |
|
|
signal iTXFIFOFull : std_logic; -- TX FIFO is full
|
324 |
|
|
signal iTXFIFO16Full : std_logic; -- TX FIFO 16 byte mode is full
|
325 |
|
|
signal iTXFIFO64Full : std_logic; -- TX FIFO 64 byte mode is full
|
326 |
|
|
signal iTXFIFOUsage : std_logic_vector(5 downto 0); -- RX FIFO usage
|
327 |
|
|
signal iTXFIFOQ : std_logic_vector(7 downto 0); -- TX FIFO output
|
328 |
|
|
signal iRXFIFOClear : std_logic; -- Clear RX FIFO
|
329 |
|
|
signal iRXFIFOWrite : std_logic; -- Write to RX FIFO
|
330 |
|
|
signal iRXFIFORead : std_logic; -- Read from RX FIFO
|
331 |
|
|
signal iRXFIFOEmpty : std_logic; -- RX FIFO is empty
|
332 |
|
|
signal iRXFIFOFull : std_logic; -- RX FIFO is full
|
333 |
|
|
signal iRXFIFO16Full : std_logic; -- RX FIFO 16 byte mode is full
|
334 |
|
|
signal iRXFIFO64Full : std_logic; -- RX FIFO 64 byte mode is full
|
335 |
|
|
signal iRXFIFOD : std_logic_vector(10 downto 0); -- RX FIFO input
|
336 |
|
|
signal iRXFIFOQ : std_logic_vector(10 downto 0); -- RX FIFO output
|
337 |
|
|
signal iRXFIFOUsage : std_logic_vector(5 downto 0); -- RX FIFO usage
|
338 |
|
|
signal iRXFIFOTrigger : std_logic; -- FIFO trigger level reached
|
339 |
|
|
signal iRXFIFO16Trigger : std_logic; -- FIFO 16 byte mode trigger level reached
|
340 |
|
|
signal iRXFIFO64Trigger : std_logic; -- FIFO 64 byte mode trigger level reached
|
341 |
|
|
signal iRXFIFOPE : std_logic; -- Parity error from FIFO
|
342 |
|
|
signal iRXFIFOFE : std_logic; -- Frame error from FIFO
|
343 |
|
|
signal iRXFIFOBI : std_logic; -- Break interrupt from FIFO
|
344 |
|
|
|
345 |
|
|
-- UART transmitter signals
|
346 |
|
|
signal iSOUT : std_logic; -- Transmitter output
|
347 |
|
|
signal iTXStart : std_logic; -- Start transmitter
|
348 |
|
|
signal iTXClear : std_logic; -- Clear transmitter status
|
349 |
|
|
signal iTXFinished : std_logic; -- TX finished, character transmitted
|
350 |
|
|
signal iTXRunning : std_logic; -- TX in progress
|
351 |
|
|
|
352 |
|
|
-- UART receiver signals
|
353 |
|
|
signal iSINr : std_logic; -- Synchronized SIN input
|
354 |
|
|
signal iSIN : std_logic; -- Receiver input
|
355 |
|
|
signal iRXFinished : std_logic; -- RX finished, character received
|
356 |
|
|
signal iRXClear : std_logic; -- Clear receiver status
|
357 |
|
|
signal iRXData : std_logic_vector(7 downto 0); -- RX data
|
358 |
|
|
signal iRXPE : std_logic; -- RX parity error
|
359 |
|
|
signal iRXFE : std_logic; -- RX frame error
|
360 |
|
|
signal iRXBI : std_logic; -- RX break interrupt
|
361 |
|
|
|
362 |
|
|
-- UART control signals
|
363 |
|
|
signal iFERE : std_logic; -- Frame error detected
|
364 |
|
|
signal iPERE : std_logic; -- Parity error detected
|
365 |
|
|
signal iBIRE : std_logic; -- Break interrupt detected
|
366 |
|
|
signal iFECounter : integer range 0 to 64; -- FIFO error counter
|
367 |
|
|
signal iFEIncrement : std_logic; -- FIFO error counter increment
|
368 |
|
|
signal iFEDecrement : std_logic; -- FIFO error counter decrement
|
369 |
|
|
signal iRDAInterrupt : std_logic; -- Receiver data available interrupt (DA or FIFO trigger level)
|
370 |
|
|
signal iTimeoutCount : unsigned(5 downto 0); -- Character timeout counter (FIFO mode)
|
371 |
|
|
signal iCharTimeout : std_logic; -- Character timeout indication (FIFO mode)
|
372 |
|
|
signal iLSR_THRERE : std_logic; -- LSR THRE rising edge for interrupt generation
|
373 |
|
|
signal iTHRInterrupt : std_logic; -- Transmitter holding register empty interrupt
|
374 |
|
|
signal iTXEnable : std_logic; -- Transmitter enable signal
|
375 |
|
|
signal iRTS : std_logic; -- Internal RTS signal with/without automatic flow control
|
376 |
|
|
|
377 |
|
|
signal WB_ACK_R : std_logic;
|
378 |
|
|
|
379 |
|
|
|
380 |
|
|
begin
|
381 |
|
|
|
382 |
|
|
|
383 |
|
|
iWrite <= '1' when WB_CYC = '1' and WB_STB = '1' and WB_WE = '1' and WB_ACK_r='1' else '0';
|
384 |
|
|
iRead <= '1' when WB_CYC = '1' and WB_STB = '1' and WB_WE = '0' and WB_ACK_r='1' else '0';
|
385 |
|
|
|
386 |
|
|
-- UART registers read/write signals
|
387 |
|
|
iRBRRead <= '1' when iRead = '1' and iA = "000" and iLCR_DLAB = '0' else '0';
|
388 |
|
|
iTHRWrite <= '1' when iWrite = '1' and iA = "000" and iLCR_DLAB = '0' else '0';
|
389 |
|
|
iDLLWrite <= '1' when iWrite = '1' and iA = "000" and iLCR_DLAB = '1' else '0';
|
390 |
|
|
iDLMWrite <= '1' when iWrite = '1' and iA = "001" and iLCR_DLAB = '1' else '0';
|
391 |
|
|
iIERWrite <= '1' when iWrite = '1' and iA = "001" and iLCR_DLAB = '0' else '0';
|
392 |
|
|
iIIRRead <= '1' when iRead = '1' and iA = "010" else '0';
|
393 |
|
|
iFCRWrite <= '1' when iWrite = '1' and iA = "010" else '0';
|
394 |
|
|
iLCRWrite <= '1' when iWrite = '1' and iA = "011" else '0';
|
395 |
|
|
iMCRWrite <= '1' when iWrite = '1' and iA = "100" else '0';
|
396 |
|
|
iLSRRead <= '1' when iRead = '1' and iA = "101" else '0';
|
397 |
|
|
iMSRRead <= '1' when iRead = '1' and iA = "110" else '0';
|
398 |
|
|
iSCRWrite <= '1' when iWrite = '1' and iA = "111" else '0';
|
399 |
|
|
|
400 |
|
|
-- Async. input synchronization
|
401 |
|
|
UART_IS_SIN: slib_input_sync port map (CLK, RST, SIN, iSINr);
|
402 |
|
|
UART_IS_CTS: slib_input_sync port map (CLK, RST, CTSN, iCTSNs);
|
403 |
|
|
UART_IS_DSR: slib_input_sync port map (CLK, RST, DSRN, iDSRNs);
|
404 |
|
|
UART_IS_DCD: slib_input_sync port map (CLK, RST, DCDN, iDCDNs);
|
405 |
|
|
UART_IS_RI: slib_input_sync port map (CLK, RST, RIN, iRINs);
|
406 |
|
|
|
407 |
|
|
-- Input filter for UART control signals
|
408 |
|
|
UART_IF_CTS: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iCTSNs, iCTSn);
|
409 |
|
|
UART_IF_DSR: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iDSRNs, iDSRn);
|
410 |
|
|
UART_IF_DCD: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iDCDNs, iDCDn);
|
411 |
|
|
UART_IF_RI: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iRINs, iRIn);
|
412 |
|
|
|
413 |
|
|
|
414 |
|
|
-- Global device signals
|
415 |
|
|
iA(2 downto 0) <= WB_ADR(2 downto 0);
|
416 |
|
|
iDIN <= WB_DIN;
|
417 |
|
|
|
418 |
|
|
-- WB_ACK <= WB_CYC and WB_STB after 1 ns;
|
419 |
|
|
WB_ACK <= WB_ACK_r;
|
420 |
|
|
|
421 |
|
|
WB_ACK_PR: process (CLK, RST)
|
422 |
|
|
begin
|
423 |
|
|
if (RST = '1') then
|
424 |
|
|
WB_ACK_r <= '1';
|
425 |
|
|
elsif (CLK'event and CLK = '1') then
|
426 |
|
|
if (WB_ACK_r = '1') then
|
427 |
|
|
WB_ACK_r <= '0';
|
428 |
|
|
elsif (WB_CYC='1' and WB_STB='1') then
|
429 |
|
|
WB_ACK_r <= '1';
|
430 |
|
|
end if;
|
431 |
|
|
end if;
|
432 |
|
|
end process;
|
433 |
|
|
|
434 |
|
|
|
435 |
|
|
-- Divisor latch register
|
436 |
|
|
UART_DLR: process (CLK, RST)
|
437 |
|
|
begin
|
438 |
|
|
if (RST = '1') then
|
439 |
|
|
iDLL <= (others => '0');
|
440 |
|
|
iDLM <= (others => '0');
|
441 |
|
|
elsif (CLK'event and CLK = '1') then
|
442 |
|
|
if (iDLLWrite = '1') then
|
443 |
|
|
iDLL <= iDIN;
|
444 |
|
|
end if;
|
445 |
|
|
if (iDLMWrite = '1') then
|
446 |
|
|
iDLM <= iDIN;
|
447 |
|
|
end if;
|
448 |
|
|
end if;
|
449 |
|
|
end process;
|
450 |
|
|
|
451 |
|
|
-- Interrupt enable register
|
452 |
|
|
UART_IER: process (CLK, RST)
|
453 |
|
|
begin
|
454 |
|
|
if (RST = '1') then
|
455 |
|
|
iIER(3 downto 0) <= (others => '0');
|
456 |
|
|
elsif (CLK'event and CLK = '1') then
|
457 |
|
|
if (iIERWrite = '1') then
|
458 |
|
|
iIER(3 downto 0) <= iDIN(3 downto 0);
|
459 |
|
|
end if;
|
460 |
|
|
end if;
|
461 |
|
|
end process;
|
462 |
|
|
|
463 |
|
|
iIER_ERBI <= iIER(0);
|
464 |
|
|
iIER_ETBEI <= iIER(1);
|
465 |
|
|
iIER_ELSI <= iIER(2);
|
466 |
|
|
iIER_EDSSI <= iIER(3);
|
467 |
|
|
iIER(7 downto 4) <= (others => '0');
|
468 |
|
|
|
469 |
|
|
-- Interrupt control and IIR
|
470 |
|
|
UART_IIC: uart_interrupt port map (CLK => CLK,
|
471 |
|
|
RST => RST,
|
472 |
|
|
IER => iIER(3 downto 0),
|
473 |
|
|
LSR => iLSR(4 downto 0),
|
474 |
|
|
THI => iTHRInterrupt,
|
475 |
|
|
RDA => iRDAInterrupt,
|
476 |
|
|
CTI => iCharTimeout,
|
477 |
|
|
AFE => iMCR_AFE,
|
478 |
|
|
MSR => iMSR(3 downto 0),
|
479 |
|
|
IIR => iIIR(3 downto 0),
|
480 |
|
|
INT => INT
|
481 |
|
|
);
|
482 |
|
|
-- THR empty interrupt
|
483 |
|
|
UART_IIC_THRE_ED: slib_edge_detect port map (CLK => CLK, RST => RST, D => iLSR_THRE, RE => iLSR_THRERE);
|
484 |
|
|
UART_IIC_THREI: process (CLK, RST)
|
485 |
|
|
begin
|
486 |
|
|
if (RST = '1') then
|
487 |
|
|
iTHRInterrupt <= '0';
|
488 |
|
|
elsif (CLK'event and CLK = '1') then
|
489 |
|
|
if (iLSR_THRERE = '1' or iFCR_TXFIFOReset = '1' or (iIERWrite = '1' and iDIN(1) = '1' and iLSR_THRE = '1')) then
|
490 |
|
|
iTHRInterrupt <= '1'; -- Set on THRE, TX FIFO reset (FIFO enable) or ETBEI enable
|
491 |
|
|
elsif ((iIIRRead = '1' and iIIR(3 downto 1) = "001") or iTHRWrite = '1') then
|
492 |
|
|
iTHRInterrupt <= '0'; -- Clear on IIR read (if source of interrupt) or THR write
|
493 |
|
|
end if;
|
494 |
|
|
end if;
|
495 |
|
|
end process;
|
496 |
|
|
|
497 |
|
|
iRDAInterrupt <= '1' when (iFCR_FIFOEnable = '0' and iLSR_DR = '1') or
|
498 |
|
|
(iFCR_FIFOEnable = '1' and iRXFIFOTrigger = '1') else '0';
|
499 |
|
|
iIIR_PI <= iIIR(0);
|
500 |
|
|
iIIR_ID0 <= iIIR(1);
|
501 |
|
|
iIIR_ID1 <= iIIR(2);
|
502 |
|
|
iIIR_ID2 <= iIIR(3);
|
503 |
|
|
iIIR_FIFO64 <= iIIR(5);
|
504 |
|
|
iIIR(4) <= '0';
|
505 |
|
|
iIIR(5) <= iFCR_FIFO64E when iFCR_FIFOEnable = '1' else '0';
|
506 |
|
|
iIIR(6) <= iFCR_FIFOEnable;
|
507 |
|
|
iIIR(7) <= iFCR_FIFOEnable;
|
508 |
|
|
|
509 |
|
|
-- Character timeout indication
|
510 |
|
|
UART_CTI: process (CLK, RST)
|
511 |
|
|
begin
|
512 |
|
|
if (RST = '1') then
|
513 |
|
|
iTimeoutCount <= (others => '0');
|
514 |
|
|
iCharTimeout <= '0';
|
515 |
|
|
elsif (CLK'event and CLK = '1') then
|
516 |
|
|
if (iRXFIFOEmpty = '1' or iRBRRead = '1' or iRXFIFOWrite = '1') then
|
517 |
|
|
iTimeoutCount <= (others => '0');
|
518 |
|
|
elsif (iRXFIFOEmpty = '0' and iBaudtick2x = '1' and iTimeoutCount(5) = '0') then
|
519 |
|
|
iTimeoutCount <= iTimeoutCount + 1;
|
520 |
|
|
end if;
|
521 |
|
|
|
522 |
|
|
-- Timeout indication
|
523 |
|
|
if (iFCR_FIFOEnable = '1') then
|
524 |
|
|
if (iRBRRead = '1') then
|
525 |
|
|
iCharTimeout <= '0';
|
526 |
|
|
elsif (iTimeoutCount(5) = '1') then
|
527 |
|
|
iCharTimeout <= '1';
|
528 |
|
|
end if;
|
529 |
|
|
else
|
530 |
|
|
iCharTimeout <= '0';
|
531 |
|
|
end if;
|
532 |
|
|
end if;
|
533 |
|
|
end process;
|
534 |
|
|
|
535 |
|
|
-- FIFO control register
|
536 |
|
|
UART_FCR: process (CLK, RST)
|
537 |
|
|
begin
|
538 |
|
|
if (RST = '1') then
|
539 |
|
|
iFCR_FIFOEnable <= '0';
|
540 |
|
|
iFCR_RXFIFOReset <= '0';
|
541 |
|
|
iFCR_TXFIFOReset <= '0';
|
542 |
|
|
iFCR_DMAMode <= '0';
|
543 |
|
|
iFCR_FIFO64E <= '0';
|
544 |
|
|
iFCR_RXTrigger <= (others => '0');
|
545 |
|
|
elsif (CLK'event and CLK = '1') then
|
546 |
|
|
-- FIFO reset pulse only
|
547 |
|
|
iFCR_RXFIFOReset <= '0';
|
548 |
|
|
iFCR_TXFIFOReset <= '0';
|
549 |
|
|
|
550 |
|
|
if (iFCRWrite = '1') then
|
551 |
|
|
iFCR_FIFOEnable <= iDIN(0);
|
552 |
|
|
iFCR_DMAMode <= iDIN(3);
|
553 |
|
|
iFCR_RXTrigger <= iDIN(7 downto 6);
|
554 |
|
|
|
555 |
|
|
if (iLCR_DLAB = '1') then
|
556 |
|
|
iFCR_FIFO64E <= iDIN(5);
|
557 |
|
|
end if;
|
558 |
|
|
|
559 |
|
|
-- RX FIFO reset control, reset on FIFO enable/disable
|
560 |
|
|
if (iDIN(1) = '1' or (iFCR_FIFOEnable = '0' and iDIN(0) = '1') or (iFCR_FIFOEnable = '1' and iDIN(0) = '0')) then
|
561 |
|
|
iFCR_RXFIFOReset <= '1';
|
562 |
|
|
end if;
|
563 |
|
|
-- TX FIFO reset control, reset on FIFO enable/disable
|
564 |
|
|
if (iDIN(2) = '1' or (iFCR_FIFOEnable = '0' and iDIN(0) = '1') or (iFCR_FIFOEnable = '1' and iDIN(0) = '0')) then
|
565 |
|
|
iFCR_TXFIFOReset <= '1';
|
566 |
|
|
end if;
|
567 |
|
|
end if;
|
568 |
|
|
end if;
|
569 |
|
|
end process;
|
570 |
|
|
|
571 |
|
|
iFCR(0) <= iFCR_FIFOEnable;
|
572 |
|
|
iFCR(1) <= iFCR_RXFIFOReset;
|
573 |
|
|
iFCR(2) <= iFCR_TXFIFOReset;
|
574 |
|
|
iFCR(3) <= iFCR_DMAMode;
|
575 |
|
|
iFCR(4) <= '0';
|
576 |
|
|
iFCR(5) <= iFCR_FIFO64E;
|
577 |
|
|
iFCR(7 downto 6) <= iFCR_RXTrigger;
|
578 |
|
|
|
579 |
|
|
-- Line control register
|
580 |
|
|
UART_LCR: process (CLK, RST)
|
581 |
|
|
begin
|
582 |
|
|
if (RST = '1') then
|
583 |
|
|
iLCR <= (others => '0');
|
584 |
|
|
elsif (CLK'event and CLK = '1') then
|
585 |
|
|
if (iLCRWrite = '1') then
|
586 |
|
|
iLCR <= iDIN;
|
587 |
|
|
end if;
|
588 |
|
|
end if;
|
589 |
|
|
end process;
|
590 |
|
|
|
591 |
|
|
iLCR_WLS <= iLCR(1 downto 0);
|
592 |
|
|
iLCR_STB <= iLCR(2);
|
593 |
|
|
iLCR_PEN <= iLCR(3);
|
594 |
|
|
iLCR_EPS <= iLCR(4);
|
595 |
|
|
iLCR_SP <= iLCR(5);
|
596 |
|
|
iLCR_BC <= iLCR(6);
|
597 |
|
|
iLCR_DLAB <= iLCR(7);
|
598 |
|
|
|
599 |
|
|
-- Modem control register
|
600 |
|
|
UART_MCR: process (CLK, RST)
|
601 |
|
|
begin
|
602 |
|
|
if (RST = '1') then
|
603 |
|
|
iMCR(5 downto 0) <= (others => '0');
|
604 |
|
|
elsif (CLK'event and CLK = '1') then
|
605 |
|
|
if (iMCRWrite = '1') then
|
606 |
|
|
iMCR(5 downto 0) <= iDIN(5 downto 0);
|
607 |
|
|
end if;
|
608 |
|
|
end if;
|
609 |
|
|
end process;
|
610 |
|
|
|
611 |
|
|
iMCR_DTR <= iMCR(0);
|
612 |
|
|
iMCR_RTS <= iMCR(1);
|
613 |
|
|
iMCR_OUT1 <= iMCR(2);
|
614 |
|
|
iMCR_OUT2 <= iMCR(3);
|
615 |
|
|
iMCR_LOOP <= iMCR(4);
|
616 |
|
|
iMCR_AFE <= iMCR(5);
|
617 |
|
|
iMCR(6) <= '0';
|
618 |
|
|
iMCR(7) <= '0';
|
619 |
|
|
|
620 |
|
|
-- Line status register
|
621 |
|
|
UART_LSR: process (CLK, RST)
|
622 |
|
|
begin
|
623 |
|
|
if (RST = '1') then
|
624 |
|
|
iLSR_OE <= '0';
|
625 |
|
|
iLSR_PE <= '0';
|
626 |
|
|
iLSR_FE <= '0';
|
627 |
|
|
iLSR_BI <= '0';
|
628 |
|
|
iFECounter <= 0;
|
629 |
|
|
elsif (CLK'event and CLK = '1') then
|
630 |
|
|
-- Overrun error
|
631 |
|
|
if ((iFCR_FIFOEnable = '0' and iLSR_DR = '1' and iRXFinished = '1') or
|
632 |
|
|
(iFCR_FIFOEnable = '1' and iRXFIFOFull = '1' and iRXFinished = '1')) then
|
633 |
|
|
iLSR_OE <= '1';
|
634 |
|
|
elsif (iLSRRead = '1') then
|
635 |
|
|
iLSR_OE <= '0';
|
636 |
|
|
end if;
|
637 |
|
|
-- Parity error
|
638 |
|
|
if (iPERE = '1') then
|
639 |
|
|
iLSR_PE <= '1';
|
640 |
|
|
elsif (iLSRRead = '1') then
|
641 |
|
|
iLSR_PE <= '0';
|
642 |
|
|
end if;
|
643 |
|
|
-- Frame error
|
644 |
|
|
if (iFERE = '1') then
|
645 |
|
|
iLSR_FE <= '1';
|
646 |
|
|
elsif (iLSRRead = '1') then
|
647 |
|
|
iLSR_FE <= '0';
|
648 |
|
|
end if;
|
649 |
|
|
-- Break interrupt
|
650 |
|
|
if (iBIRE = '1') then
|
651 |
|
|
iLSR_BI <= '1';
|
652 |
|
|
elsif (iLSRRead = '1') then
|
653 |
|
|
iLSR_BI <= '0';
|
654 |
|
|
end if;
|
655 |
|
|
|
656 |
|
|
-- FIFO error
|
657 |
|
|
-- Datasheet: Cleared by LSR read when no subsequent errors in FIFO
|
658 |
|
|
-- Observed: Cleared when no subsequent errors in FIFO
|
659 |
|
|
if (iFECounter /= 0) then
|
660 |
|
|
iLSR_FIFOERR <= '1';
|
661 |
|
|
--elsif (iLSRRead = '1' and iFECounter = 0 and not (iRXFIFOEmpty = '0' and iRXFIFOQ(10 downto 8) /= "000")) then
|
662 |
|
|
elsif (iRXFIFOEmpty = '1' or iRXFIFOQ(10 downto 8) = "000") then
|
663 |
|
|
iLSR_FIFOERR <= '0';
|
664 |
|
|
end if;
|
665 |
|
|
|
666 |
|
|
-- FIFO error counter
|
667 |
|
|
if (iRXFIFOClear = '1') then
|
668 |
|
|
iFECounter <= 0;
|
669 |
|
|
else
|
670 |
|
|
if (iFEIncrement = '1' and iFEDecrement = '0') then
|
671 |
|
|
iFECounter <= iFECounter + 1;
|
672 |
|
|
elsif (iFEIncrement = '0' and iFEDecrement = '1') then
|
673 |
|
|
iFECounter <= iFECounter - 1;
|
674 |
|
|
end if;
|
675 |
|
|
end if;
|
676 |
|
|
end if;
|
677 |
|
|
end process;
|
678 |
|
|
|
679 |
|
|
iRXFIFOPE <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(8) = '1' else '0';
|
680 |
|
|
iRXFIFOFE <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(9) = '1' else '0';
|
681 |
|
|
iRXFIFOBI <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(10) = '1' else '0';
|
682 |
|
|
UART_PEDET: slib_edge_detect port map (CLK, RST, iRXFIFOPE, iPERE);
|
683 |
|
|
UART_FEDET: slib_edge_detect port map (CLK, RST, iRXFIFOFE, iFERE);
|
684 |
|
|
UART_BIDET: slib_edge_detect port map (CLK, RST, iRXFIFOBI, iBIRE);
|
685 |
|
|
iFEIncrement <= '1' when iRXFIFOWrite = '1' and iRXFIFOD(10 downto 8) /= "000" else '0';
|
686 |
|
|
iFEDecrement <= '1' when iFECounter /= 0 and iRXFIFOEmpty = '0' and (iPERE = '1' or iFERE = '1' or iBIRE = '1') else '0';
|
687 |
|
|
|
688 |
|
|
iLSR(0) <= iLSR_DR;
|
689 |
|
|
iLSR(1) <= iLSR_OE;
|
690 |
|
|
iLSR(2) <= iLSR_PE;
|
691 |
|
|
iLSR(3) <= iLSR_FE;
|
692 |
|
|
iLSR(4) <= iLSR_BI;
|
693 |
|
|
iLSR(5) <= iLSR_THRE;
|
694 |
|
|
iLSR(6) <= iLSR_TEMT;
|
695 |
|
|
iLSR(7) <= '1' when iFCR_FIFOEnable = '1' and iLSR_FIFOERR = '1' else '0';
|
696 |
|
|
iLSR_DR <= '1' when iRXFIFOEmpty = '0' or iRXFIFOWrite = '1' else '0';
|
697 |
|
|
iLSR_THRE <= '1' when iTXFIFOEmpty = '1' else '0';
|
698 |
|
|
iLSR_TEMT <= '1' when iTXRunning = '0' and iLSR_THRE = '1' else '0';
|
699 |
|
|
|
700 |
|
|
-- Modem status register
|
701 |
|
|
iMSR_CTS <= '1' when (iMCR_LOOP = '1' and iRTS = '1') or (iMCR_LOOP = '0' and iCTSn = '0') else '0';
|
702 |
|
|
iMSR_DSR <= '1' when (iMCR_LOOP = '1' and iMCR_DTR = '1') or (iMCR_LOOP = '0' and iDSRn = '0') else '0';
|
703 |
|
|
iMSR_RI <= '1' when (iMCR_LOOP = '1' and iMCR_OUT1 = '1') or (iMCR_LOOP = '0' and iRIn = '0') else '0';
|
704 |
|
|
iMSR_DCD <= '1' when (iMCR_LOOP = '1' and iMCR_OUT2 = '1') or (iMCR_LOOP = '0' and iDCDn = '0') else '0';
|
705 |
|
|
|
706 |
|
|
-- Edge detection for CTS, DSR, DCD and RI
|
707 |
|
|
UART_ED_CTS: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_CTS, RE => iCTSnRE, FE => iCTSnFE);
|
708 |
|
|
UART_ED_DSR: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_DSR, RE => iDSRnRE, FE => iDSRnFE);
|
709 |
|
|
UART_ED_RI: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_RI, RE => iRInRE, FE => iRInFE);
|
710 |
|
|
UART_ED_DCD: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_DCD, RE => iDCDnRE, FE => iDCDnFE);
|
711 |
|
|
|
712 |
|
|
UART_MSR: process (CLK, RST)
|
713 |
|
|
begin
|
714 |
|
|
if (RST = '1') then
|
715 |
|
|
iMSR_dCTS <= '0';
|
716 |
|
|
iMSR_dDSR <= '0';
|
717 |
|
|
iMSR_TERI <= '0';
|
718 |
|
|
iMSR_dDCD <= '0';
|
719 |
|
|
elsif (CLK'event and CLK = '1') then
|
720 |
|
|
-- Delta CTS
|
721 |
|
|
if (iCTSnRE = '1' or iCTSnFE = '1') then
|
722 |
|
|
iMSR_dCTS <= '1';
|
723 |
|
|
elsif (iMSRRead = '1') then
|
724 |
|
|
iMSR_dCTS <= '0';
|
725 |
|
|
end if;
|
726 |
|
|
-- Delta DSR
|
727 |
|
|
if (iDSRnRE = '1' or iDSRnFE = '1') then
|
728 |
|
|
iMSR_dDSR <= '1';
|
729 |
|
|
elsif (iMSRRead = '1') then
|
730 |
|
|
iMSR_dDSR <= '0';
|
731 |
|
|
end if;
|
732 |
|
|
-- Trailing edge RI
|
733 |
|
|
if (iRInFE = '1') then
|
734 |
|
|
iMSR_TERI <= '1';
|
735 |
|
|
elsif (iMSRRead = '1') then
|
736 |
|
|
iMSR_TERI <= '0';
|
737 |
|
|
end if;
|
738 |
|
|
-- Delta DCD
|
739 |
|
|
if (iDCDnRE = '1' or iDCDnFE = '1') then
|
740 |
|
|
iMSR_dDCD <= '1';
|
741 |
|
|
elsif (iMSRRead = '1') then
|
742 |
|
|
iMSR_dDCD <= '0';
|
743 |
|
|
end if;
|
744 |
|
|
end if;
|
745 |
|
|
end process;
|
746 |
|
|
|
747 |
|
|
iMSR(0) <= iMSR_dCTS;
|
748 |
|
|
iMSR(1) <= iMSR_dDSR;
|
749 |
|
|
iMSR(2) <= iMSR_TERI;
|
750 |
|
|
iMSR(3) <= iMSR_dDCD;
|
751 |
|
|
iMSR(4) <= iMSR_CTS;
|
752 |
|
|
iMSR(5) <= iMSR_DSR;
|
753 |
|
|
iMSR(6) <= iMSR_RI;
|
754 |
|
|
iMSR(7) <= iMSR_DCD;
|
755 |
|
|
|
756 |
|
|
-- Scratch register
|
757 |
|
|
UART_SCR: process (CLK, RST)
|
758 |
|
|
begin
|
759 |
|
|
if (RST = '1') then
|
760 |
|
|
iSCR <= (others => '0');
|
761 |
|
|
elsif (CLK'event and CLK = '1') then
|
762 |
|
|
if (iSCRWrite = '1') then
|
763 |
|
|
iSCR <= iDIN;
|
764 |
|
|
end if;
|
765 |
|
|
end if;
|
766 |
|
|
end process;
|
767 |
|
|
|
768 |
|
|
|
769 |
|
|
-- Baudrate generator
|
770 |
|
|
iBaudgenDiv <= iDLM & iDLL;
|
771 |
|
|
UART_BG16: uart_baudgen port map (CLK => CLK,
|
772 |
|
|
RST => RST,
|
773 |
|
|
CE => BAUDCE,
|
774 |
|
|
CLEAR => '0',
|
775 |
|
|
DIVIDER => iBaudgenDiv,
|
776 |
|
|
BAUDTICK => iBaudtick16x
|
777 |
|
|
);
|
778 |
|
|
UART_BG2: slib_clock_div generic map (RATIO => 8)
|
779 |
|
|
port map (CLK => CLK,
|
780 |
|
|
RST => RST,
|
781 |
|
|
CE => iBaudtick16x,
|
782 |
|
|
Q => iBaudtick2x
|
783 |
|
|
);
|
784 |
|
|
UART_RCLK: slib_edge_detect port map (CLK => CLK,
|
785 |
|
|
RST => RST,
|
786 |
|
|
D => RCLK,
|
787 |
|
|
RE => iRCLK
|
788 |
|
|
);
|
789 |
|
|
|
790 |
|
|
-- Transmitter FIFO
|
791 |
|
|
UART_TXFF: slib_fifo generic map (WIDTH => 8, SIZE_E => 6)
|
792 |
|
|
port map (CLK => CLK,
|
793 |
|
|
RST => RST,
|
794 |
|
|
CLEAR => iTXFIFOClear,
|
795 |
|
|
WRITE => iTXFIFOWrite,
|
796 |
|
|
READ => iTXFIFORead,
|
797 |
|
|
D => iDIN,
|
798 |
|
|
Q => iTXFIFOQ,
|
799 |
|
|
EMPTY => iTXFIFOEmpty,
|
800 |
|
|
FULL => iTXFIFO64Full,
|
801 |
|
|
USAGE => iTXFIFOUsage
|
802 |
|
|
);
|
803 |
|
|
-- Transmitter FIFO inputs
|
804 |
|
|
iTXFIFO16Full <= iTXFIFOUsage(4);
|
805 |
|
|
iTXFIFOFull <= iTXFIFO16Full when iFCR_FIFO64E = '0' else iTXFIFO64Full;
|
806 |
|
|
iTXFIFOWrite <= '1' when ((iFCR_FIFOEnable = '0' and iTXFIFOEmpty = '1') or (iFCR_FIFOEnable = '1' and iTXFIFOFull = '0')) and iTHRWrite = '1' else '0';
|
807 |
|
|
iTXFIFOClear <= '1' when iFCR_TXFIFOReset = '1' else '0';
|
808 |
|
|
|
809 |
|
|
-- Receiver FIFO
|
810 |
|
|
UART_RXFF: slib_fifo generic map (WIDTH => 11, SIZE_E => 6)
|
811 |
|
|
port map (CLK => CLK,
|
812 |
|
|
RST => RST,
|
813 |
|
|
CLEAR => iRXFIFOClear,
|
814 |
|
|
WRITE => iRXFIFOWrite,
|
815 |
|
|
READ => iRXFIFORead,
|
816 |
|
|
D => iRXFIFOD,
|
817 |
|
|
Q => iRXFIFOQ,
|
818 |
|
|
EMPTY => iRXFIFOEmpty,
|
819 |
|
|
FULL => iRXFIFO64Full,
|
820 |
|
|
USAGE => iRXFIFOUsage
|
821 |
|
|
);
|
822 |
|
|
-- Receiver FIFO inputs
|
823 |
|
|
iRXFIFORead <= '1' when iRBRRead = '1' else '0';
|
824 |
|
|
iRXFIFO16Full <= iRXFIFOUsage(4);
|
825 |
|
|
iRXFIFOFull <= iRXFIFO16Full when iFCR_FIFO64E = '0' else iRXFIFO64Full;
|
826 |
|
|
|
827 |
|
|
|
828 |
|
|
-- Receiver FIFO outputs
|
829 |
|
|
iRBR <= iRXFIFOQ(7 downto 0);
|
830 |
|
|
|
831 |
|
|
-- FIFO trigger level: 1, 4, 8, 14
|
832 |
|
|
iRXFIFO16Trigger <= '1' when (iFCR_RXTrigger = "00" and iRXFIFOEmpty = '0') or
|
833 |
|
|
(iFCR_RXTrigger = "01" and (iRXFIFOUsage(2) = '1' or iRXFIFOUsage(3) = '1')) or
|
834 |
|
|
(iFCR_RXTrigger = "10" and iRXFIFOUsage(3) = '1') or
|
835 |
|
|
(iFCR_RXTrigger = "11" and iRXFIFOUsage(3) = '1' and iRXFIFOUsage(2) = '1' and iRXFIFOUsage(1) = '1') or
|
836 |
|
|
iRXFIFO16Full = '1' else '0';
|
837 |
|
|
-- FIFO 64 trigger level: 1, 16, 32, 56
|
838 |
|
|
iRXFIFO64Trigger <= '1' when (iFCR_RXTrigger = "00" and iRXFIFOEmpty = '0') or
|
839 |
|
|
(iFCR_RXTrigger = "01" and (iRXFIFOUsage(4) = '1' or iRXFIFOUsage(5) = '1')) or
|
840 |
|
|
(iFCR_RXTrigger = "10" and iRXFIFOUsage(5) = '1') or
|
841 |
|
|
(iFCR_RXTrigger = "11" and iRXFIFOUsage(5) = '1' and iRXFIFOUsage(4) = '1' and iRXFIFOUsage(3) = '1') or
|
842 |
|
|
iRXFIFO64Full = '1' else '0';
|
843 |
|
|
iRXFIFOTrigger <= iRXFIFO16Trigger when iFCR_FIFO64E = '0' else iRXFIFO64Trigger;
|
844 |
|
|
|
845 |
|
|
-- Transmitter
|
846 |
|
|
UART_TX: uart_transmitter port map (CLK => CLK,
|
847 |
|
|
RST => RST,
|
848 |
|
|
TXCLK => iBaudtick2x,
|
849 |
|
|
TXSTART => iTXStart,
|
850 |
|
|
CLEAR => iTXClear,
|
851 |
|
|
WLS => iLCR_WLS,
|
852 |
|
|
STB => iLCR_STB,
|
853 |
|
|
PEN => iLCR_PEN,
|
854 |
|
|
EPS => iLCR_EPS,
|
855 |
|
|
SP => iLCR_SP,
|
856 |
|
|
BC => iLCR_BC,
|
857 |
|
|
DIN => iTSR,
|
858 |
|
|
TXFINISHED => iTXFinished,
|
859 |
|
|
SOUT => iSOUT
|
860 |
|
|
);
|
861 |
|
|
iTXClear <= '0';
|
862 |
|
|
|
863 |
|
|
-- Receiver
|
864 |
|
|
UART_RX: uart_receiver port map (CLK => CLK,
|
865 |
|
|
RST => RST,
|
866 |
|
|
RXCLK => iRCLK,
|
867 |
|
|
RXCLEAR => iRXClear,
|
868 |
|
|
WLS => iLCR_WLS,
|
869 |
|
|
STB => iLCR_STB,
|
870 |
|
|
PEN => iLCR_PEN,
|
871 |
|
|
EPS => iLCR_EPS,
|
872 |
|
|
SP => iLCR_SP,
|
873 |
|
|
SIN => iSIN,
|
874 |
|
|
PE => iRXPE,
|
875 |
|
|
FE => iRXFE,
|
876 |
|
|
BI => iRXBI,
|
877 |
|
|
DOUT => iRXData,
|
878 |
|
|
RXFINISHED => iRXFinished
|
879 |
|
|
);
|
880 |
|
|
iRXClear <= '0';
|
881 |
|
|
iSIN <= iSINr when iMCR_LOOP = '0' else iSOUT;
|
882 |
|
|
|
883 |
|
|
-- Transmitter enable signal
|
884 |
|
|
-- TODO: Use iCTSNs instead of iMSR_CTS? Input filter increases delay for Auto-CTS recognition.
|
885 |
|
|
iTXEnable <= '1' when iTXFIFOEmpty = '0' and (iMCR_AFE = '0' or (iMCR_AFE = '1' and iMSR_CTS = '1')) else '0';
|
886 |
|
|
|
887 |
|
|
-- Transmitter process
|
888 |
|
|
UART_TXPROC: process (CLK, RST)
|
889 |
|
|
type state_type is (IDLE, TXSTART, TXRUN, TXEND);
|
890 |
|
|
variable State : state_type;
|
891 |
|
|
begin
|
892 |
|
|
if (RST = '1') then
|
893 |
|
|
State := IDLE;
|
894 |
|
|
iTSR <= (others => '0');
|
895 |
|
|
iTXStart <= '0';
|
896 |
|
|
iTXFIFORead <= '0';
|
897 |
|
|
iTXRunning <= '0';
|
898 |
|
|
elsif (CLK'event and CLK = '1') then
|
899 |
|
|
-- Defaults
|
900 |
|
|
iTXStart <= '0';
|
901 |
|
|
iTXFIFORead <= '0';
|
902 |
|
|
iTXRunning <= '0';
|
903 |
|
|
|
904 |
|
|
case State is
|
905 |
|
|
when IDLE => if (iTXEnable = '1') then
|
906 |
|
|
iTXStart <= '1'; -- Start transmitter
|
907 |
|
|
State := TXSTART;
|
908 |
|
|
else
|
909 |
|
|
State := IDLE;
|
910 |
|
|
end if;
|
911 |
|
|
when TXSTART => iTSR <= iTXFIFOQ;
|
912 |
|
|
iTXStart <= '1'; -- Start transmitter
|
913 |
|
|
iTXFIFORead <= '1'; -- Increment TX FIFO read counter
|
914 |
|
|
State := TXRUN;
|
915 |
|
|
when TXRUN => if (iTXFinished = '1') then -- TX finished
|
916 |
|
|
State := TXEND;
|
917 |
|
|
else
|
918 |
|
|
State := TXRUN;
|
919 |
|
|
end if;
|
920 |
|
|
iTXRunning <= '1';
|
921 |
|
|
iTXStart <= '1';
|
922 |
|
|
when TXEND => State := IDLE;
|
923 |
|
|
when others => State := IDLE;
|
924 |
|
|
end case;
|
925 |
|
|
end if;
|
926 |
|
|
end process;
|
927 |
|
|
|
928 |
|
|
-- Receiver process
|
929 |
|
|
UART_RXPROC: process (CLK, RST)
|
930 |
|
|
type state_type is (IDLE, RXSAVE);
|
931 |
|
|
variable State : state_type;
|
932 |
|
|
begin
|
933 |
|
|
if (RST = '1') then
|
934 |
|
|
State := IDLE;
|
935 |
|
|
iRXFIFOWrite <= '0';
|
936 |
|
|
iRXFIFOClear <= '0';
|
937 |
|
|
iRXFIFOD <= (others => '0');
|
938 |
|
|
elsif (CLK'event and CLK = '1') then
|
939 |
|
|
-- Defaults
|
940 |
|
|
iRXFIFOWrite <= '0';
|
941 |
|
|
iRXFIFOClear <= iFCR_RXFIFOReset;
|
942 |
|
|
|
943 |
|
|
case State is
|
944 |
|
|
when IDLE => if (iRXFinished = '1') then -- Receive finished
|
945 |
|
|
iRXFIFOD <= iRXBI & iRXFE & iRXPE & iRXData;
|
946 |
|
|
if (iFCR_FIFOEnable = '0') then
|
947 |
|
|
iRXFIFOClear <= '1'; -- Non-FIFO mode
|
948 |
|
|
end if;
|
949 |
|
|
State := RXSAVE;
|
950 |
|
|
else
|
951 |
|
|
State := IDLE;
|
952 |
|
|
end if;
|
953 |
|
|
when RXSAVE => if (iFCR_FIFOEnable = '0') then
|
954 |
|
|
iRXFIFOWrite <= '1'; -- Non-FIFO mode: Overwrite
|
955 |
|
|
elsif (iRXFIFOFull = '0') then
|
956 |
|
|
iRXFIFOWrite <= '1'; -- FIFO mode
|
957 |
|
|
end if;
|
958 |
|
|
State := IDLE;
|
959 |
|
|
when others => State := IDLE;
|
960 |
|
|
end case;
|
961 |
|
|
end if;
|
962 |
|
|
end process;
|
963 |
|
|
|
964 |
|
|
-- Automatic flow control
|
965 |
|
|
UART_AFC: process (CLK, RST)
|
966 |
|
|
begin
|
967 |
|
|
if (RST = '1') then
|
968 |
|
|
iRTS <= '0';
|
969 |
|
|
elsif (CLK'event and CLK = '1') then
|
970 |
|
|
if (iMCR_RTS = '0' or (iMCR_AFE = '1' and iRXFIFOTrigger = '1')) then
|
971 |
|
|
-- Deassert when MCR_RTS is not set or AFC is enabled and the RX FIFO trigger level is reached
|
972 |
|
|
iRTS <= '0';
|
973 |
|
|
elsif (iMCR_RTS = '1' and (iMCR_AFE = '0' or (iMCR_AFE = '1' and iRXFIFOEmpty = '1'))) then
|
974 |
|
|
-- Assert when MCR_RTS is set and AFC is disabled or when AFC is enabled and the RX FIFO is empty
|
975 |
|
|
iRTS <= '1';
|
976 |
|
|
end if;
|
977 |
|
|
end if;
|
978 |
|
|
end process;
|
979 |
|
|
|
980 |
|
|
-- Output registers
|
981 |
|
|
UART_OUTREGS: process (CLK, RST)
|
982 |
|
|
begin
|
983 |
|
|
if (RST = '1') then
|
984 |
|
|
BAUDOUTN <= '0';
|
985 |
|
|
OUT1N <= '0';
|
986 |
|
|
OUT2N <= '0';
|
987 |
|
|
RTSN <= '0';
|
988 |
|
|
DTRN <= '0';
|
989 |
|
|
SOUT <= '0';
|
990 |
|
|
elsif (CLK'event and CLK = '1') then
|
991 |
|
|
-- Default values
|
992 |
|
|
BAUDOUTN <= '0';
|
993 |
|
|
OUT1N <= '0';
|
994 |
|
|
OUT2N <= '0';
|
995 |
|
|
RTSN <= '0';
|
996 |
|
|
DTRN <= '0';
|
997 |
|
|
SOUT <= '0';
|
998 |
|
|
|
999 |
|
|
-- BAUDOUTN
|
1000 |
|
|
if (iBaudtick16x = '0') then
|
1001 |
|
|
BAUDOUTN <= '1';
|
1002 |
|
|
end if;
|
1003 |
|
|
-- OUT1N
|
1004 |
|
|
if (iMCR_LOOP = '1' or iMCR_OUT1 = '0') then
|
1005 |
|
|
OUT1N <= '1';
|
1006 |
|
|
end if;
|
1007 |
|
|
-- OUT2N
|
1008 |
|
|
if (iMCR_LOOP = '1' or iMCR_OUT2 = '0') then
|
1009 |
|
|
OUT2N <= '1';
|
1010 |
|
|
end if;
|
1011 |
|
|
-- RTS
|
1012 |
|
|
if (iMCR_LOOP = '1' or iRTS = '0') then
|
1013 |
|
|
RTSN <= '1';
|
1014 |
|
|
end if;
|
1015 |
|
|
-- DTR
|
1016 |
|
|
if (iMCR_LOOP = '1' or iMCR_DTR = '0') then
|
1017 |
|
|
DTRN <= '1';
|
1018 |
|
|
end if;
|
1019 |
|
|
-- SOUT
|
1020 |
|
|
if (iMCR_LOOP = '1' or iSOUT = '1') then
|
1021 |
|
|
SOUT <= '1';
|
1022 |
|
|
end if;
|
1023 |
|
|
end if;
|
1024 |
|
|
end process;
|
1025 |
|
|
|
1026 |
|
|
|
1027 |
|
|
-- UART data output
|
1028 |
|
|
UART_DOUT: process (WB_ACK_r,iA, iLCR_DLAB, iRBR, iDLL, iDLM, iIER, iIIR, iLCR, iMCR, iLSR, iMSR, iSCR)
|
1029 |
|
|
begin
|
1030 |
|
|
WB_DOUT(7 downto 0) <= (others => '0');
|
1031 |
|
|
if WB_ACK_r='1' then
|
1032 |
|
|
case iA is
|
1033 |
|
|
when "000" => if (iLCR_DLAB = '0') then
|
1034 |
|
|
WB_DOUT <= iRBR;
|
1035 |
|
|
else
|
1036 |
|
|
WB_DOUT <= iDLL;
|
1037 |
|
|
end if;
|
1038 |
|
|
when "001" => if (iLCR_DLAB = '0') then
|
1039 |
|
|
WB_DOUT <= iIER;
|
1040 |
|
|
else
|
1041 |
|
|
WB_DOUT <= iDLM;
|
1042 |
|
|
end if;
|
1043 |
|
|
when "010" => WB_DOUT <= iIIR;
|
1044 |
|
|
when "011" => WB_DOUT <= iLCR;
|
1045 |
|
|
when "100" => WB_DOUT <= iMCR;
|
1046 |
|
|
when "101" => WB_DOUT <= iLSR;
|
1047 |
|
|
when "110" => WB_DOUT <= iMSR;
|
1048 |
|
|
when "111" => WB_DOUT <= iSCR;
|
1049 |
|
|
when others => WB_DOUT <= iRBR;
|
1050 |
|
|
end case;
|
1051 |
|
|
end if;
|
1052 |
|
|
end process;
|
1053 |
|
|
|
1054 |
|
|
end rtl;
|
1055 |
|
|
|
1056 |
|
|
|