如果使用三元运算符 - Verilog

时间:2013-07-15 18:40:46

标签: verilog

我正在尝试在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&lt; = UP? STATE&gt;&gt; 1:STATE&lt;&lt; 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都关闭。可能我的代码中存在问题,但我无法理解为什么我的第一个代码根本无法编译。 谢谢你的帮助!

harrym

1 个答案:

答案 0 :(得分:2)

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

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

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

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

要使合成器做得更好,首先需要同步异步控制信号。使用与CDC相同的技术(时钟域交叉; Cliff Cummings的论文进入拘留here)。一个基本的例子:

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);