FSM (машина Мура) verilog

когда мы пишем конечный автомат в Verilog, есть два способа записать конечный автомат: сначала использовать 3 всегда блок (1 для комбинационной логики следующего состояния + 1 для последовательной логики presene-> следующего состояния + 1 для выходной логики), а второй способ - использовать только один всегда блокируется для всех трех операций, но моя выходная волна для обоих случаев разная .. почему это так?

например, я закодировал простой fsm обоими способами, и мой выход сдвинут на 20 единиц времени

первый способ:

//using one alwys block
module moore_20_1(x_in,y_out,clk,reset);
input wire clk,reset,x_in;
output reg y_out;

reg [1:0] state;

parameter start=2'b00,s0=2'b01,s1=2'b10,s2=2'b11;

always @ (posedge clk)//next state logic + ps->ns logic + output logic
begin
  if(reset==1'b1) begin
    state<=start;
    y_out<=0;
  end
else begin
  case(state)
    start: begin if(x_in) state<=s0;
          else state<=s0;
            y_out<=0;
          end
    s0: begin if(x_in) state<=s1;
      else state<=s0;
      y_out<=0;
    end
    s1: begin if(x_in) state<=s2;
      else state<=s1 ;         
      y_out<=0;
    end
    s2: begin if(x_in) state<=s0;
      else state<=s2;
      y_out<=1;
    end
    endcase


end
end
endmodule

второй способ

    //moore machine using 3 always block(ps->ns+output logic+next-sate logic)
module moore_5_20_2(x_in,y_out,clk,reset);
input wire clk,reset,x_in;
output reg y_out;

reg [1:0] state;
reg [1:0] next_state; 

parameter start=2'b00,s0=2'b01,s1=2'b10,s2=2'b11;

//ps->ns logic
always@ (posedge(clk))
if(reset==1'b1) 
  next_state<= #1 start;
else
  next_state<= #1 state;


//next-stae logic  
always @(next_state,x_in)
case(next_state)
  start: begin if(x_in) state<=s0;
          else state=s0;
          end
    s0: begin if(x_in) state<=s1;
      else state=s0;
    end
    s1: begin if(x_in) state<=s2;
      else state=s1 ;         
    end
    s2: begin if(x_in) state<=s0;
      else state=s2;
    end
    endcase

//OUTPUT LOGIc

always@(next_state)
if (reset==1'b1) y_out<= 0;
else begin 
    case(next_state)
      start:y_out<= 0;
      s0: y_out<=   0;
      s1: y_out<=0;
      s2: y_out<=#1 1;

    endcase
  end
endmodule

почему вывод сдвинут на 20 единиц ..?


person user3091069    schedule 22.07.2014    source источник
comment
Почему вы назначаете next_state <= state на позе? Обычно все наоборот, next_state комбинаторно управляется состоянием и входами, а затем posedge state <= next_state.   -  person Tim    schedule 22.07.2014
comment
это просто имена рег ... для удобства я использую его ... но вся моя логика построена только на этих именах ...! :)   -  person user3091069    schedule 22.07.2014
comment
Да, вероятно, это не источник проблемы, но простой взгляд на этот код, вероятно, сбивает с толку большинство людей, имеющих опыт работы с конечными автоматами, поскольку имена как бы перевернуты. Вы смотрели формы сигналов ваших двух конечных автоматов? Было бы полезно показать волновые сравнения в вашем вопросе о состоянии и выходах.   -  person Tim    schedule 23.07.2014


Ответы (1)


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

initial begin 
  clk = 0; 
  forever #10 clk = ~clk; 
end

И я также предполагаю, что второй способ на 20 (или, может быть, 19?) Единиц времени опережает первый способ, исходя из того, что, по моему мнению, идет не так.

По сути, первый способ - это буферизация вывода y_out в регистре, а второй способ - установка y_out комбинационным образом.

Поскольку это машина Мура (которой являются обе эти реализации), вывод зависит только от текущего состояния. В первом случае на фронте тактового сигнала y_out устанавливается значение, основанное на «текущем» состоянии (то есть, в каком состоянии находится момент прямо перед фронтом тактового сигнала). Хотя состояние может также измениться на фронте тактового сигнала, этого не произойдет до тех пор, пока не будет определено следующее значение y_out для этого тактового цикла. Это означает, что в одном тактовом цикле y_out будет установлен на основе того, какое состояние было в предыдущем цикле, и останется таким до следующего фронта тактового сигнала.

Во втором случае y_out устанавливается комбинационно, а не по фронту тактового сигнала. В этом случае логика следующего состояния определит state, и когда наступит фронт часов, next_state станет state (по какой-то причине через 1 единицу времени ....). Таким образом, теперь комбинационный блок, который определяет выход y_out, проснется и установит y_out на любое значение для этого состояния. Следовательно, y_out примет выход для текущего состояния, состояния для этого тактового цикла, а не для предыдущего тактового цикла, как в первом способе.

Например, предположим, что мы находимся в состоянии s1 и заявлено x_in. Таким образом, по второму пути state все готово к s2 в рамках подготовки к переходу. Наступает край часов.

В первом случае просыпается блокировка всегда. reset не утверждается так в заявлении case. Мы находимся в s1, и x_in заявлено, поэтому state станет s2, а y_out будет установлен в 0. Готово до следующего фронта тактового сигнала. Таким образом, это будет выглядеть так, как будто мы находимся в s2, а y_out равен 0, до следующего фронта тактового сигнала, когда время y_out станет 1.

Во втором случае регистр состояния всегда блокируется, и next_state становится s2 через 1 единицу времени. Как только next_state становится s2, логика вывода всегда блокируется для y_out, и теперь next_state равно s2, поэтому y_out станет 1 сейчас (или снова через 1 единицу времени?). Таким образом, это будет выглядеть так, как будто мы находимся в s2, а y_out равно 1 (примерно), что примерно на 20 единиц времени впереди.

ПРИМЕЧАНИЕ: Большая часть путаницы, связанной с этим (частично, как упомянул Тим), не является особенно хорошим стилем. Я предпочитаю второй способ, но то, как вы его реализовали, несколько неидеально. Вот предлагаемая переписать для справок в будущем (хотя я тоже позволил себе некоторые упрощения):

module nice_moore_machine(
  input wire clock, reset, x_in,
  output reg y_out);

reg [1:0] state, next_state;

parameter start = 2'b00, s0 = 2'b01, s1 = 2'b10, s2 = 2'b11;

/* State register (synchronous reset) */
always @(posedge clk) begin
  if (reset) begin
    state <= start;
  end
  else begin
    state <= next_state;
  end
end

/* Next state logic */
always @(*) begin
  case (state)
    start: begin
      next_state = s0;
    end
    s0: begin
      next_state = (x_in) ? s1 : s0;
    end
    s1: begin
      next_state = (x_in) ? s2 : s1;
    end
    s2: begin
      next_state = (x_in) ? s0 : s2;
    end
  endcase
end

/* Output logic */
always @(*) begin
  y_out = (state == s2); /* Note that y_out could be a net and use an assign in this case */
end

endmodule

Надеюсь, это поможет вам лучше понять!

person Unn    schedule 31.07.2014
comment
так как мы должны писать FSM первым или вторым способом ..? - person user3091069; 24.08.2014