Verilog 自动售货机 FSM
Verilog Vending machine FSM
我正在尝试在 verilog 中为自动售货机构建一个有限状态机,它接受 5、10、25 美分作为输入,然后输出苏打水或饮食,并输出适当的零钱(作为五分硬币的数量) .我目前收到一条错误消息,显示 ERROR:HDLCompiler:806 - "D:/Xilinx Stuff/FSM/FSM.v" 第 128 行:"endmodule" 附近的语法错误。
我对 verilog 还很陌生,虽然我知道这可能是一个愚蠢的错误,比如忘记了分号或其他东西,但我终其一生都找不到它。我的代码如下:
module FSM(quarter, nickel, dime, soda, diet,clk, reset, change_count, give_soda,give_diet);
input quarter, nickel, dime, soda, diet,clk, reset,give_soda,give_diet;
output change_count;
reg[3:0] current_state, next_state;
parameter cent0 = 0, cent5= 1, cent10 = 2, cent15=3, cent20 =4, cent25 =5, cent30=6,cent35=7,cent40=8;
always @(posedge clock or posedge reset)
begin
if(reset)
begin
current_state = cent0;
end
else
current_state = next_state;
end
always @(current_state | ((quarter ^ nickel) ^ dime))
begin
case(current_state)
cent0: begin
if(nickel)
next_state = cent5;
else if(dime)
next_state = cent10;
else if(quarter)
next_state = cent25;
end
cent5: begin
if(nickel)
next_state = cent10;
else if(dime)
next_state = cent15;
else if(quarter)
next_state = cent30;
end
cent10: begin
if(nickel)
next_state = cent15;
else if(dime)
next_state = cent20;
else if(quarter)
next_state = cent35;
end
cent15: begin
if(nickel)
next_state = cent20;
else if(dime)
next_state = cent25;
else if(quarter)
next_state = cent40;
end
cent20: begin
if(nickel)
next_state = cent25;
else if(dime)
next_state = cent30;
else if(quarter)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent25: begin
if(nickel)
next_state = cent30;
else if(dime)
next_state = cent35;
else if(quarter)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent30: begin
if(nickel)
next_state = cent35;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent35: begin
if(nickel)
next_state = cent40;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent40: begin
if(nickel)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(dime)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(quarter)
next_state = cent0;
change_count = 4;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
default: next_state = current_state;
endcase
endmodule
我不确定你为什么使用:
always @(current_state | ((quarter ^ nickel) ^ dime))
标准编码风格将使用:
always @(current_state or quarter or nickel or dime)
对于 Verilog 2001 或 System Verilog,您可以使用逗号分隔的敏感度列表,如下所示:
always @(current_state, quarter, nickel, dime)
最后在 verilog 2001 及更高版本中,您可以对组合逻辑始终块使用通配符:
always @(*)
如果您需要对输入进行去抖动或确保一次断言的硬币信号不超过一个,则可能应该在状态机之外完成。
//this is the correct verilog code,
module FSM(quarter, nickel, dime, soda, diet,clk, reset, current_state, next_state, change_count, give_soda, give_diet);
input quarter, nickel, dime, soda, diet,clk, reset;
output [3:0] current_state;
output next_state, change_count, give_soda, give_diet;
reg current_state, change_count, next_state, give_soda, give_diet;
parameter cent0 = 0, cent5= 1, cent10 = 2, cent15=3, cent20 =4, cent25 =5, cent30=6,cent35=7,cent40=8;
always @(posedge clk or posedge reset)
begin
if(reset)
current_state = cent0;
else
current_state = next_state;
end
always @(nickel or dime or quarter)
begin
case(current_state)
cent0: begin
if(nickel)
next_state = cent5;
else if(dime)
next_state = cent10;
else if(quarter)
next_state = cent25;
end
cent5: begin
if(nickel)
next_state = cent10;
else if(dime)
next_state = cent15;
else if(quarter)
next_state = cent30;
end
cent10: begin
if(nickel)
next_state = cent15;
else if(dime)
next_state = cent20;
else if(quarter)
next_state = cent35;
end
cent15: begin
if(nickel)
next_state = cent20;
else if(dime)
next_state = cent25;
else if(quarter)
next_state = cent40;
end
cent20: begin
if(nickel)
next_state = cent25;
else if(dime)
next_state = cent30;
else if(quarter)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent25: begin
if(nickel)
next_state = cent30;
else if(dime)
next_state = cent35;
else if(quarter)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent30: begin
if(nickel)
next_state = cent35;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent35: begin
if(nickel)
next_state = cent40;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent40: begin
if(nickel)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(dime)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(quarter)
next_state = cent0;
change_count = 4;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
default: next_state = current_state;
endcase
end
endmodule
我正在尝试在 verilog 中为自动售货机构建一个有限状态机,它接受 5、10、25 美分作为输入,然后输出苏打水或饮食,并输出适当的零钱(作为五分硬币的数量) .我目前收到一条错误消息,显示 ERROR:HDLCompiler:806 - "D:/Xilinx Stuff/FSM/FSM.v" 第 128 行:"endmodule" 附近的语法错误。 我对 verilog 还很陌生,虽然我知道这可能是一个愚蠢的错误,比如忘记了分号或其他东西,但我终其一生都找不到它。我的代码如下:
module FSM(quarter, nickel, dime, soda, diet,clk, reset, change_count, give_soda,give_diet);
input quarter, nickel, dime, soda, diet,clk, reset,give_soda,give_diet;
output change_count;
reg[3:0] current_state, next_state;
parameter cent0 = 0, cent5= 1, cent10 = 2, cent15=3, cent20 =4, cent25 =5, cent30=6,cent35=7,cent40=8;
always @(posedge clock or posedge reset)
begin
if(reset)
begin
current_state = cent0;
end
else
current_state = next_state;
end
always @(current_state | ((quarter ^ nickel) ^ dime))
begin
case(current_state)
cent0: begin
if(nickel)
next_state = cent5;
else if(dime)
next_state = cent10;
else if(quarter)
next_state = cent25;
end
cent5: begin
if(nickel)
next_state = cent10;
else if(dime)
next_state = cent15;
else if(quarter)
next_state = cent30;
end
cent10: begin
if(nickel)
next_state = cent15;
else if(dime)
next_state = cent20;
else if(quarter)
next_state = cent35;
end
cent15: begin
if(nickel)
next_state = cent20;
else if(dime)
next_state = cent25;
else if(quarter)
next_state = cent40;
end
cent20: begin
if(nickel)
next_state = cent25;
else if(dime)
next_state = cent30;
else if(quarter)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent25: begin
if(nickel)
next_state = cent30;
else if(dime)
next_state = cent35;
else if(quarter)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent30: begin
if(nickel)
next_state = cent35;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent35: begin
if(nickel)
next_state = cent40;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent40: begin
if(nickel)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(dime)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(quarter)
next_state = cent0;
change_count = 4;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
default: next_state = current_state;
endcase
endmodule
我不确定你为什么使用:
always @(current_state | ((quarter ^ nickel) ^ dime))
标准编码风格将使用:
always @(current_state or quarter or nickel or dime)
对于 Verilog 2001 或 System Verilog,您可以使用逗号分隔的敏感度列表,如下所示:
always @(current_state, quarter, nickel, dime)
最后在 verilog 2001 及更高版本中,您可以对组合逻辑始终块使用通配符:
always @(*)
如果您需要对输入进行去抖动或确保一次断言的硬币信号不超过一个,则可能应该在状态机之外完成。
//this is the correct verilog code,
module FSM(quarter, nickel, dime, soda, diet,clk, reset, current_state, next_state, change_count, give_soda, give_diet);
input quarter, nickel, dime, soda, diet,clk, reset;
output [3:0] current_state;
output next_state, change_count, give_soda, give_diet;
reg current_state, change_count, next_state, give_soda, give_diet;
parameter cent0 = 0, cent5= 1, cent10 = 2, cent15=3, cent20 =4, cent25 =5, cent30=6,cent35=7,cent40=8;
always @(posedge clk or posedge reset)
begin
if(reset)
current_state = cent0;
else
current_state = next_state;
end
always @(nickel or dime or quarter)
begin
case(current_state)
cent0: begin
if(nickel)
next_state = cent5;
else if(dime)
next_state = cent10;
else if(quarter)
next_state = cent25;
end
cent5: begin
if(nickel)
next_state = cent10;
else if(dime)
next_state = cent15;
else if(quarter)
next_state = cent30;
end
cent10: begin
if(nickel)
next_state = cent15;
else if(dime)
next_state = cent20;
else if(quarter)
next_state = cent35;
end
cent15: begin
if(nickel)
next_state = cent20;
else if(dime)
next_state = cent25;
else if(quarter)
next_state = cent40;
end
cent20: begin
if(nickel)
next_state = cent25;
else if(dime)
next_state = cent30;
else if(quarter)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent25: begin
if(nickel)
next_state = cent30;
else if(dime)
next_state = cent35;
else if(quarter)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent30: begin
if(nickel)
next_state = cent35;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent35: begin
if(nickel)
next_state = cent40;
else if(dime)
next_state = cent40;
else if(quarter)
next_state = cent0;
change_count = 2;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
cent40: begin
if(nickel)
next_state = cent0;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(dime)
next_state = cent0;
change_count = 1;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
else if(quarter)
next_state = cent0;
change_count = 4;
if(soda)
give_soda = 1;
else if(diet)
give_diet = 1;
end
default: next_state = current_state;
endcase
end
endmodule