引言
FPGA最初阶段的学习可以分为两部分。一是HDL的语法,二是相关工具的使用。
这第一部分,就是verilog HDL或者VHDL,国内用verilog的占得比例多一些。
对于第二部分,这要看具体的FPGA开发过程,一般过程如下:
3.1 FPGA开发flow
1》进行需求分析,算法设计,模块划分,形成文档,用的matlab,vesio或者ppt比较多。(分析设计)
2》用UE或者,SlickEdit,notepad++或者sourceInsight,或者IDE自带的编辑工具进行行为建模。(编码)
3》用modleSim进行功能仿真,或用$dumpfile("rill.fsdb")生成fsdb文件。(前仿真)
4》将fsdb文件导入debussy软件,进行问题查找定位,修改代码。(调试)
5》用synplify pro进行综合,生成vqm文件。(综合)
6》用quartusII或者ISE对vqm文件进行P&R(布局和布线),生成vo文件和sdo文件。(布局布线)
7》再用modleSim对vo和sdo进行时序仿真,当然需要将FPGA厂家的仿真库文件一同编译进modleSim的仿真库。(后仿真)
8》用quartusII 的time request添加约束并仿真。生成sof或者pof配置文件。(实现)
9》烧写配置文件。(OK)
对于做IC/ASIC,步骤还会有元件库的映射等工作。
3.1.1 形式验证
形式验证是一种静态的验证手段,它根据电路静态地判断两个设计在功能上是否等价,常用来判断一个设计在修改前和修改后其功能是否保持一致。它运行时无需测试向量,但是必须有一个参照设计和一个待验证的设计。参照设计时设计者认为功能上完备无缺的设计,理论上它可以用高级语言如C,C++实现的,也可以是用集成电路的建模镅詓ystemC,或者验证语言vera或SpecmanE实现的;但是就实现而言,多数形式验证过程中参照设计就是我们的RTL设计,一般用verilog或VHDL实现的。
当RTL级功能仿真或FPGA验证结束后,传统的IC设计流程需要完成一下几次门级仿真:综合后门级仿真;DFT之后的门级仿真;布局布线之后的门级仿真等,如果设计很大或者电路很复杂,往往需要庞大的测试向量来验证设计的功能及时序是否正确,这就使得我们花费在门级仿真的时间随着电路规模的增直线上升。
形式验证在ASIC设计流程中犹如一个迭代算法,其最初的输入是RTL设计,每次比较,都将上一次比较后的设计(第n-1次)作为参照设计处理之后的结果(第n次)进行比较,之所以这么做,是基于以下考虑:
1.形式验证工具开始比较前,首先在两个设计中找到一一对应的比较点。
2.如果一个设计改动太大,改变前后的功能是完全一致的,但如果形式验证工具无法找到适合的比较点,也会认为这两个设计不等价 形式验证在ASIC设计流程中主要应用在以下几个方面:RTL-RTL的对比,RTL-GATE的对比,GATE-GATE的对比。采用形式验证进行RTL 与RTL的比较,可以在较短的时间内验证并保证代码修改的过程中没有引入功能性的错误;进行RTL与GATE的对比,是验证源代码与综合之后的门级网表是否等价,以保证综合过程中不会出现任何错误;进行GATE与GATE的对比,主要是发生在验证插入DFT后的电路网表在功能上是否一致;生成时钟树前后的电路网表在功能上是否一致;布局布线前后的电路网表在功能上是否一致等。
3.2 verilog HDL
我试图通过一个例子来说明verilog的语法。我自己写的例子,希望能仔细体会。
一个反相器:
3.2.1 反相器的行为级建模
module rill_not_behv ( input in, output reg out ); always @* begin if(1 == in) begin out = 0; end else begin out = 1; end end endmodule
3.2.2 RTL级建模
module rill_not_rtl ( input in, output out ); assign out = in?0:1; endmodule
3.2.3 门级建模
module rill_not_gate ( input in, output out ); not rill_not(out,in); endmodule
3.2.4 开关级建模,叶级建模
module rill_not_leaf ( input in, output out ); supply1 pwr; supply0 gnd; pmos (out,pwr,in); nmos (out,gnd,in); endmodule
3.2.5 用户自定义原语(UDP)
primitive rill_not_pri ( input in, output out ); specify (in=>out) = 2;// or (in*>out) = 2; endspecify table //in :out 0 :1; 1 :0; endtable endprimitive
3.3 测试,一定要习惯写testbench
module rill_not_tb; reg in; wire out; $dumpfile("rill.fsdb"); $dumpvars; rill_not(.out(out),.in(in)); always begin #10 in = ~in; $display ("in:%d,out:%d",in,out); end initial begin #100 $stop; end $setup(clk,in,3); $hold(in,clk,3); $width(in,10); endmodule
3.4 小结
语法不是学会的,是实践会的。百炼自得,你懂的。希望你把上面的代码都能理解,并且知道他们之间的区别和联系。
以后说工具,modulesim,debussy,Synplify,quartusII及其内部小工具。