[原创]FPGA编译生成锁存器原因与解决办法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ysgjiangsu/article/details/82718462

遇到的问题:

在quartus ii中,编译工程,报出如下警告:

Warning (335093): TimeQuest Timing Analyzer is analyzing 160 combinational loops as latches.

Quartus 官方给出的Help如下:

CAUSE: The TimeQuest Timing Analyzer found latches implemented using non-optimal 
resources (look-up tables (LUTs) with combinational feedback).  The TimeQuest analyzer 
replaces the combinational loop with an equivalent latch. The TimeQuest analyzer treats 
this logic as a synchronous endpoint, and will not analyze the path through the node. 

ACTION: You must implement these latches with registers using asynchronous load and 
data signals, or remove them from your design. For more information, 
run the check_timing tcl command in the TimeQuest analyzer. 

以上翻译过来就是,
原因:时序分析发现了 锁存器(使用了非优化的资源:带有组合逻辑反馈的查找表)。时序分析用等效的锁存器替代了这里的组合逻辑环路。时序分析会把该处当做同步端点,不会分析通过这个节点的路径时序。

措施:你必须(注意是必须)用异步加载数据信号的寄存器实现这些锁存器,或者索性从设计中删除他们。。。

这里关于寄存器与锁存器展开一下:

组合电路是一个真值表,一组输入对应一组输出,实时跟踪变化,这样也就容易有冒险、竞争之类的问题产生毛刺。而锁存器就是组合电路的一种。

锁存器特点:电平敏感

always @ (A,B)
    C <= A & B;

只要A或者B变化,条件就被触发,C被赋值A and B

触发器特点:边沿敏感

always @ (posedge clk)
    C <= A & B;

只有当clk上升沿到来时,C才被赋值A and B
特别地,如果把C <= A & B; 换成 Q <= D; 这就是D触发器的原始模型了(没有复位信号的D触发器)

(异步)寄存器特点:由触发器构成,可以保存N bit数据
以1 bit寄存器为例

always @ (posedge clk or negedge n_rst)

if (!n_rst)
    Q <= 0;
else 
    if (load)
        Q <= D;

当load信号有效后的下一个clk上升沿,将输出赋值为D。复位信号到来,直接清零。其余情况,保持上次的值不变。

(同步)寄存器特点:由锁存器构成,可以保存N bit数据
就是说输入是地址索引,函数是真值表,存储的数据就是 f(x), 即 真值表(输入) = 输出。认为这里的输出是与输入同步的(虽然存在信号的传输延迟)。小标题写的保存N bit数据 应该加引号,因为它并不是真正意义保存。甚至不能称其为寄存器,N bit寄存器应该是可以写入,可以读取。而组合逻辑电路一旦确定。其真值表也将确定,“保存的数据”也就确定了。

关于项目中遇到的问题

在以下代码中,生成N多锁存器,

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

always@(posedge clk or negedge n_rst)
begin
    if(!n_rst)
    begin
        edata <= rstVal;
        state <= {A,C};
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此处省略一万*****
    end

原因:生成锁存器的原因是,表面上我是按照触发器的方式在写代码,实则不然。在异步复位代码段,我的输出依然由外界输入决定,因此综合之后产生了锁存器。
将代码作如下修改,问题解决

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

always@(posedge clk or negedge n_rst)
begin
    if(!n_rst)
    begin
        edata <= 32'd0;
        state <= 2'd0;
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此处省略一万*****
    end

问题解决了,但是我还有一个问题,就是这样的改动并不是我想要的,我就是要在n_rst为低的时候,执行edata <= rstVal; 。可以做如下处理:取消 negedge n_rst ,在语句内把!n_rst 当作是另一种使能信号,即:

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

always@(posedge clk)
begin
    if(!n_rst)
    begin
        edata <= rstVal;
        state <= {A,C};
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此处省略一万*****
    end

问题解决

猜你喜欢

转载自blog.csdn.net/ysgjiangsu/article/details/82718462
今日推荐