Verilog有限状态机

时间:2012-09-24 17:44:35

标签: verilog hdl

我正在尝试在verilog中创建一个有限状态机。系统有4个1-bit 输入 rstclkAB和一个输出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 个答案:

答案 0 :(得分:1)

您可以使用以下工具:

GHDL是VHDL语言的开源模拟器(User Guide

此外,这些是最受欢迎的模拟工具

更多资源:

还有stackexchange electronics社区和codereview

另外,请注意C to HDL编译器工具

(..我怀疑很多人可以在3分钟内检查你的代码,我也不想要它们)

答案 1 :(得分:0)

你没有下一个状态逻辑,所以状态永远不会改变,并且没有复位所以状态将从1'bz开始。我建议在编码状态机时从Xilinx guidelines开始。

答案 2 :(得分:0)

你对触发器的定义有点不对劲。你有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