【问题标题】:Weird Behavior of A Very Simple FSM一个非常简单的 FSM 的奇怪行为
【发布时间】:2018-04-02 14:07:20
【问题描述】:

我正在尝试使用 EDA Playground 学习 Verilog。我正在尝试通过结合下一个状态和输出逻辑来重写示例中的摩尔机器:http://www.edaplayground.com/x/B

这是我所做的:

    /*
 * Finite state machine.Moore Machine
 * If input 'a' is asserted, the state machine
 * moves IDLE->STATE_1->FINAL and remains in FINAL.
 * If 'a' is not asserted, FSM returns to idle.
 * Output 'out1' asserts when state machine is in
 * STATE_1. 'out2' asserts when state machine is in
 * FINAL state.
 */ 
module fsm(clk, reset, a, out1, out2);
  input  clk;
  input  a;
  input reset;
  output out1, out2;
  // State encodings
  parameter [2:0]
    IDLE    = 3'b001,
    STATE_1 = 3'b010,
    FINAL   = 3'b100;  
  reg [2:0] /* synopsys enum states */ current_state, next_state;
// synopsys state_vector current_state
reg out1, out2;
  /*------- Sequential Logic ----*/
always@(posedge clk or negedge reset)
  if (!reset) current_state <= IDLE;
    else current_state <= next_state;
/* next state logic and output logic – combined so as to share state decode logic */
  always @(posedge clk or negedge reset) 
    begin
      out1 = 0; out2 = 0;
      case (current_state)
        IDLE:
          begin
            if (a) 
              begin out1= 1; out2=0; next_state <= STATE_1; end  
            else  
              begin out1= 0; out2=0;next_state <= IDLE;      end 
          end
        STATE_1:
          begin
            if (a) 
              begin out1= 0; out2=1;next_state <= FINAL;    end
            else 
               begin out1= 0; out2=0;next_state <= IDLE; end
          end
        FINAL:
          begin
            if (a) 
             begin out1= 0; out2=1;next_state <= FINAL; end 
            else 
              begin  out1= 0; out2=0;next_state <= IDLE;end
          end
        default:
          begin out1= 0; out2=0; next_state <= IDLE;end
      endcase
    end

endmodule

但是,结果不正确,我得到了

# KERNEL: ASDB file was created in location /home/runner/dataset.asdb
run -all;
# KERNEL: Initial a: 0,out1: x, out2: x
# KERNEL: IDLE a: 0 ,out1: 0, out2: 0
# KERNEL: STATE_1 a: 1 ,out1: 1, out2: 0
# KERNEL: FINAL a: 1 ,out1: 1, out2: 0
# KERNEL: FINAL a: 1,out1: 1, out2: 0
# KERNEL: IDLE a: 0 ,out1: 0, out2: 0
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit

但是,预期的结果应该是:

run -all;
# KERNEL: Initial a: 0,out1: x, out2: x
# KERNEL: IDLE a: 0 ,out1: 0, out2: 0
# KERNEL: STATE_1 a: 1 ,out1: 1, out2: 0
# KERNEL: FINAL a: 1 ,out1: 0, out2: 1
# KERNEL: FINAL a: 1,out1: 0, out2: 1
# KERNEL: IDLE a: 0 ,out1: 0, out2: 0
# KERNEL: Simulation has finished. There are no more test vectors to simulate.

请问我做错了什么?

这是测试夹具:

// Testbench
module test;

  reg  clk, reset, a;
  wire out1, out2;

  // Instantiate device under test
  fsm FSM(.clk(clk),.reset(reset),
          .a(a),
          .out1(out1),
          .out2(out2));

  initial begin
    // Dump waves
    $dumpfile("dump.vcd");
    $dumpvars(1, test);

    clk = 0;
    reset = 1;
    a = 0;
    $display("Initial a: %0h,out1: %0h, out2: %0h",
      a,out1, out2);

    toggle_clk;
    $display("IDLE a: %0h ,out1: %0h, out2: %0h",
     a, out1, out2);

    a = 1;
    toggle_clk;
    $display("STATE_1 a: %0h ,out1: %0h, out2: %0h",
      a,out1, out2);

    toggle_clk;
    $display("FINAL a: %0h ,out1: %0h, out2: %0h",
      a,out1, out2);

    toggle_clk;
    $display("FINAL a: %0h,out1: %0h, out2: %0h",
      a,out1, out2);

    a = 0;
    toggle_clk;
    $display("IDLE a: %0h ,out1: %0h, out2: %0h",
      a,out1, out2);
  end

  task toggle_clk;
    begin
      #10 clk = ~clk;
      #10 clk = ~clk;
    end
  endtask

endmodule

非常感谢您,

CS

【问题讨论】:

  • 提示:next_state 应该是在带有阻塞 (=) 分配的 always @* 中分配的组合逻辑。
  • 非常感谢 Greg 提供的非常有用的提示。哟是绝对正确的。我必须在敏感度列表中添加一个。

标签: verilog fsm


【解决方案1】:

我试图在 Verilog 95 中实现 Mealy 机器,但是,我的敏感度列表不完整。也非常感谢 Greg 的帮助。

   /*
 * Finite state machine.Moore Machine
 * If input 'a' is asserted, the state machine
 * moves IDLE->STATE_1->FINAL and remains in FINAL.
 * If 'a' is not asserted, FSM returns to idle.
 * Output 'out1' asserts when state machine is in
 * STATE_1. 'out2' asserts when state machine is in
 * FINAL state.
 */ 
module fsm(clk, reset, a, out1, out2);
  input  clk;
  input  a;
  input reset;
  output out1, out2;
  // State encodings
  parameter [2:0]
    IDLE    = 3'b001,
    STATE_1 = 3'b010,
    FINAL   = 3'b100;  
  reg [2:0] /* synopsys enum states */ current_state, next_state;
// synopsys state_vector current_state
reg out1, out2;
  /*------- Sequential Logic ----*/
always@(posedge clk or negedge reset)
  if (!reset) current_state <= IDLE;
    else current_state <= next_state;
/* next state logic and output logic – combined so as to share state decode logic */
  always @(posedge clk or negedge reset or a) 
    begin
      out1 = 0; out2 = 0;
      case (current_state)
        IDLE:
          begin
            if (a) 
              begin out1= 1; out2=0; next_state = STATE_1; end  
            else  
              begin out1= 0; out2=0;next_state = IDLE;      end 
          end
        STATE_1:
          begin
            if (a) 
              begin out1= 0; out2=1;next_state = FINAL;    end
            else 
               begin out1= 0; out2=0;next_state = IDLE; end
          end
        FINAL:
          begin
            if (a) 
             begin out1= 0; out2=1;next_state = FINAL; end 
            else 
              begin  out1= 0; out2=0;next_state = IDLE;end
          end
        default:
          begin out1= 0; out2=0; next_state = IDLE;end
      endcase
    end

endmodule

【讨论】:

  • 那仍然是错误的敏感度列表。组合逻辑不应对时钟或任何posedge/negedge 信号敏感。对于 Verilog-95,它应该是 always @(current_state or a)。对于 Verilog-2001 及更高版本,请使用 always @* 或同义词 always @(*)
  • 你是绝对正确的。再一次非常感谢你。我会在接下来的努力中考虑到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 2020-01-10
  • 2016-03-13
  • 2011-03-01
  • 2013-12-14
  • 2020-12-02
相关资源
最近更新 更多