Состояния на этом компьютере FSM изменяются слишком быстро из-за проблемы с обновлением текущего состояния часов.

Я нахожусь в процессе реализации конечного автомата в Verilog, и я столкнулся с проблемой. Тем не менее, я знаю, в чем проблема, но я не уверен, как это исправить.

Это мой текущий код:

module moore_SM(clk, rstn, btn, z, rstLED, state);

  //Port Assignments
  input clk, rstn;
  input [2:0] btn;
  output  z;
  output reg rstLED;
  output reg [5:0] state;

  //Internal Port Assignments
  reg [1:0] w, x; //NOTE: This is typically the input in FSM, 
                  //but it is internal because there is a conversion from btn to w.
  reg [2:0] y, Y; //Present state and next state respectively
  reg [2:0] pstBtn; 
  reg [31:0] cnt;

  //Define some parameters
      //Input Type (i.e. A, B or C)
      parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10; //DC => don't care - shouldn't affect FSM

      //State (i.e. S1, S2, S3, S4, S5 or S6)
      parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;

  initial begin 
      state = 0;
  end

  //Determine which button is active
  always @(*)
      begin
            case(btn)
                3'b110: begin w = A; end
                3'b101: begin w = B; end
                3'b011: begin w = C; end
            //  default: w = DC;
            endcase
      end

  //Define the next state and output combinational circuits
  always @(w,y)
    begin
        case(y)

            S1: begin
                    state = 6'b000001;
                    if(w == A) begin Y = S2; end
                    else begin Y = S1; end
                 end

            S2: begin
                    state = 6'b000010;
                    if(w == B) begin Y = S3; end
                    else begin if(w == A) begin Y = S2; end
                    else Y = S1; end
                 end

            S3: begin
                    state = 6'b000100;
                    if(w == A) begin Y = S2; end
                    else begin if(w == B) begin Y = S4; end
                    else Y = S1; end 
                 end

            S4: begin
                    state = 6'b001000;
                    if(w == A) begin Y = S5; end
                    else begin Y = S1; end
                 end

            S5: begin
                    state = 6'b010000;
                    if(w == A) begin Y = S2; end
                    else begin if(w == B) begin Y = S3; end
                    else Y = S6; end
                 end

            S6: begin 
                    state = 6'b100000;
                    if(w == A) begin Y = S2; end
                    else begin Y = S1; end
                 end

            //default: Y = 3'b111;

        endcase

      end

    //assign z = (Y == S2);

  //Define the sequential block
  always @(posedge clk)
    begin
        y <= Y;
    end

endmodule

Этот код должен идентифицировать шаблон ABBAC. Я считаю, что логика выполняет эту цель.

Однако я столкнулся с проблемой. Когда я нажимаю одну из трех кнопок, первая всегда блокируется -always @(*) - выполняет и оценивает изменение. Состояние кнопки кодируется и сохраняется вw. В то же время следующий всегда блок -always @(w,y) - чувствует изменение и определяет, в каком состоянии находиться. Как я и ожидал, если я отправлю входAмашина движется отS1 вS2.

Теперь, если я отправлю входB, машина возвращается в состояниеS1, После того, как я изменил несколько вещей вокруг, я определил то, что я считаю проблемой. Обратите внимание на последний всегда блок:always @(posedge clk). Этот блок постоянно обновляет текущее состояние,y. Когда я нажимаю кнопку, я предполагаю, что происходит то, что второй всегда блокирует,always @(w,y), получает обновленныйy на 50 мГц (в моем случае), что, очевидно, намного быстрее, чем я могу нажать и отпустить кнопку. Предполагая, что я нажимаюB кнопка в то время как в состоянииS2состояние быстро меняется наS3 вS4 а затемS1 из-за постоянного обновления.

Тем не менее, у меня возникли некоторые проблемы, связанные с решением этой проблемы. Мне в принципе нужен какой-то способ изменить только одно состояние за нажатие кнопки.

Обратите внимание, что я в основном тестирую этот код на экспериментальной плате. Я написал тестовый стенд, но симуляция, похоже, не соответствует тому, что я вижу на панели дизайна. Если кто-то захочет увидеть код тестового стенда, я разместил его ниже:

`timescale 1ns/1ns
module moore_SM_TB();
    reg clk;
    reg [2:0] btn;
    wire [5:0] state;
    wire z;
    wire rstLED;

  initial begin 
    clk = 1;
    #0 btn = 3'b111;
    #50 btn = 3'b110;
    #50 btn = 3'b111;
    #50 btn = 3'b101;
    #50 btn = 3'b111;
    #50 btn = 3'b011;
    #50 btn = 3'b111;
 end

always begin
  #20 clk = ~clk;    
end

  //MUT
  moore_SM MUT (clk, 0, btn, z, rstLED, state);

endmodule

ПРИМЕЧАНИЕ: я считаю, что решение в конечном итоге будет включать изменение способа обработки кнопок. Когда я отпускаю кнопку, это также регистрируется как изменение. Следовательно, я должен был закомментировать случай по умолчанию, потому что это также испортило бы, в каком состоянии находится машина.

ОБНОВЛЕНИЕ: я написал сокращенную версию FSM, которую я разместил выше, чтобы попытаться отладить код. Он пытается обнаружить последовательность AB.

module moore_SM(clk, btn, rstN, state, rstLED);
//Port assignments
input clk;
input rstN;
input [2:0] btn;
output reg rstLED;
output reg [5:0] state;

//Internal Port Assignments
reg [1:0] w;
reg [2:0] y, Y;
reg [2:0] pstBtn;

//Define some parameters
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b11, DC = 2'b10;
parameter [2:0] S1 = 3'b000, S2 = 3'b001, S3 = 3'b010, S4 = 3'b011, S5 = 3'b100, S6 = 3'b101;

//Initialize some values to prevent Quartus from doing
initial 
    begin
        y = S1;
        Y = y;
        state = 0;
        rstLED = 0;
    end

always @(*)
    begin

        if(btn == pstBtn) begin w = DC; end

        else begin
            case(btn)
                3'b110: w = A;
                3'b101: w = B;
                3'b011: w = C;
                default: w = DC;
            endcase
        end

    end

always @(*)
    begin
        case(y)
            S1: begin
                    state = 6'b000001;
                    if(w == A) begin Y = S2; end
                    else begin Y = S1; end
                 end

            S2: begin
                    state = 6'b000010;
                    if(w == B) begin Y = S3; end
                    if(w == DC) begin Y = S2; end
                    else begin Y = S1; end
                 end

            S3: begin
                    state = 6'b000100;
                    if(w == DC) begin Y = S3; end
                    else begin Y = S1; end
                 end
            default: begin state = 6'b100000; Y = S1; end
        endcase
    end



//Update state and check for reset signal
always @(posedge clk, negedge rstN)
    begin
        pstBtn <= btn;

        if(rstN == 0) begin y <= S1; rstLED <= 1; end
        else begin y <= Y; rstLED <= 0; end
    end

endmodule

Обратите внимание, что я пытаюсь «сэмплировать» состояние кнопки в последнем блоке всегда. Я использовал этот метод в прошлом, но, похоже, он здесь не работает. Всякий раз, когда я нажимаю кнопку, состояние не меняется. Мне интересно, если это проблема времени сейчас.

Ответы на вопрос(1)

Ваш ответ на вопрос