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

📄 一个简单的uart.htm

📁 采用VHDL编写的一个简单的UART
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0056)http://www.fpga.com.cn/hdl/vhdl_example/UART/uart_ls.vhd -->
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1458" name=GENERATOR></HEAD>
<BODY><PRE>----------------------------------------------------------------
--
-- 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 &amp; 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
           write : IN    std_logic;	-- Transmit data write strobe
	      rx : IN    std_logic;	-- Receive  data line
	   reset : IN    std_logic;	-- clear dependencies
	      tx : OUT   std_logic;	-- Transmit data line
           rxrdy : OUT   std_logic;	-- Received data ready to be read
           txrdy : OUT   std_logic;	-- Transmitter ready for next byte
       parityerr : OUT   std_logic;	-- Receiver parity error
      framingerr : OUT   std_logic;	-- Receiver framing error
         overrun : OUT   std_logic;	-- Receiver overrun error 
	    data : INOUT std_logic_vector(0 TO 7)); -- Bidirectional data bus
END uart;

ARCHITECTURE exemplar OF uart IS
    -- Transmit data holding register
    SIGNAL      txhold : std_logic_vector(0 TO 7);

    -- Transmit shift register bits
    SIGNAL       txreg : std_logic_vector(0 TO 7);
    SIGNAL      txtag2 : std_logic;	-- tag bits for detecting 
    SIGNAL      txtag1 : std_logic;	--    empty shift reg
    SIGNAL    txparity : std_logic;	-- Parity generation register

    -- Transmit clock and control signals
    SIGNAL       txclk : std_logic;     -- Transmit clock: 1/16th of clkx16
    SIGNAL      txdone : std_logic;	-- '1' when shifting of byte is done
    SIGNAL paritycycle : std_logic;	-- '1' on next to last shift cycle
    SIGNAL   txdatardy : std_logic;     -- '1' when data is ready in txhold

    -- 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_txclk:
    PROCESS (reset, clkx16)
	VARIABLE cnt  : std_logic_vector(2 DOWNTO 0);
    BEGIN
	-- Toggle txclk every 8 counts, which divides the clock by 16
	IF reset='1' THEN
	    txclk &lt;= '0' ;
	    cnt := (OTHERS=&gt;'0') ;
	ELSIF clkx16'event AND clkx16='1' THEN
	    IF (cnt = "000") THEN 
	        txclk &lt;= NOT txclk; 
	    END IF;
	    cnt := cnt + "001"; -- Use the exemplar_1164 "+" on std_logic_vector
	END IF;
    END PROCESS;

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=&gt;'0') ;
	    rx1 := '0' ;
	    rxclk &lt;= '0' ;
	ELSIF clkx16'EVENT AND clkx16 = '1' THEN

	    -- rxclk = clkx16 divided by 16 
	    rxclk &lt;= 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:
txshift:
    PROCESS (reset, txclk)
    BEGIN
	IF reset='1' THEN
	    txreg &lt;= (OTHERS=&gt;'0') ; 
	    txtag1 &lt;= '0' ;
	    txtag2 &lt;= '0' ;
            txparity &lt;= '0' ;
	    tx &lt;= '0' ;
	ELSIF txclk'event AND txclk = '1' THEN 
	    IF (txdone AND txdatardy) = '1'  THEN
	        -- Initialize registers and load next byte of data
	        txreg    &lt;= txhold; -- Load tx register from txhold
	        txtag2   &lt;= '1';    -- Tag bits for detecting 
	        txtag1   &lt;= '1';    --    when shifting is done
	        txparity &lt;= '1';    -- Parity bit.Initializing to 1==odd parity
	        tx       &lt;= '0';    -- Start bit
	    ELSE
	        -- Shift data
	        txreg &lt;= txreg(1 TO 7) &amp; txtag1;
	        txtag1        &lt;= txtag2;
	        txtag2 	  &lt;= '0';

	        -- Form parity as each bit goes by
	        txparity      &lt;= txparity XOR txreg(0);

	        -- Shift out data or parity bit or stop/idle bit
	        IF txdone = '1' THEN
		    tx &lt;= '1';	-- stop/idle bit
	        ELSIF paritycycle = '1' THEN
		    tx &lt;= txparity;	-- Parity bit
	        ELSE
	    	    tx &lt;= txreg(0);	--Shift data bit
	        END IF;
	    END IF ;
	END IF;
    END PROCESS;

    -- paritycycle = 1 on next to last cycle (When txtag2 has reached txreg(1))
    --   (Enables putting the parity bit out on tx)
    paritycycle &lt;= txreg(1) AND NOT (txtag2 OR txtag1 OR 
				     txreg(7) OR txreg(6) OR txreg(5) OR 
				     txreg(4) OR txreg(3) OR txreg(2));

    -- txdone = 1 when done shifting (When txtag2 has reached tx)
    txdone &lt;= NOT (txtag2 OR txtag1 OR
		  txreg(7) OR txreg(6) OR txreg(5) OR txreg(4) OR 
		  txreg(3) OR txreg(2) OR txreg(1) OR txreg(0));

rx_proc: 	-- Shift data on each rxclk when not idling
    PROCESS (reset, rxclk) 
    BEGIN
	IF reset='1' THEN
	    rxreg &lt;= (OTHERS=&gt;'0') ;
            rxparity &lt;= '0' ;
            paritygen &lt;= '0' ;
            rxstop &lt;= '0' ;
	ELSIF rxclk'event AND rxclk = '1' THEN
	    IF rxidle = '1' THEN 
	        -- Load all ones when idling
	        rxreg &lt;= (OTHERS=&gt;'1');
	        rxparity &lt;= '1';
	        paritygen &lt;= '1';	-- Odd parity
	        rxstop &lt;= '0';
	    ELSE
	        -- Shift data when not idling
	        -- bug in assigning to slices
	        -- rxreg (0 TO 6) &lt;= rxreg (1 TO 7);
	        -- rxreg(7) &lt;= rxparity;
	        rxreg &lt;= rxreg (1 TO 7) &amp; rxparity;
	        rxparity &lt;= rxstop;
	        paritygen &lt;= paritygen XOR rxstop;-- Form parity as data shifts by
	        rxstop &lt;= 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 &lt;= '0';
        ELSIF rxclk'EVENT and rxclk = '1' THEN
           rxidle &lt;= NOT rxidle AND NOT rxreg(0);
        END IF;
    END PROCESS async;

txio:	-- Load txhold and set txdatardy on falling edge of write
	-- Clear txdatardy on falling edge of txdone
    PROCESS (reset, clkx16)
	VARIABLE wr1,wr2: std_logic;	-- write signal delayed 1 and 2 cycles
	VARIABLE txdone1: std_logic;        -- txdone signal delayed one cycle
    BEGIN
	IF reset='1' THEN
	    txdatardy &lt;= '0' ;
	    wr1 := '0' ;
	    wr2 := '0' ;
	    txdone1 := '0' ;
	ELSIF clkx16'event AND clkx16 = '1' THEN
	    IF wr1 = '0' AND wr2= '1' THEN
	        -- Falling edge on write signal. New data in txhold latches
	        txdatardy  &lt;= '1';
	    ELSIF txdone = '0' AND txdone1 = '1' THEN
	        -- Falling edge on txdone signal. Txhold has been read.
	        txdatardy  &lt;= '0';
	    END IF;

	    -- Delayed versions of write and txdone signals for edge detection
    	    wr2 := wr1;
	    wr1 := write;
	    txdone1 := txdone;
	END IF ;
    END PROCESS;

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 &lt;= '0' ;
	    rxhold &lt;= (OTHERS=&gt;'0') ;
	    parityerr &lt;= '0' ;
            framingerr &lt;= '0' ;
	    rxdatardy &lt;= '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 &lt;= '1';
	        ELSE
		    -- No overrun error since holding register is empty
		    overrun &lt;= '0';

		    -- Update holding register
		    rxhold &lt;= rxreg;

		    -- paritygen = 1 if parity error
		    parityerr &lt;= paritygen;

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

		    -- Signal that data is ready for reading
		    rxdatardy &lt;= '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  &lt;= '0';
	        parityerr  &lt;= '0';
	        framingerr &lt;= '0';
	        overrun    &lt;= '0';
	    END IF;
	    rd2 := rd1;	-- Edge detect for read
	    rd1 := read;	-- (Must be assigned AFTER reference)
	    IF reset = '1' THEN 
	        rxdatardy &lt;= '0'; 
	    END IF;
	END IF ;
    END PROCESS;

    -- Drive data bus only during read
    data &lt;= rxhold WHEN read = '1' ELSE (OTHERS=&gt;'Z') ;

    -- Latch data bus during write
    txhold &lt;= data WHEN write = '1' ELSE txhold;

    -- Receive data ready output signal
    rxrdy &lt;= rxdatardy;

    -- Transmitter ready for write when no data is in txhold
    txrdy &lt;= NOT txdatardy;

    -- Run-time simulation check for transmit overrun
    ASSERT write = '0' OR txdatardy = '0'
	REPORT "Transmitter overrun error" SEVERITY WARNING;

END exemplar;
</PRE></BODY></HTML>

⌨️ 快捷键说明

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