FPGA 点滴
2013-06-25 11:34:49
转自:http://blog.sina.com.cn/s/blog_49a879e40100bd2w.html
以此记录心得以及重要的知识点。
1.FPGA器件是Xilinx公司于1985年首家退出的,它是一种新型的高密度PLD,采用CMOS-SRAM工艺制作。FPGA的结构与门阵列PLD不同,其内部有许多独立的可编程逻辑模块组成,逻辑模块之间可以灵活的相互连接。FPGA结构一般分为三部分:可编程逻辑模块、可编程I/O模块和可编程内部连线。配置数据存放在片内SRAM或熔丝图上,基于SRAM的FPGA器件工作前需要从芯片外部加载配置数据。配置数据可以存储在片外的EPROM或者计算机上,设计人员可以控制加载过程,在现场修改器件的逻辑功能,即所谓现场可编程。
目前绝大多数FPGA器件都采用了基于SRAM的查找表结构。查找表本质上就是一个RAM。FPGA中多使用4输入的LUT,所以每一个LUT可以看成一个有四位地址线的RAM。当用户通过原理图或HDL语言描述了一个逻辑电路以后,PLD/FPGA开发软件会自动计算逻辑电路所有可能的结果,并把结果事先写入RAM.这样,每输入一个信号进行逻辑运算就等于输入一个地址进行查表,找出地址对应的内容,然后输出即可。
2.VHDL语言中,由于BIT数据类型只能取值逻辑量‘0’或‘1’,而在实际电路设计和仿真中,还存在象高阻态,不定值等其他状态,故IEEE STD1164标准定义了STD_LOGIC数据类型,包含了9种不同值。
3.实体说明一般由类属参数和端口说明两部分组成,端口说明很熟悉了,说一下类属说明:类属参数说明必须放在端口说明之前,用于设置实体和外部电路之间的静态参数。设计者可以通过改变这些参数来对整个设计实体进行修改。在元件例化中,应用与此相同。
4.rtl视图,其实就是寄存器级传输图,它在综合及布局布线前就生成了,并非设计的最终电路结构,是设计输入的最忠实的体现,它的主要作用是帮助设计者检查设计输入中的问题。就像是用XST综合的时候,有一个view rtl schematic和一个view technology schematic,区别是前者仅仅是语法分析得到的结构,是你的设计单纯的综合效果,可以帮助你理解你的算法;而后者才是放在FPGA中综合的效果,是用chipscope可以看到的,反映了实际的电路和资源使用情况。
5.跨时钟阈问题的解决:比方说设计输入有2M和3M两个时钟,那么可以采用两种办法,第一个用异步FIFO,第二个是加一个6M的全局时钟,然后让2M和3M做为使能端。
6.每对信号赋值一次,延迟一个时钟,比方说a<=b,c<=a;那么b相对于a延迟一个时钟,a相对于c又延迟一个时钟。
7.对于电平信号输入的,如读写请求信号,那么怎么检测它们的边沿,以达到边沿触发的目的呢。有一个方法,设输入为wrreq,则有Q1 <= WRREQ; Q2 <= Q1;Wrpulse <= Q2 and not(Q1);此方法即为当wrreq下降沿时,wrpulse为1,后续判断wrpulse即可。Q1 <= WRREQ; Q2 <= Q1;Wrpulse <= Q1 and not(Q2);此时当wrreq上升沿时,wrpulse为1。
8.在用modelsim进行仿真时,要注意赋初始值,即rst='1'时要都赋值,要不然会出现红线的不定态。
9.用ISE调用modelsim进行仿真相对来讲还是比较方便的,它可以直接建立相应的testbench模块,即verilog test fixture 和 vhdl test bench。用ISE10.1 和 modelsim6.3f配合使用的时候,vhdl 语言没有问题;但是用verilog写的模块,调用modelsim 的时候会提示一些库的错误,但是这时候直接新打开modelsim,并change directory 到此目录下,则能正确进行。又重新在ISE下编译了一下verilog HDL的仿真库,问题解决,回忆了一下可能是在我笔记本上当时编译Modelsim仿真库的时候,只编译了VHDL的。ISE环境下,edit->preferences->integrated tools 下面设置用modelsim、synplify等,此页还有TEXT editor的设置等。
10.ISE中直接编译modelsim仿真所需要的库:首先在source for project 中选中器件,然后在下面process中点开Design Entry Utilities,然后双击compile HDL Simulation Libraries即可。还有一点要注意,有一次我明明编译完成了,当天使用也不再提示找不到库文件的错误,但是第二天另一个工程仿真的时候又提示了,说明呢库的路径信息没有保存下来,需要先把modelsim安装目录下的modelsim.ini文件取消只读属性,这样编译后的路径信息就保存了。
11. tsu : setup time,
定义输入数据讯号在 clock edge 多久前就需稳定提供的最大须求;以 正缘触发(positive edge trigger)的D flip-flop 来举例就是 D 要比 CLK 提前 tsu 时间以前就要准备好,此 flip-flop 就能于某特定之频率下正常工作.
th : hold time,
定义输入数据讯号在 clock edge 后多久内仍需稳定提供的最大须求;以 正缘触发(positive edge trigger)的D flip-flop 来举例就是 D 要在 CLK 正缘触发 th 时间内仍要提供稳定之数据,此 flip-flop 就能于某特定之频率下正常工作.
tco : clock output delay,
定义由 clock latch/trigger 到输出数据有效之最大延迟时间 ;以正缘触发(positive edge trigger)的D flip-flop 来举例就是Q 要在 CLK 正缘触发后至多 tco 时间就会稳定输出.
tpd : propagation delay,
定义由输入脚到输出脚最大延迟时间,一般定义予 combination logic circuit 较适合.
12.ISE中调用一个IP核后,在edit-language template-core generator-选中要例化的核即可例化;还有更简便的方法,在process栏里直接有一个view.....。
13.在安装目录xilinx\10.1\ise\doc\usenglish\books\docs下可以查看FPGA设计的相关文档。象在XST文件夹下就介绍了一些常用模块的编码风格等。
14.xilinx对一个输入管脚,如果添加了IO BUF,那么在这个模块内它就只能被调用一次。去掉BUF是一种解决办法。
15.自顶向下开发,刚开始有一点体会。就是说从顶层开始写,用到的信号先写上,后面再一层一层往下对顶层用到的信号进行定义和相应的赋值。
16.状态机尽量不要用一段式写法,一段是将状态转移、状态输出和转移条件等都写在一个always块或一个process中;两段式是写一个always块描述同步状态转移,一个always块用组合逻辑描述状态转移的条件和相应的输出;三段式相比于两段式是另外再加一个always块专门对各状态的输出做一级寄存同步输出,就是将两段式的状态输出部分摘出来。
17.FPGA设计中没有用到的管脚,要设置输入三态(as input tri-stated),在想做的转换模块没有用到的CPLD管脚是不是有这个问题引发了一些干扰呢,不过以后还是注意这一点的好。
18.对于扇出的问题一直听说,一直没有搞太明白,今天总算明白了一些。扇出指的是门电路的带负载能力,就是说一个门电路的输出能同时驱动几个门电路,当然它跟门电路的开关特性有关,象CMOS门电路驱动能力就比TTL大。在FPGA设计中,有一个门控时钟的概念,门控时钟指的是不用FPGA内部的全局时钟资源BUFG来控制触发器的时钟沿输入端而是采用组合逻辑和其它时序逻辑(如分频器)产生的信号作为触发器的时钟沿输入端。门控时钟容易带来时钟漂移、毛刺等,使得触发器误动作,通常,对于驱动的触发器数量较少的门控时钟,编译器可以自动将分布时钟缓冲器将其布线优化,但是对于驱动触发器较多的门控时钟,将会使布线不稳定,重者造成设计混乱。门控时中较多,也会使得整个设计的最大工作速度下降,降低产品的性能。对于门控时钟问题,通常的解决办法是将分频器做成与系统时钟宽度一个周期宽度的脉冲信号,所谓系统时钟就是用全局时钟资源BUFG驱动的高扇出、零漂移、零畸变的时钟资源,在FPGA内部的布线结构是树形结构。将分频器的输出送入触发器的ce端,当系统时钟到来时,检测ce信号的有效性,当ce信号有效时,将触发器的输出改变,和分频器的作用完全一样,而且这样处理也使得布线更加优化。
对于多扇出问题,通常是指用一个节点驱动多个下级逻辑器件,对于门控时钟驱动较多的触发器,也可以归为此类问题,此问题会严重影响FPGA布线的稳定性,设计的时候要多加注意,此时采用的是复制寄存器策略:CLK为系统时钟,M1为1MHz方波信号,由于M1信号驱动的模块较多,所以M1的扇出较多(假定扇出数为140),为了减少扇出,用系统时钟采样,将M1信号驱动7个D触发器,然后将7个D触发器的输出端分给7个模块,这样每个复制点(DUP0~DUP6)平均扇出变为20,M1的信号扇出变为7,这样就减少了每个信号的扇出,优化了逻辑,也提高了设计的整体性能。上述模块的VHDL语言描述为:
library ieee;
use ieee.std_logic_1164.all;
entity RegDup is
port(clk:in std_logic;
Dup:out std_logic_vector(6 downto 0);
M1:in std_logic);
end RegDup;
architecture rtl of RegDup is
begin
process(Clk)
begin
if Clk'event and Clk='1'then --系统时钟采样
Dup(0)<=M1; --复制M1信号
Dup(1)<=M1;
Dup(2)<=M1;
Dup(3)<=M1;
Dup(4)<=M1;
Dup(5)<=M1;
Dup(6)<=M1;
end if;
end process;
end rtl;
19.甲辰说:组合逻辑的敏感信号列表他一般用always @(*),说信号少了不行,多了没事;FPGA的初始状态是在编译以后就赋上的;
20.如果组合逻辑不使用always块,则肯定不会产生锁存器,像使用assign语句,因为它不需要保存上一状态的值。在基于always块的语句中,产生锁存器的情况一般为两种,一种是在if语句中没有else分支,再一个就是case语句没有使用default,如果本意想生成锁存器的话也要显示说明,这样可以提高程序的稳健性和可读性。
21.实现奇数分频可以使用错位异或法,其实就是两路计数,一路计上升沿,一路计下降沿,两路在适当的时候翻转,最后进行或运算即可。
22.在工程目录IP核文件夹下example_design目录下,有相关的使用IP核的例子。
23.在用quartus进行波形仿真的时候,要在vwf文件修改数据的属性,比如进制显示等,这样在simulation report就不用每次都改了。用ep2c35f484c8做了一个FIFO的仿真,有以下几点:write full信号:在写到第N+1(fifo深度为N)个数据时,有效,在读出第一个数据后无效;
read empty信号:初始有效,读出最后一个数据时候也有效,在写到N/2个数据的时候无效;
在写满的时候再写是写不进去的,也不会冲掉原来的;
在读空的时候只能读出最后一个数据。
还有一个FIFO的问题,在加入IP核时,会有一步让你选是否用le来实现FIFO,而不管是否有memory,但是这个选项只能在FIFO不太大时才能让选。
24.在用verilog写程序的时候,有一些错误很难发现,像module后面不加模块名,if(rst)语句后面多个语句不加begin和end等,需要特别注意。
25.使用quartus加入IP核的时候,第一次会弹出是否产生qip文件并加入工程,选择是的话以后创建IP核会自动加入,但是你如果将加入的IP核删去的话会提示找不到qip文件,这时候你要从project->add/remove files in project将相应的qip文件remove就可以了。
26.quartus中的反标注布线信息就是将你一次编译以后时序没有问题的模块的信息给记录下来,下次编译的时候它的布线就不变,当然它的先决条件是你的这个模块是一个固定大小(fixed size)和锁定位置(locked location)的logic lock的模块。quartus本身还有一个incremental compilation的功能,就是你没有改变的逻辑再编译的时候是保持不变的,这样会减少编译时间。logic lock这样设置,alt+l快捷键打开logic lock regions窗口,新建一个region,指定开始坐标(origion)和大小,然后将你需要锁定的逻辑直接从compilation hierarchy窗口中拖过来放在上面就行了。反标注布线信息是右键选择该region,然后properties,然后有一个content back_annotation,里面就有相关的选项。
27.ISE下设置仿真的工具为MODELSIM时,先要在edit->preference->integrated tools下设置MODELSIM的路径,然后还要在project->design properties->simulator下选择MODELSIM才行。另外前提还要先编译HDL的仿真库,在implementation窗口下选择compile HDL simulation libraries。
28.modelsim下file->save format将需要仿真的信号保存下来(wave.do),下次file->load就行了。
29.产生一个周期的触发信号:根据触发条件,如果一个信号的上升沿或下降沿来触发一个trigger,那直接用检测沿的方式产生这个trigger就行了;如果没有什么触发条件,那就多用一个信号,
if(B==1'b1), A<=1'b0; else A<=1'b1; if(A== 1'b1) B<=1'b1; else B<=B;那么A就是一个脉冲的trigger信号。
30.状态机的三要素:状态、输入和输出。常用的应该都是米勒型状态机吧,就是输出不仅跟状态有关,还和输入条件有关。个人认为如果想输出只与状态有关,简单的逻辑还行,如果逻辑复杂了,那设计出来的状态肯定很多啊。
31.用modelsim仿真的时候提示Module 'BLK_MEM_GEN_V3_3' is not defined错误,看modelsim加载的xilinx的library发现目录是10.1版本下的xilinxCoreLib目录,里面确实没有这个文件,在ISE11.4环境重新编译了一下xilinx的仿真库,问题就解决了。但是后来用批处理文件运行vsim来进行仿真的时候,又出现了这个问题,打开modelsim.ini,发现我虽然在ISE的环境下编译了xilinx的仿真库,但是并没有把信息更新到modelsim.ini,将XILINXCORELIB_VER = d:\Xilinx\10.1\ISE\vhdl\mti_se\xilinxcorelib_ver改到正确的路径XILINXCORELIB_VER = d:\Xilinx\11.1\ISE\verilog\mti_se\6.5\nt\xilinxcorelib_ver,其他四个库类似,然后就没有问题了。
32.双向信号的仿真:加一个使能信号en,一个reg,一个wire,wire就是例化时候的输出,然后加上
assign wire = en? reg:z;就OK了。
33."Always Construct warning at <location>: inferring latch(es) for variable "<name>", which holds its previous value in one or more paths through the always construct",综合出锁存器了,要在always块一开始就赋一个初值。
34.开启resource sharing功能,则在互斥逻辑中使用的加法器、乘法器等资源就可以共享以减少资源使用。
35.乘法运算要注意位宽的设置,如果在一个计算式中,有一个变量和一个常数相乘,那么这个变量的位宽要大于等于乘积实际的位宽才行。
36.ISE下place and route messages - errors窗口下,右键error,选择search for answers record,则自动会转到xilinx的网站去寻找相应的解答。

浙公网安备 33010602011771号