Verilog Finite State Machine

Я пытаюсь создать конечный автомат в Verilog. В системе 4 1-bit входные rst, clk, A, B и один выход, Z,

Z равно 1, если либо: A имел одинаковое значение на последних двух фронтах тактового сигнала.

или B был высоким (1) на каждом фронте тактового сигнала с момента последнего правила.

Иначе z=0;

У меня нет инструментов для имитации моих попыток. Так что мне интересно, если это правильный метод и я на правильном пути?

module StateMachine( R, A, B, clk, Z);
   input R, A, B, clk;
   output reg Z;

   reg ATemp;
   reg state;

   always @ (posedge clk or A)
      if (A == 1'b1) 
      /////////////////
      begin
         if (ATemp == 1'b1) state <= 1'b1; 
         else ATemp <= A;
       end
       ////////////////
       else
       ////////////
       begin
          if (ATemp == 1'b0) state <= 1'b1;
          else ATemp <= A;
       end


   always @ (state)
      case(state)
         1'b0: Z=0;
         1'b1: Z=1;

         default: Z=0;
      endcase

endmodule

3 ответа

Решение

Вы можете использовать следующие инструменты:

GHDL - это симулятор с открытым исходным кодом для языка VHDL ( Руководство пользователя)

Кроме того, это самые популярные инструменты моделирования:

Другие ресурсы:

Существует также сообщество электроники stackexchange и codereview.

Кроме того, обратите внимание на инструмент компилятора C to HDL

(.. Я сомневаюсь, что многие могут просмотреть ваш код за 3 минуты, и я бы тоже их не хотел)

Ваше определение триггера немного неверно. У тебя есть always @ (posedge clk or A), Вы не должны комбинировать триггеры края и не-триггеры края. Это может работать в симуляции, но вы не получите то, что вы хотите в синтезе.

Если вы хотите, чтобы значение изменялось только по фронту тактовой частоты, используйте always @( posedge clk) или для комбинаторного ввода, то есть выход изменяется с использованием ввода always @( A ) или более современная версия always @*, @* сработает для любых изменений. Пропущенные элементы из списка чувствительности используются в качестве основной причины для синтезированного кода, не имитирующего то же самое, что RTL.

Сказав, что если вы строите триггер, вы должны включить сброс. always @ (posedge clk or negedge rst_n)

Также обратите внимание, что состояние никогда не устанавливается на 0, поэтому первое впечатление состоит в том, что это будет привязано к определенному состоянию / выходу. Мне трудно понять, как код реализует заданный вопрос. Мое решение будет что-то вроде:

module statemachine(
  input      rst,
  input      A,
  input      B,
  input      clk,
  output reg Z
);

  reg  [1:0] a_last_two;
  wire      rule_one;

  always @ (posedge clk or negedge rst) begin
    if (~rst) begin
      a_last_two <= 2'b0;
    end
    else begin
      a_last_two <= {a_last_two[0] ,A}; 
    end
  end

  assign rule_one = (a_last_two[1] == a_last_two[0]); 
  //rule one could be written as ~^a_last_two (xnor reduction operator)

  reg rule_two;
  always @ (posedge clk or negedge rst) begin
    if (~rst) begin
      rule_two <= 1'b0 ;
    end
    else begin
      //rule 2 resets when rule_one is true
      if (rule_one) begin
        rule_two <= 1'b1 ;
      end
      else begin
        rule_two <= rule_two & B ;
      end
    end
  end

  assign Z = rule_one | rule_two ;

endmodule

У вас нет логики следующего состояния, поэтому состояние никогда не изменится, и нет сброса, поэтому состояние будет начинаться с 1'bz. Я рекомендую начинать с рекомендаций Xilinx при кодировании конечных автоматов.

Другие вопросы по тегам