(ISE使用流程)逻辑设计实验_第1页
(ISE使用流程)逻辑设计实验_第2页
(ISE使用流程)逻辑设计实验_第3页
(ISE使用流程)逻辑设计实验_第4页
(ISE使用流程)逻辑设计实验_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

实验一ISE工具的使用流程--拨码开关控制LED实验1.1实验目的1.学会ISE的基本开发流程和常用功能的使用,本实验直接使用新建一个拨码开关控制led实验来作为设计文件,通过ise综合、映射、布局布线后,生成FPGA位流配置文件,通过JTAG口对开发板上FPGA进行配置。2学会最基本拨码开关和led工作原理。1.2实验原理实验开发板的拨码开关向上拨动时处于低电平,向下处于高电平,用此来控制LED灯。LED灯的的一端已经接高电平,另一端接FPGA的IO口,因此当IO输出低电平是便可点亮LED灯,否则LED为暗。按键默认为高电平,按键按下时接地为低电平来检测按键的按下的复位信号。1.3实验步骤打开ISE应用程序,进入图形化界面图表SEQ图表\*ARABIC1点击File->Newproject,在弹出的对话框中设定工程和工程路径,用HDL源码,NEXT图表SEQ图表\*ARABIC2选定器件和封装,点击NEXT.图表SEQ图表\*ARABIC3在工程中创建源文件,选择NewSource.,选中VerilogModule,输入源文件名称图表SEQ图表\*ARABIC4可在弹出的对话框中输入信号的输入输出定义,也可暂时不定义图表SEQ图表\*ARABIC56.点击下一步,点击finish,然后自动回到creatanewsource对话框,点击下一步,再击下一步,然后点击finish。图表SEQ图表\*ARABIC6点击设计的源文件,然后整个界面如图所示图表SEQ图表\*ARABIC7将鼠标置于输入输出的下方,点击工具栏中的,然后进入各子目录选择如下,这是一个快捷操作模板。右键useinfile,可在源文件中看到已经添加相应的模板,然后修改一些端口、添加内容完善整个工程设计。图表SEQ图表\*ARABIC8写源文件的代码如下modulekey_led(clk,key,reset_n,led);inputclk;inputkey;inputreset_n;outputled; regled; //UsageofasynchronousresetsmaynegativelyimpactFPGAresources//andtiming.IngeneralfasterandsmallerFPGAdesignswill//resultfromnotusingasynchronousresets.Pleasereferto//theSynthesisandSimulationDesignGuideformoreinformation.always@(posedgeclkornegedgereset_n)if(!reset_n)beginled<=1;endelsebeginif(key==0) led<=0; else led<=1;end endmodule可用designUtilities点击createschematicsymbol下观看所生成的原理图来分析电路的性能。添加约束文件,sourcefor选择在synthesis….,选中源文件,右键newsource,选择如图所示,输入文件名,点击next,然后finish.可以看到已经添加到工程中。图表SEQ图表\*ARABIC9添加测试文件,在sourcefor选择在behavioral….,newsource,然后选择Verilogtestfixture,建立测试文件。Next,选择关联key_led,点击完成图表SEQ图表\*ARABIC1011.编写测试文件代码如下:选中测试文件,在processes中的modelsimsimulator中的下拉菜单中双击simulate….这样就可以仿真了。(注意在仿真之前要进行xilinxlibrary库的编辑,方法见附录1)modulekey_led_tb_v; //Inputs regclk; regkey; regreset_n; //Outputs wireled; //InstantiatetheUnitUnderTest(UUT) key_leduut( .clk(clk), .key(key), .reset_n(reset_n), .led(led) );always#5clk=~clk; initialbegin //InitializeInputs clk=0; key=1; reset_n=1; //Wait100nsforglobalresettofinish #100key=0; #100reset_n=0; #100reset_n=1; #100key=1; #100$stop; //Addstimulushere endendmodule图表SEQ图表\*ARABIC1112.管脚分配,回到sythesis…下,选中ucf文件,在process中双击打开assignpackagePins,按照管脚分配图进行相应配置,然后保存。图表SEQ图表\*ARABIC1213.回到主界面选中HDL设计文件,双击generate…,然后修改到成功没有错误为止。如下图所示图表SEQ图表\*ARABIC1314.生成Bit文件,在generate….下拉菜单中,双击第二个,进行JTAG下载配置(先进行实验板上的下载硬件配置连接)。然后会提示成功与否图表SEQ图表\*ARABIC1415.进行开发板验证。实验步骤结束1.4实验结果分析仿真如图所示图表SEQ图表\*ARABIC15通过实验板验证可以看到,当讲拨码开关拨向ON时,灯亮,拨向OFF时暗,当不论在什么状态下,按下复位键则灯立即变暗,直至松手。因此简单本设计符合设计预期的要求。通过本实验,了解了最基本的硬件知识和建立一个工程,代码编写、综合、约束、分析、调试、下载观察等过程。通过本次实验,进一步了解了FPGA工程使用的一个简单流程,在实验过程中需要认真做好每一个环节,配合实验说明书找到解决方法。实验过程中遇到的问题和解决方法:生成的bit文件后,下载实验现象没有变化:可能保存的路径错了,导致屡试屡败无法正常显示窗口:修改桌面系统主题,该回经典xp等默认主题,这是由于EDK与操作系统的一些不兼容造成的。综合错误:修改成可综合代码。有警告:可稍微看一下警告的内容,但这是正常现象。附录1:xilinxlibrary编译方法两种(选其中一种):(一)、在ISEProjectNavigator中编译仿真库1、打开文件:安装路径:\Modeltech_6.2b,选中文件夹中的配置文件modelsim.ini,右击,将文件属性中的只读去掉,变成可写入的,接着用写字板程序打开;2、在sources窗口中选择设计的目标器件xc3s500e-4pq208;在processes窗口中会出现designUtilties,选择CompileHDLSimulationLibraries项。单击右键,在下拉菜单中选中Properties命令,打开对话框如图所示。3、ProcessProperties按如图选择,单击ok按钮关闭对话框。4、双击CompileHDLSimulationLibraries,程序会自动完成对库文件的编译。5、观看是否在modelsim.ini文件中加入以下部份。 ;VerilogSection unisims_ver=库文件所在地址/unisims_ver uni9000_ver=库文件所在地址/uni9000_ver simprims_ver=库文件所在地址/simprims_ver xilinxcorelib_ver=库文件所在地址/xilinxcorelib_ver aim_ver=库文件所在地址/abel_ver/aim_ver cpld_ver=库文件所在地址/cpld_ver ;VHDLSection unisim=库文件所在地址/unisim simprim=库文件所在地址/simprim xilinxcorelib=库文件所在地址/xilinxcorelib aim=库文件所在地址/abel/aim pls=库文件所在地址/abel/pls cpld=库文件所在地址/cpld6、再将modelsim.ini设为只读即可7、可采用modelsim进行仿真了。(二)、另一种方法在桌面上点击开始――运行――输入cmd,进入dos.在dos下输入:compxlib–smti_se–archall–lall–dir%xilinx%/lib–w等编译完成后便可在安装目录下的lib中生成库,将生成的库加入modelsim中。方法:打开文件:安装路径:\Modeltech_6.2b,选中文件夹中的配置文件modelsim.ini,右击,将文件属性中的只读去掉,变成可写入的,接着用写字板程序打开;在modelsim.ini中加入一下内容(库文件所在地址为->安装路径:\Xilinx92i\lib,比如有的同学是装在D盘,那就是:D:\Xilinx92i\lib,这一步完成后将modelsim.ini再设为只读) ;VerilogSection unisims_ver=库文件所在地址/unisims_ver uni9000_ver=库文件所在地址/uni9000_ver simprims_ver=库文件所在地址/simprims_ver xilinxcorelib_ver=库文件所在地址/xilinxcorelib_ver aim_ver=库文件所在地址/abel_ver/aim_ver cpld_ver=库文件所在地址/cpld_ver ;VHDLSection unisim=库文件所在地址/unisim simprim=库文件所在地址/simprim xilinxcorelib=库文件所在地址/xilinxcorelib aim=库文件所在地址/abel/aim pls=库文件所在地址/abel/pls cpld=库文件所在地址/cpld实验二用CoreGenerator生成DCM并进行仿真验证2.1实验目的学会用coregenerate生成dcm,并使用modelsim进行仿真。2.2实验原理1.DCM是数字时钟管理器,它在xilinx的FPGA的设计中应用广泛,dcm可以产生输入时钟的一倍频、二倍频,或M/D倍频等功能,也可以产生90、180、270度相移的时钟,例如FPGA输入时钟为66M,而我们的系统需要133M的时钟,则可以用到DCM二倍频。2.编译库,将库文件加入modelsim中,然后可以进行联合仿真调试。2.3实验步骤1.在桌面上点击开始-》程序—》xilinxise10.1—ISE》accesseries—》Coregenerator,界面如下:图表SEQ图表\*ARABIC162.单击file->newproject,系统出现如下画面,然后选择工程路径和名字。然后next,设置工程的基本参数:part参数设置,generation参数,advanced,然后点击OK。图表SEQ图表\*ARABIC173.完成新建工程向导后,按顺序展开FPGAfeaturesanddesign-》clocking-》spartan_3e,可以看到DCM_SP,双击singleDCM_SP。图表SEQ图表\*ARABIC184.双击SingleDCM_SP后,进入dcm生成向导,设定名称为dcm_test.,点击ok后,进入下一界面进行如下图的配置。图表SEQ图表\*ARABIC195.下一步进入下图所示的界面,设定完成后点击next.区域一:DCM_SP的基本模型,根据实际情况在需要的输入输出上打勾;区域二:设定输入DCM的时钟频率,或者是周期,根据需要选择一种;区域三:设定DCM的输出时钟和输入时钟的相对位移,一般情况下不进行设置;区域四:选择输出时钟源,是FPGA外部输入,还是内部时钟信号,一般第一级的dcm是外部输入,二级、三级dcm是前一级的dcm输出,是内部信号;区域五:时钟反馈类型,是外部还是内部反馈,一般是直接使用DCM的clk0或者clk2x做内部反馈,特殊情况需要外部输入的时钟进行反馈,但很少使用;区域六:设定clkdv的分频数,即相对于clkin的分频数,如图选择的值为5,则50Mhz的输入进行五分频,那么clkdv输出为10Mhz。如果没有勾clkdv输出,则不需要进行参数设置;区域七:反馈类型选择,可以是时钟的1或者2分频。区域八:时钟dutycycle的矫正,默认选上,可以更好的占空比为50%的时钟信号。图表SEQ图表\*ARABIC206.下一步进入clockbuffer的设置,默认使用个咯罢了globalbuffer。点击next图表SEQ图表\*ARABIC217.下一步设置的是clkfx的时钟输出,一般采用设置M和D的值来控制clkFX的输出,计算公式为clkfx=clkin*(m/d),输入预计好的M、D值,点击calculate即可得到clkfx的输出频率,如果最开始没有选择clkfx输出,则可以跳过。图表SEQ图表\*ARABIC228.点击next,点击finish,完成DCM的生成。完成后的界面如图所示。图表SEQ图表\*ARABIC239.在ise里面新建工程,将生成的dcm_test拷贝到工程目录下,并添加到工程文件中。建完后如下图所示图表SEQ图表\*ARABIC24观看综合后的原理图方法为:10.给dcm_test添加测试文件,具体过程可参考实验一,建完后修改补充测试文件如下(这里的dcm为高电平复位):`timescale1ns/1ps`defineclk_cycle15//////////////////////////////////////////////////////////////////////////////////Company://Engineer://CreateDate:18:42:4301/02/2010//DesignName:dcm_test//ModuleName:E:/xilinx/project/lab2/dcm_11M/dcm_11M_tb.v//ProjectName:dcm_11M//TargetDevice://Toolversions://Description://VerilogTestFixturecreatedbyISEformodule:dcm_test//Dependencies://Revision://Revision0.01-FileCreated//AdditionalComments:///////////////////////////////////////////////////////////////////////////////moduledcm_11M_tb_v; //Inputs regCLKIN_IN; regRST_IN; //Outputs wireCLKDV_OUT; wireCLKFX_OUT; wireCLKIN_IBUFG_OUT; wireCLK0_OUT; wireLOCKED_OUT; //InstantiatetheUnitUnderTest(UUT) dcm_testuut( .CLKIN_IN(CLKIN_IN), .RST_IN(RST_IN), .CLKDV_OUT(CLKDV_OUT), .CLKFX_OUT(CLKFX_OUT), .CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT), .CLK0_OUT(CLK0_OUT), .LOCKED_OUT(LOCKED_OUT) );always#(`clk_cycle/2)CLKIN_IN=~CLKIN_IN; initialbegin //InitializeInputs CLKIN_IN=0; RST_IN=0; //Wait100nsforglobalresettofinish #500RST_IN=1;#100RST_IN=0; #500$stop; endendmodule11.添加管脚时许约束文件,先建立约束文件,然后双击creattimingconstraints—》global—》双击clock——in的period,如图所示进行配置,然后保存退出。图表SEQ图表\*ARABIC2512.调用modelsim进行联合仿真,实验结束,可对DCM设置参数进行修改不断改变波形。图表SEQ图表\*ARABIC2613.综合后几个常用的工具,如观察RTL级的电路结构和门级结构的原理图图表SEQ图表\*ARABIC272.4实验结果分析1.调用modelsim的仿真结果如下图表SEQ图表\*ARABIC28结果分析:由于本实验在区域六选择的是6分频,clkfx也是六分频,无位相移动因此可以从波形很直观的看出实验结果。即clkfx和clkdv都是六分频和clkin是同相位的2.为了得到其他的频率输出可以对DCM参数进行修改,如将clkdv改成3分频后的仿真波形。可以看到clkdv输出变成了3分频,而clkfx不做改变图表SEQ图表\*ARABIC293.将clk180选中,将clkfx180选中,两者都是六分频,仿真波形如图所示,从图形可以看出实验结果与预期的相符合。Clkfx180和clk180与clkfx和clkdv是反相关系。图表SEQ图表\*ARABIC30实验心得和体会:通过本次实验操作,初步了解了利用DCM产生我们所需要的波形的基本流程,也对DCM产生波形的利用有了更进一步的了解。为下下一步的进一步深入学习起到一个好的开始。实验过程中存在的问题和解决方法无法在ise里面调用modelsim进行仿真:可能是没有编译xilinx库文件,或者编译后并没有在modelsim中进行添加。若还是不行,先进行常规仿真,看是否有软件有问题,有问题进行再次重装。修改了DCM参数后为何仿真波形没有改变:首先确认是否是将生成的dcm_test.v拷贝至工程目录再添加,还是直接从dcm工程里面的文件添加到ise工程文件中,拷贝的需要再次拷贝更新后的文件到工程中再添加,若是后者只要更新工程即可,若更改了输入输出需要对测试文件重新关联。如何更直观的去查看自己写出来的代码综合后的电路图:ise提供了可观察综合后的RTL级电路结构和门级的电路结构原理图,可以让设计人员通过更直观的的原理图来观察自己所写代码的原理图,这样更能加深对硬件描述语言的了解。实验三按键检测实验3.1实验目的1.学会鉴别信号的上升沿和下降沿,熟练掌握信号的检测。2.学会按键检测原理,熟练掌握按键信号的检测,掌握和理解按键抖动对信号检测的影响。3.2实验原理3.2.1信号检测原理 信号的采集就是对信号的上升沿和下降沿进行采集,上图是一个信号enable,它变为高电平几个周期后再变为低电平。首先对信号的enable进行一拍时钟采样,也就是一个时钟周期的延迟,经过处理后的信号enably_dly是enable的一个延迟一个时钟周期后的信号,如图所示。图表SEQ图表\*ARABIC313.2.2键盘检测原理 按键检测原理是:当按键按下时,输入电平由高变低,按键松开后,输入电平有低变高,如此会产生一个下降沿和一个上升沿,只要扑捉到这两个沿,就可以确定按键按下。3.2.3键盘防抖原理 在按键被按下的瞬间,由于物理上的原因,导致按键在被按键的瞬间的过程中其实是处于高电平和低电平之间进行抖动,加上本实验的时钟频率很高,容易产生信号采集错误,导致检测失败,无法得到正确的结果。若要正确防抖,需要在检测到按键上升沿后延迟一小段信号在进行上升沿和下降沿检测。3.3实验步骤1.建立ise工程,建立按键检测文件和测试文件如图所示:图表SEQ图表\*ARABIC32键盘检测程序如下:modulekey_scan(clk,reset_n,key,led);inputclk;inputreset_n;inputkey;outputled;regkey_dly;regkey_dly1;regkey_pose_flag;regkey_nege_flag;regkey_pulse; regled;always@(negedgereset_norposedgeclk)beginif(reset_n==1'b0)key_dly<=1'b0;elsekey_dly<=key;endalways@(negedgereset_norposedgeclk)beginif(reset_n==1'b0)key_dly1<=1'b0;elsekey_dly1<=key_dly;endalways@(negedgereset_norposedgeclk)beginif(reset_n==1'b0)key_nege_flag<=1'b0;elseif(key_dly==1'b0&&key_dly1==1'b1)key_nege_flag<=1'b1;elseif(key_pulse==1'b1)key_nege_flag<=1'b0;endalways@(negedgereset_norposedgeclk)beginif(reset_n==1'b0)key_pose_flag<=1'b0;else if(key_nege_flag==1'b1) begin if(key_dly==1'b1&&key_dly1==1'b0) key_pose_flag<=1'b1; elseif(key_pulse==1'b1) key_pose_flag<=1'b0; end end always@(negedgereset_norposedgeclk)beginif(reset_n==1'b0)key_pulse<=1'b0;elseif(key_pose_flag==1'b1&&key_nege_flag==1'b1)key_pulse<=~key_pulse;else key_pulse<=key_pulse; end always@(posedgeclkornegedgereset_n) begin if(reset_n==1'b0) led<=1'b1; else if(key_pulse==1'b1) led<=~led; end endmodule测试文件:`include"./key_scan.v"`timescale1ns/1nsmodulekey_scan_t;regclk,key,reset_n;wireled;key_scantest(.clk(clk),.key(key),.reset_n(reset_n),.led(led));always#1clk=~clk;initialbeginreset_n=0;key=1;clk=0;#10reset_n=0;#10reset_n=1;#10key=0;#10key=1;#10key=0;#10reset_n=0;#10reset_n=1;#10key=1;#10key=0;#10key=1; #10key=0; #10key=1; #10key=0; #10key=1; #10key=0; #10key=1;#100$stop;endendmodule2.对键盘检测文件进行综合和仿真。综合结果如图所示图表SEQ图表\*ARABIC33门级的原理图如下:图表SEQ图表\*ARABIC343.在ise工程中添加ucf文件,完成管脚分配布局布线生成FPGA的bit文件,下载到实验板进行检测图表SEQ图表\*ARABIC354.下载到实验板进行实验,然后修改至正常检测。3.4实验结果分析1.键盘检测仿真波形图表SEQ图表\*ARABIC36波形分析: 通过波形我们可以看出,在经过检测键盘按下的下降沿和上升沿得到上升标志和下降标志延迟了将近2个时钟周期,在键盘松手后,产生一个时钟周期的脉冲信号使灯的状太相反,如波形所示,本程序能较好的完成了键盘的检测。2.心得与体会:通过本次实验,使我进一步明白了键盘检测的原理,通过实验想象进行更直观的学习键盘检测。同时通过本次实验,让我充分感受到在进行实验板调试之前的功能仿真的重要性。信号的检测使我不会再滥用信号的边沿触发,纠正了我进行代码便携的一大误区,同时也加深理解了硬件语言和软件语言的区别。3.实验过程中存在的问题和解决方法。1)综合无法通过提示混合信号赋值:大有可能是因为进行了在统一always模块当中进行了阻塞和非阻塞同时赋值的情况,这是不可综合的。2)按键按下后,灯就一直亮着,只能按下复位键让其变暗:这是因为实验指导书的范例程序没有对灯点亮信号进行翻转,只要检测到一次键盘按下便进行点亮保持。3)发现键盘有时感觉不灵敏:这是由于按键在按下的过程中会发生抖动的现象,加上实验开发板的时钟频率比较大,因此需要加上一段延迟才能更准确的消除抖动,因此本实验需要在后续的学习和实践中进一步的晚上,才能写出一个较完美的键盘检测消抖程序。实验四LCD数字秒表4.1实验目的1.学会比较大型的数字系统的设计方法和步骤2.掌握LCD的控制协议和时序工作状态3.掌握可综合代码的编写和仿真4.掌握利用状态机来描述接口协议和状态转移控制5.熟练掌握分频器的设计6.掌握整个系统设计的初步能力和方法4.2实验原理1.LCD工作时序如下图所示,并有相对应的时间约束,由于本实验只用到写时序,因此只介绍读的工作时序。下图是整个LCD的写数据和命令的控制时许,在本实验中需要编写一个lcd_ctrl模块文件来描述此时序要求来发送数据。图表SEQ图表\*ARABIC372.LCD工作控制原理,在本实验中需要将数据写道LCD的内部的寄存器当中,达到控制显示的要求。本实验开发板中由于选择四位的传送模式,因此须在初始化过程的最开始进行设定其中需要在开机后进行LCD初始化操作,然后再不断的进行数据传输扫描显示,初始过程可参考如下:图表SEQ图表\*ARABIC383.LCD接口功能定义如下:图表SEQ图表\*ARABIC394.本试验程序的设计方法和流程1)本实验程序将整个LCD数字秒表系统分成三大模块,分别是LCD时序发生控制模块,数据和命令读写控制状态模块,数字时钟信号产生模块,数据和命令读写控制模块调用其他两个模块实现整个数字系统,系统框图如下:图表SEQ图表\*ARABIC402)时钟发生器程序设计流程时钟发生器由两部分构成,一个是功能键盘,一个是时钟计数器,的时钟由外部晶振提供,第一级产生周期为10ms的时钟进行ms计数,产生百位和十位,百位十位采用十进制计数方式便于数据的输出,分别产生4位的数据,每一个数字为的4位与30H拼接成8位,构成ASCII输出。同时长生S时钟,由秒时钟产生分钟时钟,采用和ms相类似的计数方式,输出都是八位二进制数。流程如下:图表SEQ图表\*ARABIC413)LCD时序控制模块的设计LCD时序控制主要是为了产生和LCD接口协议和时序相吻合的时序,根据时序图可以得出如下的状态流程:图表SEQ图表\*ARABIC42设计流程:图表SEQ图表\*ARABIC434)数据发送控制模块本模块起到协调各模块的作用来控制写数据和写命令,状态机如图所示,首先进行初始化,然后进行数据传输数字跑表的显示,循环进行扫描显示。图表SEQ图表\*ARABIC44设计流程如下:图表SEQ图表\*ARABIC455.LCD数据传送格式。本实验程序设计将数据一次十位数据在读写使能触发后,锁存进入LCD时序模块,防止过程数据变化带来的读写数据错误。低八位为控制命令数据或者显示命令数据,第九位是控制写命令还是写数据的RS信号,第十位控制是读数据还是写数据,由于本实验只涉及写数据,因此整个过程默认为低电平及写数据。在LCD初始化后,状态机便进入数字跑表的数据显示传送。在这个传送的过程中将要显示的8个字符组合成一个字符串首位串接10'b0010000100及在第五个位置开始显示,当显示一串完毕后,再次写入控制数据返回到写显示第一个字符的地方重新刷新显示。整个字符串内容如下:2'b00,8'h84,2'b01,minu_h,2'b01,minu_l,2'b01,8'h3a,2'b01,sec_h,2'b01,sec_l,2'b01,8'h3a,2'b01,ms_h,2'b01,ms_l,2'b00,8'h846.键盘检测键盘检测与实验三的原理相似,这里不再详述7.状态机流程控制本实验共有两个状态机,状态机的转移由相对应的标志信号来控制举例如下:对于function_set状态来说,当进入这个状态后,将此状态需要延迟的时钟信号付给计数器,生成function_set_ok标志信号,然后转向wait状态,开始发出发送数据命令,在nibble标志位的作用下先发送高四位,LCD时序控制模块产生发送完毕应答信号后进入发送低四位,当再次接到接到应答信号时,转入下一状态。具体可参考附录程序。4.3实验步骤1.先在modelsim进行程序的设计,分模块进行编写和测试,如键盘检测、时钟发生器、时序控制模块、读写数据发送模块等并分别进行测试,将模块合成一个系统进行代码编写测试。然后按照LCD时序和预期状态机来观察波形是否符合设计要求,并不断进行代码修改。2.在ise里面间建好工程,添加已经功能仿真通过的程序源文件。如下图所示图表SEQ图表\*ARABIC463.进行代码综合,修改代码,并进行再次调试,综合和功能通过后,查看门级电路结构下图为整个结构图图表SEQ图表\*ARABIC474.建立约束文件进行、管脚分配布局布线,生成bit文件图表SEQ图表\*ARABIC485.通过JTAG口下载实验代码进行实验观察,之后进行实验程序的改进。4.4实验结果分析1.仿真结果波形功能验证:1)下图显示的刚开始的时候,初始化后即将06H命令传送完后第一次扫描输出的结果如图所示:84H,30h,30h,3ah,30h,30h,3ah,30h,30h,84h。验证了输出的可靠性。图表SEQ图表\*ARABIC492)如图显示的是数字秒表显示为00:00:07的状态图表SEQ图表\*ARABIC50如图显示的是一个扫描周期的LCD显示00:01:12图表SEQ图表\*ARABIC512.仿真波形的时序验证,及LCD时序模块的波形,由于一直处于写模式,所以lcd_rw一直为低电平,当触发时能信号wrce来临后,整个读写时序开始形成,经图形可验证时序控制模块正常工作。图表SEQ图表\*ARABIC52时钟发生器的波形仿真,从时钟计数器的波形可以看出,时钟计数正常工作。图表SEQ图表\*ARABIC53周期性变化的高八位和低四位数据交换标志,以及8位传送结束应答信号图表SEQ图表\*ARABIC54其余的众多信号都可以通过波形得到验证。实验过程中遇到的问题和解决方法功能仿真通过了,但LCD还是无法正常显示:首先检查LCD是否正常工作,其次检验程序的各类接口约束时间与LCD手册是否相符LCD重复多次显示多段显示时钟:这可能是由于没有进行写地址为操作造成的时钟走的比预期慢很多,在40S的时候出现很奇怪的现象,时钟卡住,走的很慢:在这个问题上卡了很久很久,一直通过波形寻找答案,最后发现原来是时钟发生器的程序设计和键盘进行接口时发生混乱造成的。状态机一直无法跳入下一个状态:首先找出跳入下一状态的条件,检查程序文件,分析是否错误,进行仿真,查看波形。将每一个信号与预期进行对应,找出问题的根源。开机后秒表不是从零开始:这是由于在复位后和开机后默认时钟发生器工作,而LCD需要进行一段时间的初始化,因此才导致这个问题的存在。解决方法有两种:第一种是设置两个异步复位信号,一个使系统复位,一个是时钟的复位信号;第二种方法是将系统开机和复位后默认时钟是停止的,只是比较简答和快捷的做法,只有按下开始/暂停的功能键,时钟才进入运行。提示大量的警告:可以忽略也可以进行查看还未解决的一问题:在这次设计的过程中,我曾在modelsim进行功能仿真通过后,在ise里面调用modelsim进行仿真,可是没有出错,但功能一直没实现,全部显示为零。实验心的和体会:这是本学期学完逻辑设计和硬件描述语言后第一次真正意义上的代码编写和测试,在这个短短的时间里,让我体会到数字系统的魅力时,更让我深深的感受到:只有投入常人不想投入的时间,才会作出常人做不到的事情。在本次实验中有一下几点收获和体会通过编写小的程序模块,综合进行查看门及电路结构会加深对硬件语言的了解,如阻塞和非阻塞,优先级等只要功能仿真通过了,那么真个设计也就差不多了,这是我在本次试验中体会最深刻的一点,反反复复的仿真、查看波形验证时序直至得到自己想要的结果。在仿真时分模块进行仿真会使设计简单化,然后再进行总体仿真。在这次仿真验证的过程中也进一步熟悉了modelsim的使用技巧,如查看内部寄存器波形等将理论上的硬件和实际硬件联系起来,才能设计出更稳定的HDL模型在编写代码之前有一个和软件非常类似的过程就是程序设计的流程,这会大大简化在设计过程中的工作量,同时会使得思路清晰明了只有不断的实践练习,才能不断的提高和掌握理论知识。附录:实验四程序清单//数据读写发送顶层模块moduletest_lcd_fsm( rst_n , //Activelowclk , //100MHzpause,lcd_rs ,lcd_rw ,lcd_en ,lcd_db );inputpause;input rst_n ; //Activelowinput clk ; //100MHz output lcd_rs ;output lcd_rw ;output lcd_en ;output [7:4] lcd_db ; parameterthd_40ms=60000,thd_2ms=2000,thd_39us=6;parameteridle=3'b000, function_set=3'b001, waits=3'b010, disp_on=3'b011, disp_clear=3'b100, entry_mode_set=3'b101, putchar=3'b110, finish=3'b111; parameterdb_function_set =10'b00_0010_1100; parameterdb_disp_on =10'b00_0000_1111; parameterdb_disp_clear =10'b00_0000_0001; parameterdb_entry_mode_set =10'b00_0000_0110; reg [15:0] ns_cnt; reg us_pulse; reg [15:0] us_cnt; reg us_cnt_overflow; reg [2:0] cur_state; reg [2:0]next_state; reg function_set_ok; reg disp_on_ok; reg disp_clear_ok; reg entry_mode_set_ok; reg char_ok; reg char_ok_sft; reg string_ok; reg [79:0] string; reg putchar_en; reg putchar_en_sft; reg [3:0] putchar_step; reg send_cmd; reg send_cmd_sft; reg [3:0] lcd_db_in; reg nibble_swap; reg nibble_swap_sft; reg dataL_ack;reg lcd_wrce;reg[9:0]bus2ip_data; wire lcd_rs_in; wire lcd_ack; wire rst; wirelcd_en; wirelcd_rw; wirelcd_rs; wirepause,clk; wire[7:0]minu_h,minu_l,sec_h,sec_l,ms_h,ms_l; lcd_ctrllcd_ctrl_init ( .rst (rst) , //Activehigh .clk (clk), //100MHz .lcd_rs_in(lcd_rs_in) , .lcd_db_in(lcd_db_in) , .lcd_rdce(1'b0) , .lcd_wrce (lcd_wrce), .lcd_ack(lcd_ack) , .lcd_rs (lcd_rs) , .lcd_rw (lcd_rw), .lcd_en (lcd_en), .lcd_db (lcd_db) );lcd_clocklcd_clock_init(.pause(pause),.clk(clk),.rst_n(rst_n),.minu_h(minu_h),.minu_l(minu_l),.sec_h(sec_h),.sec_l(sec_l),.ms_h(ms_h),.ms_l(ms_l));assignlcd_rs_in=bus2ip_data[8]; assignrst=~rst_n; /*--------------------------------------------------------------------- --1uscountergenerationandcontroll ----------------------------------------------------------------------*/ always@(posedgerstorposedgeclk) begin if(rst==1'b1) ns_cnt<=99; else if(cur_state==idle) ns_cnt<=99; else if(ns_cnt==0) ns_cnt<=99; else ns_cnt<=ns_cnt-1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) us_pulse<='b0; else if(ns_cnt==1) us_pulse<=1'b1; else us_pulse<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) us_cnt<=0; else case(cur_state) idle: us_cnt<=thd_40ms; function_set,entry_mode_set,disp_on,putchar: us_cnt<=thd_39us; disp_clear: us_cnt<=thd_2ms; waits: if(us_pulse==1'b1) us_cnt<=us_cnt-1'b1; default: us_cnt<=0; endcase end always@(posedgerstorposedgeclk) begin if(rst==1'b1) us_cnt_overflow<=1'b0; else if(us_cnt==1) us_cnt_overflow<=1'b1; else us_cnt_overflow<=1'b0; end /*--------------------------------------------------------------------- --statecontrolstatemachine ----------------------------------------------------------------------*/ always@(*) begin if(rst==1'b1) next_state<=idle; else case(cur_state) idle: next_state<=function_set; function_set: if(dataL_ack==1'b0) next_state<=function_set; else next_state<=waits; disp_on: if(dataL_ack==1'b0) next_state<=disp_on; else next_state<=waits; disp_clear: if(dataL_ack==1'b0) next_state<=disp_clear; else next_state<=waits; waits: if(us_cnt_overflow==1'b0) next_state<=waits; elseif(function_set_ok==1'b1) next_state<=disp_on; elseif(disp_on_ok==1'b1) next_state<=disp_clear; elseif(disp_clear_ok==1'b1) next_state<=entry_mode_set; else next_state<=putchar; entry_mode_set: if(dataL_ack==1'b0) next_state<=entry_mode_set; else next_state<=waits; putchar: if(string_ok==1'b1) next_state<=finish; else next_state<=waits; finish: next_state<=putchar; default: next_state<=idle; endcase end always@(posedgerstorposedgeclk) begin if(rst==1'b1) cur_state<=idle; else cur_state<=next_state; end /*--------------------------------------------------------------------- --statemachinecontrol ----------------------------------------------------------------------*/ always@(posedgerstorposedgeclk) begin if(rst==1'b1) function_set_ok<=1'b0; else if(cur_state==function_set) function_set_ok<=1'b1; elseif(cur_state==disp_on) function_set_ok<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) disp_on_ok<=1'b0; else if(cur_state==disp_on) disp_on_ok<=1'b1; elseif(cur_state==disp_clear) disp_on_ok<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) disp_clear_ok<=1'b0; else if(cur_state==disp_clear) disp_clear_ok<=1'b1; elseif(cur_state==entry_mode_set) disp_clear_ok<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) entry_mode_set_ok<=1'b0; else if(cur_state==entry_mode_set) entry_mode_set_ok<=1'b1; elseif(cur_state==putchar) entry_mode_set_ok<=1'b0; end /*--------------------------------------------------------------------- --putchardatacontroll ----------------------------------------------------------------------*/ always@(posedgerstorposedgeclk) begin if(rst==1'b1) send_cmd<=1'b0; else if(cur_state==idle||cur_state==waits) send_cmd<=1'b0; else send_cmd<=1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) send_cmd_sft<=1'b0; else send_cmd_sft<=send_cmd; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) lcd_wrce<=1'b0; else if((send_cmd==1'b1&&send_cmd_sft==1'b0)|| (putchar_en==1'b1&&putchar_en_sft==1'b0)|| (char_ok==1'b1&&char_ok_sft==1'b0)|| (nibble_swap==1'b0&&nibble_swap_sft==1'b1) ) lcd_wrce<=1'b1; elseif(lcd_ack==1'b1) lcd_wrce<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) nibble_swap<=1'b1; else if(send_cmd==1'b1&&send_cmd_sft==1'b0) nibble_swap<=1'b1; elseif(lcd_ack==1'b1) nibble_swap<=~nibble_swap; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) nibble_swap_sft<=1'b0; else nibble_swap_sft<=nibble_swap; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) dataL_ack<=1'b0; else if(nibble_swap==1'b0&&lcd_ack==1'b1) dataL_ack<=1'b1; else dataL_ack<=1'b0; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) bus2ip_data<='b0; else case(cur_state) function_set: bus2ip_data<=db_function_set; disp_on: bus2ip_data<=db_disp_on; disp_clear: bus2ip_data<=db_disp_clear; entry_mode_set: bus2ip_data<=db_entry_mode_set; putchar: bus2ip_data<={2'b01,string[79:72]}; endcase end always@(posedgerstorposedgeclk) begin if(rst==1'b1) lcd_db_in<=4'h0; else if(nibble_swap==1'b1) lcd_db_in<={bus2ip_data[7:4]}; else lcd_db_in<={bus2ip_data[3:0]}; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) putchar_en<=1'b0; else if(putchar_step==4'b1001) putchar_en<=1'b0; elseif(cur_state==putchar) putchar_en<=1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) putchar_en_sft<=1'b0; else putchar_en_sft<=putchar_en; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) putchar_step<=4'h0; else if(putchar_en==1'b0) putchar_step<=4'h0; elseif(dataL_ack==1'b1) putchar_step<=putchar_step+1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) string<={8'h84,minu_h,minu_l,8'h3a,sec_h,sec_l,8'h3a,ms_h,ms_l,8'h84}; else if(cur_state==finish) string<={8'h84,minu_h,minu_l,8'h3a,sec_h,sec_l,8'h3a,ms_h,ms_l,8'h84}; elseif(putchar_en==1'b1&&dataL_ack==1'b1) string<={string[(79-8):0],8'h00}; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) char_ok<=1'b0; else if(cur_state==putchar) char_ok<=1'b0; elseif(putchar_en==1'b1&&cur_state==waits) char_ok<=1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) char_ok_sft<=1'b0; else char_ok_sft<=char_ok; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) string_ok<=1'b0; else if(cur_state==idle||cur_state==finish) string_ok<=1'b0; elseif(putchar_step==4'b1001) string_ok<=1'b1; endendmodule//LCD时序控制模块`timescale1ns/10psmodulelcd_ctrl( input rst , //Activehigh input clk , //100MHz input lcd_rs_in , input [7:4]lcd_db_in , input lcd_rdce , input lcd_wrce , outputreglcd_ack , output reg lcd_rs , output reg lcd_rw , output reg lcd_en , output reg [7:4] lcd_db ); parametertsu_40ns=7, tw_450ns=63, tw_230ns=31, tc_500ns=63, tc_1000ns=127, thd_10ns=3; parameteridle=3'b000, setup=3'b001, enable=3'b010, hold=3'b011, finish=3'b100; reg [2:0] cur_timing; reg [2:0] next_timing; reg tsu_over; reg tw_over; reg thd_over; reg tc_over; reg [7:0] tsu_cnt; reg [7:0] tw_cnt; reg [7:0] thd_cnt; reg [7:0] tc_cnt; reg lcd_wrce_sft; reg lcd_rdce_sft; /*--------------------------------------------------------------------- --Opbbusinterfacecontroll ----------------------------------------------------------------------*/ always@(posedgerstorposedgeclk) begin if(rst==1'b1) begin lcd_wrce_sft<=1'b0; lcd_rdce_sft<=1'b0; end else begin lcd_wrce_sft<=lcd_wrce; lcd_rdce_sft<=lcd_rdce; end end always@(posedgerstorposedgeclk) begin if(rst==1'b1) lcd_ack<=1'b0; else if(tc_over==1'b1) lcd_ack<=1'b1; else lcd_ack<=1'b0; end /*--------------------------------------------------------------------- --Statemachinecontroll ----------------------------------------------------------------------*/ always@(posedgerstorposedgeclk) begin if(rst==1'b1) tsu_cnt<=8'h00; else if((lcd_wrce==1'b1&&lcd_wrce_sft==1'b0)|| (lcd_rdce==1'b1&&lcd_rdce_sft==1'b0) ) tsu_cnt<=tsu_40ns; elseif(cur_timing==setup) tsu_cnt<=tsu_cnt-1'b1; end always@(posedgerstorposedgeclk) begin if(rst==1'b1) tw_cnt<=8'h00; else if(lcd_wrce==1'b1&&lcd_wrce_sft==1'b0) tw_cnt<=tw_230ns; elseif(lcd_rdce==1'b1&&lcd_rdce_sft==1'b0) tw_cnt<=tw_450ns; elseif(cur_timing==enable) tw_cnt<=tw_cnt-1'b1; end always@(posedgerstorposedgeclk) begin if(rst==

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论