数字电路经过半个世纪,从分立元件到小规模集成电路、中等规模集成电路、大规模、超大规模,集成度越来越高,运算能力越来越强,功耗越来越低,人类已经将数字集成电路发展到接近摩尔定律极限。
FPGA是这样一类数字电路,它可以反复修改自身逻辑功能,具有灵活多变的特性,设计FPGA的过程其实是遵循数字电路设计的一般流程的:
(1)需求分析
(2)抽象逻辑表示(真值表、状态流图)
(3)具体逻辑表示(HDL、布尔方程)
(4)将逻辑表示综合为可实现的电路(门电路、LUT和触发器)
(5)验证
FPGA逻辑工程师一般是从应用需求出发,用Verilog或VHDL来描述算法,并通过综合实现工具、仿真工具、调试工具来协助完成设计。
针对Xilinx器件,开发工具为ISE(Project Navigator,ISim,iMact,Chipscope),有时需要用Modelsim工具完成HDL仿真。
Zynq内部包含PL,资源前面已经说过了,大量LUT,FF,DSP48E1等着你来组织,开发PL可以完全脱离PS,采用传统开发工具ISE完成。
下面给出只利用PL实现流水灯的例子,希望能有抛砖引玉的功效。
上一节介绍了使用ARM控制流水灯的例子,这里完成同样的功能,但用PL实现控制,将PS冷落一旁,不用理它。
首先运行ISE Design Suite 14.5,打开Project Navigator软件。
File->New Project,新建一个工程,弹出对话框如下:
按照上图进行工程设置,然后点Next
设置器件为XC7Z020,即我们Zedboard上的主芯片型号。封装为CLG484,速度级别为-1,语言选择VHDL。点Next,Finish。
我们分析一下怎样完成这个设计。数字电路都需要有时钟源,我们的PL也不例外,板子上有专为PL提供时钟输入的晶振,在原理图中找到:
可见晶振输入为100MHz,直接送入Y9引脚(位于PL部分)。如此高的时钟速率,需要经过分频,LED闪烁速率最好低于10Hz,这样人眼才能分辨出来。
用ISE提供的IP核可以实现分频,在工程中Add Source:
选择IP(Core Generator),输入名称为clk_module,如上图,点Next。
从“FPGA Features and Design”中"Clocking“下找到Clocking Wizard,点Next,Finish。进入配置IP的环节。
第一步,默认设置,Next。。。
第二步,将CLK_OUT1输出频率设置为5MHz(貌似不能再小了),其他不改,点Next。
第三步里把复位和锁定引脚去掉,如下图所示,后面都一路Next到结束。
这样生成了第一个分频器,输入为100MHz,输出为5MHz,需要进一步分频。
再New Source一下,选VHDL模块,命名为myled.vhd,输入代码如下:
---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 20:59:03 08/16/2013 -- Design Name: -- Module Name: myled - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity myled is Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; led : out STD_LOGIC_VECTOR(7 downto 0)); end myled; architecture Behavioral of myled is signal clk_5M : STD_LOGIC; signal localbuffer :STD_LOGIC_VECTOR(7 downto 0); component clk_module port (-- Clock in ports CLK_IN1 : in std_logic; -- Clock out ports CLK_OUT1 : out std_logic ); end component; begin myclk : clk_module port map (-- Clock in ports CLK_IN1 => clk, -- Clock out ports CLK_OUT1 => clk_5M); process(clk_5M,rst) variable cnt : integer := 0; begin led <= localbuffer; if(rst = '1') then localbuffer <= X"01"; elsif(clk_5M'EVENT and clk_5M = '1') then cnt := cnt + 1; if (cnt = 5000000) then localbuffer <= localbuffer(6 downto 0)&localbuffer(7); cnt := 0; end if; end if; end process; end Behavioral;
这里使用计数器实现了分频,输出为1Hz。
Add Source,选UCF,命名myled.ucf,内容如下:
## ## This is an updated UCF file from the original version by Digilink. ## The CS signal has been removed and all the other signals are mapped to ## proper pin on the Zynq FPGA. ## For the reset, the middle-push button is used. ## Modified by Farhad Abdolian ([email protected]) Nov. 5, 2012 ## Net "clk" LOC=Y9 | IOSTANDARD=LVCMOS33; Net "clk" TNM_NET = sys_clk_pin; TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz; NET "led[0]" LOC = T22; NET "led[1]" LOC = T21; NET "led[2]" LOC = U22; NET "led[3]" LOC = U21; NET "led[4]" LOC = V22; NET "led[5]" LOC = W22; NET "led[6]" LOC = U19; NET "led[7]" LOC = U14; NET "led[7]" IOSTANDARD = LVCMOS33; NET "led[6]" IOSTANDARD = LVCMOS33; NET "led[5]" IOSTANDARD = LVCMOS33; NET "led[4]" IOSTANDARD = LVCMOS33; NET "led[3]" IOSTANDARD = LVCMOS33; NET "led[2]" IOSTANDARD = LVCMOS33; NET "led[1]" IOSTANDARD = LVCMOS33; NET "led[0]" IOSTANDARD = LVCMOS33; #We use the center push button as the reset for this project Net "rst" LOC = P16 | IOSTANDARD = LVCMOS33;
源文件都已经OK,接下来进行综合、实现、生成bit、iMPACT下载即可(按照标准FPGA开发流程),效果与前面的实验相同,略去不表。这里由于逻辑比较简单,省去了功能仿真、时序仿真等流程。真正的逻辑开发最好经过仿真后再下载到硬件中。
从上面这个例子发现,不考虑ARM时,PL部分开发与普通的FPGA开发并没有任何区别。
恰恰是由于ARM的存在,我们的PL可以实现更多复杂的功能!
1. DDR控制。采用逻辑来实现DDR2存储器访问非常复杂,调试也非常耗费时间。ARM核的存在,使得PL可以借助ARM来做DDR2控制器,访问时只需遵循PS与PL之间的通信协议——AXI就可以了。
2. 操作系统。同样,FPGA上运行操作系统是一件费力不讨好的事情,浪费大量逻辑资源,如果用软核实现CPU,性能又不高。如果有ARM硬核负责操作系统的日常维护,必要时FPGA仍然通过AXI总线与ARM上的操作系统进行交互。
3. 网络。
4. USB通信
从传统FPGA开发到Zynq上PL开发需要改变一个观念:逻辑可以实现一切。嵌入硬核恰恰说明一点:有些事还是别让逻辑来做!