我正在尝试在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
答案 0 :(得分:2)
合成器不清楚如何用3个异步控制信号控制STATE
。
你的合成器很可能试图将STATE
映射到具有异步低电平有效设置和复位的D触发器。例如,它可能正在尝试合成以下内容:
dff state_0_(.Q(STATE[0], .CLK(DOWN), .SET_N(UP), .RST_N(RES(, .D(/*...*/));
在具有异步设置和重置的真实翻牌中,默认值应该是同意并且会在第一个代码中解释错误。在您的第二次尝试中,UP
与DOWN
一起成为组合逻辑云的一部分。 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);