全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 制造与封装 >

FPGA时序分析-建立时间和保持时间裕量都是inf怎么

时间:2023-07-30 10:26

人气:

作者:admin

标签: 时序分析  FPGA设计  Vivado 

导读:FPGA时序分析-建立时间和保持时间裕量都是inf怎么解决呢?-今天有个小伙伴遇到一个问题,就是在vivado里面综合后看到的建立时间和保持时间裕量都是inf,我们来看看怎么解决这个问题...

今天有个小伙伴遇到一个问题,就是在vivado里面综合后看到的建立时间和保持时间裕量都是inf,我们来看看怎么解决这个问题。

实验一:

 

module testMem(
    input clk,
    input [9:0] addr,
    input we,
    input [7:0] wdata,
    output reg [7:0] rdata
     );
    reg [7:0] mem [1023:0];
    reg [7:0] data;
    reg [7:0] data1;
    reg [7:0] data2;
    reg [7:0] data3;
    always@(posedge clk)begin
        if(we)begin
            mem[addr] <= wdata;
        end
    end
    
    always@(posedge clk)begin
            rdata <= mem[addr];
    end
    
endmodule

 

时序约束如下:

 

create_clock -period 5.000 -name sys_clk [get_ports clk]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports clk]

 

代码非常简单,大家一看就可以知道,这段代码会被映射到一个Bram上。综合后的资源报告也印证了我们的想法:

1bfc7b42-2df8-11ee-815d-dac502259ad0.jpg

但是看时序分析:

1c127afa-2df8-11ee-815d-dac502259ad0.png

是不是感觉很奇怪明明我们约束时钟了,为什么时序分析后是inf呢,我们来看一下他综合后的框图就明白了。

1c290982-2df8-11ee-815d-dac502259ad0.png

可以看到在上图里面,clk只和bram的时钟管脚相连,这种情况下怎么做时序分析嘛,一般我们在片内做的时序分析都是一个寄存器到另一个寄存器的。

时序分析一共四种模型,可以参考下面四张图,分别是Input to Flip-flop Path,Flip-flop to Output Path,Flip-flop to Flip-flop Path,Input to Output Path图片来源于Static Timing Analysis for Nanometer Designs也就是静态时序分析圣经,这本必读哦。

1c498432-2df8-11ee-815d-dac502259ad0.png

1c6764fc-2df8-11ee-815d-dac502259ad0.png

1c7e88ee-2df8-11ee-815d-dac502259ad0.png

1c9bc4c2-2df8-11ee-815d-dac502259ad0.png

实验二:

那怎么改变,vivado计算出来是inf呢,首先给输入输出加上

 

(*DONT_TOUCH="yes"*)

 

这个约束看看,代码就变成了下面这个样子

 


module testMem(
    input clk,
    (*DONT_TOUCH="yes"*)input [9:0] addr,
    (*DONT_TOUCH="yes"*)input we,
    (*DONT_TOUCH="yes"*)input [7:0] wdata,
    (*DONT_TOUCH="yes"*)output reg [7:0] rdata
    );
    
    reg [7:0] mem [1023:0];
    always@(posedge clk)begin
        if(we)begin
            mem[addr] <= wdata;
        end
    end
    
    always@(posedge clk)begin
            rdata <= mem[addr];
    end
    
endmodule

 

1cbedc6e-2df8-11ee-815d-dac502259ad0.png

这次呢时序分析对了,我们来看一下综合后的结果,可以看到不再是孤零零的一个bram的ip了,这个就是典型的Flip-flop to Flip-flop Path的时序分析了。

1cebedf8-2df8-11ee-815d-dac502259ad0.png

但是注意到没有,实现的资源从bram变成lut和FF了,这个是因为在xilinx的器件里面,bram必须至少要有一级寄存器,那你可能又要问了,我们不是在代码里面rdata有一级寄存器吗,为啥没有被综合成bram呢,这个是因为加了dont touch的约束之后,vivado就不会再去优化这个寄存器,这样这个寄存器就不能被优化到bram里面了,这样自然就不会使用bram资源来实现上面的代码了。

实验三:

我们可以通过手动再加一级寄存器的方案,来让他使用bram资源,代码如下:

 


module testMem(
    input clk,a
    (*DONT_TOUCH="yes"*)input [9:0] addr,
    (*DONT_TOUCH="yes"*)input we,
    (*DONT_TOUCH="yes"*)input [7:0] wdata,
    (*DONT_TOUCH="yes"*)output reg [7:0] rdata
    );
    
    reg [7:0] mem [1023:0];
    reg [7:0] data;
    always@(posedge clk)begin
        if(we)begin
            mem[addr] <= wdata;
        end
    end
    
    
    always@(posedge clk)begin
            data <= mem[addr];
    end
    always@(posedge clk)begin
            rdata <= data ;
    end
    
endmodule

 

1d12c216-2df8-11ee-815d-dac502259ad0.png

1d2ac348-2df8-11ee-815d-dac502259ad0.png

可以看到时序分析,资源分析和我们预期是一致的。

1d451e1e-2df8-11ee-815d-dac502259ad0.png

综合后的结果也和我们预期一致,可以和实验一做对比,这次在bram后面多了一级寄存器哦。

实验四:

那么我们在上面的代码里面继续去掉dont touch约束看看会发生什么。

 

module testMem(
    input clk,a
    input [9:0] addr,
    input we,
    input [7:0] wdata,
    output reg [7:0] rdata
    );
    
    reg [7:0] mem [1023:0];
    reg [7:0] data;
    always@(posedge clk)begin
        if(we)begin
            mem[addr] <= wdata;
        end
    end
    
    
    always@(posedge clk)begin
            data <= mem[addr];
    end
    always@(posedge clk)begin
            rdata <= data ;
    end
    
endmodule

 

1d862576-2df8-11ee-815d-dac502259ad0.png

可以看到又变成了inf,再来看一下综合后的框图,和实验一一样,你可能会问,我们不是加了两级寄存器了吗,怎么bram的输出一个都没有呢,这是因为这两级寄存器都被bram给吸收了呢。

小提示,这样两级寄存器的方式比一级的时序会好很多哦,当然如果如果寄存器不少纯打拍的话,他是不会被吸收进去的。

1db43ede-2df8-11ee-815d-dac502259ad0.png

实验五:

既然打两拍不行,那就多打几拍咯。

代码变成下面的样子:

 




module testMem(
    input clk,
    input [9:0] addr,
    input we,
    input [7:0] wdata,
    output reg [7:0] rdata
    );
    
    reg [7:0] mem [1023:0];
    reg [7:0] data;
    reg [7:0] data1;
    reg [7:0] data2;
    reg [7:0] data3;
    always@(posedge clk)begin
        if(we)begin
            mem[addr] <= wdata;
        end
    end
    
    always@(posedge clk)begin
            data <= mem[addr];
    end
    always@(posedge clk)begin
            data1 <= data;
            data2 <= data1;
            data3 <= data2;
            rdata <= data3;
    end
    
endmodule



 

1dddcff6-2df8-11ee-815d-dac502259ad0.png

1dfbd0a0-2df8-11ee-815d-dac502259ad0.png

可以看到一切和我们的预期一致。

1e11a2fe-2df8-11ee-815d-dac502259ad0.png

总之做FPGA一定要知道自己写的代码会被映射到什么资源上去哦。






审核编辑:刘清

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信