状态变化太快,我在basys-2中使用按钮

时间:2015-11-26 17:47:46

标签: verilog fsm

我在模拟自动售水机。现在,我们在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";

1 个答案:

答案 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中使用fivetentwentyfive一样(即按钮连接到一条线路进入btn并且其中一个信号连接到pbPulse,请注意您需要三个这样的模块。)

其他一些注意事项,您不应使用always @(state, five, ten, twentyfive)(即明确的敏感度列表),而是使用always @(*)。另外,不要在组合块中使用NBA(<=)(即,不always @(posedge clk)),也不要在顺序块中阻塞赋值(=)(即,{{1} }})。