【FPGA——时序篇】时序优化的几种方法

参考博文:https://www.cnblogs.com/sepeng/p/5578402.html

参考书目:英文版:《advanced FPGA design》    中文版:《高级FPGA设计,结构,实现,和优化》

衡量FPGA设计的两个重要指标是吞吐率和延迟。

吞吐率:指系统每一个时钟周期内能够处理的数据数量,为了获得更高的吞吐率就需要减少组合逻辑延迟,在组合逻辑中间插入寄存器,也就是流水线设计。

延迟:指数据从输入系统到输出系统总共需要的时间,为了获得更短的延迟,可以减少组合逻辑延迟,或者删减路径上的寄存器,第二种方法显然不利于系统获得更好的性能。

 

时序优化的几种方法

这里说的优化是让FPGA设计获得更高的工作频率,也就是通常说的性能和吞吐率。

1.插入寄存器(pipeline)

这种方式会增加设计的时滞(clock latency)。插入了几个寄存器,结果输出就会延长几个周期,在不违反设计规格(对clock latency有要求)以及功能没有影响的时滞情况之下可以这么做。举例说明,如果下面一个FIR滤波器的设计没能满足时序要求。

module fir(
    output [7:0] Y,
    input  [7:0] A,B,C,X,
    input        clk,
    input        validsample);
    always @(posedge clk)
        if(validsample) begin
            X1<=X;
            X2<=X1;
            Y<=A*X+B*X1+C*X2;
        end
endmodule

  从代码可以看出,X2这条路径过长,是整个设计的Critical Path,如果采用流水线设计可以用寄存器暂存自已在执行Y的运算,改进如下:

module fir(
    output   [7:0] Y,
    input    [7:0] A,B,C,X,
    input            clk,
    input            validsample);
    reg       [7:0] X1,X2,Y;
    reg       [7:0] prod1,prod2,prod3;
    always @(posedge clk) begin
        if(validsample) begin
            X1<=X;
            X2<=X1;
            prod1<=A*X;
            prod2<=B*X1;
            prod3<=C*X2;
        end
        Y<=prod1+prod2+prod3;
    end
endmodule

2.并行化设计

  并行化设计的思想是将一个逻辑函数分解为几个小一些的逻辑函数并行计算,从而减少关键路径上的延迟 。

  例如计算两个8bits数的乘法,将8bits数分为两个4bits数,则乘法运算可以被分解为下面几个部分: 

X∗X={A,B}∗{A,B}={(A∗A),(2∗A∗B),(B∗B)};X∗X={A,B}∗{A,B}={(A∗A),(2∗A∗B),(B∗B)}; 

  通过这种方法可以将设计简化为一系列4bits乘法器的实现。

module power3(
    output  [7:0] XPower,
    input   [7:0] X,
    input         clk);
    reg     [7:0] XPower1;
    //部分结果寄存器
    reg     [3:0] XPower2_ppAA,XPower2_ppAB,XPower2_ppBB;
    reg     [3:0] XPower3_ppAA,XPower3_ppAB,XPower3_ppBB;
    reg     [7:0] X1,X2;
    wire    [7:0] XPower2;
    wire    [3:0] XPower1_A = XPower1[7:4];
    wire    [3:0] XPower1_B = XPower1[3:0];
    wire    [3:0] X1_A      = X1[7:4];
    wire    [3:0] X1_B      = X1[3:0];
    wire    [3:0] XPower2_A = XPower2[7:4];
    wire    [3:0] XPower2_B = XPower2[3:0];
    wire    [3:0] X2_A      = X2[7:4];
    wire    [3:0] X2_B      = X2[3:0];
    assign XPower2 = (XPower2_ppAA << 8) + (2*XPower2_ppBB << 4) + XPower2_ppBB;
    assign XPower  = (XPower3_ppAA << 8) + (2*XPower3_ppBB << 4) + XPower3_ppBB;
    always @(posedge clk) begin
       //第一级流水线
       X1 <=X;
       XPower1 <= X;
       //第二级流水线
       X2 <= X1;
       XPower2_ppAA <= XPower1_A * X1_A;
       XPower2_ppAB <= XPower1_A * X1_B;
       XPower2_ppBB <= XPower1_B * X1_B;
       //第三级流水线
       XPower3_ppAA <= XPower2_A * X2_A;
       XPower3_ppAB <= XPower2_A * X2_B;
       XPower3_ppBB <= XPower2_B * X2_B;
       end
endmodule

3.逻辑展平

通过优化掉设计中的优先级译码电路,逻辑结构被展平,路径延迟得以缩短,优先级译码电路常出现在IF/ELSE结构语句中出现。

module regwrite(
    output reg [3:0] rout,
    input            clk,in,
    input      [3:0] ctrl);
    always @(posedge clk)
        if(ctrl[0])      rout[0] <= in;
        else if(ctrl[1]) rout[1] <= in;
        else if(ctrl[2]) rout[2] <= in;
        else if(ctrl[3]) rout[3] <= in;
endmodule

上面代码综合后就会产生优先级译码器,通过各项平级的if语句或者case语句可以避免这样的优先级译码设计

//改进后
module regwrite(
    output reg [3:0] rout,
    input            clk,in,
    input      [3:0] ctrl);
    always @(posedge clk) begin
        if(ctrl[0]) rout[0] <= in;
        if(ctrl[1]) rout[1] <= in;
        if(ctrl[2]) rout[2] <= in;
        if(ctrl[3]) rout[3] <= in;
    end
endmodule

4.均衡设计

均衡设计的思想是把 Critical Path 上的组合逻辑拿出一部分放在 short path 上进行,从而缩短 Critical Path 的延迟。

下面举例一个8位加法器。

module adder(
    output reg [7:0] Sum,
    input      [7:0] A,B,C,
    input            clk);
    reg        [7:0] rA,rB,rC;
    always @(posedge clk) begin
        rA <= A;
        rB <= B;
        rC <= C;
        Sum <= rA+rB+rC;
    end
endmodule

可以看到,在寄存器rA,rB,rC之前的路径上没有组合逻辑,所以可以考虑把一部分计算拿到寄存器之前

//改进后
module adder(
    output reg [7:0] Sum,
    input      [7:0] A,B,C,
    input            clk);
    reg        [7:0] rABSum,rC;
    always @(posedge clk) begin
        rABSum <= A + B;
        rC     <= C
        Sum    <= rABSum + rC;
    end
endmodule

5.优化路径

最后一种方法也是我认为最难的,通过优化数据流的路径来缩短 Critical Path ,提升系统性能。重新布局和 Critical Path 在一起的路径,从而 Critical Path上的逻辑门可以更靠近目标寄存器。举一个栗子:

module randomlogic(
    output reg [7:0] Out,
    input      [7:0] A,B,C,
    input            clk,
    input            Cond1,Cond2);
    always @(posedge clk)
        if(Cond1)
            Out <= A;
        else if(Cond2&&(C<8))
            Out <= B;
        else
            Out <= C;
endmodule

可以看到C作为B的输出条件的路径最长,经过了一个比较器和两个逻辑门,是整个设计的 Critical Path ,可以做后续优化。

//改进后
module randomlogic(
    output reg [7:0] Out,
    input      [7:0] A,B,C,
    input            clk,
    input            Cond1,Cond2);
    wire CondB = (Cond2 &!Cond1);
    always @(posedge clk)
        if(CondB&& (C<8))
            Out <= b;
        else if(Cond1)
            Out <= A;
        else
            Out <= C;
endmodule

 

<think>嗯,用户问的是如何使用Design Compiler(DC)工具在组合逻辑中插入寄存器以实现流水线设计。首先,我需要回忆一下DC工具的基本流程和流水线设计的原理。流水线设计通常通过将组合逻辑分成多个阶段,并在每个阶段之间插入寄存器来提高电路的工作频率。 我记得在DC中,设置时序约束是关键步骤。用户需要定义时钟频率,这样工具才能知道目标周期时间。然后,组合逻辑的划分可能需要手动调整,比如在代码中插入寄存器层次,或者使用DC的命令来自动分割。不过,自动分割可能不如手动控制精确。 接下来,可能需要使用compile_ultra命令进行综合优化,这个命令支持高级优化策略,包括自动流水线化。另外,retime命令可以自动调整寄存器的位置,优化时序。但要注意,retime可能受限于设计结构和约束条件。 验证阶段也很重要,生成时序报告检查是否满足时钟周期要求,以及面积和功耗报告。如果发现时序违规,可能需要调整约束或重新划分逻辑层次。 用户提供的引用中,引用[2]提到DC是Synopsys公司的RTL级逻辑综合工具,所以需要确保用户已经正确设置DC环境,并编写了合适的RTL代码。同时,可能需要注意代码风格是否适合流水线设计,比如避免过长的组合逻辑路径。 用户可能遇到的问题包括如何确定分割点,如何处理数据相关性,以及如何处理控制信号。这时候可能需要举例说明代码修改前后的变化,比如在组合逻辑中插入寄存器层次,并展示DC命令的使用方法。 还需要考虑是否需要多级流水线,以及每级之间的时序平衡。此外,流水线可能引入的额外延迟对系统整体性能的影响也需要评估。 总之,步骤大致是:约束设置、逻辑划分、综合优化时序验证。过程中要合理使用DC的命令,并确保RTL代码适合流水线结构。同时,引用相关文档和最佳实践,比如Synopsys的官方指南,来增强建议的可靠性。</think>在数字电路设计中,使用Design Compiler(DC)工具为组合逻辑插入寄存器进行流水线处理,主要包含以下关键步骤和技术要点: ### 一、流水线设计原理 流水线通过将组合逻辑分割为多级,在每级之间插入寄存器(D触发器)来提升系统时钟频率。其数学表达式为: $$ T_{max} = max(T_{comb1}, T_{comb2}, ..., T_{combN}) $$ 其中$T_{comb}$表示各级组合逻辑延迟,通过分割使每级延迟小于时钟周期$T_{clk}$[^3]。 ### 二、DC工具实现流程 1. **时序约束设置** ```tcl create_clock -period 5 [get_ports clk] # 设置5ns时钟周期 set_clock_uncertainty 0.5 [get_clocks clk] set_input_delay 1.0 [all_inputs] ``` 需确保组合逻辑分割后的单级延迟小于时钟周期约束[^2]。 2. **逻辑层次划分** - 手动插入寄存器层次: ```verilog // 原始组合逻辑 always @(*) begin out = (a & b) | (c ^ d); end // 流水线化后 reg stage1, stage2; always @(posedge clk) begin stage1 <= (a & b); stage2 <= (c ^ d); out <= stage1 | stage2; end ``` - 使用DC命令自动分割: ```tcl set_pipeline_stage_options -max_stages 3 \ -enable_register_merging true ``` 3. **综合优化** ```tcl compile_ultra -pipeline retime -min_period_only ``` `compile_ultra`命令启用高级优化算法,`retime`实现寄存器重定时[^2]。 ### 三、验证与调试 1. 时序报告分析: ```tcl report_timing -path full -delay max -max_paths 10 ``` 2. 流水线效果验证指标: - 时钟频率提升比例 - 吞吐量增益:$$ Throughput = \frac{N}{T_{total}} $$ 其中$N$为流水线级数 ### 四、典型问题处理 1. **数据相关性冲突**:需添加前馈通路或重排序电路 2. **控制信号同步**:使用流水线控制寄存器保持状态同步 3. **面积权衡**:通过`set_max_area`约束控制寄存器数量增长
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值