电子线路EDA课程设计.docx
《电子线路EDA课程设计.docx》由会员分享,可在线阅读,更多相关《电子线路EDA课程设计.docx(28页珍藏版)》请在冰豆网上搜索。
电子线路EDA课程设计
课程设计任务书
学生姓名:
高顺强专业班级:
电子科学与技术0702班
指导教师:
葛华工作单位:
信息工程学院
题目:
8×9先进先出(FIFO)缓冲器设计
初始条件:
QuartusⅡ软件、微机、FPGA实验箱
要求完成的主要任务:
深入研究和掌握FIFO的理论知识。
利用QuartusⅡ软件强大的编译和仿真功能,实现FIFO缓冲器的设计、仿真以及硬件功能实现。
设计一个8×9先进先出(FIFO)缓冲器,要求达到一下功能:
1、8位字深,9位字宽;
2、当读信号ready有效时,FIFO的输出data_out使能,当ready无效时,FIFO的输出处于高阻态;
3、当写信号write有效时,9位款的寄存器进行写操作;
4、信号rdinc和wrinc被用来作为寄存器读和写指针递增,以指示该位寄存器的读和写;
5、信号rdptclr和wrptclr复位读写指针指向FIFO的第一个寄存器;
6、data_in是将被载入到一个寄存器的数据;
7、ef、ff分别作为缓冲器空和满的标志(附加)。
时间安排:
学习FIFO缓冲器的基本理论知识第1天
学习QuartusⅡ软件的基本操作第2、3天
学习VHDL语言的基本知识及应用环境第4、5天
课程设计第6-9天
答辩第10天
指导教师签名:
年月日
系主任(或责任教师)签名:
年月日
目录
摘要I
AbstractII
1绪论1
2FIFO缓冲器原理2
2.1FIFO缓冲器的结构2
2.2FIFO的一些重要参数2
2.3FIFO的分类3
2.4FIFO缓冲器的应用场合4
2.5FIFO缓冲器空/满状态的算法4
3方案论证6
4FIFO缓冲器设计7
4.1方案一——FIFO定制7
4.1.1设计步骤7
4.1.2功能验证8
4.2方案二——8个字长为9的变量构成寄存器10
4.2.1设计步骤10
4.2.2仿真12
4.3方案三——8×9数组构成寄存器13
4结束语14
5致谢15
参考文献16
附录117
附录219
摘要
先进先出(FIFO)缓冲器是双端口数据存储器,其存储结构与RAM相同,仅存储方式存在差异。
本文详细介绍了基于FPGA开发环境QuartusII、用VHDL语言编程实现FIFO缓冲器的方法和过程。
通过仿真和实验实现了FIFO缓冲器的数据读写功能、读写指针移动和复位功能、缓冲器空、满指示标志功能。
此外,设计者从增强FIFO功能和提高FIFO存储速度和出发,拟定了三种设计方案,使FIFO缓冲器性能得以优化,并且都进行了仿真和FPGA实现。
关键词:
FIFO缓冲器,FPGA,QuartusII,VHDL
Abstract
FirstInFirstOut(FIFO)bufferisadual-portdatamemory.IthasthesamestoragestructurewithRAM,butdifferencesinthestoragepattern.ThisarticledescribesthemethodsandprocessesofdesigningaFIFObuffer,whichbasedonQuartusII--theFPGAdevelopmentenvironment.ThedesignisprogrammedbyVHDLlanguage.Viathesimulationandexperiment,suchFIFObufferfunctionsisachived,asdatareadingandwriting,movingandresettingthereadandwritepointer,signagefeatureofemptyandfull.Inaddition,inordertoenhancingthefunctionandimprovethestoringspeedofFIFO,thedesignerdevelopedthreedesignoptionsandhavecarriedoutsimulationandimplementationonFPGAchip,sothatFIFObuffer’sperformancecanbeoptimized.
Keywords:
FIFObuffer,FPGA,QuartusII,VHDL
1绪论
随着电子工程和计算机科学(EECS)的迅猛发展,数字电路系统的发展也十分迅速。
电子器件在最近几十年经历了从小规模集成电路到中、大规模集成电路的发展历程。
从简单的可编程器件到高密度可编程器件。
设计方法也在从根本上转变。
由原来的手工设计发展到现在的电子设计自动化EDA(ElectronicDesignAutomation)技术。
EDA技术就是依赖功能强大的计算机。
在EDA工具软件平台上.以硬件描述语言VHDL(VeryHighSpeedInte-gratedCircuitHardwareDescriptionLanguage)为系统逻辑捕述手段。
自顶而下地逐层完成相应的描述、综合、优化、仿真与验证,直至生成器件。
QuartusII是Altera公司的综合性PLD开发软件,支持原理图、VHDL、VerilogHDL以及AHDL(AlteraHardwareDescriptionLanguage)等多种设计输入形式,内嵌自有的综合器以及仿真器,可以完成从设计输入到硬件配置的完整PLD设计流程。
QuartusII可以在XP、Linux以及Unix上使用,除了可以使用Tcl脚本完成设计流程外,提供了完善的用户图形界面设计方式。
具有运行速度快,界面统一,功能集中,易学易用等特点。
Altera的QuartusII可编程逻辑软件属于第四代PLD开发平台。
该平台支持一个工作组环境下的设计要求,其中包括支持基于Internet的协作设计。
Quartus平台与Cadence、Exe-mplarLogic、MentorGraphics、Synopsys和Synplicity等EDA供应商的开发工具相兼容。
改进了软件的LogicLock模块设计功能,增添了FastFit编译选项,推进了网络编辑性能,而且提升了调试能力。
Altera在QuartusII中包含了许多诸如SignalTapII、ChipEditor和RTLV-iewer的设计辅助工具,集成了SOPC和HardCopy设计流程,并且继承了MaxplusII友好的图形界面及简便的使用方法。
此外,QuartusII通过和DSPBuilder工具与Matlab/Simulink相结合,可以方便地实现各种DSP应用系统;支持Altera的片上可编程系统(SOPC)开发,集系统级设计、嵌入式软件开发、可编程逻辑设计于一体,是一种综合性的开发平台。
本文采用VHDL语言来实现FIFO缓冲器的读写等功能,通过硬件化设计到软件化设计转化,从而体现数字电路从硬件设计向软件化方向发展的新思路。
2FIFO缓冲器原理
FIFO是英文FirstInFirstOut的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
2.1FIFO缓冲器的结构
FIFO缓冲器一般由三部分构成,分别为写地址产生器、读地址产生器、双端寄存器。
各部分都有各自的时钟信号,有数据输入输出端口、读写操作控制信号、有缓冲空满标志位。
FIFO缓冲器一般结构简图如图2-1所示。
2.2FIFO的一些重要参数[5]
FIFO的宽度:
也就是英文资料里常看到的THEWIDTH,它指的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。
FIFO的深度:
THEDEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。
如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12,就可以存储12个8位的数据,FIFO的深度可大可小,个人认为FIFO深度的计算并无一个固定的公式。
在FIFO实际工作中,其数据的满/空标志可以控制数据的继续写入或读出。
在一个具体的应用中也不可能由一些参数算数精确的所需FIFO深度为多少,这在写速度大于读速度的理想状态下是可行的,但在实际中用到的FIFO深度往往要大于计算值。
一般来说根据电路的具体情况,在兼顾系统性能和FIFO成本的情况下估算一个大概的宽度和深度就可以了。
而对于写速度慢于读速度的应用,FIFO的深度要根据读出的数据结构和读出数据的由那些具体的要求来确定。
满标志:
FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。
空标志:
FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。
读时钟:
读操作所遵循的时钟,在每个时钟沿来临时读数据。
写时钟:
写操作所遵循的时钟,在每个时钟沿来临时写数据。
读指针:
指向下一个读出地址。
读完后自动加1。
写指针:
指向下一个要写入的地址的,写完自动加1。
读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。
2.3FIFO的分类
根据FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。
同步FIFO是指读时钟和写时钟为同一个时钟。
在时钟沿来临时同时发生读写操作。
异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
异步FIFO缓冲器结构原理图如图2-2所示。
2.4FIFO缓冲器的应用场合
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位100KSPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。
另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。
2.5FIFO缓冲器空/满状态的算法
FIFO设计的难点在于怎样判断FIFO的空/满状态。
为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。
在空的状态下不能进行读操作。
怎样判断FIFO的满/空就成了FIFO设计的核心问题。
由于同步FIFO几乎很少用到,这里只描述异步FIFO的空/满标志产生问题。
经查阅资料,了解到很多关于FIFO的文章其实讨论的都是空/满标志的不同算法问题。
第一个算法:
构造一个指针宽度为N+1,深度为2^N字节的FIFO(为方便比较将格雷码指针转换为二进制指针)。
当指针的二进制码中最高位不一致而其它N位都相等时,FIFO为满(在CliffordE.Cummings的文章中以格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。
当指针完全相等时,FIFO为空。
这也许不容易看出,举个例子说明一下:
一个深度为8字节的FIFO怎样工作(使用已转换为二进制的指针)。
FIFO_WIDTH=8,FIFO_DEPTH=2^N=8,N=3,指针宽度为N+1=4。
起初rd_ptr_bin和wr_ptr_bin均为“0000”。
此时FIFO中写入8个字节的数据。
wr_ptr_bin=“1000”,rd_ptr_bin=“0000”。
当然,这就是满条件。
现在,假设执行了8次的读操作,使得rd_ptr_bin=“1000”,这就是空条件。
另外的8次写操作将使wr_ptr_bin等于“0000”,但rd_ptr_bin仍然等于“1000”,因此FIFO为满条件。
显然起始指针无需为“0000”。
假设它为“0100”,并且FIFO为空,那么8个字节会使wr_ptr_bin=“1100”,,rd_ptr_bin仍然为“0100”。
这又说明FIFO为满。
第二种算法:
CliffordE.Cummings的文章中提到的STYLE#2。
它将FIFO地址分成了4部分,每部分分别用高两位的MSB00、01、11、10决定FIFO是否为goingfull或goingempty(即将满或空)。
如果写指针的高两位MSB小于读指针的高两位MSB则FIFO为“几乎满”。
若写指针的高两位MSB大于读指针的高两位MSB则FIFO为“几乎空”。
在VijayA.Nebhrajani的《异步FIFO结构》第三部分的文章中也提到了一种方法,那就是方向标志与门限。
设定了FIFO容量的75%作为上限,设定FIFO容量的25%为下限。
当方向标志超过门限便输出满/空标志,这与CliffordE.Cummings的文章中提到的STYLE#2可谓是异曲同工。
他们都属于保守的空满判断。
其实这时输出空满标志FIFO并不一定真的空/满。
[4]
在本设计中,总结了以上算法,应用到简单的8×9FIFO缓冲器中的空/满标标志位判断,提出一下算法:
满标志判断:
读指针指向起始位置,写指针直向末尾位置,或者写指针+1=读指针;空标志判断:
写指针指向起始位置,读指针直向末尾位置,或者读指针+1=写指针。
出现空/满的情况,则停止读写。
说到此,我们已经清楚地看到,FIFO设计最关键的就是产生空/满标志的算法的不同产生了不同的FIFO。
但无论是精确的空满还是保守的空满都是为了保证FIFO工作的可靠。
3方案论证
根据以上阐述的FIFO结构及原理,最为直接的设计方案就是用VHDL语言分别编写读地址生成模块,写地址生成模块,寄存器模块和产生空/满标志模块,然后用PORTMAP将各个模块连接在一起。
这种方法思路清晰,结构明了,也较容易实现。
但是由于挨个模块的编写,代码冗余度高,浪费资源。
所以,从简化设计流程、提高代码效率的角度出发,提出了一下三种方案。
方案一充分利用QuartusII软件的强大集成环境,直接定制FIFO模块,系统提供现成的电路结构图、程序代码、仿真波形等文件。
只需用户简单的调用和设置就可以完成,非常方便快捷,而且准确。
方案二使用VHDL语言编写程序实现FIFO功能。
从提高代码有效率的角度出发,用8个向量为9的变量存储数据,并将读写操作同内部寄存器融合在一起编写。
整合模块,提高利用率。
方案三同样是使用VHDL语言编写程序实现FIFO功能。
但使用数组定义存储空间,结构形象,而且将元素号变量化,避免重复的声明定义,提高了代码效率。
以上三种方案都可行之处,故一一实现之。
4FIFO缓冲器设计
三种方案分别为FIFO定制、8个字长为9的变量构成寄存器、8×9数组构成寄存器。
4.1方案一——FIFO定制
4.1.1设计步骤
方案一直接QuartusII自带的FIFO利用设计步骤如下:
[1]
(1)打开MegaWizardPlug-InManager初始对话框。
在Tools菜单中选择MegaWizard
Plug-InManager,产生如图4-1所示的界面,选择Createanewcustom…项(如果要修改一个已编辑好的LPM模块,则选择Editanexistingcustom…项),即定制一个新的模块。
单击Next按钮后,产生如图4-2所示的对话框,在左栏选择Storage项下的FIFO,再选择Cyclone器件和VHDL语言方式;最后输入FIFO文件存放的路径和文件名:
d:
\sin_gnt\data_rom.vhd(定制的ROM元件文件名),单击Next按钮。
(2)输出信号控制线。
选择full、empty、usedw。
(3)单击Next按钮后继续执行以下设置。
后面的设置基本都默认,直接单击NEXT,直至出现如图4-4所示的界面。
选中所有的文件,即可生成.vhd、.inc、.cmp、.bsf、.jpg等文件。
至此,FIFO宏定制设计完成。
下面检测验证其功能。
4.1.2功能验证
打开桌面EDA课设文件夹中.bsf文件,得到如图4-5所示的功能模块图;打开.jpg文件得到如图4-6的波形图。
当写使能write=1,read=0时的时候,遇到第一个脉冲上升沿就将输入端口的001送到内部双端寄存器里面,第二个脉冲时把002送进去;之后读使能
read=1,将第一个数001送到输出端口;read=0,写入第三个数003;再次读使能read=1,读出第二个数001。
当aclr=1时,地址清零。
在写入第一个数后,读指针加1等于写指针,故判为空。
双击如图4-5所示的框图,则调出了其隐含的程序,如附录1所示。
将附录一的程序复制到新建的一个工程里运行仿真,得到与图4-6相同的波形,经此验证,可得出功能完全正确,符合FIFO功能。
4.2方案二——8个字长为9的变量构成寄存器
4.2.1设计步骤
方案二和方案三都是用VHDL语言编写的程序以实现FIFO的设计,两种方案的程序均分为四个部分,即写操作、读操作、满标志、空标志。
[2]
设计步骤如下:
运行QuartusII软件,新建VHDL文件,在程序编辑区编写VHDL程序。
首先编写VHDL库的调用,由于FIFO功能及程序需要,需调用IEEE库和STD库。
调用程序如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
然后编写工程实体。
工程实体应当包含参数例化和端口声明。
应当注意程序中的实体名应和工程设置中的实体名一致。
实体编程如下:
entitymyfifois
generic(width:
integer:
=9;depth:
integer:
=8;addr:
integer:
=3);
port(data_in:
instd_logic_vector(width-1downto0);
data_out:
outstd_logic_vector(width-1downto0);
wrptclr,rdptclr:
instd_logic;
clk:
instd_logic;--时钟信号
write,ready:
instd_logic;--写读使能端
wradd,rdadd:
outstd_logic_vector(addr-1downto0);--读、写指针输出
ef,ff:
outstd_logic);--栈空满信号
end;
在结构体内主要是信号的声明,在进程里主要是变量的声明和主程序。
方案二我们将寄存器设为8个字长为9的矢量。
signalqx:
std_logic_vector(width-1downto0);
其中x是0-7的数,width=9。
主程序部分分为四大块,写操作、读操作、满标志、空标志。
现分述如下:
写操作:
当wrptclr为0时,首先将写地址wrinc清零。
当wrptclr为1且写使能write=1、读使能无效ready=0时,将data_in写入寄存器。
程度段如下:
write_prog:
process(wrptclr,clk)is
begin
if(wrptclr='0')then
wrinc<=(others=>'0');wradd<=wrinc;
elsif(clk'eventandclk='1')then
if(write='1')then
casewrincis
when"000"=>q0<=data_in;
………………
读操作:
与写操作算法相同,只是读指针为rdinc,读指针清零控制变量rdptclr。
if(rdptclr='0')thenrdinc<=(others=>'0');
elsif(clk'eventandclk='1')then
if(ready='1')then--加入当ready无效时,输出处于高阻态
caserdincis
when"000"=>data_out<=q0;…………
elsedata_out<="ZZZZZZZZZ";
产生满标志:
根据2.5节FIFO空/满标志算法讨论,满标志在写地址指针=读地址指针+1,或者写标志指向首单元,读标志位指向尾单元。
产生满标志进程,程序段如下:
if(clk'eventandclk='1')then
if(write='1'andready='0')then
if(w=r1)or((wrinc=conv_std_logic_vector(depth-1,3))and(rdinc="000"))thenff<='1';
产生空标志:
同满标志情况。
if(clk'eventandclk='1')then
if(ready='1'andwrite='0')then
if(r=w1)or((rdinc=conv_std_logic_vector(depth-1,3))and(wrinc="000"))thenef<='1';
--注:
conv_std_logic_vector(depth-1,3)为类型转换函数,将depth-1转化为3位矢量。
至此,程序整体结构全部完成,完整程序见附录2。
4.2.2仿真
新建一个VectorWaveformFiles,在NAME区域选择右键菜单中的InsertNodeorBus,点击List按钮,在左边的List菜单里选择要观察波形的端口名,点击“>”符号将其选入右边的列表里。
点击OK,再确定回到VectorWaveformFiles界面。
然后设置输入端口信号,如clk将其设置为频率为40ns的脉冲时钟信号。
设置好的信号如图4-7所示。
选择Processing菜单中选择SimulatorTool,Simulatormodel选择Functional,点击右面的
按钮,然后点击下面的
开始仿真,再点击右下角的
按钮,即可观察到如下波形。
仿真波形如图4-7所示。
分析如下:
写操作:
当write=1,ready=0时,在时钟脉冲上升沿时刻将data_in数据送如寄存器,写地址加1,而输出成高阻态。
读操作:
当ready=1时,将读地址指针指向的内容送到输出端口,读地址指针加1。
空标志:
当rdadd=100,wradd=101时,r