常用时序收敛方法

结构调整

结构调整是提高时域性能的一种方法,它是在不改变原有组合逻辑功能的前提下,通过调整其内部逻辑门之间的连接关系,来达到减少逻辑门级数的目的,进而提高时域性能的方法。举例如下:
现在有同步输入总线A、B、C、D,需要在下一时钟周期就能以寄存的方式输出它们的和SUM。那么通常来说,你可能会将HDL代码写成这样:

--VHDL example
--all inputs are scalar type
PROCESS (clk)
BEGIN
    IF clk'event AND clk = '1' THEN
        SUM <= A + B + C + D;
    END IF;
END PROCESS;
// Verilog example
// all inputs are bus type
always@(posedge clk)
begin
    SUM<=A+B+C+D;
end

对于上述代码,编译器通常会将它翻译成如图所示的电路。

由此可见,该电路中从“输入A~D”到“输出SUM的寄存器输人”之间,最长的逻辑路径依次经过了3个加法器,也就是说上述电路中的组合逻辑部分有3级加法器,如果一个加法器的时间延迟为T,那么整个组合逻辑的时间延迟就是3T.
编译器之所以会给出如此结构的电路,主要是因为在HDL语言中,“+”运算符号对应的运算优先关系为从左至右,因此A、B先参与运算,而其结果再和C一起送人下一个加法器运算,而这次的结果再和D一起送人第三个加法器进行运算,至此才得到组合形式输出的和。
通过进一步分析上述电路可以发现,当A、B进行运算时,C、D其实闲着没事干(虽然事实不是这样,但是此时第二、第三个加法器进行的运算都是无效的),因为第一、第二个加法器的输出还没有稳定;而当A、B或C参与有效运算时,D其实一直是闲着没事干的(解释类似同前),因为第二个加法器的输出还没有稳定。由此可见,上述电路中的逻辑结构不是很合理,因为我们更希望编译器得出的电路是同时使用两个加法器分别处理A、B和C、D的求和,然后再使用一个加法器处理这两个加法器的结果即可。为了达到这种效果,可以对上例进行一些修改,结果如下:

--VHDL example
--all inputs are scalar type
PROCESS (clk)
BEGIN
    IF clk'event AND clk = '1' THEN
        SUM <= (A + B) + (C + D);
    END IF;
END PROCESS;

可见,我们仅仅通过添加了两个小括号,就调整了原有算式中不太合理的运算优先级关系,这便是“小括号的妙用”。对应上述代码,编译器给出的电路结构如图所示。

 

1、插入寄存器

将计算逻辑分成多个时钟周期实现,这是常用的时序优化方法,可以减少过多的组合逻辑层数,但会增加延时。

这里以一个多路输入求和计算为例

module sum(
    input        clk,
    input  [15:0] data_A,
    input  [15:0] data_B,
    input  [15:0] data_C,
    input  [15:0] data_D,
    output [17:0] sum_o);

    always @(posedge clk) begin
        sum_o <= data_A + data_B + data_C + data_D;
     end

endmodule

增加寄存器后,改为

module sum(
    input        clk,
    input  [15:0] data_A,
    input  [15:0] data_B,
    input  [15:0] data_C,
    input  [15:0] data_D,
    output [17:0] sum_o);

    reg [16:0] sum0, sum1;

    always @(posedge clk) begin
        sum0 <= data_A + data_B;
        sum1 <= data_C + data_D;
     end

    always @(posedge clk) begin
        sum_o <= sum0 + sum1;
     end

endmodule

2、逻辑展平设计

优化代码中优先级译码电路逻辑,主要出现在IF/ELSE结构语句中,这样逻辑结构被展平,路径延迟得以缩短。

IF ELSE结构语句存在明显的优先级,建议尽量用CASE语句来替代。

3、防止变量被优化

HDL综合布线软件会根据实际情况,自动优化代码逻辑,可能存在将多个不同寄存器变量合并成一个寄存器变量的情况。

对于不希望被优化的变量,可以在变量定义前,添加(* keep = "ture" *)

高扇出

高扇出问题,原因是一个寄存器驱动后级数超过了它本身的驱动能力,导致延迟时间过大,不满足时序。

1、使用max_fanout
在变量定义前,可以添加(* max_fanout = n *),来设置变量的最大扇出数n,超过这个扇出数,综合软件会自动复制多份变量。

2、复位信号高扇出
复位信号是常见的高扇出问题,主要解决办法有:

(1)减少复位信号的使用,能使用使能信号控制的,就用使能信号。

(2)对于大型模块,复位信号可以使用BUFG来驱动复位信号,可以增加复位信号的驱动能力

资源消耗

FPGA器件的整个工程资源消耗,不管是LUT还是BRAM等资源,建议不超过80%。

一旦资源消耗超过80%,在布线综合时,就出现布线资源不够,导致出现布线拥塞,从而出现了时序不收敛的情况。

布线拥塞也分为全局拥塞和局部拥塞,可能是高扇出信号过多,也可能是局部布线资源不够用,导致时序路径过长。

1、优化代码逻辑,减少资源消耗。

在资源不够用的情况下,建议检查代码是否可优化,设置的RAM大小是否过大等等。

2、使用替代资源实现

在FPGA中实现RAM时,可以根据整个资源的使用情况,考虑使用Distributed RAM、URAM等资源来减少BRAM的消耗。

posted @ 2024-03-28 10:01  Radiumlrb  阅读(191)  评论(0编辑  收藏  举报