始终阻止具有多种敏感性
Always Blocks with multiple sensitivities
我正在尝试实现一个 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 为高电平,当我想要反应的实际敏感参数时to 是 B。我怎样才能在 Verilog 中做到这一点?
一种方法是注册 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)在前一个时钟周期是否为低电平,现在是否为高电平。
无论哪种方式,您都需要跟踪 "A has been depressed and has not yet been released," 等的状态。您可以在状态机外部跟踪该状态,如@wilcroft 的回答,或者作为您状态的一部分机器。要将此作为状态机的一部分进行处理,您需要更改敏感度列表以响应按下或释放(即不仅仅是姿势),并包含一个或两个按钮处于打开状态的状态信息:
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 添加更多信息 table 可以显着增加您的状态并使整个状态机成为一个好的处理更复杂和像意大利面条一样,因为你的预期状态可能最终成为 A_ON、B_ON 和 AB_ON 的附加子状态。
另一方面,根据您尝试执行的操作,假设您尝试构建一个基于 A 或 B 被按下的状态机,那么很可能至少其中一些信息可能已经存在暗示(例如,至少 某些 按钮被按下)在您最初想到的状态中,因此它可能不会改变那么多复杂性。
(请注意,如果您担心同时按下或释放两个按钮的可能性,这也会使此实现更加复杂。)
我正在尝试实现一个 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 为高电平,当我想要反应的实际敏感参数时to 是 B。我怎样才能在 Verilog 中做到这一点?
一种方法是注册 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)在前一个时钟周期是否为低电平,现在是否为高电平。
无论哪种方式,您都需要跟踪 "A has been depressed and has not yet been released," 等的状态。您可以在状态机外部跟踪该状态,如@wilcroft 的回答,或者作为您状态的一部分机器。要将此作为状态机的一部分进行处理,您需要更改敏感度列表以响应按下或释放(即不仅仅是姿势),并包含一个或两个按钮处于打开状态的状态信息:
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 添加更多信息 table 可以显着增加您的状态并使整个状态机成为一个好的处理更复杂和像意大利面条一样,因为你的预期状态可能最终成为 A_ON、B_ON 和 AB_ON 的附加子状态。
另一方面,根据您尝试执行的操作,假设您尝试构建一个基于 A 或 B 被按下的状态机,那么很可能至少其中一些信息可能已经存在暗示(例如,至少 某些 按钮被按下)在您最初想到的状态中,因此它可能不会改变那么多复杂性。
(请注意,如果您担心同时按下或释放两个按钮的可能性,这也会使此实现更加复杂。)