library Synopsys, IEEE; -- use Synopsys.types.all; use Synopsys.attributes.all; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; --use IEEE.std_logic_signed.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_misc.all; library XC4000; use XC4000.components.all; entity UART is port(signal OREADY,SDATAOUT : inout std_logic; -- next line for timing sim only! signal GSR : in std_logic; signal SDATAIN : in std_logic; signal IREADY: inout std_logic; signal CHARIN : inout std_logic_vector(7 downto 0); signal CHAROUT : inout std_logic_vector(7 downto 0); signal BAUD_CLOCK,RESET : in std_logic; signal WRITE,READ : inout std_logic); end UART; -- -- architecture -- architecture behavior of UART is signal CLKCNT, OUTCNT, INCNT, SYNCNT : std_logic_vector(3 downto 0); signal SHIFTOUT : std_logic_vector(9 downto 0); signal CHAROUT_BUF : std_logic_vector(7 downto 0); signal SHIFTIN : std_logic_vector(7 downto 0); signal BITCLK, OLDSDIN, READ_CHAR : std_logic; signal IREADY_SET, IREADY_CLR, WRITE_CLR, WRITE_REQ: std_logic; signal INFLAG: std_logic; begin -- behaviour of UART ------------------------------------------------------------------------------ --This process sends input data back out as outputdata --For testing only - replace with your computer`s I/O operations --TO write: -- wait for oready, set charout=ASCII character to output and strobe write --TO read: -- wait for iready, read in charin and strobe read high -- Note: must also change some inout vars to in or out when removing ECHO ECHO: process begin WRITE<='0'; READ<='0'; INFLAG<='0'; wait until (BITCLK'event and BITCLK='1'); If IREADY='1' then CHAROUT<=CHARIN; INFLAG<='1'; end if; wait until (BITCLK'event and BITCLK='1'); If OREADY='1' AND IREADY='1' AND INFLAG='1' then READ<='1'; WRITE<='1'; end if; wait until (BITCLK'event and BITCLK='1'); end process ECHO; ------------------------------------------------------------------------------- --This process syncs characters to output to the baudrate clock WRITE_UART: process begin wait until (WRITE'event and WRITE='1'); CHAROUT_BUF<=CHAROUT; end process WRITE_UART; ------------------------------------------------------------------------------- --This process generates IREADY_CLR READ_UART: process(READ) begin IF READ='1' then IREADY_CLR<='1'; else IREADY_CLR<='0'; end if; end process READ_UART; ------------------------------------------------------------------------------- -- The process generates IREADY -- Tricky because of async. clocks in uart -- Process READ_UART generates IREADY_CLR -- Process RECV_UART generates IREADY_SET GEN_IREADY: process(IREADY_SET,IREADY_CLR,RESET) begin If RESET='1' then IREADY<='0'; else If IREADY_CLR='1' then IREADY<='0'; else If IREADY_SET'EVENT AND IREADY_SET='1' then IREADY<='1'; end if; end if; end if; end process GEN_IREADY; ------------------------------------------------------------------------------- -- The process generates WRITE_REQ -- Tricky because of async. clocks in uart -- Process ECHO_UART generates WRITE - SETS WRITE_REQ -- Process SEND_UART generates WRITE_CLR GEN_WRITE_REQ: process(WRITE,WRITE_CLR,RESET) begin If RESET='1' then WRITE_REQ<='0'; else If WRITE_CLR='1' then WRITE_REQ<='0'; else If WRITE'EVENT AND WRITE='1' then WRITE_REQ<='1'; end if; end if; end if; end process GEN_WRITE_REQ; --------------------------------------------------------------------------------- --This process sends serial data out to the terminal SEND_UART: process begin wait until (BAUD_CLOCK'event and BAUD_CLOCK='1'); If RESET='1' then OREADY <= '1'; SDATAOUT<= '1'; SHIFTOUT(9) <= '1'; SHIFTOUT(8 Downto 1) <=conv_std_logic_vector(-1,8); SHIFTOUT(0) <= '0'; CLKCNT <= conv_std_logic_vector(0,4); OUTCNT <= conv_std_logic_vector(0,4); WRITE_CLR <= '0'; else CLKCNT <= CLKCNT + conv_std_logic_vector(1,4); end if; -- UART WRITE OPERATION? If WRITE_REQ='1' then SHIFTOUT(8 downto 1) <= CHAROUT_BUF; SHIFTOUT(9) <= '1'; SHIFTOUT(0) <= '0'; OREADY <= '0'; CLKCNT <= conv_std_logic_vector(0,4); OUTCNT <= conv_std_logic_vector(0,4); WRITE_CLR <='1'; end if; -- END OF CHAR? If CLKCNT= conv_std_logic_vector(-1,4) AND OUTCNT=conv_std_logic_vector(-6,4) then OREADY<='1'; OUTCNT <= conv_std_logic_vector(0,4); -- START AND STOP BITS SHIFTOUT(9) <= '1'; SHIFTOUT(0) <= '0'; else -- SEND OUT NEXT SERIAL BIT? If CLKCNT= conv_std_logic_vector(-1,4) then If OREADY='0' then OUTCNT <= OUTCNT + conv_std_logic_vector(1,4); SDATAOUT <= SHIFTOUT(0); -- Loopback for testing -- SDATAIN <= SHIFTOUT(0); SHIFTOUT(8 DOWNTO 0) <= SHIFTOUT(9 DOWNTO 1); WRITE_CLR <='0'; end if; end if; end if; end process SEND_UART; -------------------------------------------------------------------------------- --This process reads in serial data coming from the terminal RECV_UART: process begin wait until (BITCLK'event and BITCLK='1'); If RESET='1' then INCNT <= conv_std_logic_vector(0,4); IREADY_SET <= '0'; READ_CHAR <= '0'; else If SDATAIN='0' AND READ_CHAR='0' then READ_CHAR<= '1'; IREADY_SET<= '0'; else -- SHIFT IN NEXT SERIAL BIT If READ_CHAR = '1' then IF INCNT/= conv_std_logic_vector(-8,4) then INCNT <= INCNT + conv_std_logic_vector(1,4); SHIFTIN(6 DOWNTO 0) <= SHIFTIN(7 DOWNTO 1); SHIFTIN(7) <= SDATAIN; IREADY_SET <= '0'; -- END OF CHARACTER else CHARIN <= SHIFTIN(7 DOWNTO 0); READ_CHAR<='0'; IREADY_SET <= '1'; INCNT <= conv_std_logic_vector(0,4); end if; end if; end if; end if; end process RECV_UART; -------------------------------------------------------------------------------- -- DERIVES BITCLK FOR RECV process FROM INCOMING SERIAL DATA SYNC_SDIN: process begin wait until (BAUD_CLOCK'event and BAUD_CLOCK='1'); If RESET='1' then BITCLK<= '1'; OLDSDIN<= '1'; SYNCNT <= conv_std_logic_vector(0,4); else IF SDATAIN/=OLDSDIN then SYNCNT <= conv_std_logic_vector(0,4); BITCLK <='0'; OLDSDIN<=SDATAIN; else IF SYNCNT=conv_std_logic_vector(-1,4) then SYNCNT <= conv_std_logic_vector(0,4); BITCLK <='0'; else IF SYNCNT=conv_std_logic_vector(7,4) then BITCLK <='1'; end if; SYNCNT <= SYNCNT + conv_std_logic_vector(1,4); end if; end if; end if; end process SYNC_SDIN; end behavior;