我正在尝试实现一个FSM,它对正在按下的两个按钮中的任何一个做出反应。让我们调用这些按钮A和B.我想要的是:
always@(posedge A or posedge B) begin
if(A) begin **do one thing**
end else if (B) begin **do another**
end
end
我害怕的情况是,例如,用户按住按钮A然后按B. if语句将检测到A为高,当我想要反应的实际敏感参数是B.我怎样才能在Verilog中做到这一点?
答案 0 :(得分:2)
一种方法是注册A和B的值,并将它们与当前值进行比较。这需要某种系统时钟,但您可能已经使用了一个FSM。
举个例子:
input A, B;
input clk;
reg A_prev, B_prev;
always @(posedge clk)
begin
A_prev <= A;
B_prev <= B;
end
always @(*)
begin
if (A && !A_prev) **do whatever**
else if (B && !B_prev) **do whatever**
end
由于A和B已注册,第二个always
块将检测A(或B)在前一个时钟周期是否为低电平且现在为高电平。
答案 1 :(得分:2)
无论如何,你需要跟踪“A已被压低但尚未被释放”等状态。您可以在状态机外部跟踪该状态,如@ wilcroft的回答,或作为状态机的一部分。要将其作为状态机的一部分来处理,您需要更改灵敏度列表以响应按下或释放(即不仅仅是posedge),并包括其中一个或两个按钮的状态信息:
always @(A or B) begin
if (state == NONE_ON) begin
if(A) begin next_state = A_ON; **do one thing**
end else if (B) begin next_state = B_ON; **do another**
end
end
else if (state == A_ON) begin
if (!A) begin next_state = NONE_ON;
end else if (B) begin next_state = AB_ON; **do the B things***
end
end
else if (state == B_ON) begin
if (!B) begin next_state = NONE_ON;
end else if (A) begin next_state = AB_ON; **do the A things***
end
end
else if (state == AB_ON) begin
if (!A) begin next_state = B_ON;
end else if (!B) begin next_state = A_ON;
end
end
end
在某种意义上,跟踪这样的状态是状态机的重点,这就是你所说的你想要构建的,这是建立状态机的一个共同动机。
但是,如果您打算构建的状态机完全复杂,那么将更多的A / B信息添加到状态表可能会显着增加您的状态,并使整个状态机变得更加复杂和意大利面条状,因为您的预期状态可能最终成为A_ON,B_ON和AB_ON的附加子状态。
另一方面,根据您尝试做的事情,鉴于您尝试构建基于A或B的状态机被按下,似乎很可能已经隐含了至少部分此类信息(例如,至少某些按钮被按下了)在您最初想到的状态中,因此它可能不会更改复杂性。
(请注意,如果您担心处理同时按下或释放两个按钮的可能性,也会使此实现更加复杂。)