从输入端口到输出端口: 这种路径是指组合逻辑的延迟,指信号从输入到输出没有经过任何寄存器。给这种路径加约束条件,需要虚拟一个时钟,然后通过约束来指定哪些路径是要受该虚拟时钟的约束。 在Synplifypro和Precision中都有相应的约束来处理这种路径。 前面的帖子里讲述了关于输入输出延迟的一些参数的含义和计算方法。如果要把这些参数和altera,xilinx的软件结合起来,也不是一件容易的事情。以前altera和xilinx的约束条件设定非常烦杂,各自都有一套。似乎大家也不太看重约束条件的设定,大多时候都是无论如何先上板,然后通过signaltap和Chipscope来调。当FPGA规模大了之后,布线一次都需要很长时间,这种方法的弊端就越来越严重。 实际上可以借鉴ASIC的设计方法:加比较完善的约束条件,然后通过RTL仿真,时序分析,后仿真来解决问题,尽量避免在FPGA电路板上来调试。 altera最先意识到这一点,它采用了Synopsys的SDC格式。SDC的格式也得到了逻辑综合器的支持。而且设定方法比较容易掌握。 这个帖子会详细讨论一下这种格式的约束设定方法。 时钟的设定方法: 时钟要分成两种,一种是从端口上直接输入的时钟,另一种是在FPGA内部产生的时钟。内部产生的时钟又要分成两种,从锁相环出来的(包括altera的PLL和Xilinx的DLL)和从逻辑单元出来的,例如一般的计数器分频就是这种情况。 从锁相环出来的时钟可以通过端口直接加,因为一般的综合工具和布线工具都能够自动的把端口的时钟约束传递到锁相环,并且根据锁相环的倍频关系自动施加到下一级。 而从逻辑单元出来的就需要单独对其进行约束。 在SDC格式中,创建时钟的命令 create_clock, 后面要带3个参数:name ,period, waveform. name的含义是指创建这个时钟约束的名字,而不是时钟本身的名字。 要把这个约束和时钟信号关联起来,还需要在后面加些东西。 period的单位缺省是ns. waveform是用来指定占空比。 除了这三个参数以外,常常还要加 get_ports的命令,来指定时钟的输入端口。 下面的例子是一个较为完整的设定时钟的例子: create_clock -name clk1 -period 10.000 –waveform. { 2.000 8.000 } [get_ports sysclk] 这个例子表示,有一个clk1的约束,在这个约束中设定了时钟的周期为10ns, 占空比为2ns低电平,8ns高电平。 这个叫做clk1的约束是针对sysclk这个端口的。 如果是利用内部锁相环分频出来很多其他时钟的约束,可以不再另外施加其他约束,逻辑综合器和布线器都能根据锁相环的参数自动计算。 如果是利用内部的逻辑单元分频出来的信号,则必须利用get_registers指定分频的寄存器名。 例如上例: create_clock -name clk1 -period 10.000 –waveform. { 2.000 8.000 } [get_registers cnt_clk]. 对于逻辑单元分频的时钟信号,也可以采用命令create_generated_clock会更加精确。举例如下: create_generated_clk -name clk2 -source [getports sysclk] -div 4 [get_registers cnt_clk] 这个约束命令描述了 一个clk2的约束,约束的对象是由sysclk分频4次得到的时钟,这个时钟是由cnt_clk这个寄存器产生的。 在高速的系统中,对时钟的描述可能会要求的更多,更加细致。 例如,会要求对时钟的抖动和时钟的延迟进行描述。 在SDC的文件格式中,可以通过两个命令来描述:set_clock_uncertainty 和 set_clock_latency 来设定。 时钟的延迟相对来讲比较简单。延迟一般分为外部延迟和内部时钟线网的延迟。 通常在约束时只对外部延迟做约束,在set_clock_latency的命令后带 -source的参数就可以了。 例如: set_clock_latency -source 2 [get_clocks {clk_in} ] |