如何在Verilog中创建一个锁存器

时间:2013-01-30 06:05:31

标签: verilog hdl

我有一个带有表示复位按钮的数字输入的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

3 个答案:

答案 0 :(得分:2)

您能否认为按下按钮的脉冲长度比设备的时钟频率长?如果它是一个物理按钮,我认为这是一个非常安全的假设。在这种情况下,我认为这将完美无缺:

always @(clk_10m) 
   pwr_off_req_latched <= power_off_req_latched | power_off_req;

答案 1 :(得分:1)

锁存器在HDL中也不错,它们只需要考虑一下,隐含的锁存器会忘记在组合部分中指定else子句是不好的,因为你不会得到你期望的硬件,并且可能会产生时序问题。

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

此外,锁存器应使用=而不是<=,启用它们时它们是组合(开放)并且不会破坏反馈循环。

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

//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

答案 2 :(得分: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

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


除了:

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

  • 一个电路,其输出保持两个输入中的任何一个为最后一个高位(a Set/Reset or SR latch
  • 一个电路,其输出在控制信号无效时保持输入值,但在控制信号为低电平时跟随输入 - a transparent latch

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