| 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 |
|
|
|