1 |
2 |
jclaytons |
--------------------------------------------------------------------------
|
2 |
|
|
-- Package of UART components
|
3 |
|
|
--
|
4 |
|
|
-- This UART uses a squarewave input for the BAUDRATE clock. In other
|
5 |
|
|
-- words, the BAUD rate is exactly the same as the frequency of the
|
6 |
|
|
-- incoming clock. This is in contrast to other UARTs which need a
|
7 |
|
|
-- Baud rate clock which is some multiple of the actual Baud rate
|
8 |
|
|
-- desired. Because of the 1x nature of the Baud clock, the receiver
|
9 |
|
|
-- needs at least one Baud Clock interval in which to measure the
|
10 |
|
|
-- Baud clock versus the system clock, before it can start working.
|
11 |
|
|
-- Also, the system clock must be somewhat higher than the Baud clock
|
12 |
|
|
-- in order for the receiver to work.
|
13 |
|
|
--
|
14 |
|
|
-- This package contains the UART, plus individual async_tx and async_rx
|
15 |
|
|
-- modules, which are the transmit and receive sections of the UART.
|
16 |
|
|
--
|
17 |
|
|
--
|
18 |
|
|
|
19 |
|
|
library IEEE;
|
20 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
21 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
22 |
|
|
|
23 |
|
|
package uart_sqclk_pack is
|
24 |
|
|
|
25 |
|
|
component uart_sqclk
|
26 |
|
|
port (
|
27 |
|
|
|
28 |
|
|
sys_rst_n : in std_logic;
|
29 |
|
|
sys_clk : in std_logic;
|
30 |
|
|
sys_clk_en : in std_logic;
|
31 |
|
|
|
32 |
|
|
-- rate and parity
|
33 |
|
|
parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
34 |
|
|
rate_clk_i : in std_logic;
|
35 |
|
|
|
36 |
|
|
-- serial I/O
|
37 |
|
|
tx_stream : out std_logic;
|
38 |
|
|
rx_stream : in std_logic;
|
39 |
|
|
|
40 |
|
|
--control and status
|
41 |
|
|
tx_wr_i : in std_logic; -- Starts Transmit
|
42 |
|
|
tx_dat_i : in unsigned(7 downto 0);
|
43 |
|
|
tx_done_o : out std_logic;
|
44 |
|
|
rx_restart_i : in std_logic; -- High clears error flags, clears rx_done_o
|
45 |
|
|
rx_dat_o : out unsigned(7 downto 0);
|
46 |
|
|
rx_wr_o : out std_logic; -- High pulse means store rx_dat_o.
|
47 |
|
|
rx_done_o : out std_logic; -- Remains high after receive, until clk edge with rx_restart_i=1
|
48 |
|
|
frame_err_o : out std_logic; -- High = error. Reset when rx_restart_i asserted.
|
49 |
|
|
parity_err_o : out std_logic -- High = error. Reset when rx_restart_i asserted.
|
50 |
|
|
);
|
51 |
|
|
end component;
|
52 |
|
|
|
53 |
|
|
component async_tx_sqclk
|
54 |
|
|
port (
|
55 |
|
|
|
56 |
|
|
sys_rst_n : in std_logic;
|
57 |
|
|
sys_clk : in std_logic;
|
58 |
|
|
sys_clk_en : in std_logic;
|
59 |
|
|
|
60 |
|
|
-- rate and parity
|
61 |
|
|
tx_parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
62 |
|
|
tx_clk_i : in std_logic;
|
63 |
|
|
|
64 |
|
|
-- serial output
|
65 |
|
|
tx_stream : out std_logic;
|
66 |
|
|
|
67 |
|
|
-- control and status
|
68 |
|
|
tx_wr_i : in std_logic; -- Starts Transmit
|
69 |
|
|
tx_dat_i : in unsigned(7 downto 0);
|
70 |
|
|
tx_done_o : out std_logic
|
71 |
|
|
);
|
72 |
|
|
end component;
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
component async_rx_sqclk
|
76 |
|
|
port (
|
77 |
|
|
|
78 |
|
|
sys_rst_n : in std_logic;
|
79 |
|
|
sys_clk : in std_logic;
|
80 |
|
|
sys_clk_en : in std_logic;
|
81 |
|
|
|
82 |
|
|
-- rate and parity
|
83 |
|
|
rx_parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
84 |
|
|
rx_clk_i : in std_logic;
|
85 |
|
|
|
86 |
|
|
-- serial input
|
87 |
|
|
rx_stream : in std_logic;
|
88 |
|
|
|
89 |
|
|
-- control and status
|
90 |
|
|
rx_restart_i : in std_logic; -- High clears error flags, clears rx_done_o
|
91 |
|
|
rx_dat_o : out unsigned(7 downto 0);
|
92 |
|
|
rx_wr_o : out std_logic; -- High pulse means store rx_dat_o.
|
93 |
|
|
rx_done_o : out std_logic; -- Remains high after receive, until rx_restart_i
|
94 |
|
|
frame_err_o : out std_logic; -- High = error. Reset when rx_restart_i asserted.
|
95 |
|
|
parity_err_o : out std_logic -- High = error. Reset when rx_restart_i asserted.
|
96 |
|
|
);
|
97 |
|
|
end component;
|
98 |
|
|
|
99 |
|
|
component half_duplex_switch
|
100 |
|
|
generic (
|
101 |
|
|
HANG_TIME : integer; -- Units of timer_i rising edges
|
102 |
|
|
TX_DELAY : integer -- Units of timer_i rising edges
|
103 |
|
|
);
|
104 |
|
|
port (
|
105 |
|
|
|
106 |
|
|
sys_rst_n : in std_logic;
|
107 |
|
|
sys_clk : in std_logic;
|
108 |
|
|
sys_clk_en : in std_logic;
|
109 |
|
|
|
110 |
|
|
-- Full Duplex side
|
111 |
|
|
tx_i : in std_logic;
|
112 |
|
|
rx_o : out std_logic;
|
113 |
|
|
|
114 |
|
|
-- Half Duplex side
|
115 |
|
|
hd_o : out std_logic;
|
116 |
|
|
hd_i : in std_logic;
|
117 |
|
|
hd_drive_o : out std_logic;
|
118 |
|
|
|
119 |
|
|
-- Timer
|
120 |
|
|
tick_i : in std_logic
|
121 |
|
|
);
|
122 |
|
|
end component;
|
123 |
|
|
|
124 |
|
|
end uart_sqclk_pack;
|
125 |
|
|
|
126 |
|
|
package body uart_sqclk_pack is
|
127 |
|
|
end uart_sqclk_pack;
|
128 |
|
|
|
129 |
|
|
|
130 |
|
|
--------------------------------------------------------------------
|
131 |
|
|
-- UART. Variable Speed, RX Buffer, but no TX buffer
|
132 |
|
|
-- High Speed Asynchronous Receiver & Transmitter
|
133 |
|
|
--
|
134 |
|
|
-- Description:
|
135 |
|
|
-- This block receives and transmits asynchronous serial bytes. The Baudrate
|
136 |
|
|
-- and parity are selectable through inputs, but the number of bits per character
|
137 |
|
|
-- is fixed at eight.
|
138 |
|
|
--
|
139 |
|
|
-- NOTES:
|
140 |
|
|
-- Transmit starts when tx_wr_i is detected high at a rising clock edge.
|
141 |
|
|
-- Once the transmit operation is completed, tx_done_o latches high.
|
142 |
|
|
--
|
143 |
|
|
-- The receive input is passed through two layers of synchronizing flip-flops
|
144 |
|
|
-- to help mitigate metastability issues, since this signal can come from
|
145 |
|
|
-- outside of the sys_clk clock domain. All other logic connecting to inputs
|
146 |
|
|
-- of this function are assumed to be within the same clock domain.
|
147 |
|
|
--
|
148 |
|
|
-- The receiver looks for a new start bit immediately following the rx_wr_o
|
149 |
|
|
-- pulse, but rx_done_o is delayed until the expected end of the received
|
150 |
|
|
-- character. If a new start bit is detected just prior to the expected end
|
151 |
|
|
-- of the received character, then rx_done_o is not asserted.
|
152 |
|
|
--
|
153 |
|
|
-- Receive begins when the falling edge of the start bit is detected.
|
154 |
|
|
-- Then after 10 or 11 bit times have passed (depending on the parity setting)
|
155 |
|
|
-- the rx_wr_o signal will pulse high for one clock period, indicating rx_dat_o
|
156 |
|
|
-- contains valid receive data. The rx_wr_o pulse is only issued if there is
|
157 |
|
|
-- no parity error, and the stop bit is actually detected high at the sampling
|
158 |
|
|
-- time.
|
159 |
|
|
-- The rx_dat_o outputs will hold the received data until the next rx_wr_o pulse.
|
160 |
|
|
-- The rx_dat_o output provides the received data, even in the presence of a
|
161 |
|
|
-- parity or stop-bit error.
|
162 |
|
|
-- Error flags are valid during rx_wr_o, but they remain latched, until
|
163 |
|
|
-- rx_restart_i.
|
164 |
|
|
--
|
165 |
|
|
-- The Baud rate is equal to the frequency of the rate_clk_i input.
|
166 |
|
|
-- It should be, as nearly as possible, a square wave of the desired
|
167 |
|
|
-- communications rate.
|
168 |
|
|
--
|
169 |
|
|
library IEEE;
|
170 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
171 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
172 |
|
|
|
173 |
|
|
entity uart_sqclk is
|
174 |
|
|
port (
|
175 |
|
|
|
176 |
|
|
sys_rst_n : in std_logic;
|
177 |
|
|
sys_clk : in std_logic;
|
178 |
|
|
sys_clk_en : in std_logic;
|
179 |
|
|
|
180 |
|
|
-- rate and parity
|
181 |
|
|
parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
182 |
|
|
rate_clk_i : in std_logic;
|
183 |
|
|
|
184 |
|
|
-- serial I/O
|
185 |
|
|
tx_stream : out std_logic;
|
186 |
|
|
rx_stream : in std_logic;
|
187 |
|
|
|
188 |
|
|
--control and status
|
189 |
|
|
tx_wr_i : in std_logic; -- Starts Transmit
|
190 |
|
|
tx_dat_i : in unsigned(7 downto 0);
|
191 |
|
|
tx_done_o : out std_logic;
|
192 |
|
|
rx_restart_i : in std_logic; -- High clears error flags, clears rx_done_o
|
193 |
|
|
rx_dat_o : out unsigned(7 downto 0);
|
194 |
|
|
rx_wr_o : out std_logic; -- High pulse means store rx_dat_o.
|
195 |
|
|
rx_done_o : out std_logic; -- Remains high after receive, until clk edge with rx_restart_i=1
|
196 |
|
|
frame_err_o : out std_logic; -- High = error. Reset when rx_restart_i asserted.
|
197 |
|
|
parity_err_o : out std_logic -- High = error. Reset when rx_restart_i asserted.
|
198 |
|
|
);
|
199 |
|
|
end uart_sqclk;
|
200 |
|
|
|
201 |
|
|
library work;
|
202 |
|
|
use work.uart_sqclk_pack.all;
|
203 |
|
|
|
204 |
|
|
architecture beh of uart_sqclk is
|
205 |
|
|
|
206 |
|
|
-- Components
|
207 |
|
|
|
208 |
|
|
begin
|
209 |
|
|
|
210 |
|
|
tx1: async_tx_sqclk
|
211 |
|
|
port map (
|
212 |
|
|
sys_rst_n => sys_rst_n,
|
213 |
|
|
sys_clk => sys_clk,
|
214 |
|
|
sys_clk_en => sys_clk_en,
|
215 |
|
|
|
216 |
|
|
-- rate and parity
|
217 |
|
|
tx_parity_i => parity_i, -- 0=none, 1=even, 2 or 3=odd
|
218 |
|
|
tx_clk_i => rate_clk_i,
|
219 |
|
|
|
220 |
|
|
-- serial output
|
221 |
|
|
tx_stream => tx_stream,
|
222 |
|
|
|
223 |
|
|
-- control and status
|
224 |
|
|
tx_wr_i => tx_wr_i, -- Starts Transmit
|
225 |
|
|
tx_dat_i => tx_dat_i,
|
226 |
|
|
tx_done_o => tx_done_o
|
227 |
|
|
);
|
228 |
|
|
|
229 |
|
|
rx1: async_rx_sqclk
|
230 |
|
|
port map (
|
231 |
|
|
sys_rst_n => sys_rst_n,
|
232 |
|
|
sys_clk => sys_clk,
|
233 |
|
|
sys_clk_en => sys_clk_en,
|
234 |
|
|
|
235 |
|
|
-- rate and parity
|
236 |
|
|
rx_parity_i => parity_i, -- 0=none, 1=even, 2 or 3=odd
|
237 |
|
|
rx_clk_i => rate_clk_i,
|
238 |
|
|
|
239 |
|
|
-- serial input
|
240 |
|
|
rx_stream => rx_stream,
|
241 |
|
|
|
242 |
|
|
-- control and status
|
243 |
|
|
rx_restart_i => rx_restart_i, -- High clears error flags, clears rx_done_o
|
244 |
|
|
rx_dat_o => rx_dat_o,
|
245 |
|
|
rx_wr_o => rx_wr_o, -- High pulse means store rx_dat_o.
|
246 |
|
|
rx_done_o => rx_done_o, -- Remains high after receive, until rx_restart_i
|
247 |
|
|
frame_err_o => frame_err_o, -- High = error. Reset when rx_restart_i asserted.
|
248 |
|
|
parity_err_o => parity_err_o -- High = error. Reset when rx_restart_i asserted.
|
249 |
|
|
);
|
250 |
|
|
|
251 |
|
|
end beh;
|
252 |
|
|
|
253 |
|
|
|
254 |
|
|
-------------------------------------------------------------------------------
|
255 |
|
|
-- Asynchronous Transmitter With No Buffering
|
256 |
|
|
-------------------------------------------------------------------------------
|
257 |
|
|
--
|
258 |
|
|
-- Author: John Clayton
|
259 |
|
|
-- Date : Aug 08, 2013 Added this change log header, which was missing.
|
260 |
|
|
-- Changed tx_done_o signal so that it pulses after
|
261 |
|
|
-- the stop bit is finished. How could this have
|
262 |
|
|
-- remained so woefully incorrect for so long?!
|
263 |
|
|
-- Jan 02, 2014 Fixed a latent bug in the logic for asserting
|
264 |
|
|
-- tx_done_o. Prior to this fix, it was possible
|
265 |
|
|
-- for a write that was coincident with do_txbit to
|
266 |
|
|
-- be ignored! Once again, how could this have
|
267 |
|
|
-- remained so woefully incorrect all this time?!
|
268 |
|
|
-- Jan 07, 2014 Rewrote the startup logic to allow for cases
|
269 |
|
|
-- when tx_wr_i='1' and tx_bcnt="0000" and do_txbit='1'
|
270 |
|
|
-- Also rewrote the tx_done_o signal so that it is
|
271 |
|
|
-- asserted earlier - when "tx_almost_done" is high.
|
272 |
|
|
-- This is all calculated to allow the transmitter
|
273 |
|
|
-- to send characters back-to-back using its own
|
274 |
|
|
-- tx_done_o signal as a tx_wr_i signal. This is
|
275 |
|
|
-- actually getting pretty neat. The unit sends out
|
276 |
|
|
-- asynchronous characters, but insists on doing it
|
277 |
|
|
-- in synchronism with the tx_clk_i input... so it
|
278 |
|
|
-- isn't really very asynchronous in that sense!
|
279 |
|
|
--
|
280 |
|
|
-- Description
|
281 |
|
|
-------------------------------------------------------------------------------
|
282 |
|
|
-- Squarewave tx_clk_i input determines rate.
|
283 |
|
|
-- (tx_clk_i need not be a squarewave for this module, since only the rising
|
284 |
|
|
-- edge is used. In the accompanying receiver, however, both edges are used.)
|
285 |
|
|
--
|
286 |
|
|
-- Description:
|
287 |
|
|
-- This block transmits asynchronous serial bytes. The Baudrate and parity
|
288 |
|
|
-- are determined by inputs, but the number of bits per character is
|
289 |
|
|
-- fixed at eight.
|
290 |
|
|
--
|
291 |
|
|
-- NOTES:
|
292 |
|
|
-- Transmit starts when the transmitter is idle and tx_wr_i is detected high
|
293 |
|
|
-- at a rising sys_clk edge.
|
294 |
|
|
--
|
295 |
|
|
-- Once the transmit operation is completed, done_o latches high.
|
296 |
|
|
--
|
297 |
|
|
-- Since the baud clock might be asynchronous to the sys_clk, there are
|
298 |
|
|
-- syncronizing flip-flops on it inside this module.
|
299 |
|
|
|
300 |
|
|
library IEEE;
|
301 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
302 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
303 |
|
|
|
304 |
|
|
entity async_tx_sqclk is
|
305 |
|
|
port (
|
306 |
|
|
|
307 |
|
|
sys_rst_n : in std_logic;
|
308 |
|
|
sys_clk : in std_logic;
|
309 |
|
|
sys_clk_en : in std_logic;
|
310 |
|
|
|
311 |
|
|
-- rate and parity
|
312 |
|
|
tx_parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
313 |
|
|
tx_clk_i : in std_logic;
|
314 |
|
|
|
315 |
|
|
-- serial output
|
316 |
|
|
tx_stream : out std_logic;
|
317 |
|
|
|
318 |
|
|
-- control and status
|
319 |
|
|
tx_wr_i : in std_logic; -- Starts Transmit
|
320 |
|
|
tx_dat_i : in unsigned(7 downto 0);
|
321 |
|
|
tx_done_o : out std_logic
|
322 |
|
|
);
|
323 |
|
|
end async_tx_sqclk;
|
324 |
|
|
|
325 |
|
|
architecture beh of async_tx_sqclk is
|
326 |
|
|
|
327 |
|
|
-- TX signals
|
328 |
|
|
-- TX clock synchronizing flip-flops and rising edge detection
|
329 |
|
|
signal tx_clk_r1 : std_logic;
|
330 |
|
|
signal tx_clk_r2 : std_logic;
|
331 |
|
|
-- TX clock enable, shift register and bit count
|
332 |
|
|
signal do_txbit : std_logic;
|
333 |
|
|
signal tx_sr : unsigned(9 downto 0);
|
334 |
|
|
signal tx_bcnt : unsigned(3 downto 0); -- Number of bits
|
335 |
|
|
signal tx_almost_done : std_logic;
|
336 |
|
|
signal tx_done : std_logic;
|
337 |
|
|
|
338 |
|
|
begin
|
339 |
|
|
|
340 |
|
|
-- This process detects the rising edge of tx_clk_i
|
341 |
|
|
tx_clk_edge_proc: Process(sys_rst_n,sys_clk)
|
342 |
|
|
BEGIN
|
343 |
|
|
if (sys_rst_n = '0') then
|
344 |
|
|
tx_clk_r1 <= '0';
|
345 |
|
|
tx_clk_r2 <= '0';
|
346 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
347 |
|
|
if (sys_clk_en='1') then
|
348 |
|
|
tx_clk_r1 <= tx_clk_i;
|
349 |
|
|
tx_clk_r2 <= tx_clk_r1;
|
350 |
|
|
end if;
|
351 |
|
|
end if;
|
352 |
|
|
END PROCESS tx_clk_edge_proc;
|
353 |
|
|
do_txbit <= (tx_clk_r1 and not tx_clk_r2); -- rising edge detect
|
354 |
|
|
|
355 |
|
|
-- This process loads the shift register, then counts as the bits transmit out.
|
356 |
|
|
byte_tx: Process(sys_rst_n,sys_clk)
|
357 |
|
|
BEGIN
|
358 |
|
|
if (sys_rst_n = '0') then
|
359 |
|
|
tx_sr <= (others=>'0');
|
360 |
|
|
tx_bcnt <= (others=>'0');
|
361 |
|
|
tx_stream <= '1';
|
362 |
|
|
tx_done <= '1';
|
363 |
|
|
elsif (sys_clk'event and sys_clk='1') then
|
364 |
|
|
if (sys_clk_en='1') then
|
365 |
|
|
-- Start a new transmission when ready
|
366 |
|
|
-- Case 1 is starting while do_txbit is high
|
367 |
|
|
if tx_bcnt="0000" and do_txbit='1' and tx_wr_i='1' then
|
368 |
|
|
tx_stream <= '0'; -- Provide start bit
|
369 |
|
|
tx_sr(7 downto 0) <= tx_dat_i; -- Load the TX data
|
370 |
|
|
tx_sr(8) <= '1'; -- Default the parity bit to one
|
371 |
|
|
if(tx_parity_i = "00") then --If no parity...
|
372 |
|
|
tx_bcnt <= "1001"; -- send start, 8 data bits, and stop
|
373 |
|
|
elsif (tx_parity_i = "01") then --If even parity...
|
374 |
|
|
tx_bcnt <= "1010"; -- send start, 8 data bits, parity, and stop
|
375 |
|
|
tx_sr(8) <= tx_dat_i(0) XOR tx_dat_i(1) XOR tx_dat_i(2) XOR tx_dat_i(3) XOR
|
376 |
|
|
tx_dat_i(4) XOR tx_dat_i(5) XOR tx_dat_i(6) XOR tx_dat_i(7);
|
377 |
|
|
else --If odd parity...
|
378 |
|
|
tx_bcnt <= "1011"; --send start, 8 data bits, parity, and stop
|
379 |
|
|
tx_sr(8) <= NOT (tx_dat_i(0) XOR tx_dat_i(1) XOR tx_dat_i(2) XOR tx_dat_i(3) XOR
|
380 |
|
|
tx_dat_i(4) XOR tx_dat_i(5) XOR tx_dat_i(6) XOR tx_dat_i(7));
|
381 |
|
|
end if;
|
382 |
|
|
tx_done <= '0';
|
383 |
|
|
-- Case 2 is starting while do_txbit is low
|
384 |
|
|
elsif tx_done='1' and tx_wr_i='1' then -- Only allow loads when transmitter is idle
|
385 |
|
|
tx_sr(0) <= '0'; -- Load start bit
|
386 |
|
|
tx_sr(8 downto 1) <= tx_dat_i; -- Load the TX data
|
387 |
|
|
tx_sr(9) <= '1'; -- Default the parity bit to one
|
388 |
|
|
if(tx_parity_i = "00") then --If no parity...
|
389 |
|
|
tx_bcnt <= "1010"; -- send start, 8 data bits, and stop
|
390 |
|
|
elsif (tx_parity_i = "01") then --If even parity...
|
391 |
|
|
tx_bcnt <= "1011"; -- send start, 8 data bits, parity, and stop
|
392 |
|
|
tx_sr(9) <= tx_dat_i(0) XOR tx_dat_i(1) XOR tx_dat_i(2) XOR tx_dat_i(3) XOR
|
393 |
|
|
tx_dat_i(4) XOR tx_dat_i(5) XOR tx_dat_i(6) XOR tx_dat_i(7);
|
394 |
|
|
else --If odd parity...
|
395 |
|
|
tx_bcnt <= "1011"; --send start, 8 data bits, parity, and stop
|
396 |
|
|
tx_sr(9) <= NOT (tx_dat_i(0) XOR tx_dat_i(1) XOR tx_dat_i(2) XOR tx_dat_i(3) XOR
|
397 |
|
|
tx_dat_i(4) XOR tx_dat_i(5) XOR tx_dat_i(6) XOR tx_dat_i(7));
|
398 |
|
|
end if;
|
399 |
|
|
tx_done <= '0';
|
400 |
|
|
-- Process through the remaining data
|
401 |
|
|
elsif(tx_bcnt>"0000" and do_txbit='1') then -- Still have bits to send?
|
402 |
|
|
tx_bcnt <= tx_bcnt-1;
|
403 |
|
|
tx_sr(8 downto 0) <= tx_sr(9 downto 1); -- Right shift the data (send LSB first)
|
404 |
|
|
tx_sr(9) <= '1';
|
405 |
|
|
tx_stream <= tx_sr(0);
|
406 |
|
|
end if;
|
407 |
|
|
-- Assert tx_done when truly finished.
|
408 |
|
|
if tx_almost_done='1' and tx_wr_i='0' then
|
409 |
|
|
tx_done <= '1';
|
410 |
|
|
end if;
|
411 |
|
|
end if; -- sys_clk_en
|
412 |
|
|
end if; -- sys_clk'event...
|
413 |
|
|
END PROCESS byte_tx;
|
414 |
|
|
|
415 |
|
|
tx_almost_done <= '1' when (tx_done='0' and tx_bcnt="0000" and do_txbit='1') else '0';
|
416 |
|
|
tx_done_o <= '1' when tx_done='1' or tx_almost_done='1' else '0';
|
417 |
|
|
|
418 |
|
|
end beh;
|
419 |
|
|
|
420 |
|
|
|
421 |
|
|
-------------------------------------------------------------------------------
|
422 |
|
|
-- Asynchronous Receiver With Output Buffer
|
423 |
|
|
-------------------------------------------------------------------------------
|
424 |
|
|
--
|
425 |
|
|
-- Author: John Clayton
|
426 |
|
|
-- Date : Aug 05, 2013 Added this change log header, which was missing.
|
427 |
|
|
-- Added first_edge signal to avoid erroneous initial
|
428 |
|
|
-- baud interval measurement (John Clayton & Philip
|
429 |
|
|
-- Kasavan)
|
430 |
|
|
-- Jan. 2, 2014 Added output buffer, changed idle_prep to include
|
431 |
|
|
-- the actual transition to IDLE state. Added
|
432 |
|
|
-- POST_RECV state, so that the rx_done_o signal will
|
433 |
|
|
-- reflect the true end of the received character.
|
434 |
|
|
-- This helps in applications where a received
|
435 |
|
|
-- asynchronous input is "echoed back" directly,
|
436 |
|
|
-- as the rx_wr_o signal can be used to switch the
|
437 |
|
|
-- signal at the correct time.
|
438 |
|
|
-- Feb. 6, 2014 Added requirement for half_baud to be non-zero
|
439 |
|
|
-- before leaving IDLE state. This prevents leaving
|
440 |
|
|
-- IDLE due to falling edges prior to the first Baud
|
441 |
|
|
-- interval measurement.
|
442 |
|
|
--
|
443 |
|
|
-- Description
|
444 |
|
|
-------------------------------------------------------------------------------
|
445 |
|
|
-- Squarewave tx_clk_i input determines rate.
|
446 |
|
|
-- (tx_clk_i does not really need to be a squarewave. Only the rising edges
|
447 |
|
|
-- are measured and used.)
|
448 |
|
|
--
|
449 |
|
|
-- Description:
|
450 |
|
|
-- This block receives asynchronous serial bytes. The Baudrate and parity
|
451 |
|
|
-- are determined by inputs, but the number of bits per character is
|
452 |
|
|
-- fixed at eight.
|
453 |
|
|
--
|
454 |
|
|
-- NOTES:
|
455 |
|
|
-- The receive input and baudrate clock are passed through two layers of
|
456 |
|
|
-- synchronizing flip-flops to mitigate metastability, since those signals can
|
457 |
|
|
-- originate outside of the sys_clk clock domain. All other logic connecting to
|
458 |
|
|
-- input of this function are assumed to be within the same clock domain.
|
459 |
|
|
--
|
460 |
|
|
-- The receiver looks for a new start bit immediately following the rx_wr_o
|
461 |
|
|
-- pulse, but rx_done_o is delayed until the expected end of the received
|
462 |
|
|
-- character. If a new start bit is detected just prior to the expected end
|
463 |
|
|
-- of the received character, then rx_done_o is not asserted.
|
464 |
|
|
--
|
465 |
|
|
-- Receive begins when the falling edge of the start bit is detected.
|
466 |
|
|
-- Then after 10 or 11 bit times have passed (depending on the parity setting)
|
467 |
|
|
-- the rx_wr_o signal will pulse high for one clock period, indicating rx_dat_o
|
468 |
|
|
-- contains valid receive data. The rx_wr_o pulse is only issued if there is
|
469 |
|
|
-- no parity error, and the stop bit is actually detected high at the sampling
|
470 |
|
|
-- time.
|
471 |
|
|
-- The rx_dat_o outputs will hold the received data until the next rx_wr_o pulse.
|
472 |
|
|
-- The rx_dat_o output provides the received data, even in the presence of a
|
473 |
|
|
-- parity or stop-bit error.
|
474 |
|
|
-- Error flags are valid during rx_wr_o, but they remain latched, until
|
475 |
|
|
-- rx_restart_i.
|
476 |
|
|
--
|
477 |
|
|
-- Although the receiver immediately restarts itself to receive the next
|
478 |
|
|
-- character, the rx_restart_i input can clear the error indicators. The rx_restart_i
|
479 |
|
|
-- input is like a synchronous reset in this respect since it will cause a receive
|
480 |
|
|
-- operation to abort.
|
481 |
|
|
--
|
482 |
|
|
|
483 |
|
|
library IEEE;
|
484 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
485 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
486 |
|
|
|
487 |
|
|
entity async_rx_sqclk is
|
488 |
|
|
port (
|
489 |
|
|
|
490 |
|
|
sys_rst_n : in std_logic;
|
491 |
|
|
sys_clk : in std_logic;
|
492 |
|
|
sys_clk_en : in std_logic;
|
493 |
|
|
|
494 |
|
|
-- rate and parity
|
495 |
|
|
rx_parity_i : in unsigned(1 downto 0); -- 0=none, 1=even, 2 or 3=odd
|
496 |
|
|
rx_clk_i : in std_logic;
|
497 |
|
|
|
498 |
|
|
-- serial input
|
499 |
|
|
rx_stream : in std_logic;
|
500 |
|
|
|
501 |
|
|
-- control and status
|
502 |
|
|
rx_restart_i : in std_logic; -- High clears error flags, synchronously resets receiver
|
503 |
|
|
rx_dat_o : out unsigned(7 downto 0);
|
504 |
|
|
rx_wr_o : out std_logic; -- High pulse means store rx_dat_o.
|
505 |
|
|
rx_done_o : out std_logic; -- Indicates receiver is idle
|
506 |
|
|
frame_err_o : out std_logic; -- High = error. Reset when rx_restart_i asserted.
|
507 |
|
|
parity_err_o : out std_logic -- High = error. Reset when rx_restart_i asserted.
|
508 |
|
|
);
|
509 |
|
|
end async_rx_sqclk;
|
510 |
|
|
|
511 |
|
|
architecture beh of async_rx_sqclk is
|
512 |
|
|
|
513 |
|
|
|
514 |
|
|
-- RX signals
|
515 |
|
|
-- rx_clk_i synchronizing flip-flops and rising edge detector
|
516 |
|
|
signal rx_clk_r1 : std_logic;
|
517 |
|
|
signal rx_clk_r2 : std_logic;
|
518 |
|
|
-- RX input synchronizing flip flops
|
519 |
|
|
signal rx_stream_r1 : std_logic;
|
520 |
|
|
signal rx_stream_r2 : std_logic;
|
521 |
|
|
-- RX signals
|
522 |
|
|
-- RX State Machine
|
523 |
|
|
type RX_STATE_TYPE is (IDLE, CHECK_START_1, CHECK_START_2, RECV_DATA, POST_RECV);
|
524 |
|
|
signal rx_state : RX_STATE_TYPE;
|
525 |
|
|
signal start_bit_start : std_logic; -- Signals falling edge of rx_stream_i
|
526 |
|
|
signal rx_sr : unsigned(8 downto 0); -- Shift register
|
527 |
|
|
signal rx_bcnt : unsigned(3 downto 0); -- Number of bits left, counts down
|
528 |
|
|
signal rx_bcnt_start : unsigned(3 downto 0); -- Total number of bits
|
529 |
|
|
signal rx_parity_good : std_logic;
|
530 |
|
|
-- Timers have been sized to hold baud interval for speeds as slow as 9600 bps at 100MHz sys_clk
|
531 |
|
|
signal rx_timer : unsigned(13 downto 0); -- Elapsed sys_clks from last bit time start
|
532 |
|
|
signal half_baud : unsigned(13 downto 0); -- One half of full_baud
|
533 |
|
|
signal full_baud : unsigned(13 downto 0); -- Baud interval, as measured from rx_clk_i
|
534 |
|
|
signal baud_timer : unsigned(13 downto 0); -- Used to measure baud interval
|
535 |
|
|
signal bit_sampled : std_logic; -- High indicates bit is already sampled, don't allow resampling.
|
536 |
|
|
|
537 |
|
|
signal first_edge : std_logic;
|
538 |
|
|
|
539 |
|
|
begin
|
540 |
|
|
|
541 |
|
|
-- Synchronizing flip flops to avoid metastability issues...
|
542 |
|
|
rx_stream_syncproc: Process(sys_rst_n,sys_clk)
|
543 |
|
|
BEGIN
|
544 |
|
|
if (sys_rst_n = '0') then
|
545 |
|
|
rx_stream_r1 <= '1';
|
546 |
|
|
rx_stream_r2 <= '1';
|
547 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
548 |
|
|
if (sys_clk_en='1') then
|
549 |
|
|
rx_stream_r2 <= rx_stream_r1;
|
550 |
|
|
rx_stream_r1 <= rx_stream;
|
551 |
|
|
end if;
|
552 |
|
|
end if;
|
553 |
|
|
END PROCESS rx_stream_syncproc;
|
554 |
|
|
start_bit_start <= rx_stream_r2 and not rx_stream_r1;
|
555 |
|
|
|
556 |
|
|
-- Synchronizing flip flops to avoid metastability issues...
|
557 |
|
|
rx_clk_syncproc: Process(sys_rst_n,sys_clk)
|
558 |
|
|
BEGIN
|
559 |
|
|
if (sys_rst_n = '0') then
|
560 |
|
|
rx_clk_r1 <= '0';
|
561 |
|
|
rx_clk_r2 <= '0';
|
562 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
563 |
|
|
if (sys_clk_en='1') then
|
564 |
|
|
rx_clk_r2 <= rx_clk_r1;
|
565 |
|
|
rx_clk_r1 <= rx_clk_i;
|
566 |
|
|
end if;
|
567 |
|
|
end if;
|
568 |
|
|
END PROCESS rx_clk_syncproc;
|
569 |
|
|
|
570 |
|
|
-- This is the baud interval measuring process.
|
571 |
|
|
-- Measurements are only made between rising edges
|
572 |
|
|
baud_measure_proc: Process(sys_rst_n,sys_clk)
|
573 |
|
|
BEGIN
|
574 |
|
|
if (sys_rst_n = '0') then
|
575 |
|
|
full_baud <= (others=>'0');
|
576 |
|
|
baud_timer <= (others=>'0');
|
577 |
|
|
first_edge <= '0';
|
578 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
579 |
|
|
if (sys_clk_en='1') then
|
580 |
|
|
if(first_edge = '1')then
|
581 |
|
|
if (rx_clk_r1='1' and rx_clk_r2='0') then
|
582 |
|
|
full_baud <= baud_timer;
|
583 |
|
|
baud_timer <= (others=>'0');
|
584 |
|
|
else
|
585 |
|
|
baud_timer <= baud_timer+1;
|
586 |
|
|
end if;
|
587 |
|
|
elsif(rx_clk_r1='1' and rx_clk_r2='0') then
|
588 |
|
|
first_edge <= '1';
|
589 |
|
|
end if;
|
590 |
|
|
end if;
|
591 |
|
|
end if;
|
592 |
|
|
END PROCESS baud_measure_proc;
|
593 |
|
|
|
594 |
|
|
|
595 |
|
|
-- This process handles the incoming bits
|
596 |
|
|
uart_rx_bits: Process(sys_rst_n,sys_clk)
|
597 |
|
|
|
598 |
|
|
procedure idle_prep is
|
599 |
|
|
begin
|
600 |
|
|
rx_done_o <= '1';
|
601 |
|
|
bit_sampled <= '0';
|
602 |
|
|
rx_bcnt <= (others=>'0');
|
603 |
|
|
rx_timer <= (others=>'0');
|
604 |
|
|
rx_state <= IDLE;
|
605 |
|
|
end idle_prep;
|
606 |
|
|
|
607 |
|
|
begin
|
608 |
|
|
if (sys_rst_n = '0') then
|
609 |
|
|
idle_prep;
|
610 |
|
|
rx_sr <= (others=>'0');
|
611 |
|
|
frame_err_o <= '0';
|
612 |
|
|
parity_err_o <= '0';
|
613 |
|
|
rx_wr_o <= '0';
|
614 |
|
|
rx_dat_o <= (others=>'0');
|
615 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
616 |
|
|
if (sys_clk_en='1') then
|
617 |
|
|
-- Default values
|
618 |
|
|
rx_wr_o <= '0'; -- Default to no data write
|
619 |
|
|
-- Handle incrementing the sample timer
|
620 |
|
|
rx_timer<=rx_timer+1;
|
621 |
|
|
-- State transitions
|
622 |
|
|
case rx_state is
|
623 |
|
|
|
624 |
|
|
when IDLE =>
|
625 |
|
|
rx_done_o <= '1'; -- Indicate receive is done.
|
626 |
|
|
bit_sampled <= '0'; -- Indicate bit is not yet sampled.
|
627 |
|
|
if (rx_restart_i='1') then
|
628 |
|
|
idle_prep;
|
629 |
|
|
frame_err_o <= '0'; -- At rx_restart, also clear error flags
|
630 |
|
|
parity_err_o <= '0';
|
631 |
|
|
elsif (half_baud/=0 and start_bit_start='1') then
|
632 |
|
|
rx_timer <= (others=>'0'); -- Reset timer back to zero
|
633 |
|
|
rx_bcnt <= rx_bcnt_start; -- Initialize bit counter
|
634 |
|
|
rx_done_o <= '0';
|
635 |
|
|
rx_state <= CHECK_START_1;
|
636 |
|
|
end if;
|
637 |
|
|
|
638 |
|
|
when CHECK_START_1 =>
|
639 |
|
|
if (rx_restart_i='1') then -- Restart has very high priority
|
640 |
|
|
idle_prep;
|
641 |
|
|
elsif (rx_stream_r2='1') then -- High during this time is an error
|
642 |
|
|
frame_err_o <= '1';
|
643 |
|
|
idle_prep;
|
644 |
|
|
elsif (rx_timer>=half_baud) then -- Must use >= since threshold may change downward
|
645 |
|
|
rx_state <= CHECK_START_2;
|
646 |
|
|
end if;
|
647 |
|
|
|
648 |
|
|
when CHECK_START_2 => -- During second half of start bit, don't verify low level
|
649 |
|
|
if (rx_restart_i='1') then -- Restart has very high priority
|
650 |
|
|
idle_prep;
|
651 |
|
|
elsif (rx_timer>=full_baud or rx_stream_r2='1') then -- Wait for end of start bit
|
652 |
|
|
rx_timer <= (others=>'0'); -- Reset timer back to zero
|
653 |
|
|
rx_state <= RECV_DATA;
|
654 |
|
|
end if;
|
655 |
|
|
|
656 |
|
|
when RECV_DATA =>
|
657 |
|
|
if (rx_restart_i='1') then -- Restart has very high priority
|
658 |
|
|
idle_prep;
|
659 |
|
|
elsif (rx_timer>=full_baud) then -- Must use >= since threshold may change downward
|
660 |
|
|
rx_timer <= (others=>'0'); -- Reset timer back to zero
|
661 |
|
|
bit_sampled <= '0';
|
662 |
|
|
elsif (rx_timer>=half_baud and bit_sampled='0') then -- Must use >= since threshold may change downward
|
663 |
|
|
bit_sampled <= '1';
|
664 |
|
|
if (rx_bcnt="0000") then
|
665 |
|
|
rx_state <= POST_RECV;
|
666 |
|
|
rx_dat_o <= rx_sr(7 downto 0);
|
667 |
|
|
if (rx_parity_good='1' and rx_stream_r2='1') then
|
668 |
|
|
rx_wr_o <= '1'; -- If all is correct, create a one clock long pulse to store rx_dat_o.
|
669 |
|
|
else
|
670 |
|
|
if (rx_stream_r2='0') then
|
671 |
|
|
frame_err_o <= '1'; -- Record error if there is a bad stop bit
|
672 |
|
|
end if;
|
673 |
|
|
if (rx_parity_good='0') then
|
674 |
|
|
parity_err_o <= '1'; -- Record error if there is bad parity
|
675 |
|
|
end if;
|
676 |
|
|
end if;
|
677 |
|
|
else -- Process a new bit
|
678 |
|
|
rx_sr(7 downto 0) <= rx_sr(8 downto 1);
|
679 |
|
|
if (rx_parity_i = "00") then
|
680 |
|
|
rx_sr(7) <= rx_stream_r2; -- Store the new incoming bit
|
681 |
|
|
else
|
682 |
|
|
rx_sr(8) <= rx_stream_r2;
|
683 |
|
|
end if;
|
684 |
|
|
rx_bcnt <= rx_bcnt-1;
|
685 |
|
|
end if;
|
686 |
|
|
end if;
|
687 |
|
|
|
688 |
|
|
when POST_RECV => -- Wait out latter half of stop bit, checking for start bits...
|
689 |
|
|
if (rx_restart_i='1') then
|
690 |
|
|
bit_sampled <= '0';
|
691 |
|
|
frame_err_o <= '0'; -- At rx_restart, also clear error flags
|
692 |
|
|
parity_err_o <= '0';
|
693 |
|
|
idle_prep;
|
694 |
|
|
elsif (start_bit_start='1') then
|
695 |
|
|
bit_sampled <= '0';
|
696 |
|
|
rx_timer <= (others=>'0'); -- Reset timer back to zero
|
697 |
|
|
rx_bcnt <= rx_bcnt_start; -- Initialize bit counter
|
698 |
|
|
rx_done_o <= '0';
|
699 |
|
|
rx_state <= CHECK_START_1;
|
700 |
|
|
elsif (rx_timer>=full_baud) then -- Wait for end of start bit
|
701 |
|
|
bit_sampled <= '0'; -- Indicate bit is not yet sampled.
|
702 |
|
|
idle_prep; -- Asserts rx_done_o to indicate completion
|
703 |
|
|
end if;
|
704 |
|
|
|
705 |
|
|
when others => null;
|
706 |
|
|
|
707 |
|
|
end case;
|
708 |
|
|
end if;
|
709 |
|
|
end if;
|
710 |
|
|
end process uart_rx_bits;
|
711 |
|
|
|
712 |
|
|
-------------------------
|
713 |
|
|
-- Assign number of bits to shift in.
|
714 |
|
|
rx_bcnt_start <= "1000" when (rx_parity_i="00") else "1001";
|
715 |
|
|
|
716 |
|
|
-------------------------
|
717 |
|
|
-- Assign half baud period
|
718 |
|
|
half_baud <= ('0' & full_baud(13 downto 1));
|
719 |
|
|
|
720 |
|
|
-------------------------
|
721 |
|
|
-- Parity check process
|
722 |
|
|
rx_parity_check: process(rx_sr, rx_parity_i)
|
723 |
|
|
begin
|
724 |
|
|
if (rx_parity_i="00") then -- No parity...
|
725 |
|
|
rx_parity_good <= '1'; -- (always good.)
|
726 |
|
|
elsif (rx_parity_i="01") then -- Even parity...
|
727 |
|
|
rx_parity_good <= not (rx_sr(0) XOR rx_sr(1) XOR rx_sr(2) XOR rx_sr(3) XOR rx_sr(4)
|
728 |
|
|
XOR rx_sr(5) XOR rx_sr(6) XOR rx_sr(7) XOR rx_sr(8));
|
729 |
|
|
else -- Odd parity...
|
730 |
|
|
rx_parity_good <= (rx_sr(0) XOR rx_sr(1) XOR rx_sr(2) XOR rx_sr(3) XOR rx_sr(4)
|
731 |
|
|
XOR rx_sr(5) XOR rx_sr(6) XOR rx_sr(7) XOR rx_sr(8));
|
732 |
|
|
end if;
|
733 |
|
|
end process;
|
734 |
|
|
|
735 |
|
|
end beh;
|
736 |
|
|
|
737 |
|
|
|
738 |
|
|
-------------------------------------------------------------------------------
|
739 |
|
|
-- Half Duplex Switch -- automatic priority to TX, with "hang timer" and delay
|
740 |
|
|
-------------------------------------------------------------------------------
|
741 |
|
|
--
|
742 |
|
|
-- Author: John Clayton
|
743 |
|
|
-- Date : Oct. 09, 2015 Initial creation.
|
744 |
|
|
-- Oct. 20, 2015 Updated to include delay, thereby allowing for
|
745 |
|
|
-- switching from TX to RX at the very end of the
|
746 |
|
|
-- TX data, at the expense of waiting additional
|
747 |
|
|
-- time for the TX data to emerge.
|
748 |
|
|
--
|
749 |
|
|
-- Description
|
750 |
|
|
-------------------------------------------------------------------------------
|
751 |
|
|
--
|
752 |
|
|
-- This unit implements a simple switch for routing both TX and RX signals
|
753 |
|
|
-- over a single wire, called "half duplex" communication. This is needed
|
754 |
|
|
-- for 2 wire RS-232 or 3 wire RS-485/RS-422 communications.
|
755 |
|
|
--
|
756 |
|
|
-- The switch immediately goes into transmit mode when the non-idle state
|
757 |
|
|
-- is detected on the tx_i input. After HANG_TIME rising edges of the
|
758 |
|
|
-- tick_i input, with the idle state continuously present on the tx_i input,
|
759 |
|
|
-- the switch reverts to the receive mode. The tick_i may be connected
|
760 |
|
|
-- to the Baudrate clock, or any other desired clock, but it must not
|
761 |
|
|
-- be tied to a constant value, since the edges are needed to advance
|
762 |
|
|
-- the timer.
|
763 |
|
|
--
|
764 |
|
|
-- It is recommended to set HANG_TIME to exceed the time needed for one
|
765 |
|
|
-- character to be transmitted, since that will prevent mid-character
|
766 |
|
|
-- timeouts.
|
767 |
|
|
--
|
768 |
|
|
-- An additional parameter, DELAY, allows for the transmit data to be
|
769 |
|
|
-- delayed by DELAY rising edges of the tick_i input. Note that this
|
770 |
|
|
-- delays the TX data after the activity check, so that the moment when
|
771 |
|
|
-- the "hang" timer expires can effectively be lined up with the end of
|
772 |
|
|
-- the final TX data byte. Take care! If DELAY is set greater than
|
773 |
|
|
-- HANG_TIME, then some of the TX data can be effectively curtailed.
|
774 |
|
|
--
|
775 |
|
|
-- Note that the delay shift register effectively samples tx_i data
|
776 |
|
|
-- on the detected rising edges of tick_i. Thus, tick_i rising edges
|
777 |
|
|
-- should be a synchronized 1x Baud rate clock, or else an unsynchronized
|
778 |
|
|
-- clock at more than 2x the Baud rate, to satisfy Nyquist criteria. By
|
779 |
|
|
-- setting DELAY=0, this constraint is removed, since the shift register
|
780 |
|
|
-- is not used for zero DELAY, and no re-sampling of tx_i actually occurs.
|
781 |
|
|
--
|
782 |
|
|
-- The hd_drive_o signal is provided so that tristates may be kept at the top
|
783 |
|
|
-- level of the system.
|
784 |
|
|
--
|
785 |
|
|
-- No synchronization flip flops are implemented within this switch
|
786 |
|
|
-- module. If needed, they are assumed to be included elsewhere.
|
787 |
|
|
--
|
788 |
|
|
|
789 |
|
|
library IEEE;
|
790 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
791 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
792 |
|
|
|
793 |
|
|
library work;
|
794 |
|
|
use work.convert_pack.all;
|
795 |
|
|
|
796 |
|
|
entity half_duplex_switch is
|
797 |
|
|
generic (
|
798 |
|
|
HANG_TIME : natural := 12; -- Units of timer_i rising edges
|
799 |
|
|
TX_DELAY : natural := 12 -- Units of timer_i rising edges
|
800 |
|
|
);
|
801 |
|
|
port (
|
802 |
|
|
|
803 |
|
|
sys_rst_n : in std_logic;
|
804 |
|
|
sys_clk : in std_logic;
|
805 |
|
|
sys_clk_en : in std_logic;
|
806 |
|
|
|
807 |
|
|
-- Full Duplex side
|
808 |
|
|
tx_i : in std_logic;
|
809 |
|
|
rx_o : out std_logic;
|
810 |
|
|
|
811 |
|
|
-- Half Duplex side
|
812 |
|
|
hd_o : out std_logic;
|
813 |
|
|
hd_i : in std_logic;
|
814 |
|
|
hd_drive_o : out std_logic;
|
815 |
|
|
|
816 |
|
|
-- Timer
|
817 |
|
|
tick_i : in std_logic
|
818 |
|
|
);
|
819 |
|
|
end half_duplex_switch;
|
820 |
|
|
|
821 |
|
|
architecture beh of half_duplex_switch is
|
822 |
|
|
|
823 |
|
|
-- TX signals
|
824 |
|
|
signal timer : unsigned(timer_width(HANG_TIME)-1 downto 0);
|
825 |
|
|
signal delay_sr : unsigned(15 downto 0);
|
826 |
|
|
signal tick_r1 : std_logic;
|
827 |
|
|
signal tx_data : std_logic;
|
828 |
|
|
|
829 |
|
|
begin
|
830 |
|
|
|
831 |
|
|
main_proc: Process(sys_rst_n,sys_clk)
|
832 |
|
|
begin
|
833 |
|
|
if (sys_rst_n = '0') then
|
834 |
|
|
tick_r1 <= '0';
|
835 |
|
|
timer <= (others=>'0');
|
836 |
|
|
delay_sr <= (others=>'1');
|
837 |
|
|
elsif (sys_clk'event AND sys_clk='1') then
|
838 |
|
|
if (sys_clk_en='1') then
|
839 |
|
|
tick_r1 <= tick_i;
|
840 |
|
|
-- Handle the delay shift register
|
841 |
|
|
if (tick_r1='0' and tick_i='1') then
|
842 |
|
|
delay_sr <= delay_sr(14 downto 0) & tx_i;
|
843 |
|
|
end if;
|
844 |
|
|
-- Handle the hang timer
|
845 |
|
|
if (tx_i='0') then
|
846 |
|
|
timer <= to_unsigned(HANG_TIME,timer'length);
|
847 |
|
|
elsif (tick_r1='0' and tick_i='1') then
|
848 |
|
|
if (timer>0) then
|
849 |
|
|
timer <= timer-1;
|
850 |
|
|
end if;
|
851 |
|
|
end if;
|
852 |
|
|
end if;
|
853 |
|
|
end if;
|
854 |
|
|
end process main_proc;
|
855 |
|
|
|
856 |
|
|
tx_data <= tx_i when (TX_DELAY=0) else delay_sr(TX_DELAY-1);
|
857 |
|
|
|
858 |
|
|
rx_o <= '1' when (timer>0) else hd_i;
|
859 |
|
|
hd_o <= tx_data when (timer>0) else '1';
|
860 |
|
|
hd_drive_o <= '1' when (timer>0) else '0';
|
861 |
|
|
|
862 |
|
|
end beh;
|
863 |
|
|
|
864 |
|
|
|