zoukankan      html  css  js  c++  java
  • 关于VerilogHDL生成的锁存器

           总是会遇到有写文档中提到,不要生成锁存器。问题是

           一: 什么叫锁存器

          二 : 为什么不要生成锁存器

          三 : 如何避免生成锁存器

        好,现在就这三个问题,一一做出解答

        一  什么叫锁存器

    锁存器(Latch)是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制其与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。
          我的理解就是一个锁进信号并存储一段时间的电路,简称锁存器。
     
     
        二  为什么不要生成锁存器
          一种说法 : 把该信号的变化暂存起来,待敏感电平列表中的某一个信号变化时再起作用,纯组合逻辑电路不可能作到这一点,综合器会发出警告。综合工具会将Latch优化掉,造成前、后仿真结果不一致。
         第二种说法: 锁存器为电平触发,无效电平锁存,有效电平输入即反应到输出,由于延时不同容易产生毛刺。组合逻辑中数据不需要锁存,需要避免产生锁存器。FPGA资源中木有锁存器,需要触发器加逻辑门构成,消耗逻辑资源较多,但有时为了需要满足一些规范协议,会用到锁存器,总之FPGA用的很少。 而ASIC设计中,由于锁存器构成较简单,传输速度快,用锁存器可以有效提高集成度,所以用的比较多!
     
     
         三   如何避免生成锁存器
    一份资料说  在case () 后面加上    //synthesis full_case。代码中//synthesis full_case 是综合命令,告知综合工具case中已是全部列举可能的情况,这样综合后无锁存器。又有人说他在以下代码中加入 //synthesis full_case 没有效果
     
    module datadistributor(datain,sel,enable,a,b,c,d);
    input datain;
    input[1:0] sel;
    input enable;
    output a;
    output c;
    output d;
    output b;
    reg a,b,c,d;
    always @(datain or enable or sel)
       begin
          if(enable==1'b1)
              begin
                 case(sel)
                    2'b00:a<=datain;
                    2'b01:b<=datain;
                    2'b10:c<=datain;
                    2'b11:d<=datain;
                    default:a<=datain;
                  endcase
              end
           else
              begin
                 a<=1'bz;
                 b<=1'bz;
                 c<=1'bz;
                 d<=1'bz;
              end
       end  
    endmodule

    这个帖子的结论就是 //synthesis full_case 去除的是没有描述到的case情况所产生的锁存器。所以上述代码中产生的锁存器是无法通过这条简单的语句来消除的,好又有大神提及到

    在 always 块的 if..else 语句中如果所列的条件不完整,综合时则会产生锁存器。

      example:
            always @(action) 
              if(action)  out1 <= 1'b1;

            没有考虑到 !action 的情况,默认out1保持不变,这就产生了锁存器。
                    优化方法:1.列出 !action 的情况,2.对out1赋初始值
            1.always @(action) 
              if(action)  out1 <= 1'b1;
              else    out1 <= 1'b0;
    |
            2.always @(action)  begin
              out <= 1'b0;
              if(action)  out1 <= 1'b1;
              end

     满满以为这个我就可以大功告成,总算知道怎么样避免产生锁存器了。于是检查了一下我的代码,发现锁存器好多啊,比如这个

     1 //pulse_count  and  bit_count  
     2 reg [2:0]  pulse_count  = 3'd0;
     3 reg [3:0]  bit_count    = 4'd0;
     4 always @ (posedge i2c_clk)  begin 
     5     if (curr_state == `IDLE)  begin 
     6          pulse_count <= 3'd0;
     7           bit_count   <= 4'd0;
     8      end else begin 
     9              if (pulse_count == 3'd4)  pulse_count <= 3'd0;
    10                 else if ((curr_state != `WAIT) || scl ) 
    11                          pulse_count <= pulse_count + 3'd1;
    12                 if (((curr_state == `TX) || (curr_state == `RX))  &&  (pulse_count == 3'd4))  begin 
    13                     if (bit_count == 4'd8) bit_count <= 4'd0;
    14                      else                   bit_count <= bit_count + 4'd1;
    15                 end 
    16          end 
    17 end 

    第12行产生的真值表并不全面那么事产生了锁存器吗?这个是李亚民老师的代码

    上面那位大神博文我只看了一半,后来才发现下面这么写:

    但是,在描述时序逻辑的时候,也通常利用 if 语句的隐式条件对带时钟使能的 D 触发器建模

      example:
            always@(posedge clk, negedge rst_n)  begin
              if(!rst_n)  sum <= 0;
              else if(EN)  sum <= a+b;
            表示在时钟正沿来临时,如果 EN 为 1 ,则将 a+b 的值赋给 sum, 言下之意是如果 EN 为 0, 那么 sum 保持原值不变。这里综合工具会把代码综合成一个带时钟使能的 D 触发器。
     
     
     

     结论 : 组合逻辑,有无效状态就会产生锁存器 

     (补充:看到博文说case 有优先级,可是我记得在特权的书上以及自己做的实验上是看到if  else 有优先级,case是并行处理的啊。当时我记得看的是RTL viewer,是不死后粗糙了点。是不是要去追寻到更底层去验证呢)

  • 相关阅读:
    .Net Core调用NodeJs
    ASP.NET Core中间件中渲染Razor视图
    ASP.NET Core自定义View查找路径,实现主题切换
    Core路由2-Endpoint终结点路由
    Core路由1
    .NET Core的本地化机制(多语言)【转】
    实现ASP.NET Core MVC的插件式开发(ApplicationPart)
    Gitflow工作流程
    Git-开发中遇到紧急任务如何处理
    多线程笔记-CancellationToken(取消令牌)
  • 原文地址:https://www.cnblogs.com/sepeng/p/3333545.html
Copyright © 2011-2022 走看看