⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.vhd

📁 CPLDFPGA嵌入式应用开发技术白金手册所配套源代码
💻 VHD
字号:
----------------------------------------------------------------
--
-- Copyright (c) 1992,1993,1994, Exemplar Logic Inc. All rights reserved.
--
----------------------------------------------------------------
--
-- This design implements a UART. 
--
-- 
--     Version 1.1 : Original Creation
--     Version 1.2 : Modified to std_logic types
--     Version 2.1 : Extended reset to be more effective.
--                   Introduced OTHERS clause.
--	download from: www.pld.com.cn & www.fpga.com.cn 
----------------------------------------------------------------




LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;



ENTITY uart IS
    PORT (clkx16 : IN    std_logic;	-- Input clock. 16x bit clock
            read : IN    std_logic;	-- Received data read strobe
	      rx : IN    std_logic;	-- Receive  data line
	   reset : IN    std_logic;	-- clear dependencies
           rxrdy : OUT   std_logic;	-- Received data ready to be read
       parityerr : OUT   std_logic;	-- Receiver parity error
      framingerr : OUT   std_logic;	-- Receiver framing error
         overrun : OUT   std_logic;	-- Receiver overrun error 
	    data : out std_logic_vector(7 downto 0)); -- Bidirectional data bus
END uart;

ARCHITECTURE exemplar OF uart IS

    -- Receive shift register bits
    SIGNAL      rxhold : std_logic_vector(0 TO 7);-- Holds received data for read
    SIGNAL       rxreg : std_logic_vector(0 TO 7);-- Receive data shift register
    SIGNAL    rxparity : std_logic;	-- Parity bit of received data
    SIGNAL   paritygen : std_logic;	-- Generated parity of received data
    SIGNAL      rxstop : std_logic;	-- Stop bit of received data

    -- Receive clock and control signals
    SIGNAL       rxclk : std_logic;		-- Receive data shift clock
    SIGNAL      rxidle : std_logic;     -- '1' when receiver is idling
    SIGNAL   rxdatardy : std_logic;     -- '1' when data is ready to be read

BEGIN 


make_rxclk:
    PROCESS  (reset, clkx16) 
	VARIABLE rxcnt : std_logic_vector(0 TO 3); -- Count of clock cycles
	VARIABLE rx1   : std_logic;	-- rx delayed one cycle
	VARIABLE hunt  : boolean;	-- Hunting for start bit 
    BEGIN
	IF reset='1' THEN
	    -- Reset all generated signals and variables
	    hunt := FALSE ;
	    rxcnt := (OTHERS=>'0') ;
	    rx1 := '0' ;
	    rxclk <= '0' ;
	ELSIF clkx16'EVENT AND clkx16 = '1' THEN

	    -- rxclk = clkx16 divided by 16 
	    rxclk <= rxcnt(0);

	    -- Hunt=TRUE when we are looking for a start bit:
	    --  A start bit is eight clock times with rx=0 after a falling edge

	    IF (rxidle = '1' AND rx = '0' AND rx1 = '1') THEN
                -- Start hunting when idle and falling edge is found
	        hunt := TRUE;
	    END IF ;
	    IF rxidle = '0' OR rx = '1' THEN
	        -- Stop hunting when shifting in data or a 1 is found on rx
	        hunt := FALSE;
	    END IF;
	    rx1 := rx;	-- rx delayed by one clock for edge detection
			-- (Must be assigned AFTER reference)

	    -- Increment count when not idling or when hunting
	    IF (rxidle = '0' OR hunt) THEN
	        -- Count clocks when not rxidle or hunting for start bit
	        rxcnt := rxcnt + "0001";
	    ELSE
	        -- hold at 1 when rxidle and waiting for falling edge
	        rxcnt := "0001";
	    END IF;
	END IF ;
    END PROCESS;

-- transmit shift register:
rx_proc: 	-- Shift data on each rxclk when not idling
    PROCESS (reset, rxclk) 
    BEGIN
	IF reset='1' THEN
	    rxreg <= (OTHERS=>'0') ;
            rxparity <= '0' ;
            paritygen <= '0' ;
            rxstop <= '0' ;
	ELSIF rxclk'event AND rxclk = '1' THEN
	    IF rxidle = '1' THEN 
	        -- Load all ones when idling
	        rxreg <= (OTHERS=>'1');
	        rxparity <= '1';
	        paritygen <= '1';	-- Odd parity
	        rxstop <= '0';
	    ELSE
	        -- Shift data when not idling
	        -- bug in assigning to slices
	        -- rxreg (0 TO 6) <= rxreg (1 TO 7);
	        -- rxreg(7) <= rxparity;
	        rxreg <= rxreg (1 TO 7) & rxparity;
	        rxparity <= rxstop;
	        paritygen <= paritygen XOR rxstop;-- Form parity as data shifts by
	        rxstop <= rx;
	    END IF ;
        END IF;
    END PROCESS;

    
async:  -- rxidle requires async preset since it is clocked by rxclk and  
        -- its value determines whether rxclk gets generated 
    PROCESS ( reset, rxclk )
    BEGIN
        IF reset = '1' THEN
           rxidle <= '0';
        ELSIF rxclk'EVENT and rxclk = '1' THEN
           rxidle <= NOT rxidle AND NOT rxreg(0);
        END IF;
    END PROCESS async;

rxio:
    PROCESS (reset, clkx16)
	VARIABLE rd1, rd2 : std_logic;	-- Read input delayed 1 and 2 cycles
	VARIABLE rxidle1  : std_logic;	-- rxidle signal delayed 1 cycle
    BEGIN
	IF reset='1' THEN
	    overrun <= '0' ;
	    rxhold <= (OTHERS=>'0') ;
	    parityerr <= '0' ;
            framingerr <= '0' ;
	    rxdatardy <= '0' ;
	    rd1 := '0' ;
            rd2 := '0' ;
	    rxidle1 := '0' ;
	ELSIF clkx16'event AND clkx16 = '1' THEN

	    -- Look for rising edge on idle and update output registers
	    IF rxidle = '1' AND rxidle1 = '0' THEN
	        IF rxdatardy = '1' THEN
	    	    -- Overrun error if previous data is still there
		    overrun <= '1';
	        ELSE
		    -- No overrun error since holding register is empty
		    overrun <= '0';

		    -- Update holding register
		    rxhold <= rxreg;

		    -- paritygen = 1 if parity error
		    parityerr <= paritygen;

		    -- Framingerror if stop bit is not 1
		    framingerr <= NOT rxstop;

		    -- Signal that data is ready for reading
		    rxdatardy <= '1';
	        END IF;
	    END IF;
	    rxidle1 := rxidle;	-- rxidle delayed 1 cycle for edge detect

	    --  Clear error and data registers when data is read
	    IF (NOT rd2 AND rd1) = '1' THEN
	        rxdatardy  <= '0';
	        parityerr  <= '0';
	        framingerr <= '0';
	        overrun    <= '0';
	    END IF;
	    rd2 := rd1;	-- Edge detect for read
	    rd1 := read;	-- (Must be assigned AFTER reference)
	    IF reset = '1' THEN 
	        rxdatardy <= '0'; 
	    END IF;
	END IF ;
    END PROCESS;
      -- Drive data bus only during read
    data <= rxhold WHEN read = '1' ELSE (OTHERS=>'Z') ;
    -- Latch data bus during write
    -- Receive data ready output signal
    rxrdy <= rxdatardy;
    -- Transmitter ready for write when no data is in txhold
    -- Run-time simulation check for transmit overrun
END exemplar;


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -