可编程逻辑器件 - CPLD/FPGA


FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。

以硬件描述语言(Verilog或VHDL)所完成的电路设计,可以经过简单的综合与布局,快速的烧录至FPGA上进行测试,是现代IC设计验证的技术主流。这些可编辑元件可以被用来实现一些基本的逻辑门电路(比如AND、OR、XOR、NOT)或者更复杂一些的组合功能比如解码器或数学方程式。在大多数的FPGA里面,这些可编辑的元件里也包含记忆元件例如触发器(Flip-flop)或者其他更加完整的记忆块。 系统设计师可以根据需要通过可编辑的连接把FPGA内部的逻辑块连接起来,就好像一个电路试验板被放在了一个芯片里。一个出厂后的成品FPGA的逻辑块和连接可以按照设计者而改变,所以FPGA可以完成所需要的逻辑功能。

FPGA一般来说比ASIC(专用集成电路)的速度要慢,实现同样的功能比ASIC电路面积要大。但是他们也有很多的优点比如可以快速成品,可以被修改来改正程序中的错误和更便宜的造价。厂商也可能会提供便宜的但是编辑能力差的FPGA。

开发

FPGA的开发相对于传统PC、单片机的开发有很大不同。FPGA以并行运算为主,以硬件描述语言来实现;相比于PC或单片机(无论是冯诺依曼结构还是哈佛结构)的顺序操作有很大区别,也造成了FPGA开发入门较难。FPGA开发需要从顶层设计、模块分层、逻辑实现、软硬件调试等多方面着手。

产品比较

早在1980年代中期,FPGA已经在PLD设备中扎根。CPLD和FPGA包括了一些相对大数量的可编辑逻辑单元。CPLD逻辑门的密度在几千到几万个逻辑单元之间,而FPGA通常是在几万到几百万。

  • CPLD和FPGA的主要区别是他们的系统结构。CPLD是一个有点限制性的结构。这个结构由一个或者多个可编辑的结果之和的逻辑组列和一些相对少量的锁定的寄存器组成。这样的结果是缺乏编辑灵活性,但是却有可以预计的延迟时间和逻辑单元对连接单元高比率的优点。而FPGA却是有很多的连接单元,这样虽然让它可以更加灵活的编辑,但是结构却复杂的多。
  • CPLD和FPGA另外一个区别是大多数的FPGA含有高层次的内置模块(比如加法器和乘法器)和内置的存储器。因此很多新的FPGA支持完全或者部分的系统内重新配置。允许他们的设计随着系统升级或者动态重新配置而改变。一些FPGA可以让设备的一部分重新编辑而其他部分继续正常运行。
  • CPLD和FPGA还有一个区别:CPLD下电之后,原有烧入的逻辑结构不会消失;而FPGA下电之后,再次上电时,需要重新加载FLASH里面的逻辑代码,需要一定的加载时间。

发展历程

1985年,当全球首款FPGA产品——XC2064诞生, 它采用2μm工艺,包含64个逻辑模块和85000个晶体管,门数量不超过1000个。最初,FPGA只是用于胶合逻辑(Glue Logic),从胶合逻辑到算法逻辑再到数字信号处理、高速串行收发器和嵌入式处理器,FPGA真正地从配角变成了主角。22年后的2007年,FPGA业界双雄Xilinx和Altera公司纷纷推出了采用最新65nm工艺的FPGA产品,其门数量已经达到千万级,晶体管个数更是超过10亿个。一路走来,FPGA在不断地紧跟并推动着半导体工艺的进步——2001年采用150nm工艺、2002年采用130nm工艺,2003年采用90nm工艺,2006年采用65nm工艺。

在上世纪80年代中期,可编程器件从任何意义上来讲都不是当时的主流,虽然其并不是一个新的概念。可编程逻辑阵列(PLA)在1970年左右就出现了,但是一直被认为速度慢,难以使用。1980年之后,可配置可编程逻辑阵列(PLA)开始出现,可以使用原始的软件工具提供有限的触发器和查找表实现能力。PAL被视为小规模/中等规模集成胶合逻辑的替代选择被逐步接受,但是当时可编程能力对于大多数人来说仍然是陌生和具有风险的。20世纪80年代在“megaPAL”方面的尝试使这一情况更加严重,因为“megaPAL”在功耗和工艺扩展方面有严重的缺陷,限制了它的广泛应用。

当1991年Xilinx公司推出其第三代FPGA产品——XC4000系列时,人们开始认真考虑可编程技术了。XC4003包含44万个晶体管,采用0.7μm工艺,FPGA开始被制造商认为是可以用于制造工艺开发测试过程的良好工具。事实证明,FPGA可为制造工业提供优异的测试能力,FPGA开始用来代替原先存储器所扮演的用来验证每一代新工艺的角色。也许从那时起,向最新制程半导体工艺的转变就已经不可阻挡了。最新工艺的采用为FPGA产业的发展提供了机遇。

Actel公司相信,Flash将继续成为FPGA产业中重要的一个增长领域。Flash技术有其独特之处,能将非易失性和可重编程性集于单芯片解决方案中,因此能提供高成本效益,而且处于有利的位置以抢占庞大的市场份额。Actel以Flash技术为基础的低功耗IGLOO系列、低成本的ProASIC3系列和混合信号Fusion FPGA将因具备Flash的固有优势而继续引起全球广泛的兴趣和注意。

FPGA及PLD产业发展的最大机遇是替代ASIC和专用标准产品(ASSP),主要由ASICASSP构成的数字逻辑市场规模大约为350亿美元。由于用户可以迅速对PLD进行编程,按照需求实现特殊功能,与ASIC和ASSP相比,PLD在灵活性、开发成本以及产品及时面市方面更具优势。然而,PLD通常比这些替代方案有更高的成本结构。因此,PLD更适合对产品及时面市有较大需求的应用,以及产量较低的最终应用。PLD技术和半导体制造技术的进步,从总体上缩小了PLD和固定芯片方案的相对成本差,FPGA和PLD供应商的关键目标不是简单地增加更多的原型客户,而是向大批量应用最终市场和客户渗透。”John Daane为FPGA产业指明了方向。

工作原理

FPGA采用了逻辑单元阵列LCA(Logic Cell Array)这样一个概念,内部包括可配置逻辑模块CLB(Configurable Logic Block)、输入输出模块IOB(Input Output Block)和内部连线(Interconnect)三个部分。 现场可编程门阵列(FPGA)是可编程器件,与传统逻辑电路和门阵列(如PAL,GAL及CPLD器件)相比,FPGA具有不同的结构。FPGA利用小型查找表(16×1RAM)来实现组合逻辑,每个查找表连接到一个D触发器的输入端,触发器再来驱动其他逻辑电路或驱动I/O,由此构成了既可实现组合逻辑功能又可实现时序逻辑功能的基本逻辑单元模块,这些模块间利用金属连线互相连接或连接到I/O模块。FPGA的逻辑是通过向内部静态存储单元加载编程数据来实现的,存储在存储器单元中的值决定了逻辑单元的逻辑功能以及各模块之间或模块与I/O间的联接方式,并最终决定了FPGA所能实现的功能,FPGA允许无限次的编程。

主流的FPGA仍是基于查找表技术的,已经远远超出了先前版本的基本性能,并且整合了常用功能(如RAM、时钟管理和DSP)的硬核(ASIC型)模块。FPGA芯片主要由7部分组成:可编程输入输出单元、基本可编程逻辑单元、完整的时钟管理、嵌入块式RAM、丰富的布线资源、内嵌的底层功能单元和内嵌专用硬件模块。

FPGA 供电

FPGA的供电电源要求电压范围从1.2V到5V,供电电流范围从数十毫安到数安培。可用三种电源:低压差(LDO)线性稳压器、开关式DC-DC稳压器和开关式电源模块。最终选择何种电源取决于系统、系统预算和上市时间要求:

  • 如果电路板空间是首要考虑因素,低输出噪声十分重要,或者系统要求对输入电压变化和负载瞬变做出快速响应,则应使用LDO稳压器。LDO功效比较低(因为是线性稳压器),只能提供中低输出电流。输入电容通常可以降低LDO输入端的电感和噪声。LDO输出端也需要电容,用来处理系统瞬变,并保持系统稳定性。也可以使用双输出LDO,同时为VCCINT和VCCO供电。
  • 如果在设计中效率至关重要,并且系统要求高输出电流,则开关式稳压器占优势。开关电源的功效比高于LDO,但其开关电路会增加输出噪声。与LDO不同,开关式稳压器需利用电感来实现DC-DC转换。
要求

为确保正确上电,内核电压VCCINT的缓升时间必须在制造商规定的范围内。对于一些FPGA,由于VCCINT会在晶体管阈值导通前停留更多时间,因此过长的缓升时间可能会导致启动电流持续较长时间。如果电源向FPGA提供大电流,则较长的上电缓升时间会引起热应力。ADI公司的DC-DC稳压器提供可调软启动,缓升时间可以通过外部电容进行控制。缓升时间典型值在20ms至100ms范围内。

许多FPGA没有时序控制要求,因此VCCINT、VCCO和VCCAUX可以同时上电。如果这一点无法实现,上电电流可以稍高。时序要求依具体FPGA而异。对于一些FPGA,必须同时给VCCINT和VCCO供电。对于另一些FPGA,这些电源可按任何顺序接通。多数情况下,先给VCCINT后给VCCO供电是一种较好的做法。 当VCCINT在0.6V至0.8V范围内时,某些FPGA系列会产生上电涌入电流。在此期间,电源转换器持续供电。这种应用中,因为器件需通过降低输出电压来限制电流,所以不推荐使用返送电流限制。但在限流电源解决方案中,一旦限流电源所供电的电路电流超过设定的额定电流,电源就会将该电流限制在额定值以下。

配电结构

对于高速、高密度FPGA器件,保持良好的信号完整性对于实现可靠、可重复的设计十分关键。适当的电源旁路和去耦可以改善整体信号完整性。如果去耦不充分,逻辑转换将会影响电源和地电压,导致器件工作不正常。此外,采用分布式电源结构也是一种主要解决方案,给FPGA供电时可以将电源电压偏移降至最低。 在传统电源结构中,AC/DC或DC/DC转换器位于一个地方,并提供多个输出电压,在整个系统内分配。这种设计称为集中式电源结构(CPA)。以高电流分配低电压时,铜线或PCB轨道会产生严重的电阻损耗,CPA就会发生问题。

CPA的替代方案是分布式电源结构(DPA)。采用DPA时,整个系统内仅分配一个半稳压的DC电压,各DC/DC转换器(线性或开关式)与各负载相邻。DPA中,DC/DC转换器与负载(例如FPGA)之间的距离近得多,因而线路电阻和配线电感引起的电压下降得以减小。这种为负载提供本地电源的方法称为负载点(POL)。

配置模式

FPGA有多种配置模式:并行主模式为一片FPGA加一片EPROM的方式;主从模式可以支持一片PROM编程多片FPGA;串行模式可以采用串行PROM编程FPGA;外设模式可以将FPGA作为微处理器的外设,由微处理器对其编程。 如何实现快速的时序收敛、降低功耗和成本、优化时钟管理并降低FPGA与PCB并行设计的复杂性等问题,一直是采用FPGA的系统设计工程师需要考虑的关键问题。如今,随着FPGA向更高密度、更大容量、更低功耗和集成更多IP的方向发展,系统设计工程师在从这些优异性能获益的同时,不得不面对由于FPGA前所未有的性能和能力水平而带来的新的设计挑战。

例如,领先FPGA厂商Xilinx推出的Virtex-5系列采用65nm工艺,可提供高达33万个逻辑单元、1,200个I/O和大量硬IP块。超大容量和密度使复杂的布线变得更加不可预测,由此带来更严重的时序收敛问题。此外,针对不同应用而集成的更多数量的逻辑功能、DSP、嵌入式处理和接口模块,也让时钟管理和电压分配问题变得更加困难。 幸运地是,FPGA厂商、EDA工具供应商正在通力合作解决65nm FPGA独特的设计挑战。不久以前,Synplicity与Xilinx宣布成立超大容量时序收敛联合工作小组,旨在最大程度地帮助系统设计工程师以更快、更高效的方式应用65nm FPGA器件。设计软件供应商Magma推出的综合工具Blast FPGA能帮助建立优化的布局,加快时序的收敛。 FPGA的配置方式已经多元化!

主要生产厂商

全球知名的FPGA生产厂商有:

  1. Altera/Intel,开发平台是Quartus II、Quartus Prime
  2. Xilinx 开发平台是ISE、Vivado
  3. Lattice,开发平台是ISPLEVER、Diamond、Radiant
  4. Actel/Microsemi,已经被Microchip收购,其开发平台是Libero

其中Altera作为世界老牌可编程逻辑器件的厂家,是可编程逻辑器件的发明者,开发软件MAX+PLUSII和Quartus II/ Quartus Prime,已经被Intel收购。Xilinx是FPGA的发明者,拥有世界一半以上的市场,开发软件一度为ISE, 现在的开发工具位Vivado。

Altera/Intel和Xilinx主要生产一般用途FPGA,其主要产品采用RAM工艺。Actel主要提供非易失性FPGA,产品主要基于反熔丝工艺和FLASH工艺。


器件总览

面积与速度的互换

这里的面积指的是FPGA的芯片资源,包括逻辑资源和I/O资源等;这里的速度指的是FPGA工作的最高频率(和DSP或者ARM不同,FPGA设计的工 作频率是不固定的,而是和设计本身的延迟紧密相连)。 在实际设计中,使用最小的面积设计出最高的速度是每一个开发者追求的目标,但是“鱼和熊掌不可兼得”,取舍之间展示了一个开发者的智慧。   

  1. 速度换面积: 速度优势可以换取面积的节约。面积越小,就意味着可以用更低的成本来实现产品的功 能。速度换面积的原则在一些较复杂的算法设计中常常会用到。在这些算法设计中,流水线设计常常是必须用到的技术。在流水线的设计中,这些被重复使用但是使 用次数不同的模块将会占用大量的FPGA资源。对FPGA的设计技术进行改造,将被重复使用的算法模块提炼出最小的复用单元,并利用这个最小的高速代替原 设计中被重复使用但次数不同的模块。当然,在改造的过程中必然会增加一些其他的资源来实现这个代替的过程。但是只要速度具有优势,那么增加的这部分逻辑依 然能够实现降低面积提高速度的目的。可以看到,速度换面积的关键是高速基本单元的复用。
  2. 面积换速度: 在这种方法中面积的复制可以换取速度的提高。支持的速度越高,就意味着可以实现更高的产品性能。一些注重产品性能的应用领域可以采用并行处理技术,实现面积换速度。
硬件可实现原则

FPGA设计通常会使用HDL语言,比如Verilog HDL或者VHDL。当采用HDL语言来描述一个硬件电路功能的时候,一定要确保代码描述的电路是硬件可实现的。 Verilog HDL语言的语法与C语言很相似,但是它们之间有着本质的区别。C语言是基于过程的高级语言,编译后可以在CPU上运行。而Verilog HDL语言描述的本身就是硬件结构,编译后是硬件电路。因此,有些语句在C语言的环境中应用是没有问题的,但是在HDL语言环境下就会导致结果不正确或者 不理想。如:  

 
  for(i=0;i<16;i++)
  DoSomething();
 

在C语言中运行没有任何问题,但是在Verilog HDL的环境下编译就会导致综合后的资源严重浪费。

同步设计原则

同步电路和异步电路是FPGA设计的两种基本电路结构形式。 异步电路的最大缺点是会产生毛刺。同步设计的核心电路是由各种触发器构成的。这类电路的任何输出都是在某个时钟的边沿驱动触发器产生的。所以,同步设计可以很好地避免毛刺的产生。

设计FPGA需要用到综合、仿真工具,每个FPGA厂商的工具从功能和流程上来讲大同小异,只是他们支持的器件不同,器件的功能不同,复杂程度也不同。详细的情况参见FPGA设计工具

1. Lattice FPGA学习

2. Xilinx FPGA系列学习平台

3. Altera/Intel FPGA系列学习平台

  1. Better rotary encoder input: 我早期尝试正交解码并不是那么好
  2. Genesys2 Mandelbrot: Artix-7分形观察器的端口到Genesys2上的Kintex-7
  3. DisplayPort: 一个DisplayPort接口
  4. HDMI Capture: 捕获HDMI数据并将其发送到串行端口
  5. HDMI Processing: 在Artix 7板上进行HDMI视频和音频提取
  6. EDID ROM: 视频项目的基本EDID
  7. SERDES symbol locking: 如何找到7系列ISERDES的工作bitlip /输入延迟设置
  8. Artix 7 1080p passthrough: 通过Nexys视频传递HDMI信号
  9. Square root: 计算数字的整数平方根
  10. Artix 7 1080p: 看看Artix-7是否可以产生1080p,并带有一点超频
  11. Mandelbrot NG 1080i: 用于Nexys视频的全高清动态Mandelbrot Fractal查看器
  12. GPS Spew: 桌面GPS干扰器
  13. OSERDESE2: 一个示例10:1序列化器,可以正常模拟
  14. Digital Microphone: 从PmodMIC3获取数据 - MEM Smicrophone和12位ADC
  15. Mandelbrot NG: 一个新的实时Mandelbrot查看器
  16. Ring Oscillator: 在FPGA中创建环形振荡器
  17. Digital Sine: 使用DAC创建相对精确的模拟正弦波
  18. PmodAD1: 使用PmodAD1读取模拟操纵杆(ADI公司的AD7476 ADC)
  19. FPGA_ESP8266: 使用低成本ESP8266模块将FPGA连接到wifi
  20. PmodMAXSONAR: 使用PmodMAXSONAR模块上的串行接口
  21. Minimal HDMI: 超重3像素的真正HDMI接口
  22. Minimal DVI-D: 超重量每像素9位DVI-D接口
  23. Log Pins: 一个微小的项目,通过RS232将11个引脚的开头发送给主机
  24. miniSpartan6+ SPI Programming: 将逻辑设计写入电路板的SPI配置FLASH
  25. miniSpartan6+ DVID Logo: 在DVI-D流上覆盖Hamsterworks徽标
  26. miniSpartan6+ Audio: 打哔哔声
  27. miniSpartan6+ DVID Output: Scarab Hardware miniSpartan6 +板的更好的DVI-D输出
  28. miniSpartan6+ bringup: 首次推出Scarab Hardware miniSpartan6 +板
  29. Stepper: 控制小型步进电机
  30. Math free digital clock一个不知道如何做加法的数字时钟!
  31. LFSR Divider 使用LFSR分频时钟信号
  32. Sonar 将低成本声纳模块连接到FPGA
  33. Simple resets don't work: 展示如何不实现重置
  34. DDS via a VGA port: 分析VGA端口产生6.25 MHz频率正弦波的能力
  35. Inferred FIFO: 如何不用IP就可以实现FIFO
  36. Cheap Analogue Input: 在没有ADC的情况下读取模拟操纵杆
  37. HDMI Input: 接收高速数字视频(DVI-D over HDMI)
  38. Intelligent LEDs: 驱动智能LED
  39. SDRAM Audio playback: 从SDRAM播放扩展音频
  40. FPGA wheelchair fairy lights: 我的男孩轮椅的LED灯
  41. Accessing the configuration clock: 使用内部振荡器
  42. High Speed Frequency Counter: 高速频率计数器
  43. DVI-D Serdes: 使用OSERDES2 Serializers创建DVI-D信号
  44. SD card testing: 在SD卡上使用SPI接口
  45. Logic Analyser Test: 一个8位200MHz计数器,用于测试逻辑分析仪
  46. Eternity2 Solver: 使用FPGA解决Eternity II难题
  47. Zedboard Audio: 在VHDL上使用Zedboard上的I2S Audio编解码器
  48. Reflow Oven: 使用台式烤箱和FPGA进行焊料回流焊
  49. FIR Filter: 在FPGA中实现FIR滤波器
  50. Solid State Relay: 从FPGA驱动固态继电器SSR
  51. Analog Wing: 使用Papilio模拟翼
  52. Thermocouple demo: 使用Adafruit热电偶接口捕获数据
  53. Simple SDRAM Controller: 一个非常简单的SDRAM控制器
  54. Zedboard_VGA_HDMI: “驱动Zedboard的VGA和HDMI接口,每个像素一个时钟,包括RGB444到YCbCr转换”
  55. Zedboard_HDMI_v2: 驱动Zedboard的HDMI接口
  56. pmodi2s: 驱动Digilent PMODI2S音频DAC
  57. pmodenc: 解码Digitent PMODENC旋转编码器的输入
  58. mains_hum_filter: 一个低通DSP滤波器,可从ADC样本中消除50Hz的嗡嗡声
  59. a2d_graph: 慢慢绘制LogicStart ADC上的通道0
  60. DSP_Filter_Design: 用于FIR滤波器设计的各种位和突发
  61. I3C2: 智能I2C控制器
  62. Audio filter: 模拟被动模拟音频滤波器
  63. Dualhead MCB Frame Buffer: 将DVI-D输出添加到MCB帧缓冲区
  64. MCB Frame Buffer: 在Pipistrello的LPDDR内存中创建一个720p帧缓冲区
  65. USB TTL RS232: 使用Papilio作为TTL RS232适配器
  66. Spartan 6 1080p: 在Spartan 6 LX上生成1080p
  67. High Speed Link: 两个FPGA之间的高速传输
  68. RS232_dumper: 捕获然后将数据转储到RS232端口
  69. Zedboard_HDMI: 驱动Zedboard的HDMI接口
  70. Zedboard_OV7670: 将低成本相机连接到Zedboard
  71. Async_VGA: 一个VGA控制器,可以处理突发数据(例如来自SDRAM)
  72. FreqSwitch Changing: DCMCLKGEN的输出在运行中以生成不同的频率
  73. FM_SOS: 使用简单的FM发射器发送SOS
  74. OV7670_camera: 从便宜的相机模块捕获视频
  75. Digilent EPP Performance: 在digilent板上的EPP端口速度的性能差异
  76. OSERDES2 clocking: 为高速串行输出设置时钟基础设施
  77. frequency_counter: GPS参考频率计数器
  78. hidef_snow: 以1080p生成静态
  79. config_flash: 在配置闪存中存储任意数据
  80. async_reset: 测试异步重置可靠性
  81. meta_test: 测试亚稳态
  82. if vs case: 测试不同的实现
  83. ray_cast: 一个“射线投射”3D迷宫走过
  84. dx_display: 极速推出TM1638 7 Seg显示器
  85. Synth: 一个简单的全数字Synth,一口大小的部分
  86. Crystal Castles: 在FPGA上重新实现旧的街机
  87. CheapScope:一个简单的结构嵌入式逻辑分析仪,具有和RS232接口
  88. dvid_test: 从Spartan 6 FPGA驱动DVI-D接口
  89. HDlife: 以全高清实现康威的生命游戏
  90. FPGAheli: 控制红外直升机
  91. shortwave: 一个非常快速和肮脏的短波发射器
  92. AVR8 core: AVR103几乎兼容软核,最初来自OpenCores
  93. 10BaseT-TX: 直接从FPGA发送以太网数据包
  94. SPDIF_Input: 从DVD播放器捕获和转换数字音频数据
  95. SPDIF_out: 生成数字音频数据输出
  96. SPDIF_Volume: 用于S / PDIF信号的简单数字音量控制 - 一种非常简单的DSP
  97. SPDIF_Thru: S / PDIF信号的传递 - DSP项目的基础
  98. VGA Display: 生成1440×900 VGA输出的时序
  99. WavePlay: 从Block RAM播放8位立体声音频样本
  100. Mandelbrot: 又一个FPGA Mandelbrot查看器
  101. DSPfract: 另一个FPGA Mandelbrot查看器 - 这次使用Spartan 6 DSP48A bocks
  102. Radix2div: VHDL中的Radix 2部分
  103. Radix4div: VHDL中的Radix 4部分
  104. SDRAM Memory Controller: Terasic DE0-nano上的SDRAM芯片的存储器控制器
  105. uClinux: 在Terasic DE0-nano板上引入uClinux
  106. MAF6502: 经典MOS6502处理器的FPGA实现
  107. Papilio Plus/Pacman: 在Spartan 6硬件上从http://fpgaarcade.com构建Pacman实现
  108. Papilio Plus/Fading counter: 一个软褪色的二进制计数器
  109. Papilio Plus/PS2 Keyboard: 使用PS / 2键盘接口
  110. Papilio Plus/SRAM test 2: 在Papilio Plus @ 100MHz上写入并验证SRAM中的测试模式
  111. CUGA-1: 使用门阵列的CPU * Design&Reuse上的IP Core资源

更多关于FPGA的资料和学习案例参见小脚丫FPGA学习