1

我正在尝试在 Verilog 中编写一个程序,该程序应该在 LED 阵列上“移动”一个 LED。使用一个按钮,灯应向左移动,而另一个按钮应向右移动。这是我的代码:

module led_shift(UP, DOWN, RES, CLK, LED);
input UP, DOWN, RES, CLK;
output reg [7:0] LED;
reg [7:0] STATE;

always@(negedge DOWN or negedge UP or negedge RES)
begin
    if(!RES)
    begin
        STATE <= 8'b00010000;
    end
    else
    begin
        STATE <= UP ? STATE>>1 : STATE<<1;
    end
end

always @ (posedge CLK)
begin
    LED <= STATE;
end
endmodule

问题在于STATE <= UP ?状态>>1:状态<<1;错误如下:

错误(10200):led_shift.v(34)处的 Verilog HDL 条件语句错误:无法将条件中的操作数与始终构造的封闭事件控制中的相应边匹配

我尝试在不使用这种 if 的情况下修改代码:

always@(negedge DOWN or negedge UP or negedge RES)
begin
    if(!RES)
        STATE <= 8'b00010000;
    else
    begin   
        if(!DOWN)
            STATE <= STATE<<1;
        else
        begin
            if(!UP)
                STATE <= STATE>>1;
            else
                STATE <= STATE;
        end
    end
end

它可以编译,但不起作用:LED 仅向左“移动”,当我按下另一个按钮时,所有 LED 都会关闭。可能我的代码有问题,但我不明白为什么我的第一个代码根本无法编译。感谢您的任何帮助!

哈里姆

4

1 回答 1

2

合成器不清楚如何STATE使用 3 个异步控制信号进行控制。

您的合成器很可能正在尝试映射STATE到具有异步低电平有效设置和复位的 D 触发器。例如,它可能会尝试合成如下内容:

dff state_0_(.Q(STATE[0], .CLK(DOWN), .SET_N(UP), .RST_N(RES(, .D(/*...*/));

在具有异步设置和重置的真实翻牌中,默认值应该是同意,并会在您的第一个代码中解释错误。在您的第二次尝试中,与 .UP一起成为组合逻辑云的一部分DOWNDOWN也被用作时钟。由于UP不是时钟,因此在UP低电平时连续发生移位,立即将 on 位完全移出。第二种情况的另一个错误实际上更合适。

为了使合成器做得更好,您首先需要同步您的异步控制信号。使用与 CDC 相同的技术(时钟域交叉;Cliff Cummings 的一篇论文在此处详细介绍)。一个基本的例子:

always @(posedge clk) begin
    pre_sync_DOWN <= DOWN;
    sync_DOWN <= pre_sync_DOWN;
end

现在控制信号已同步,STATE请输出您的组合逻辑。例子:

always @* begin
    if(!sync_RES)
        STATE = 8'b00010000;
    else
      case({sync_UP,sync_DOWN})
        2'b01  : STATE = LED>>1;
        2'b10  : STATE = LED<<1;
        default: STATE = LED;
      endcase
end

由于一切都在一个时钟域上运行并明确定义了组合逻辑,因此合成器可以使用触发器和基本门构建等效逻辑。


供参考:

要仅在某个negedge事件上移动,您需要保留最后一个同步值并检查从高到低的转换。记得在驱动sync_do_组合逻辑中进行交换STATE

always @(posedge clk)
    keep_DOWN <= sync_DOWN;
always @*
    do_DOWN = (keep_DOWN && !sync_DOWN);
于 2013-07-15T20:44:45.780 回答