UART的异步串口通信VHDL实现
- 格式:pdf
- 大小:52.20 KB
- 文档页数:4
基于FPGA的UART电路设计与仿真基于FPGA的UART电路设计与仿真Design and Simulation of UART Circuit Based on FPGA(蚌埠中国⼈民解放军汽车管理学院) 杨⼤柱Yang, Dazhu摘要:⽂章介绍了⼀种采基于FPGA 实现UART电路的⽅法,并对系统结构进⾏了模块化分解以适应⾃顶向下的设计⽅法。
采⽤有限状态机对接收器模块和发送器模块进⾏了设计,所有功能的实现全部采⽤VHDL进⾏描述,并在Modelsim环境下进⾏了仿真,结果表明了该设计的正确性和可靠性。
关键词:UART;FPGA;RS-232;有限状态机中图分类号:TP332 ⽂献标识码:AAbstract:This paper introduces a method to design UART circuit based on FPGA. and the system structure is divided into modularization to fit the design method of Top-Down.The receiver and transfer are designed by FSM (Finite State Machine).All functions are described by VHDL.We stimulate the functions under Modelsim environment,the result proves the validity and reliability of the design.Keywords:UART;FPGA;RS-232;FSMUART(通⽤异步收发器)是⼴泛使⽤的串⾏数据传输协议。
UART允许在串⾏链路上进⾏全双⼯的通信。
专⽤的UART集成电路如8250,8251,NS16450等已经相当复杂,有些含有许多辅助的模块(如FIF0),在实际应⽤中,往往只需要⽤到UART的⼏个基本功能,使⽤专⽤芯⽚会造成资源浪费和成本提⾼,我们可以将所需要的UART功能集成到FPGA内部,从⽽简化了整个系统电路,提⾼了可靠性、稳定性和灵活性。
通用异步收发器(Universal Asynchronous Receiver Transmitter,UART)是数字通信领域流行和广泛使用的一种接口设备,主要用来控制符合RS 232-C协议的计算机与串行设备间的通信。
普通串行外设和计算机间的通信,一般使用通用的串行接口芯片,但是这种接口芯片存在体积较大、接口复杂以及成本较高的缺点,会使得硬件设计更加复杂,并且结构与功能相对固定,无法根据设计的需要对其逻辑控制进行灵活的修改。
而目前日趋成熟的SOC技术则要求将整个设计的功能集成在单片或几块芯片当中,因此,将UART的功能集成在FPGA芯片当中,可以使整个系统更为灵活、紧凑,性能也更加稳定。
本文提出了一种使用VHDL语言开发UAWT的方法,实现了FPGA与计算机之间的数据通信,并将其应用于FPGA芯片开发的功能验证当中,从而衍生出了将UART嵌入到EPGA芯片,与计算机互联的一种直观的FPGA设计的验证和调试方法。
1 UART通信原理UART采用通用的RS 232-C串行接口标准,该协议的优点是使用广泛,几乎所有计算机和串行外设当中都置有这种接口,其传输距离可达15 m,并且实现较简单,用于双向连接时最少只需要2条导线即可实现基本通信。
UART的具体帧格式如图1所示,每帧数据由开始位、数据位、奇偶校验位和停止位四部分依次组成。
其中,开始位为低电平;数据位长度为5,6,7,8不等;奇偶校验的模式有无校验、奇校验、偶校验、粘附校验1和粘附校验0;停止位为高电平,具体长度为1位、1.5位和2位不等,这些选项都通过UA RT内部的线性控制寄存器来确定。
当没有数据发送时,发送和接收引脚都保持高电平。
2 UART的FPGA实现本实现中,UART主要包括接收模块、发送模块、MODEM控制器和中断仲裁4个部分。
它们的具体功能如下:接收模块具体作用是接收从串行数据输入端口SIN送来的异步数据,并进行串/并转换,此外,接收模块还包含模块控制和模块状态配置功能,用来设置接收数据帧的属性以及向中断仲裁模块输出状态信号;发送模块其作用是对从CPU送来的并行数据进行并/串转换,将串行数据从SOUT输出到串口,同接收模块相同,该模块也包含模块控制和模块状态配置功能;中断仲裁模块其作用是用来实现外部接口对内部寄存器的操作以及中断信号的仲裁操作,在UART的工作过程中,发送和接收模块的状态信号都送入该模块的线性状态寄存器中,经过内部的逻辑操作输出相应的中断信号,指示与UART相连的外部设备进行相应的读写操作;MODEM模块其作用是用来和外部的调制解调器或者其他的UART设备进行通信。
单片机UART通信实现在单片机系统中,UART(通用异步收发器)通信是一种常见的串口通信方式。
通过UART通信,可以实现单片机与外部设备之间的数据传输。
本篇文章将介绍如何使用单片机实现UART通信,并提供相应的代码示例。
一、UART通信原理UART通信是一种串行通信方式,其中数据按照位的形式依次传输。
UART接口包括发送端和接收端,发送端将要传输的数据通过串行方式发送出去,接收端将接收到的数据按位恢复为原始数据。
通信的核心是波特率,即数据传输的速度。
发送端和接收端必须以相同的波特率进行通信,以确保数据的正确传输。
二、单片机UART通信的硬件连接实现单片机UART通信的关键是正确连接相应的硬件。
典型的单片机UART通信硬件连接如下:发送端:- 单片机的TX(发送)引脚连接到外部设备的RX(接收)引脚- 单片机的GND引脚连接到外部设备的GND引脚接收端:- 单片机的RX(接收)引脚连接到外部设备的TX(发送)引脚- 单片机的GND引脚连接到外部设备的GND引脚三、单片机UART通信的软件实现在软件方面,需要编写相应的代码来配置单片机的UART通信模块。
以下是一个示例代码,用于实现基本的UART通信功能。
```c#include <reg51.h>#define BAUDRATE 9600 // 波特率设置为9600bpsvoid uart_init(){TMOD = 0x20; // 设置定时器1为8位自动重装模式TH1 = -(256 - (11059200 / 12 / 32) / BAUDRATE); // 设置波特率TL1 = TH1; // 初始化定时器1的初值TR1 = 1; // 启动定时器1SCON = 0x50; // 标识为8位UART模式EA = 1; // 允许全局中断ES = 1; // 允许串口中断}void uart_send(unsigned char dat)SBUF = dat; // 将数据写入发送寄存器 while (!TI); // 等待发送完毕TI = 0; // 清除发送完成标志}unsigned char uart_receive(){while (!RI); // 等待接收完毕RI = 0; // 清除接收标志return SBUF; // 返回接收到的数据}void main(){unsigned char data;uart_init(); // 初始化UART通信模块 while (1)data = uart_receive(); // 接收数据uart_send(data); // 发送接收到的数据}}```以上代码是基于8051系列单片机的实现示例,具体的单片机型号和编程语言可能有所不同,但基本原理是相同的。
用vhdl语言在cpld上实现串行通信一、概述串行通信是现代通信领域中最为常见的一种通信方式。
通过串行通信,现代社会中的各种设备可以以最高效的方式进行数据传输,实现快速、准确的信息交换。
而vhdl语言则是数字电路设计领域中最为常用的一种描述语言,因为vhdl 语言可以描述数字电路的不同行为,对于数字电路的模拟和仿真非常方便。
在本文中,我们将介绍如何使用vhdl语言在cpld 上实现串行通信。
二、串行通信的基本原理串行通信是指在数据传输过程中,数据位是按照顺序一个一个相继传输的。
串行通信的传输速率相对较慢,但是传输距离远,主要是通过数据信号占用两个或者三个核心线来完成的。
串行通信的数据信号一般由三个部分构成:开始位、数据位和停止位。
开始位一般用于启动数据传输,而停止位则用于结束数据传输。
三、vhdl语言概述VHDL(VHSIC Hardware Description Language)是美国国防工业联合会(VHSIC)在80年代末期为了解决数字电路设计中的复杂性而开发的一种硬件描述语言,是一种基于文本的语言。
VHDL语言主要用来描述数字逻辑和数字电路。
VHDL语言本身就是一种结构化的、层次化的语言,可以很好地体现出数字电路的层次关系。
四、使用vhdl语言在cpld上实现串行通信的步骤1、确定串行通信的传输速率和数据格式。
在确定串行通信的传输速率和数据格式之前,需要确定串行通信的基本参数,包括其传输速率、在接收端进行判定数据是否有效的时间程度、以及在发送端和接收端之间互相传输数据的位数。
这些参数对于后续的设计极为重要。
2、编写串行通信的vhdl模块。
在vhdl模块中,需要包括发送和接收两个部分,分别对应于硬件接口中的发送和接收部分。
发送部分主要是将数据按照规定的格式进行串行传输,而接收部分则主要是将串行传输的数据再转换为并行数据。
3、完成vhdl模块的仿真测试。
在完成vhdl模块的设计之后,需要进行仿真测试,以验证vhdl模块的正确性和稳定性。
VHDL设计举例:一个简单的UART-------------------------------------------------------------------- Copyright (c) 1992,1993,1994, Exemplar Logic Inc. All rights reserved.---------------------------------------------------------------------- This design implements a UART.------ V ersion : Original Creation-- V ersion : Modified to std_logic types-- V ersion : Extended reset to be more effective.-- Introduced OTHERS clause.------------------------------------------------------------------LIBRARY ieee;use _logic_;use _logic_;use _logic_;ENTITY uart ISPORT (clkx16 : IN std_logic;-- Input clock. 16x bit clockread : IN std_logic;-- Received data read strobewrite : IN std_logic;-- Transmit data write stroberx : IN std_logic;-- Receive data linereset : IN std_logic;-- clear dependenciestx : OUT std_logic;-- Transmit data linerxrdy : OUT std_logic;-- Received data ready to be readtxrdy : OUT std_logic;-- Transmitter ready for next byte parityerr : OUT std_logic;-- Receiver parity errorframingerr : OUT std_logic;-- Receiver framing erroroverrun : OUT std_logic;-- Receiver overrun errordata : INOUT std_logic_vector(0 TO 7)); -- Bidirectional data bus END uart;ARCHITECTURE exemplar OF uart IS-- Transmit data holding registerSIGNAL txhold : std_logic_vector(0 TO 7);-- Transmit shift register bitsSIGNAL txreg : std_logic_vector(0 TO 7);SIGNAL txtag2 : std_logic;-- tag bits for detectingSIGNAL txtag1 : std_logic;-- empty shift regSIGNAL txparity : std_logic;-- Parity generation register-- Transmit clock and control signalsSIGNAL txclk : std_logic; -- Transmit clock: 1/16th of clkx16SIGNAL txdone : std_logic;-- …1‟ when shifting of byte is doneSIGNAL paritycycle : std_logic;-- …1‟ on next to last shift cycleSIGNAL txdatardy : std_logic; -- …1‟ when data is ready in txhold-- Receive shift register bitsSIGNAL rxhold : std_logic_vector(0 TO 7);-- Holds received data for readSIGNAL rxreg : std_logic_vector(0 TO 7);-- Receive data shift registerSIGNAL rxparity : std_logic;-- Parity bit of received dataSIGNAL paritygen : std_logic;-- Generated parity of received dataSIGNAL rxstop : std_logic;-- Stop bit of received data-- Receive clock and control signalsSIGNAL rxclk : std_logic;-- Receive data shift clockSIGNAL rxidle : std_logic; -- …1‟ when receiver is idling SIGNAL rxdatardy : std_logic; -- …1‟ when data is ready to be readBEGINmake_txclk:PROCESS (reset, clkx16)V ARIABLE cnt : std_logic_vector(2 DOWNTO 0);BEGIN-- Toggle txclk every 8 counts, which divides the clock by 16IF reset=…1‟ THENtxclk …0‟) ;ELSIF clkx16‟event AND clkx16=…1‟ THENIF (cnt = “000”) THENtxclk …0‟) ;rx1 := …0‟ ;rxclk …0‟) ;txtag1 …0‟) ;rxparity …1‟);rxparity …0‟) ;parityerr …Z‟) ;-- Latch data bus during writetxhold <= data WHEN write = …1‟ ELSE txhold;-- Receive data ready output signalrxrdy <= rxdatardy;-- Transmitter ready for write when no data is in txholdtxrdy <= NOT txdatardy;-- Run-time simulation check for transmit overrunASSERT write = …0‟ OR txdatardy = …0‟REPORT “Transmitter overrun error” SEVERITY WARNING; END exemplar;。
UART 16倍频采样的VHDL实现随着电子设计自动化(EDA)技术的发展,可编程逻辑器件FPGA/CPLD已经在许多方面得到了广泛应用,而UART(通用异步收发器)是在数字通信和控制系统中广泛使用的串行数据传输协议。
因此越来越多用户根据自己的需要,以EDA技术作为开发手段,用一块FPGA/CPLD 设计出符合自己需要的UART芯片。
基于FPGA/ CPLD的UART设计在诸多文献中都有论述,在此不再对UART整个功能模块实现做太多的论述。
本文着重分析UART接收器起始位的检测。
3倍频采样的缺陷首先,串行异步通信规定了字符数据的传送格式。
每一帧数据由起始位、数据位、奇偶校验位、停止位和线路空闲状态组成,格式如图1所示。
一般情况起始位为1位,数据位为5、6、7或8位、奇偶校验位为1位,停止位为1、1.5或2位。
其中的起始位和停止位就是用来实现字符的同步。
在空闲状态,传送线为逻辑“1”状态。
数据的传送总是以一个“起始位”开始的,接着是要传送的若干数据位,低位先行,最后是一个“1”状态的“停止位”;那么,当接收器检测到一个“1”向“0”的跳变时,便视为可能的起始位。
起始位被确认后,就知道发送器已开始发送,当接收了已协议好的位数后并接收到字符帧中停止位就是一帧字符数据已发送完毕。
这样,接收器就知道发送器何时开始发送数据和何时结束发送数据。
要提高接收器的接收准确性,减少误码率,必须要用比数据波特率高n 倍(n≥1)的速率对数据进行采样。
文献2中采用了非常规的3倍频采样方法:用3倍频的波特率对每一位数据进行采样(如图2所示),然后对3次采样结果进行判决。
如果3次采样中至少有2次为高电平,则接收这一位数据被判决为高电平,否则,为低电平。
此方法刚开始给人感觉比常规的16倍频采样准确性高,因为每一位数据都进行3取2的判决,而16倍频采样对每位数据只进行一次中间采样。
然而笔者在实际应用中发现了其存在抗干扰性差,移植性差等不足。
异步FIFO的VHDL设计下面是一个异步FIFO的VHDL设计示例:```vhdllibrary ieee;use ieee.std_logic_1164.all;entity AsyncFIFO isgenericDATA_WIDTH : natural := 8; -- 数据宽度FIFO_DEPTH : natural := 16 -- FIFO深度portclk : in std_logic; -- 时钟信号rst : in std_logic; -- 复位信号read_en : in std_logic; -- 读使能write_en : in std_logic; -- 写使能read_data : out std_logic_vector(DATA_WIDTH-1 downto 0); -- 读数据write_data : in std_logic_vector(DATA_WIDTH-1 downto 0); -- 写数据full : out std_logic; -- FIFO满标志empty : out std_logic -- FIFO空标志end AsyncFIFO;architecture Behavioral of AsyncFIFO istype buffer_array is array (FIFO_DEPTH-1 downto 0) ofstd_logic_vector(DATA_WIDTH-1 downto 0);signal buffer : buffer_array; -- 数据缓冲区signal wr_ptr : natural range 0 to FIFO_DEPTH-1; -- 写指针signal rd_ptr : natural range 0 to FIFO_DEPTH-1; -- 读指针signal count : natural range 0 to FIFO_DEPTH-1; -- 缓冲区中数据个数beginprocess (clk)beginif rising_edge(clk) thenif rst = '1' thenwr_ptr <= 0;rd_ptr <= 0;count <= 0;elseif write_en = '1' and full = '0' then -- 写使能且FIFO非满buffer(wr_ptr) <= write_data;wr_ptr <= wr_ptr + 1;count <= count + 1;end if;if read_en = '1' and empty = '0' then -- 读使能且FIFO非空read_data <= buffer(rd_ptr);rd_ptr <= rd_ptr + 1;count <= count - 1;end if;end if;end if;end process;full <= '1' when count = FIFO_DEPTH-1 else '0';empty <= '1' when count = 0 else '0';end Behavioral;```在上面的代码中,`DATA_WIDTH`和`FIFO_DEPTH`是异步FIFO的泛型参数,可以根据实际需求进行配置。
基于VerilogHDL的UART设计季雄段吉海胡媛媛袁柯于海生(桂林电子工业学院 通信与信息工程系,广西 桂林 541004)摘要:UART是广泛使用的串行数据通信电路,因其要求的传输线少,可靠性高,传输距离远,所以系统间互联常采用RS—232接口方式,一般说来,该接口由硬件(UART专用芯片)实现。
文章基于VerilogHDL语言,结合有限状态机的设计方法来实现UART,将其核心功能集成到FPGA上,使整体设计紧凑、小巧,实现的UART功能稳定、可靠,为RS—232接口提供了一种新的解决方案;同时,与其他设计方法相比较,利用有限状态机的方法具有结构模式直观简单,设计流程短,程序层次分明,易综合,可靠性高等优点,必将在EDA技术中发挥重要作用。
关键词:VerilogHDL; UART;帧格式;状态机引言随着微机系统的广泛运用和微机网络的极大发展,UART(Universal Asynchronous Receive Transmitter)【1】在数据通信及控制系统中得到了广泛运用。
8250、NS16450等芯片都是常见的UART 器件[2],这类芯片已经相当复杂,有的含有许多辅助模块(如FIFO),但在实际中有时只需要使用UART的部分功能,因而会造成一定的资源浪费。
FPGA在现代电子设计中的广泛运用,使我们可以充分利用其资源,在芯片上集成UART的功能模块,这样就无需外接专用UART芯片,从而简化了电路,缩小了体积,设计的灵活性更大。
文章通过分析UART的功能,利用有限状态机[4]来描述UART核心控制逻辑的方法,将其核心功能集成,从而使整个设计更加稳定、可靠。
基本的UART通信只需要两条信号线就可以完成数据的相互通信。
UART的结构如图1所示。
图1 UART的结构图1 UART的帧格式在UART中,数据位是以字符为传送单位,数据的前、后要有起始位、停止位,另外可以在停止位的前面加上一个比特(bit)的校验位。
************UART VHDL**************** ----------testbench.vhd----------------------------------------------library ieee;use ieee.std_logic_1164.all;entity testbench isend testbench;architecture mtestbench of testbench iscomponent test_architecture isport(clk32mhz: in std_logic;reset: in std_logic;txdbuf_in1:in std_logic_vector(7 downto 0);txdbuf_in2:in std_logic_vector(7 downto 0);xmit_cmd_p_in1:in std_logic;xmit_cmd_p_in2:in std_logic;rec_buf1:out std_logic_vector(7 downto 0); --??????rec_buf2:out std_logic_vector(7 downto 0));end component;signal clk32mhz: std_logic:='0';signal clkperiod:time:=20 ns;signal reset: std_logic;signal xmit_cmd_p_in1:std_logic;signal txdbuf_in1:std_logic_vector(7 downto 0); --???????signal xmit_cmd_p_in2:std_logic;signal txdbuf_in2:std_logic_vector(7 downto 0); --???????signal rec_buf1:std_logic_vector(7 downto 0); --??????signal rec_buf2:std_logic_vector(7 downto 0); --??????beginclk32mhz<=not clk32mhz after clkperiod;processbeginreset<='1';txdbuf_in1<="01100111";xmit_cmd_p_in1<='0';txdbuf_in2<="10100100";xmit_cmd_p_in2<='0';wait for 200 ns;reset<='0';wait for 100 ns;xmit_cmd_p_in1<='1';xmit_cmd_p_in2<='1';wait for 200000 ns;xmit_cmd_p_in1<='0';xmit_cmd_p_in2<='0';wait;end process;uut_test_architecture: test_architecture port map (clk32mhz=>clk32mhz, reset=>reset, txdbuf_in1=>txdbuf_in1,txdbuf_in2=>txdbuf_in2, xmit_cmd_p_in1=>xmit_cmd_p_in1, xmit_cmd_p_in2=>xmit_cmd_p_in2,rec_buf1=>rec_buf1,rec_buf2=>rec_buf2);end mtestbench;--------------------------------test_architecture.vhd----------------------------------library ieee;use ieee.std_logic_1164.all;entity test_architecture isport(clk32mhz: in std_logic;reset: in std_logic;txdbuf_in1:in std_logic_vector(7 downto 0);txdbuf_in2:in std_logic_vector(7 downto 0);xmit_cmd_p_in1:in std_logic;xmit_cmd_p_in2:in std_logic;rec_buf1:out std_logic_vector(7 downto 0); --??????rec_buf2:out std_logic_vector(7 downto 0));end test_architecture;architecture mtest_architecture of test_architecture iscomponent uart_module isPort (clk32mhz,reset,rxd,xmit_cmd_p_in:in std_logic;rec_ready,txd_out,txd_done_out:out std_logic;txdbuf_in:in std_logic_vector(7 downto 0); --???????rec_buf:out std_logic_vector(7 downto 0)); --??????end component;signal rec_ready1,txd_out1,txd_done_out1:std_logic;signal rec_ready2,txd_out2,txd_done_out2:std_logic;beginuart_module_0: uart_moduleport map(clk32mhz=>clk32mhz,reset=>reset,xmit_cmd_p_in=>xmit_cmd_p_in1, rec_ready=>rec_ready1,txd_out=>txd_out1,txd_done_out=>txd_done_out1,txdbuf_in=>txdbuf_in1, rxd=>txd_out2,rec_buf=>rec_buf1);uart_module_1: uart_moduleport map(clk32mhz=>clk32mhz,reset=>reset, xmit_cmd_p_in=>xmit_cmd_p_in2, rec_ready=>rec_ready2,txd_out=>txd_out2,txd_done_out=>txd_done_out2,txdbuf_in=>txdbuf_in2,rxd=>txd_out1,rec_buf=>rec_buf2);end mtest_architecture;------------------------------- uart_module.vhd-----------------------------------------library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity uart_module isPort (clk32mhz,reset,rxd,xmit_cmd_p_in:in std_logic;rec_ready,txd_out,txd_done_out:out std_logic;txdbuf_in:in std_logic_vector(7 downto 0); --???????rec_buf:out std_logic_vector(7 downto 0)); --??????end uart_module;architecture Behavioral of uart_module iscomponent recieverPort (bclkr,resetr,rxdr:in std_logic;r_ready:out std_logic;rbuf:out std_logic_vector(7 downto 0));end component;component transferPort (bclkt,resett,xmit_cmd_p:in std_logic;txdbuf:in std_logic_vector(7 downto 0);txd:out std_logic;txd_done:out std_logic);end component;component baudPort (clk,resetb:in std_logic;bclk:out std_logic);end component;signal b:std_logic;beginu1:baud port map(clk=>clk32mhz,resetb=>reset,bclk=>b); --????u2:receiverport map(bclkr=>b,resetr=>reset,rxdr=>rxd,r_ready=>rec_ready,rbuf=>rec_buf);u3:transferport map(bclkt=>b,resett=>reset,xmit_cmd_p=>xmit_cmd_p_in,txdbuf=>txdbuf_in, txd=>txd_out,txd_done=>txd_done_out);end Behavioral;----------------------------- baud.vhd------------------------------------------------------------library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity baud isPort (clk,resetb:in std_logic;bclk:out std_logic);end baud;architecture Behavioral of baud isbeginprocess(clk,resetb)variable cnt:integer;beginif resetb='1' then cnt:=0; bclk<='0'; --??elsif rising_edge(clk) thenif cnt>=208 then cnt:=0; bclk<='1'; --??????else cnt:=cnt+1; bclk<='0';end if;end if;end process;end Behavioral;----------------------------------transfer.vhd------------------------------------------- library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity transfer isgeneric(framlent:integer:=8);Port (bclkt,resett,xmit_cmd_p:in std_logic; --????????txdbuf:in std_logic_vector(7 downto 0):="11001010";txd:out std_logic;txd_done:out std_logic);end transfer;architecture Behavioral of transfer istype states is (x_idle,x_start,x_wait,x_shift,x_stop); --??????signal state:states:=x_idle;signal tcnt:integer:=0;-----the following signals are in the main process;signal xcnt16:std_logic_vector(4 downto 0):="00000"; --??????signal xbitcnt:integer:=0;signal txds:std_logic;beginprocess(bclkt,resett,xmit_cmd_p,txdbuf) --?????????beginif resett='1' then state<=x_idle; txd_done<='0'; txds<='1'; --??elsif rising_edge(bclkt) thencase state iswhen x_idle=> --??1??????????if xmit_cmd_p='1' then state<=x_start; txd_done<='0';else state<=x_idle; end if;when x_start=> --??2?????????--if xcnt16>="01111" then state<=x_wait; xcnt16<="00000";if xcnt16>="01110" then state<=x_wait; xcnt16<="00000";else xcnt16<=xcnt16+1; txds<='0'; state<=x_start;end if;when x_wait=> --??3?????if xcnt16>="01111" thenif xbitcnt=framlent then state<=x_stop;xbitcnt<=0;xcnt16<="00000";else state<=x_shift; end if;else xcnt16<=xcnt16+1; state<=x_wait; end if;when x_shift=>txds<=txdbuf(xbitcnt); xbitcnt<=xbitcnt+1; state<=x_wait;--??4????????????when x_stop=> --??5????????if xcnt16>="01111" thenif xmit_cmd_p='0' then state<=x_idle; xcnt16<="00000";else xcnt16<=xcnt16; state<=x_stop; end if;txd_done<='1';else xcnt16<=xcnt16+1; txds<='1'; state<=x_stop;end if;when others=>state<=x_idle;end case;end if;txd<=txds;end process;end Behavioral;--------------------reveiver.vhd----------------------------------------------------------library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity reciever isgeneric(framlenr:integer:=8);Port (bclkr,resetr,rxdr:in std_logic; --????????r_ready:out std_logic;rbuf:out std_logic_vector(7 downto 0));end reciever;architecture Behavioral of reciever istype states is (r_start,r_center,r_wait,r_sample,r_stop); --??????signal state:states:=r_start;signal rxd_sync:std_logic;----the folloing signals are in the "pro2" process.signal count:std_logic_vector(3 downto 0); --??????signal rcnt:integer:=0;signal rbufs:std_logic_vector(7 downto 0);beginpro1:process(rxdr)beginif rxdr='0' then rxd_sync<='0';else rxd_sync<='1';end if;end process;pro2:process(bclkr,resetr,rxd_sync) --?????????beginif resetr='1' then state<=r_start; count<="0000"; --??elsif rising_edge(bclkr) thencase state iswhen r_start=> --??1??????if rxd_sync='0' then state<=r_center; r_ready<='0'; rcnt<=0;else state<=r_start; r_ready<='0';end if;when r_center=> --??2????????if rxd_sync='0' thenif count="1111" then state<=r_wait; count<="0000";else count<=count+1; state<=r_center;end if;else state<=r_start;end if;when r_wait=>--??3?????if count>="1110" thenif rcnt=framlenr then state<=r_stop;count<="0000";rcnt<=0;else state<=r_sample; end if;else count<=count+1; state<=r_wait;end if;when r_sample=>rbufs(rcnt)<=rxd_sync; rcnt<=rcnt+1;state<=r_wait; --??4????????when r_stop=>r_ready<='1'; rbuf<=rbufs;state<=r_start; --??4??????????when others=>state<=r_start;end case;end if;end process;end Behavioral;Notice:综合前仿真和综合后仿真结果不一致:图1. 综合前仿真结果图2. 综合后仿真结果。
UART 的异步串口通信协议的VHDL 语言实现异步串行通信的采用的波特率为9600b/s,外配晶体振荡器的频率为3.6864MHZ ,故采用分频电路package width isconstant N:integer:=8;end width;use work.width.all;library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity fredivn isGENERIC (N:integer:=6);port(clkin: in std_logic;clkout: out std_logic);end fredivn;architecture behav of fredivn issignal count : integer;beginprocess(clkin)beginif (clkin'event and clkin=1)thenif(count<N-1)thencount<=count+1;else count<=0;end if;if (count<N/2)thenclkout<='1';else clkout<='0';end if;end if;end process;end behav;异步接收模块 RXD 的端口clk 为输入时钟,rx 为串行数据接收,sig1为接收中断标志,q 为并行数据输出程序流程如下:sig1是接收中断标志位,当是低电平时,说明接收过程并未启动,于是检测电平,当rx 电平为低时,sig2开始计数,若连续8次采样rx 都是低电平,则说明是起始位,启动接收过程,每隔16个接收时钟接收1位数据直至11位接收完毕,并行输出口是一个串并转换。
本例中的数据位8位E C N CRXD data 8bitlibrary ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity rxd3 isport(clk,rx: in std_logic;sig1:buffer std_logic; --接收中断标志q:out std_logic_vector(7 downto 0)); --并行数据输出end rxd3;architecture behav of rxd3 issignal tmpreg8: std_logic_vector(8 downto 0);signal sig2: integer range 0 to 16 ; --接收时钟计数signal sig3: integer range 0 to 9 ; --接收数据位数signal sig4: std_logic; --串并转换时钟,接收是为1 ,空挡为0beginprocess(clk)beginif (clk'event and clk='1') thenif (sig1='0') then --ri 状态if (rx='0') then --此句判断是否是起始位,是则 sig1<='1'if (sig2=7) then --对应起始位的处理 sig2<='0'; sig1<='1'; sig4<='1';else sig2<=sig2+1; sig4<='0';end if;else sig2<='0';end if;else --ri 为1,对应的数据接收 if (sig2=15) thensig2<='0';if (sig3=8) then --接收完一帧否?若接收完则sig1置0,表示空闲sig3<='0' ; sig1<='0'; sig4<='0';else sig3<=sig3+1; sig4<='1';end if;else sig2<=sig2+1; sig4<='0';end if;end if;end if;end process; E C N Cprocess(sig4) --此进程完成接收数据的串并转换 beginif (sig4'event and sig4='1') thenfor i in tempreg8'high downto tempreg8'low+1 looptempreg8(i)<=tempreg8(i-1);end loop;tempreg8( tempreg8'low)<=rx;end if;end process;processbeginfor i in 7 downto 0 loopq(i)<=tempreg8(i);end loop;end process;end behav;异步发送模块TXD5的端口中,indata 为8位数据输入端口。
cs 为片选信号,低电平有效。
wr 是输出允许,高电平有效。
clk 为输入时钟信号,为发送提供时钟,txd 是串行发送端,ti 是发送中断标志,高电平表示正在发送低电平表示空闲library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity txd5 isport(indata: in std_logic_vector(7 downto 0); --8位数据输入端口cs,wr,clk:in std_logic;txd,ti: out std_logic); --txd 串行发送,ti 发送中断信号end txd5;architecture behav of txd5 issignal sig_count: std_logic_vector (3 downto 0);signal sig_ti,sig_ti1,sig_txd,sig_buffer: std_logic;signal sig_data: std_logic_vector (7 downto 0);signal sig_txddata: std_logic_vector (9 downto 0);beginprocess(clk)begin E C N Cif (clk'event and clk='1')thenif (cs='0') thenif (sig_buffer='0')then --发送中断为0,即发送不忙if (wr='1') then --读入数据准备发送for i in 8 downto 1 loopsig_txddata(i)<=indata(i-1); --并行输入数据送sig_txddataend loop;sig_txddata (9)<='0'; --加起始位 sig_txddata (0)<='1'; --加偶校验位 sig_data<=indata;sig_buffer<='1';end if;else --正在发送数据for i in 9 downto 1 loopsig_txddata (i )<=sig_txddata (i-1); --数据串行输出 end loop;sig_txd<=sig_txddata (9);sig_txddata (0)<='1'; --加结束位if (sig_count="1000") then --此if 句用于设置ti 状态sig_count<="0000";elsif (sig_count<="0000"and sig_ti='1') thensig_buffer<='0';sig_ti='0';else sig_count<=sig_count+'1'; sig_ti='1';end if;end if;end if;end if;end process;process --txd 赋值过程beginif (sig_ti='0') thentxd<='1';else txd<=sig_txd;end if;end processti<= not sig_ti;end behav; E C N C。