始终阻止被忽略

发布于 2024-12-27 16:08:45 字数 452 浏览 1 评论 0原文

作为一个更大程序的一部分,我想在按下 KEY[1] 时按顺序(0 到 8)在 DE2 板上一次激活一个绿色 LED。当我按下 KEY[2] 时,他们应该以相反的顺序一次关闭一个。我很确定 DE2 板上的按键处于低电平有效。这是我的代码:

always@(negedge KEY[1], negedge KEY[2])
begin

    if(~KEY[1])
    begin
        LEDGValue <= LEDGValue << 1;
        LEDGValue[0] <= 1;
    end

    else if(~KEY[2]) 
        LEDGValue[0] <= LEDGValue >> 1;

end

相反,当我加载程序时,所有绿色 LED 都会亮起。此时KEY[1]和KEY[2]不起作用。有人看到我的代码有问题吗?

As part of a larger program, I'd like to activate the green LEDs one at a time on my DE2 board in their order (0 to 8) when I press KEY[1]. They should turn off one at a time in reverse order when I press KEY[2]. I'm pretty sure that DE2 board keys are active low. This is my code:

always@(negedge KEY[1], negedge KEY[2])
begin

    if(~KEY[1])
    begin
        LEDGValue <= LEDGValue << 1;
        LEDGValue[0] <= 1;
    end

    else if(~KEY[2]) 
        LEDGValue[0] <= LEDGValue >> 1;

end

Instead all the green LEDs light up as soon as I load the program. At this point KEY[1] and KEY[2] have no effect. Anyone see something wrong with my code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暮凉 2025-01-03 16:08:45

这是一个边缘检测器。

module edge_detector (
    input wire clk,
    input wire in,
    output wire negedge_out
);

reg in_reg= 1'b0;

wire in_next = in;

assign negedge_out = ({in_reg,in) == 2'b10);

always @(posedge clk) in_reg <= in_next;

endmodule

以下是如何使用边缘检测器。

reg [8:0] LEDGValue = 0, LEDGValue_next;

wire key1_edge;
wire key2_edge;

edge_detector
key1_edge_detector_inst (
    .clk(clk),
    .in(KEY[1]),
    .negedge_out(key1_edge)
);

edge_detector
key2_edge_detector_inst (
    .clk(clk),
    .in(KEY[2]),
    .negedge_out(key2_edge)
);

always @* begin : combinational_logic
    LEDGValue_next = LEDGValue;
    if (key1_edge)
        LEDGValue_next = {LEDGValue[7:0], 1'b1};
    else if (key2_edge)
        LEDGValue_next = {1'b0, LEDGValue[8:1]};
end

always @(posedge clk) begin : sequential_logic
    LEDGValue <= LEDGValue_next;
end

关键是 key1_edgekey2_edge 信号仅在单个时钟周期内有效。

Here is an edge detector.

module edge_detector (
    input wire clk,
    input wire in,
    output wire negedge_out
);

reg in_reg= 1'b0;

wire in_next = in;

assign negedge_out = ({in_reg,in) == 2'b10);

always @(posedge clk) in_reg <= in_next;

endmodule

Here is how you use an edge detector.

reg [8:0] LEDGValue = 0, LEDGValue_next;

wire key1_edge;
wire key2_edge;

edge_detector
key1_edge_detector_inst (
    .clk(clk),
    .in(KEY[1]),
    .negedge_out(key1_edge)
);

edge_detector
key2_edge_detector_inst (
    .clk(clk),
    .in(KEY[2]),
    .negedge_out(key2_edge)
);

always @* begin : combinational_logic
    LEDGValue_next = LEDGValue;
    if (key1_edge)
        LEDGValue_next = {LEDGValue[7:0], 1'b1};
    else if (key2_edge)
        LEDGValue_next = {1'b0, LEDGValue[8:1]};
end

always @(posedge clk) begin : sequential_logic
    LEDGValue <= LEDGValue_next;
end

The key is that key1_edge and key2_edge signals are asserted only for a single clock cycle.

终止放荡 2025-01-03 16:08:45

应该是

 always@(negedge KEY[1] OR negedge KEY[2])

Should it be

 always@(negedge KEY[1] OR negedge KEY[2])
一身软味 2025-01-03 16:08:45

我不是 Verilogger,但看起来您是在要求代码触发两个不同信号的边沿。根据我的经验,这不是可合成的,但合成器可能会尝试某些事情并警告您(在大量其他警告中)它做了一些与您真正想要的不同的事情。


编辑:以下内容不适用于提到的板,因为它板上有去抖硬件(感谢 NathanFarrington 指出这一点),但我将其留在这里,以防其他读者使用:


即使合成器成功,边缘在开关输入上触发是一个可怕的想法:开关将反弹几次当您按下它时,FPGA 的速度足以轻松地看到所有这些边缘。

您需要的是一个由良好时钟源(毫无疑问板上有晶体)提供时钟的进程,该进程在每个时钟事件上监视您的开关信号。

为每个信号保留一个计数器,每次信号为 1 时递增计数器,每次信号为 0 时递减计数器。将这些计数器固定在 0 和某个最大时间,以便有足够的时间让开关稳定下来(几毫秒可能就足够了)。

一旦计数器到达其“行程”的任一端,只有然后您才采取一些操作(例如移动您的LEDGValue)。记住之后要等待开关被释放(等待计数到另一“端”)。

I'm not a Verilogger, but that looks like you are asking the code to trigger off edges of two different signals. This is not in my experience synthesisable, but the synthesiser may have attempting something and warned you (amongst a plethora of other warnings) that it's done something other than you really meant.


EDIT: The following doesn't apply to the board mentioned as it has debouncing hardware on board (thanks to NathanFarrington for pointing that out) but I leave it here in case it is of use to other readers:


Even if the synthesiser succeeded, edge triggering on a switch input is a dreadful idea: the switch will bounce several times when you press it, and the FPGA is easily fast enough to see all of those edges.

What you need is a process clocked from a good clock source (there's no doubt a crystal on board) which monitors both your switch signals on each clock event.

Keep a counter for each signal, increment it each time the signal is a 1, decrement it each time the signal is a 0. Clamp these counters at 0 and some maximum time which allows plenty of time for the switch to settle (a few milliseconds will probably suffice).

Once the counter has reached either end of its "travel", only then do you take some action (like shifting your LEDGValue). Remember to wait for the switch to be released afterwards (waiting for the count to go to the other 'end').

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文