我有一个带有表示复位按钮的数字输入的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
答案 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
。
如果我这样做,我会将输入运行到双触发器同步器中,然后计算同步信号的几个时钟脉冲,以确保在设置锁存信号之前它不是噪声。除非你期望真正的事件短于几个时钟脉冲,否则就可以了。
除了:
数字逻辑世界中的“锁存器”通常意味着
这与触发器相比,当控制信号(通常)从低变高到高时,其输出保持与输入相关的某些方面,并忽略输入,除了该上升沿周围的微小时间窗口。这些是D-type,T-type和JK-type触发器,具体取决于输出相对于输入的行为方式。