📄 一个简单的uart.txt
字号:
-------------------------------------------------------------------- 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 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 busEND 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 readBEGIN 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 <= '0' ; cnt := (OTHERS=>'0') ; ELSIF clkx16'event AND clkx16='1' THEN IF (cnt = "000") THEN txclk <= 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=>'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:txshift: PROCESS (reset, txclk) BEGIN IF reset='1' THEN txreg <= (OTHERS=>'0') ; txtag1 <= '0' ; txtag2 <= '0' ; txparity <= '0' ; tx <= '0' ; ELSIF txclk'event AND txclk = '1' THEN IF (txdone AND txdatardy) = '1' THEN -- Initialize registers and load next byte of data txreg <= txhold; -- Load tx register from txhold txtag2 <= '1'; -- Tag bits for detecting txtag1 <= '1'; -- when shifting is done txparity <= '1'; -- Parity bit.Initializing to 1==odd parity tx <= '0'; -- Start bit ELSE -- Shift data txreg <= txreg(1 TO 7) & txtag1; txtag1 <= txtag2; txtag2 <= '0'; -- Form parity as each bit goes by txparity <= txparity XOR txreg(0); -- Shift out data or parity bit or stop/idle bit IF txdone = '1' THEN tx <= '1'; -- stop/idle bit ELSIF paritycycle = '1' THEN tx <= txparity; -- Parity bit ELSE tx <= 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 <= 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 <= 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 <= (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;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 <= '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 <= '1'; ELSIF txdone = '0' AND txdone1 = '1' THEN -- Falling edge on txdone signal. Txhold has been read. txdatardy <= '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 <= '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 txhold <= data WHEN write = '1' ELSE txhold; -- Receive data ready output signal rxrdy <= rxdatardy; -- Transmitter ready for write when no data is in txhold txrdy <= NOT txdatardy; -- Run-time simulation check for transmit overrun ASSERT write = '0' OR txdatardy = '0' REPORT "Transmitter overrun error" SEVERITY WARNING;END exemplar;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -