1

我有一个带有代表重置按钮的数字输入的 CPLD。当按下复位按钮时,信号变为高电平。我需要做的是有一个寄存器,它的值告诉按钮是否被按下。基本上是一个闩锁。当按钮变为高电平时,锁存寄存器变为高电平并永远保持高电平。

我认为这很简单,但是当我尝试对其进行编码时,我收到了一堆警告。一点谷歌搜索显示“不要在 HDL 中制作闩锁!不好的做法!”,但我在这里并没有真正看到替代方案。

这是我的尝试。clk_10m 是一个快速自由运行的时钟,pwr_off_req 是按钮输入。

reg pwr_off_req_latched = 0;

always @ (clk_10m or pwr_off_req) begin

   if (pwr_off_req == 1'b1)
      pwr_off_req_latched <= 1'b1;   
   else
      pwr_off_req_latched <= pwr_off_req_latched;
      // I tried this to make sure it's always set to something          
end
4

3 回答 3

2

你能假设按钮按下的脉冲长度比你设备的时钟频率长得多吗?如果它是一个物理按钮,我认为这是一个非常安全的假设。在那种情况下,我认为这会很好地工作:

always @(clk_10m) 
   pwr_off_req_latched <= power_off_req_latched | power_off_req;
于 2013-01-30T06:35:56.243 回答
1

锁存器在 HDL 中并不坏,它们只是需要一些考虑,由于忘记在组合部分中指定 else 子句而隐含的锁存器是不好的,因为您最终没有得到您期望的硬件,并且可能会产生时序问题。

如果您正在应用重置,您可能需要指定一个“pragma”,以便综合工具正确识别它。

锁存器也应该使用=not <=,当它们被启用时,它们是组合的(打开的)并且不会破坏反馈循环。

这是使用异步复位创建锁存器的典型方法:

//synopsys async_set_reset "rst_an"
always @* begin
  if (~rst_an) begin
    // Reset 
    x = 1'b0;
  end
  else if (latch_open) begin
    //next datavalue
    x = y ;
  end
end

在您的情况下,您可能想要类似的东西:

//synopsys async_set_reset "rst_an"
always @* begin
  if (~rst_an) begin
    pwr_off_req_latched = 1'b0;
  end
  else if ( pwr_off_req ) begin
    pwr_off_req_latched = 1'b1 ;
  end
end
于 2013-01-30T09:42:41.110 回答
1

锁存器会给时序分析工具带来问题。它们也不直接映射到某些(FPGA)架构,因此对于布局布线工具来说要困难得多。因此发出警告。

但是,您所要求的不是我理解数字逻辑意义的锁存器 - 只是一个永远不会复位的触发器。

因此,它可以简化为一个简单的 d 型触发器,其中 D 输入连接到 1,clk 输入连接到您的pwr_off_req信号:

reg pwr_off_req_latched = 0;

always @ (posedge pwr_off_req) begin
      pwr_off_req_latched <= 1'b1;   
end

你根本没有噪声抑制 -任何正向边缘都会将触发器锁定到1.

如果我这样做,我会将输入运行到双触发器同步器中,然后对同步信号的几个时钟脉冲进行计数,以确保在设置锁存信号之前它不是噪声。除非您期望实际事件比几个时钟脉冲短,否则就是这样做的。


在旁边:

数字逻辑世界中的“锁存器”通常意味着

  • 一个电路,其输出保持两个输入中的任何一个最后为高电平(设置/复位或 SR 锁存器
  • 一种电路,其输出在控制信号无效时保持输入值,但在控制信号为低电平时跟随输入 -透明锁存器

这与触发器相比,触发器的输出在控制信号(通常)从低变为高时保持与输入相关的某些方面,并且忽略输入,除了该上升沿周围的微小时间窗口。这些是D 型T 型JK 型触发器,具体取决于输出相对于输入的行为方式。

于 2013-01-30T16:30:43.427 回答