- 易迪拓培训,专注于微波、射频、天线设计工程师的培养
MCS-51与FPGA/CPLD总线接口逻辑设计
摘要:设计一种基于MCS51单片机与FPGA/CPLD的总线接口逻辑电路,实现单片机与可编程逻辑器件数据与控制信息的可靠通信,使可编程逻辑器件与单片机相结合,优势互补,组成灵活的、软硬件都可现场编程的控制系统。设计中采用VHDL语言,实现MCS51单片机与FPGA/CPLD的总线接口逻辑设计。实验表明,该总线接口逻辑电路工作稳定、可靠,使MCS51单片机与FPGA/CPLD能够完美结合。
引言
长期以来,单片机以其性能价格比高、体积小、功能灵活、可靠性高、易于人机对话和良好的数据处理能力等方面所具有的独特优点,被广泛应用于各个领域。但受其内部资源的限制,在很多应用中,单片机需要在片外扩展相关资源,如程序存储器、数据存储器、I/O口以及中断源等。随着可编程逻辑器件(PLD)及EDA技术的发展,在系统设计中经常会用到FPGA/CPLD来扩展单片机的相关资源,使其有机结合,缩短开发周期,适应市场需要。FPGA/CPLD具有高速、高可靠以及开发便捷、规范等优点,在功能上与单片机有很强的互补性。以此两类器件相结合的电路结构在许多高性能仪器仪表和电子产品中被广泛应用。基于这种需求,笔者设计了MCS51单片机与FPGA/CPLD的总线接口逻辑电路,实现了单片机与FPGA/CPLD数据与控制信息的可靠通信,使FPGA/CPLD与单片机优势互补,组成灵活的、软硬件都可现场编程的控制系统。
1 单片机与FPGA/CPLD的接口方式
单片机与FPGA/CPLD的接口方式一般有两种,即总线方式与独立方式。
1.1 总线方式
MCS51单片机具有很强的外部总线扩展能力,利用片外三总线结构(即数据总线、地址总线、控制总线)很容易实现单片机与FPGA/CPLD的总线接口。其基本原理框图如图1所示。
图1 总线方式原理框图
单片机与FPGA/CPLD以总线方式通信的逻辑设计,重要的是要详细了解单片机的总线读写时序,根据时序图来设计逻辑结构,其通信的时序必须遵循单片机内固定的总线方式读/写时序。FPGA/CPLD的逻辑设计也相对比较复杂,在程序设计上必须与接口的单片机程序相结合,严格安排单片机能访问的I/O空间。但是,单片机以总线方式与FPGA/CPLD进行数据与控制信息通信也有许多优点:
◆ 速度快。其通信工作时序是纯硬件行为,对于MCS51单片机,只需一条单字节指令就能完成所需的读/写时序,如"MOV @DPTR,A"和"MOV A,@DPTR"。
◆ 节省PLD芯片的I/O口线。仅通过19根I/O口线,就能在FPGA/CPLD与单片机之间进行各种类型的数据与控制信息交换。
◆ 相对于非总线方式,单片机编程简捷,控制可靠。
◆ 在CPLD/FPGA中通过逻辑切换,单片机易于与SRAM或ROM接口。这种方式有许多实用之处,如利用类似于微处理器系统的DMA的工作方式,首先由FPGA/CPLD与接口的高速器件进行高速数据采样,并将数据暂存于SRAM中采样结束后,通过切换,使单片机与SRAM以总线方式进行数据通信,以便发挥单片机强大的数据处理能力。
1.2 独立方式
与总线接口方式不同,几乎所有单片机都能以独立接口方式与FPGA/CPLD进行通信,其通信的时序方式可由所设计的软件自由决定,形式灵活多样。其最大的优点是FPGA/CPLD中的接口逻辑无需遵循单片机内固定总线方式的读/写时序。FPGA/CPLD的逻辑设计与接口的单片机程序设计可以分先后相对独立地完成。事实上,目前许多流行的单片机已无总线工作方式,采用独立方式可以很好地使它们与FPGA/CPLD结合。独立方式的接口设计方法比较简单,其基本原理框图如图2所示。直接将单片机的I/O端口线与FPGA/CPLD的I/O相连即可。
图2 独立方式原理框图
2 总线接口逻辑设计
由于单片机以总线方式与FPGA/CPLD进行数据与控制信息通信有许多优点,因此在设计中,单片机与FPGA/CPLD接口采用总线方式。
2.1 接口设计思想
对MCS51单片机与FPGA/CPLD以总线方式通信的逻辑接口设计,应该详细了解MCS51单片机的总线读/写时序,并根据时序图来设计逻辑结构。MCS51单片机总线读/写的时序如图3所示,其时序电平变化速度与单片机工作时钟频率有关。
图3 MCS51单片机总线读/写时序
CLK为单片机时钟信号,ALE为地址锁存使能信号。在读/写周期开始后,CPU把低8位地址送到P0口总线上,把高8位地址送到P2口总线上,利用ALE下降沿可将低8位地址锁存于地址锁存器中,而高8位地址信息一直锁存在P2口锁存器中;同时单片机利用读指令允许信号PSEN的低电平从ROM中将指令从P0口读入,其指令读入的时机是在PSEN的上升沿之前。接下来,由P2口和P0口分别输出高8位和低8位数据地址,并由ALE的下降沿将P0口的低8位地址锁存于地址锁存器。然后根据读/写信号的状态读写外部数据,把数据送到P0口总线上;数据读/写的时机是在读/写信号的上升沿之前,将数据读入单片机或写入被寻址的地址单元。当读/写信号变为无效电平后,P0口总线变为悬浮状态,为下次总线读/写做好准备。
通过对MCS51单片机总线读/写时序的分析,可以在FPGA/CPLD中设计一个总线接口模块,实现单片机三总线信号的编码。由于在总线应用时,MCS51单片机的P0口是作为地址/数据总线分时复用的,因此应在总线接口模块中设计一个三态缓冲器,实现P0口的三态接口;又因为MCS51单片机在访问外部空间时,它的地址为16位,因此借助地址锁存使能信号ALE在FPGA/CPLD中实现高8位与低8位地址的编码,组合成16位地址,然后再根据MCS51单片机的读/写信号,实现对FPGA/CPLD的读写操作。
2.2 总线接口设计
通过对MCS51单片机总线读/写时序的分析,设计了图4所示的接口电路。在FPGA/CPLD中,设计了两个模块:一个是总线接口模块,负责单片机与FPGA/CPLD的总线接口逻辑;另一个是寄存器单元及外部接口模块,运用总线接口模块来操作此模块。
图4 MCS51单片机与FPGA/CPLD总线接口框图
图中整个总线接口逻辑模块将MCS51单片机的三总线信号编码成5个信号输出:16位地址信号addr16、读使能信号RD_EN、写使能信号WR_EN、数据输出信号Din及数据输入信号Dout。
在总线接口模块中,又分为3个小模块:三态缓冲模块、锁存器模块及编码模块。三态缓冲模块实现与单片机P0口接口;锁存器模块利用ALE信号锁存单片机输出的低8位地址。利用其下降沿将低8位地址锁存于FPGA/CPLD中的地址锁存器(address latch)中;当ALE将低8位地址通过P0及三态缓冲器锁存的同时,高8位地址已稳定建立于P2口;通过编码模块将高8位与低8位地址组合成16位地址addr16。同时根据单片机的读/写控制信号编码成RD_EN与WR_EN使能信号。
若需从FPGA/CPLD中读出数据,单片机则通过指令"MOVXA,@DPTR"使RD信号为低电平,使能RD_EN信号,由P0口将图中地址addr16所指单元的数据读入累加器A;但若将累加器A的数据写进FPGA/CPLD中,单片机则需通过指令"MOVX @DPTR,A"和写允许信号WR。这时,DPTR中的高8位和低8位数据作为高、低8位地址分别向P2和P0口输出,然后经ALE信号下降沿锁存,产生16位地址addr16。再由WR的低电平使能WR_EN信号,将累加器A的数据经P0口及三态缓冲器写入图中16位地址addr16所对应的单元中。实现单片机对FPGA/CPLD的读/写操作。
2.3 接口VHDL实现及仿真
在总线接口设计中,采用VHDL语言实现其接口逻辑。用VHDL编写接口程序,往往会很方便,但在编写时却要注意读完数据时,要把数据总线释放掉以免造成总线冲突。其源程序如下:
-FPGA/CPLD内部寄存器地址定义
libraryIEEE;
useIEEE.STD_LOGIC_1164.all;
PACKAGEInterfaceIS
CONSTANT ADDR_REG1 :STD_LOGIC_VECTOR(15 DOWNTO 0):=X"FFF1";
CONSTANT ADDR_REG2 :STD_LOGIC_VECTOR(15 DOWNTO 0):=X"FFF2";
CONSTANT ADDR_REG3 :STD_LOGIC_VECTOR(15 DOWNTO 0):=X"FFF3";
CONSTANT ADDR_REG4 :STD_LOGIC_VECTOR(15 DOWNTO 0):=X"FFF4";
ENDInterface;
-FPGA/CPLD读/写操作
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.Interface.all;
entity MCS51_FPGA is
port (
P0 : inout STD_LOGIC_VECTOR (7 downto 0);
P2 : inSTD_LOGIC_VECTOR (7 downto 0);
ALE: inSTD_LOGIC;
WR : inSTD_LOGIC;
RD : inSTD_LOGIC;
LED: outSTD_LOGIC_VECTOR (2 downto 0)
);
end MCS51_FPGA;
ArchitectureC51_FPGA_BUS OF MCS51_FPGA IS
-16位地址
signalC51_Addr16 : STD_LOGIC_VECTOR(15 downto 0);
-内部寄存器
signal Data: STD_LOGIC_VECTOR (31 downto 0);
-WR/RD 使能
signalWR_EN:STD_LOGIC;
signalRD_EN:STD_LOGIC;
Begin
-地址锁存
Address_p:process(ALE)
begin
if ALE′event and ALE='0' and ALE'LAST_VALUE='1' then
C51_Addr16<=P2&P0;
end if;
end process;
-WR/RD 使能
WR_EN<= (WR AND RD) OR WR;
RD_EN<= (WR AND RD) ORRD;
-读FPGA内部寄存器
P0 <=
Data(7 downto 0)when C51_Addr16=ADDR_REG1 and RD_EN ='0'ELSE
Data(15 downto 8) when C51_Addr16=ADDR_REG2 and RD_EN ='0'ELSE
Data(23 downto 16)when C51_Addr16=ADDR_REG3 and RD_EN ='0'ELSE
Data(31 downto 24)when C51_Addr16=ADDR_REG4 and RD_EN ='0'ELSE
"ZZZZZZZZ";