找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3526|回复: 0
收起左侧

Verilog状态机学习

[复制链接]
ID:105323 发表于 2016-2-23 03:19 | 显示全部楼层 |阅读模式
尽管接触Verilog已经两年多了,但似乎没有很系统地区学习过。一接触的时候就在学习别人写的程序,终于再次拿起书本,发现很多知识点,只是知道而已,却不怎么熟悉。今天学习的一个重点就是状态机。
  

1  有限状态机

  

有限状态机(Finite State Machine,FSM)在数字系统设计中应用十分广泛。根据状态机的输出是否与输入有关,可将状态机分为两大类:摩尔(Moore)型状态机和米莉 (Mealy)型状态机。Moore型状态机的输出仅与现态有关;Mealy型状态机的输出不仅与现态有关,而且和输入也有关。

  

有限状态机一般包括三个部分,其中组合逻辑部分包括状态译码器和输出译码器,状态译码器确定状态机的下一个状态,输出译码器确定状态机的输出,状态寄存器属于时序逻辑部分,用来存储状态机的内部状态。

  

2  好的状态机标准

  

好的状态机的标准很多,最重要的几个方面如下:

  

第一,状态机要安全,是指FSM不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快的恢复到正常的状态循环中来。这里面有两层含义。其一要求该FSM的综合实现结果无毛刺等异常扰动,其二要求FSM要完备,即使受到异常扰动进入非设计状态,也能很快恢复到正常状态。

  

第二,状态机的设计要满足设计的面积和速度的要求。

  

第三,状态机的设计要清晰易懂、易维护。

  

在芯片设计中,对综合结果评判的两个基本标准为:面积和速度。“面积”是指设计所占用的逻辑资源数量;“速度”指设计在芯片上稳定运行所能够达到的最高频率。两者是对立统一的矛盾体,要求一个设计同时具备设计面积最小,运行频率最高,这是不现实的。科学的设计目标应该是:在满足设计时序要求(包含对设计最高频率的要求)的前提下,占用最小的芯片面积,或者在所规定的面积下,使设计的时序余量更大,频率更高。另外,如果要求FSM安全,则很多时候需要使用full case的编码方式,即将状态转移变量的所有向量组合情况都在FSM 中有相应的处理,这经常势必意味着要多花更多的设计资源,有时也会影响FSM的频率所以,上述的标准要综合考虑,根据设计的要求进行权衡。

  

3  状态机描述方法

  

状态机描述时关键是要描述清楚几个状态机的要素,即如何进行状态转移,每个状态的输出是什么,状态转移的条件等。具体描述时方法各种各样,最常见的有三种描述方式:

  

(1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;

  

(2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;

  

(3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

  

一般推荐的FSM 描述方法是后两种。因为FSM和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,状态转移部分是同步时序电路而状态的转移条件的判断是组合逻辑。

  

第二种描述方法同第一种描述方法相比,将同步时序和组合逻辑分别放到不同的always模块中实现,这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在第二种方式的描述中,描述当前状态的输出用组合逻辑实现,组合逻辑很容易产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计。

  

第三种描述方式与第二种相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。

  

4  状态机的编码

  

二进制编码(Binary)、格雷码(Gray-code)编码使用最少的触发器,较多的组合逻辑,而独热码(One-hot)编码反之。独热码编码的最大优势在于状态比较时仅仅需要比较一个位,从而一定程度上简化了比较逻辑,减少了毛刺产生的概率。由于CPLD更多地提供组合逻辑资源,而FPGA更多地提供触发器资源,所以CPLD多使用二进制编码或格雷码,而FPGA多使用独热码编码。另一方面,对于小型设计使用二进制和格雷码编码更有效,而大型状态机使用独热码更高效。

  

5 避免从case语句中综合出锁存器

  

不完整的case语句会生成锁存器。

  

解决方法:

  

(1)在case语句中对变量赋初值。

  

always @ (state or A or B)

  

begin

  

      q=0;

  

      case(state)

  

             s0:  q=A & B;

  

             s1: q=A| B;

  

     endcase

  

end

  

(2)在case语句中增加default语句。

  

always @ (state or A or B)

  

begin

  

      case(state)

  

             s0:  q=A & B;

  

             s1: q=A| B;

  

             default: q=0;

  

     endcase

  

end

  

(3)在case语句中使用full_case综合指令。

  

always @ (state or A or B)

  

begin

  

      case(state) /* synthesis full_case*/

  

             s0:  q=A & B;

  

             s1: q=A| B;

  

     endcase

  

end

  

附加说明:当case语句中的所有选择项是互斥的,为了简化电路,不出现优先级解码逻辑,可以使用 synthesis parallel_case”综合指令,减少不必要的逻辑资源。

  

6 状态机例子

  

设计一个自动饮料售卖机,饮料10分钱,硬币有5分和10分两种,并考虑找零。

  

(1)点路变量分析:投入5分硬币为一个变量,定义为A,为输入;投入10分硬币为一个变量,定义为B,为输入;售货机给出饮料为一变量,定义为Y,为输出;售货机找零为一变量,定义为Z,为输出。

  

(2)状态确定:电路共有两个状态:状态S0,表示未投入任何硬币;状态S1,表示投入了5分硬币。

  

(3)设计过程:设当前为S0状态,当接收到5分硬币时,转换到S1状态,等待继续投入硬币;当接收到10分硬币时,保持S0状态,弹出饮料,不找零。当前状态为S1时,表示已经有5分硬币,若再接收5分硬币,转换到S0状态,弹出饮料,不找零;若接收到10分硬币,转换到S0状态,弹出饮料,找零。

   

  

module machine(clk,rst,A,B,Y,Z);
       input clk,rst,A,B;
       output Y,Z;
       parameter S0=2’b01;
       parameter S1=2’b10;
       reg Y,Z;
       reg [1:0] ns,cs;

      always @ (posedge clk or negedge rst)
      begin
              if(!rst)
                     cs<=2'd0;
              else
                     cs<=ns;
      end

  

always @ (cs,A,B,rst)
       begin
             if(!rst)
             begin
                     ns=2'd0;Y=1'd0;Z=1'd0;
             end
             else
             begin
                    case(cs)
                             S0:  
                             begin
                                     if(A)  //5
                                     begin
                                            ns=S1; Y=1'd0;Z=1'd0;
                                     end
                                     else if(B)  //10
                                     begin
                                            ns=S0;Y=1'd1;Z=1'd0;
                                     end
                                     else
                                     begin
                                           ns=S0;Y=1'd0;Z=1'd0;
                                     end
                           end
                           S1:
                           begin
                                    if(A)  //5
                                    begin
                                           ns=S0; Y=1'd1;Z=1'd0;
                                    end
                                    else if(B)  //10
                                    begin
                                           ns=S0; Y=1'd1;Z=1'd1;
                                    end
                                    else
                                    begin
                                          ns=S1; Y=1'd0;Z=1'd0;
                                    end
                          end
                  endcase
             end
       end

  

endmodule


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表