将有限状态机图转换为Verilog代码
我需要将下面的有限状态图转换为Verilog代码。 我已经在下面介绍了我编写的代码。在我看来,我已经正确地实现了所有逻辑,并且代码适用于前几个输入组合。然而,它最终失败了,我似乎不明白为什么将有限状态机图转换为Verilog代码,verilog,finite-automata,state-machine,Verilog,Finite Automata,State Machine,我需要将下面的有限状态图转换为Verilog代码。 我已经在下面介绍了我编写的代码。在我看来,我已经正确地实现了所有逻辑,并且代码适用于前几个输入组合。然而,它最终失败了,我似乎不明白为什么 module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b); parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11; reg
module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
reg state;
always @(posedge clk, negedge reset_b) begin
// set state
if (reset_b || !in_x) state <= S0;
else
case (state)
S0: state <= (in_y == 1) ? S1 : S3;
S1: state <= S2;
S2: state <= S3;
S3: state <= S3;
endcase
// set output
out_z <= (state == S2 || state == S3) ? 1 : 0;
end
endmodule
模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
注册州;
始终@(posedge clk,NEGDEDGE reset_b)开始
//设定状态
如果(reset_b | | | |!in_x)状态看起来您试图通过将in_x中的视为二次重置来简化FSM。我不认为这种简化是正确的,不管怎样,你试图变得太聪明。只需写出每种情况下的所有转换,要么作为嵌套的case
语句,要么作为每个状态下的一系列if
s。例如:
case (state)
S0: case ({in_x, in_y})
2'b00: state <= S0;
2'b01: state <= S0;
2'b10: state <= S3;
2'b11: state <= S1;
endcase
S2: case ({in_x, in_y})
…
案例(状态)
S0:大小写({in_x,in_y})
2'b00:state看起来您试图通过将在_x
中作为辅助重置来简化FSM。我不认为这种简化是正确的,不管怎样,你试图变得太聪明。只需写出每种情况下的所有转换,要么作为嵌套的case
语句,要么作为每个状态下的一系列if
s。例如:
case (state)
S0: case ({in_x, in_y})
2'b00: state <= S0;
2'b01: state <= S0;
2'b10: state <= S3;
2'b11: state <= S1;
endcase
S2: case ({in_x, in_y})
…
案例(状态)
S0:大小写({in_x,in_y})
2'b00:state实际上,您的实现目前存在许多问题:
当您的state
变量需要为两位时,它只有一位宽:reg state
->reg[1:0]state
很可能您实际上不想让out_z
成为寄存器,因为它应该跟随同一时钟上的状态,而不是之后的时钟周期
您的reset_b
逻辑是向后的,对于negedge重置,您需要通过检查断言!重置\u b
或~重置\u b
如前所述,您确实不应该将异步重置与任何同步输入相结合,甚至不应该将同步重置与reset\u b
和in\u x
相结合。虽然这在模拟中可以很好地工作,但大多数合成工具可能无法正确处理它。在学习Verilog时,我犯了同样的错误,花了好几天时间才发现并纠正
下面是一个更清晰的代码版本,其中实施并注释了此修复程序,因此您可以看到以下4点:
module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
reg [1:0] state; // Fix state variable
// Set output combinationally (no need for turning operator)
always @(*) begin
out_z = (state == S2 || state == S3);
end
always @(posedge clk, negedge reset_b) begin
// Invert the logic for reset and keep it separate
if (!reset_b) begin
state <= S0;
end
else begin
// You can case on inputs as was suggested, but I think casing on state is fine
// I include only logic for changing state
case (state)
S0: begin
if (in_x && in_y) begin
state <= S1;
end
else if (in_x && !in_y) begin
state <= S3;
end
end
S1: begin
if (in_x) begin
state <= S2;
end
else begin
state <= S0;
end
end
S2: begin
if (in_x) begin
state <= S3;
end
else begin
state <= S0;
end
end
S3: begin
if (!in_x) begin
state <= S0;
end
end
endcase
end
end
endmodule
模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
注册[1:0]状态;//固定状态变量
//组合设置输出(无需转动操作器)
始终@(*)开始
out_z=(状态==S2 | |状态==S3);
结束
始终@(posedge clk,NEGDEDGE reset_b)开始
//反转复位逻辑,并将其分开
如果(!reset_b)开始
state实际上,您的实现目前存在许多问题:
当您的state
变量需要为两位时,它只有一位宽:reg state
->reg[1:0]state
很可能您实际上不想让out_z
成为寄存器,因为它应该跟随同一时钟上的状态,而不是之后的时钟周期
您的reset_b
逻辑是向后的,对于negedge重置,您需要通过检查断言!重置\u b
或~重置\u b
如前所述,您确实不应该将异步重置与任何同步输入相结合,甚至不应该将同步重置与reset\u b
和in\u x
相结合。虽然这在模拟中可以很好地工作,但大多数合成工具可能无法正确处理它。在学习Verilog时,我犯了同样的错误,花了好几天时间才发现并纠正
下面是一个更清晰的代码版本,其中实施并注释了此修复程序,因此您可以看到以下4点:
module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
reg [1:0] state; // Fix state variable
// Set output combinationally (no need for turning operator)
always @(*) begin
out_z = (state == S2 || state == S3);
end
always @(posedge clk, negedge reset_b) begin
// Invert the logic for reset and keep it separate
if (!reset_b) begin
state <= S0;
end
else begin
// You can case on inputs as was suggested, but I think casing on state is fine
// I include only logic for changing state
case (state)
S0: begin
if (in_x && in_y) begin
state <= S1;
end
else if (in_x && !in_y) begin
state <= S3;
end
end
S1: begin
if (in_x) begin
state <= S2;
end
else begin
state <= S0;
end
end
S2: begin
if (in_x) begin
state <= S3;
end
else begin
state <= S0;
end
end
S3: begin
if (!in_x) begin
state <= S0;
end
end
endcase
end
end
endmodule
模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
注册[1:0]状态;//固定状态变量
//组合设置输出(无需转动操作器)
始终@(*)开始
out_z=(状态==S2 | |状态==S3);
结束
始终@(posedge clk,NEGDEDGE reset_b)开始
//反转复位逻辑,并将其分开
如果(!reset_b)开始
状态解释你所说的“工作”和“失败”是什么意思。哪个信号应该切换状态<代码>案例(状态)
不正确。我想你应该使用类似于的case({in_x,in_y})
来代替。另外,我建议对状态和条件使用不同的名称。@dave_59为测试它而编写的测试台记录了不正确的输出。@Serge该状态应在时钟上升沿更改,或在重置下降沿重置为状态0。请解释“工作”和“失败”的含义.哪个信号应该切换状态<代码>案例(状态)
不正确。我想你应该使用类似于的case({in_x,in_y})
来代替。我还建议对状态和条件使用不同的名称。@dave_59为测试它而编写的测试台记录了不正确的输出。@Serge状态应该在时钟上升沿改变,或者在重置的下降沿重置为状态0。我实现了此逻辑并再次测试了代码,但我的代码的问题似乎与out_z设置为的值有关。我实现了此逻辑并再次测试了代码,但我的代码的问题似乎与out_z设置为的值有关。