我在模拟自动售水机。现在,我们在7段解码器下有4个按钮。从左到右,前3个按钮将用于增加分总额。第一个将增加总计25美分,第二个按钮将增加10美分,第三个按钮将增加总计5美分。最后,第四个按钮将用于重置计数。
问题是:当我按下5,10或25分按钮时,总数立即变为50美分并分配水。
这是我的代码:
module DispenserFSM(clk, rst, five, ten, twentyfive, current, dispense);
input clk, rst;
input five, ten, twentyfive;
output [5:0] current;
reg [5:0] current;
output dispense;
reg dispense;
// state encoding
parameter S0= 4'b0000,
S1= 4'b0001,
S2= 4'b0010,
S3= 4'b0011,
S4= 4'b0100,
S5= 4'b0101,
S6= 4'b0110,
S7= 4'b0111,
S8= 4'b1000,
S9= 4'b1001,
S10= 4'b1010;
reg [3:0] state, nextState;
// state register logic
always@(posedge clk, posedge rst)
if(rst == 1)
state <= S0;
else
state <= nextState;
// combinational circuit
always@(state, five, ten, twentyfive)
case(state)
S0: begin
if(five == 1)
nextState <= S1;
else if(ten == 1)
nextState <= S2;
else if(twentyfive == 1)
nextState <= S5;
else
nextState <= S0;
end
S1: begin
if(five == 1)
nextState <= S2;
else if(ten == 1)
nextState <= S3;
else if(twentyfive == 1)
nextState <= S6;
else
nextState <= S1;
end
S2: begin
if(five == 1)
nextState <= S3;
else if(ten == 1)
nextState <= S4;
else if(twentyfive == 1)
nextState <= S7;
else
nextState <= S2;
end
S3: begin
if(five == 1)
nextState <= S4;
else if(ten == 1)
nextState <= S5;
else if(twentyfive == 1)
nextState <= S8;
else
nextState <= S3;
end
S4: begin
if(five == 1)
nextState <= S5;
else if(ten == 1)
nextState <= S6;
else if(twentyfive == 1)
nextState <= S9;
else
nextState <= S4;
end
S5: begin
if(five == 1)
nextState <= S6;
else if(ten == 1)
nextState <= S7;
else if(twentyfive == 1)
nextState <= S10;
else
nextState <= S5;
end
S6: begin
if(five == 1)
nextState <= S7;
else if(ten == 1)
nextState <= S8;
else if(twentyfive == 1)
nextState <= S10;
else
nextState <= S6;
end
S7: begin
if(five == 1)
nextState <= S8;
else if(ten == 1)
nextState <= S9;
else if(twentyfive == 1)
nextState <= S10;
else
nextState <= S7;
end
S8: begin
if(five == 1)
nextState <= S9;
else if(ten == 1)
nextState <= S10;
else if(twentyfive == 1)
nextState <= S10;
else
nextState <= S8;
end
S9: begin
if(five == 1)
nextState <= S10;
else if(ten == 1)
nextState <= S10;
else if(twentyfive == 1)
nextState <= S10;
else
nextState <= S9;
end
S10: begin
nextState <= S10;
end
endcase
// output logic
always@(state)
case(state)
S0: begin
current = 6'b000000;
dispense = 1'b0;
end
S1: begin
current = 6'b000101;
dispense = 1'b0;
end
S2: begin
current = 6'b001010;
dispense = 1'b0;
end
S3: begin
current = 6'b001111;
dispense = 1'b0;
end
S4: begin
current = 6'b010100;
dispense = 1'b0;
end
S5: begin
current = 6'b011001;
dispense = 1'b0;
end
S6: begin
current = 6'b011110;
dispense = 1'b0;
end
S7: begin
current = 6'b100011;
dispense = 1'b0;
end
S8: begin
current = 6'b101000;
dispense = 1'b0;
end
S9: begin
current = 6'b101101;
dispense = 1'b0;
end
S10: begin
current = 6'b110010;
dispense = 1'b1;
end
endcase
endmodule
和ucf
NET "clk" LOC = "B8";
NET "rst" LOC = "G12";
NET "five" LOC = "A7";
NET "ten" LOC = "M4";
NET "twentyfive" LOC = "C11";
NET "current[5]" LOC = "G1";
NET "current[4]" LOC = "P4";
NET "current[3]" LOC = "N4";
NET "current[2]" LOC = "N5";
NET "current[1]" LOC = "P6";
NET "current[0]" LOC = "P7";
NET "dispense" LOC = "M5";
答案 0 :(得分:2)
您遇到的问题是您假设按下按钮onces结果,机器看到给定按钮被按下一次。但是,你可能正在运行50 Mhz之类的时钟。因此,当您按下按钮甚至半秒钟时,机器会看到按下数百万个循环的按钮(精确到50 Mhz时钟的25000000个循环)。多数时间可以达到你的最终状态,然后是一些。
您需要更改处理输入的方式,方法是向机器添加状态以处理等待按钮重新启动或添加模块以将原始按钮输入转换为脉冲输入。下面是一个在模块中执行后面操作的示例:
module pb_pulse(input btn,
input clk,
output pbPulse);
reg [1:0] btnState;
// If we see a edge now, but didnt 1 cycle ago, pulse
assign pbPulse = btnState[0] & ~btnState[1];
// Shift register storing the btn state now and 1 cycle ago
always @(posedge clk) begin
btnState <= {btnState[0], btn};
end
endmodule
现在,您可以使用pbPulse
输出,就像当前在FSM中使用five
,ten
和twentyfive
一样(即按钮连接到一条线路进入btn
并且其中一个信号连接到pbPulse
,请注意您需要三个这样的模块。)
其他一些注意事项,您不应使用always @(state, five, ten, twentyfive)
(即明确的敏感度列表),而是使用always @(*)
。另外,不要在组合块中使用NBA(<=
)(即,不always @(posedge clk)
),也不要在顺序块中阻塞赋值(=
)(即,{{1} }})。