【从零开始走进FPGA】美好开始——我流啊流啊流

2016年02月24日 09:57    发布者:designapp
  按照基于Windows的语言(C、C++、C#)等编程语言的初学入门教程,第一个历程应该是“Hello World!”的例程。但由于硬件上的驱动难易程度,此例程将在在后续章程中推出。硬件工程师学习开发板的第一个例程:流水灯,一切美好的开始。
  本章将会在设计代码的同时,讲解Quartus II 软件的使用,后续章节中只讲软件的思想,以及解决方案,不再做过多的累赘描述。
  一、Step By Step 建立第一个工程
  (1)建立第一个工程,File-New-New Quartus II Project,如下图所示,OK。
  


  (2)Next,如下图所示,选择工程目录(不能有空格,中文路径),同时输入工程名与顶层文件名。
  


  (3)若有现成的代码,可以直接选择添加入工程;否则,直接next,进入下一步,如下图所示:
  


  (4)根据自己的硬件设施,选择相应的设备目标器件。
  


  (5)Next,Finish。
  二、工程代码设计
  1. water_led_design工程文件结构:
  


  如上图所示,工程分为三个模块,分别为:
  (1)顶层模块 : 例化各个模块,工程的最高级别文件。
  (2)分频模块 : 通过分频得到固定的频率(10Hz)。
  (3)LED显示模块: 随固定频率,来操作LED灯。
  2. 代码设计
  (1)warter_led.v模块设计
  a) New-File,新建verilog文件,保存于新建在工程目录下的src文件夹中(只是为了工程文件结构组织的清晰,更善于管理)。如下图所示:
  


  b) 输入代码,定义输入输出接口,如下所示:
  
module water_led

  (

  input clk, //global clock 50MHz

  input rst_n, //global clock reset

  output led_data //user led interface

  );

  endmodule
                               
                  (2)clk_design.v模块设计
  由于系统输入时钟是50Mhz,若以50MHz的速度变换LED等,人眼压根分辨不出来。因此利用分频原理,来对50MHz进行分频,而适应人眼。本模块将50MHz分频至10Hz,人眼分辨的极限是25Hz,因此10Hz能感觉得到(可以随机修改)。Led_en的频率计算公式:clk_led_en = 50_000000/(49_000000+1) = 10Hz,具体代码如下:
  
module clk_design

  (

  input clk,

  input rst_n,

  output led_en

  );

  reg cnt; //49_99999,100ms

  parameter LED_CNT = 49_999999;

  always@(posedge clk or negedge rst_n)

  begin

  if(!rst_n)
  cnt
  else if(cnt
  cnt
  else
  cnt
  end

  assign led_en = (cnt == 23'd49_99999) ? 1'b1 : 1'b0;

  endmodule
  模块没有分频产生10Hz的频率,而是生成了10Hz的使能时钟,目的是防止时钟满天飞,使得FPGA 内部布局布线紊乱,影响全局功能。虽然如此简单的工程可以不用考虑,但是“习惯了严谨便成为了一种风范”,因此使用使能时钟,来对具体的时序进行操作。具体使能时钟、门控时钟的异同、优劣将会在后续章节中解说。
  (3)led_display.v模块设计
  根据输入的led_en使能信号,来操作led灯的效果,此处采用最简单的算法——递增进位。代码如下所示:
  
module led_display

  (

  input clk,

  input rst_n,

  input led_en,

  output reg led_data

  );

  always@(posedge clk or negedge rst_n)

  begin

  if(!rst_n)
  led_data
  else if(led_en)
  led_data
  else
  led_data
  end

  endmodule

  (4)从新修改water_led_design顶层文件,添加相关例化模块。最后结果如下:

  module water_led_design

  (

  input clk, //global clock 50MHz

  input rst_n, //global clock reset

  output led_data //user led interface

  );

  //-------------------------

  //generater clock 10Hz

  wire led_en;

  clk_design clk_design_inst

  (

  .clk (clk),

  .rst_n (rst_n),

  .led_en (led_en)

  );

  //-------------------------

  //set the display of led

  led_display led_display_inst

  (

  .clk (clk),

  .rst_n (rst_n),

  .led_en (led_en),

  .led_data (led_data)

  );

  endmodule
                               
                  3. 代码编译
  (1)通过Processing-Start Compilation,或者工具栏的图标如下:
  


  (2)编译结果如下,可见相关信息:
  


  (3)警告的分析及解决:
  


  a) Warming(4)如上图所示,具体解释如下:
  i. 没有电容配置
  ii. 没有把unused的pin设置为三态。在Assignment-Device-Device and Pin Opitions-Unused Pins,设置如下图所示:
  


  iii. 没有电容配置
  iv. 可以忽略
  


  b) Critical Warming(5)如上图所示,具体解释如下:
  i. 引脚没有分配IO
  ii. 没有sdc时序约束文件
  iii. 没有sdc约束文件
  iv. 时序没有达到要求
  v. 时序没有达到要求
  出现这些警告的原因是因为Quartus II 10.1以后的版本软件,不再自带TimeQuest Timing Analyzer,只有Classic Timing Analyzer,虽然不加sdc时序约束对于一般情况也不一定会有错,但软件设计的必然会出现这样的警告。关于TimingQuest sdc,会在后续章节中阐述,此处不做具体说明。
  关于Quartus II 警告信息分析以及零警告的处理,可以右击警告查看help,altera会告诉您相应的解决方案;此外,Bingo已上传Chinaaet“Quartus II 警告分析.pdf”,下载地址为:http://www.chinaaet.com/lib/detail.aspx?id=86271
  初学折有不到之处可以查阅该pdf,记住,永远不要轻易忽略警告。
  三、Modelsim-Altera仿真
  1. 为什么要仿真
  首先讨论两个问题:
  (1)仿真?是真的吗?
  仿真,只是为了模拟真实现象,测试代码的行为以及时序的正确性;当然,仿真永远是模仿的,不可能是绝对准确的,只能在一定程度上模拟真实时序,让我们的设计变得更可靠。仿真对于电路设计者,只是一个软件测试的平台,而不是实际硬件设施的测试结果。
  (2)一定要仿真吗?
  未必!如果你有足够的把握时序的准确性,脑子里能够完成整个电路的时序逻辑工作流程,仿真就不是那个必须的了;对于已经成型的模块,保证时序准确的情况下,何必在徒劳的仿真呢?按常理,是现有Quartus II软件,再有仿真软件的吧,Testbench只是测试程序,链接两者之间的桥梁。
  回想,在n年前的老工程师,用block中用与非门与74系列芯片设计的原理图,要仿真似乎变得很难?那些老前辈们是通过实物的测试,不断的修正、改善,最后才得到可靠的电路。
  因此,仿真 不是必须的。Bingo就经常不仿真!不是说懒,是因为脑子中的电路时序逻辑,本能性的能够保证电路的准确性,或者说出了问题能够自行改正,不会失去了方向。所谓代码在电脑上,电路在脑子中,每一句行为级语言,都加增添一个电路。
  当然,并非每一个人都可以这样子的。对于初学者而言,仿真是非常重要的一个过程。原因是因为在初学者脑子中,还未呈现固定逻辑实现的时序工作流程,换句话说,经验不够丰富吧。
  当然在时序很复杂而且庞大时,时序仿真是必须的,因为在这种情况下,大脑的模拟也许无法跟计算机的计算速度比拟了。
  前文安装Quartus II 软件章节有提到过,Quartus II 9.1以前版本,软件自带仿真器,而9.1以后的版本,需要第三方软件的支持。第三放仿真软件有很多,而用的最多的,固然是Modelsim-Altera。本章节中Quartuus II 11.0与Modelsim-Altera协同工作,仿真测试本例程的代码的时序。希望通过节的分析,对时序逻辑上有一个更深刻的认识。
                               
                  2. 仿真必备的知识
  Altera_Modelsim仿真资料:http://www.chinaaet.com/lib/detail.aspx?id=86257
  四、配置FPGA
  1. 配置综合
  配置引脚简单的说就是通过软件的设置,将FPGA内部逻辑信号映射到IO上,具体有下面几种方法:
  (1)在Assignments-Pin Planner中对应IO手动输入IO引脚
  (2)Quartus II Tcl Console 手动输入,输入的格式为:“set_location_assignment PIN_28 -to clk”
  (3)Tcl Scripts,通过调入tcl 文件来进行映射
  (4)在Assignments-Import Assignments,通过调入(2)格式的文件来进行映射。
  后面两种方法具体步骤可见网友“小时不识月”的网页教程:http://www.cnblogs.com/yuphone/archive/2010/01/18/1650612.html
  配置好查看Quartus II Pin Planner,如下图所示:
  


  配置完引脚在进行综合,就少了上述提醒没有进行引脚配置的2个警告。
  注意1:对于Quartus II 中引脚配置的方法,若用最原始的第一种GUI手动输入配置,需要第一次编译后让软件在Pin Planner生成IO,然后再GUI下手动配置;若用其他三种方法,可以在第一次编译以前,用命令输入配置信息,在Quartus II 编译后,自动识别映射信息,达到同样的效果。
  注意2:对于系统及的FPGA设计,由于工程之大,引脚之多,一般编译综合需要耗费很大的时间,因此一般采用不采用第一种方法,而且在第一次编译以前事先导入映射信息。
  2. 目标板下载模式
  总而言之,Quartus II 软件只是个GUI的 用户终端,用来设计代码,综合FPGA逻辑电路,最终的目的,是通过USB Bluster、并口或者其他途径下载到目标板。具体有以下几种:
  (1)配置FPGA——JTAG Mode
  所谓配置FPGA就是将sof文件电路配置FPGA的SRAM(FPGA是基于SRAM格式的),在不掉电的情况下进行现场配置,验证。此方式是通过JTAG接口下载的。
  (2)烧录EPCS——Active Serial Programming
  所谓烧录EPCS是生成的代码信息烧录到存储芯片EPCS中,通过配置信号或者重新上电,配置FPGA SRAM;由于EPCS flash结构,因此EPCS中的掉电不丢失(类似于CPLD)。烧录EPCS有两种方法,如下
  a) 通过ASP接口下载pof文件
  b) 通过JTAG接口下载jic/jam文件,jic/jam文件由Quartus II 软件对sof文件进行转换后得到。
  (3)Passive Serial并口下载
  (4)In Socket Programming下载
  以上两种模式,由于应用不是很广泛,在此不做过多阐述。
  综上说明,在成本敏感,或者电路板空间苛刻的情况下,完全可以舍去ASP接口,而用JTAG来替换。考虑到Altera设计了两种接口的原因,是给用户更大的选择性,特殊场合下,可以只存在ASP接口,只进行一次烧录,而不用JTAG接口进行测试。
  3. JTAG的下载
  (1)在工具栏打开或者菜单栏Tool打开Programming
  


  (2)若没找到Hardware,在Hardware Setting中找到USB Bluster。
  (3)选择JTAG Mode
  (4)若没有自动加载sof文件,点击Add File导入该工程的sof文件
  (5)最后点击Start,等待下载完毕,如下图所示:
  

                               
                  4. EPCS的下载
  (1)在ASP模式下
  a) Mode切换为Active Serial Programming模式
  b) Change File为pof文件
  c) 点击Start,等待下载完毕。因为Flash速度比SRAM慢,因此下载相对于Flash会较慢。
  至此,可见目标板上的流水灯已递增的形式循环点亮。
  (2)在JTAG模式下
  a) 用Quartus II 自动生成的sof文件,通过软件转换为jic文件,步骤如下:
  i. 打开File-Convert Programming File。
  ii. 在Programming File Type选择jic文件。
  iii. Configuration device中选择目标板对应的EPCS型号
  iv. File name可默认或任意修改
  v. 在File/Data area选中Flash Loader,然后右侧点击Add Device,找到自己型号的FPGA,确认。
  vi. 在File/Data area选中SOF Data,然后在右侧点击Add File,加载本工程目录下的sof文件。
  vii. 在File/Data area选中加载的sof文件,然后再右侧点击Properties,选中Compression(压缩),确认。(若EPCS容量允许下,可以省略此步骤,来提高下载速度)
  viii. 点击Generate,生成jic文件,最终如下图所示,然后Close。
  


  b) 打开Programming,选择JTAG Mode。
  c) 选择前面生成的jic文件,选中jic文件后面的Program/Configure
  d) 点击Start,等待下载完成,如下图所示:
  


  至此,可见目标板上的流水灯已递增的形式循环点亮。
  5. 编程/配置失败原因
  (1)USB下载器没有连接好或USB线太长(没插上,或者接口插错)
  (2)设备没上电。
  (3)FPGA Device型号选择错误
  (4)EPCS型号选择错误
  (5)布局布线不佳,导致下载时序错误
  (6)FPGA芯片已损坏
  (7)EPCS芯片已损坏
  (8)USB Bluster已损坏