• (转帖) 有限狀態機FSM coding style整理 (SOC) (Verilog)


    来源:http://www.codesoso.net/Record/101092_95120_21.html

    来源:http://www.cnblogs.com/oomusou/archive/2011/06/05/fsm_coding_style.html

    Moore FSM架构

    一般在写FSM时,会以Moore FSM为主,所以先讨论Moore。由上图可知,Moore FSM内部由3个block所构成:Next state logic,State register与Output logic。

    Next state logic:纯粹的组合逻辑,以整个module的input与目前的state为输入,目的在产生下一个state值存入state register。

    State register:由D-FF所构成,将Next state logic所产生的state存入register。

    Output logic:纯粹的组合逻辑,根据目前的state产生整个module的output。

    所以可以发现,整个Moore FSM事实上是由2块的组合逻辑与1块D-FF所构成,我们常听到所谓的一段式、二段式与三段式FSM,事实上就是由这3个block排列组合而成。

    Moore FSM各种coding style比较

     Moore FSM各种coding style比较

    为了要实际比较各种coding style,在此举一个简单的例子,若input w_i为连续2个clk为high,则output会在下1个clk产生周期为1 T的high pulse,timing diagram如下图所示。

    因此设计了Moore FSM,state diagram如上图所示,接下来要做的就是用各种coding style来实现这个Moore FSM。

    simple_fsm_moore_3_always_best.v / Verilog

     1 /* 
     2 (C) OOMusou 2011 http://oomusou.cnblogs.com
     3 
     4 Filename    : simple_fsm_moore_3_always_best.v
     5 Synthesizer : Quartus II 8.1
     6 Description : 3 always block for moore fsm (BEST)
     7 Release     : Jun.05,2011 1.0
     8 */
     9 
    10 module simple_fsm (
    11   clk,
    12   rst_n,
    13   w_i,
    14   z_o
    15 );
    16 
    17 input  clk;
    18 input  rst_n;
    19 input  w_i;
    20 output z_o;
    21 
    22 parameter IDLE = 2'b00;
    23 parameter S0   = 2'b01;
    24 parameter S1   = 2'b10;
    25 
    26 reg [1:0] curr_state;
    27 reg [1:0] next_state;
    28 reg z_o;
    29 
    30 // state reg
    31 always@(posedge clk or negedge rst_n)
    32   if (~rst_n) curr_state <= IDLE;
    33   else        curr_state <= next_state;
    34     
    35 // next state logic    
    36 always@(*)
    37   case (curr_state)
    38     IDLE    : if (w_i) next_state = S0;
    39               else     next_state = IDLE;
    40     S0      : if (w_i) next_state = S1;
    41               else     next_state = IDLE;
    42     S1      : if (w_i) next_state = S1;
    43               else     next_state = IDLE;
    44     default :          next_state = IDLE;
    45   endcase    
    46 
    47 // output logic
    48 always@(*)
    49   case (curr_state)
    50     IDLE    : z_o = 1'b0;
    51     S0      : z_o = 1'b0;
    52     S1      : z_o = 1'b1;
    53     default : z_o = 1'b0;
    54   endcase
    55   
    56 endmodule

    個always是一個推薦的寫法。

    Testbench

    simple_fsm_tb.v / Verilog

     1 /* 
     2 (C) OOMusou 2011 http://oomusou.cnblogs.com
     3 
     4 Filename : simple_fsm_tb.v
     5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9
     6 Description : testbench for FSM
     7 Release : Jun.05,2011 1.0
     8  */
     9 
    10  module simple_fsm_tb;
    11 
    12  reg clk = 1'b1;
    13  reg rst_n = 1'b1;
    14  reg w_i = 1'b0;
    15  wire z_o;
    16 
    17  // clk
    18  always #10 clk = ~clk;
    19 
    20  event after_rst;
    21 
    22  // rst_n
    23  initial begin
    24   #6; // 6ns
    25   rst_n = 1'b0;
    26   #30; // 36ns
    27   rst_n = 1'b1;
    28   ->after_rst; 
    29  end
    30 
    31  // w_i
    32  initial begin
    33   @(after_rst);
    34   repeat(2)@(posedge clk); // 60ns
    35   w_i <= 1'b1;
    36   @(posedge clk); // 80 ns
    37   w_i <= 1'b0;
    38   @(posedge clk); // 100 ns
    39   w_i <= 1'b1;
    40   repeat(2)@(posedge clk); // 140 ns
    41   w_i <= 1'b0;
    42   @(posedge clk); // 160 ns
    43   w_i <= 1'b1;
    44   repeat(3)@(posedge clk); // 220 ns
    45   w_i <= 1'b0;
    46 end
    47 
    48 initial begin
    49   $fsdbDumpfile("simple_fsm.fsdb");
    50   $fsdbDumpvars(0, simple_fsm_tb);
    51 end
    52 
    53 simple_fsm u_simple_fsm (
    54   .clk (clk),
    55   .rst_n (rst_n),
    56   .w_i (w_i),
    57   .z_o (z_o)
    58 );
    59 
    60 endmodule

     

     1 /* 
     2 (C) OOMusou 2011 http://oomusou.cnblogs.com
     3 
     4 Filename    : simple_fsm_moore_3_always_best.v
     5 Synthesizer : Quartus II 8.1
     6 Description : 3 always block for moore fsm (BEST)
     7 Release     : Jun.05,2011 1.0
     8 */
     9 
    10 module simple_fsm (
    11   clk,
    12   rst_n,
    13   w_i,
    14   z_o
    15 );
    16 
    17 input  clk;
    18 input  rst_n;
    19 input  w_i;
    20 output z_o;
    21 
    22 parameter IDLE = 2'b00;
    23 parameter S0   = 2'b01;
    24 parameter S1   = 2'b10;
    25 
    26 reg [1:0] curr_state;
    27 reg [1:0] next_state;
    28 reg z_o;
    29 
    30 // state reg
    31 always@(posedge clk or negedge rst_n)
    32   if (~rst_n) curr_state <= IDLE;
    33   else        curr_state <= next_state;
    34     
    35 // next state logic    
    36 always@(*)
    37   case (curr_state)
    38     IDLE    : if (w_i) next_state = S0;
    39               else     next_state = IDLE;
    40     S0      : if (w_i) next_state = S1;
    41               else     next_state = IDLE;
    42     S1      : if (w_i) next_state = S1;
    43               else     next_state = IDLE;
    44     default :          next_state = IDLE;
    45   endcase    
    46 
    47 // output logic
    48 always@(*)
    49   case (curr_state)
    50     IDLE    : z_o = 1'b0;
    51     S0      : z_o = 1'b0;
    52     S1      : z_o = 1'b1;
    53     default : z_o = 1'b0;
    54   endcase
    55   
    56 endmodule

    simple_fsm_moore_3_always_best.v / Verilog

     1 /* 
     2 (C) OOMusou 2011 http://oomusou.cnblogs.com
     3 
     4 Filename : simple_fsm_tb.v
     5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9
     6 Description : testbench for FSM
     7 Release : Jun.05,2011 1.0
     8  */
     9 
    10  module simple_fsm_tb;
    11 
    12  reg clk = 1'b1;
    13  reg rst_n = 1'b1;
    14  reg w_i = 1'b0;
    15  wire z_o;
    16 
    17  // clk
    18  always #10 clk = ~clk;
    19 
    20  event after_rst;
    21 
    22  // rst_n
    23  initial begin
    24   #6; // 6ns
    25   rst_n = 1'b0;
    26   #30; // 36ns
    27   rst_n = 1'b1;
    28   ->after_rst; 
    29  end
    30 
    31  // w_i
    32  initial begin
    33   @(after_rst);
    34   repeat(2)@(posedge clk); // 60ns
    35   w_i <= 1'b1;
    36   @(posedge clk); // 80 ns
    37   w_i <= 1'b0;
    38   @(posedge clk); // 100 ns
    39   w_i <= 1'b1;
    40   repeat(2)@(posedge clk); // 140 ns
    41   w_i <= 1'b0;
    42   @(posedge clk); // 160 ns
    43   w_i <= 1'b1;
    44   repeat(3)@(posedge clk); // 220 ns
    45   w_i <= 1'b0;
    46 end
    47 
    48 initial begin
    49   $fsdbDumpfile("simple_fsm.fsdb");
    50   $fsdbDumpvars(0, simple_fsm_tb);
    51 end
    52 
    53 simple_fsm u_simple_fsm (
    54   .clk (clk),
    55   .rst_n (rst_n),
    56   .w_i (w_i),
    57   .z_o (z_o)
    58 );
    59 
    60 endmodule
    Testbench

    1.使用3always (三段式)

    使用1个always描述state register,因为是D-FF且含clk,所以使用nonblocking。

    由于state register区块并不包含任何逻辑,所以不会因为不同FSM而有不同写法,不同FSM只会改变next state logic与output logic的写法。

    使用1个always描述output logic,因为是纯粹组合逻辑,所以使用blocking。

    根据Moore FSM架构图所示,output logic的结果只与目前state有关,所以只需用case对state做一次分类即可。

    使用3个always写法有几个优点:

    1.可忠实地反映出原本的Moore FSM硬件架构
    2.可轻易地将state diagram改用Verilog表示
    3.将Next state logic与output logic分开,可降低code的复杂度,便于日后维护。

    Mealy FSM架构

    谈完了Moore FSM,接下来谈Mealy FSM,与Moore FSM的差别只在于Moore FSM的output logic只由目前state决定,但是Mealy FSM可由目前state与input共同决定。

    将之前的例子用Mealy FSM重新改写,原本在Moore FSM下,若input w_i为连续2个clk为high,则output会在下1个clk产生周期为1 T的high pulse,若改用Mealy FSM,则output会提早1个clk出现,如下图所示。

    原本Moore FSM需要3个state,若改用Mealy FSM后,会只剩下2个state,接下来要用各种coding style来实现Mealy FSM。

    1.使用3always (三段式)

    simple_fsm_mealy_3_always_best.v / Verilog

    之前提到使用Mealy FSM会少Moore FSM 1个state,且output会早Moore FSM 1个clk,所以最后特别将output在敲一级delay 1个clk,这样Mealy FSM就会完全与Moore FSM一样。

    使用3个always写法有几个优点:

    1.可忠实地反映出原本的Mealy FSM硬件架构
    2.可轻易地将state diagram改用Verilog表示
    3.将Next state logic与output logic分开,可降低code的复杂度,便于日后维护

     1 /* 
     2 (C) OOMusou 2011 http://oomusou.cnblogs.com
     3 
     4 Filename    : simple_fsm_mealy_3_always_best.v
     5 Synthesizer : Quartus II 8.1
     6 Description : 3 always block for mealy fsm (BEST)
     7 Release     : Jun.05,2011 1.0
     8 */
     9 
    10 module simple_fsm (
    11   clk,
    12   rst_n,
    13   w_i,
    14   z_o
    15 );
    16 
    17 input  clk;
    18 input  rst_n;
    19 input  w_i;
    20 output z_o;
    21 
    22 parameter IDLE = 2'b00;
    23 parameter S0   = 2'b01;
    24 
    25 reg [1:0] curr_state;
    26 reg [1:0] next_state;
    27 reg z;
    28 reg z_o;
    29 
    30 // state reg
    31 always@(posedge clk or negedge rst_n)
    32   if (~rst_n) curr_state <= IDLE;
    33   else        curr_state <= next_state;
    34     
    35 // next state logic    
    36 always@(*)
    37   case (curr_state)
    38     IDLE    : if (w_i) next_state = S0;
    39               else     next_state = IDLE;
    40     S0      : if (w_i) next_state = S0;
    41               else     next_state = IDLE;
    42     default :          next_state = IDLE;
    43   endcase    
    44 
    45 // output logic
    46 always@(*)
    47   case (curr_state)
    48     IDLE    : if (w_i) z = 1'b0;
    49               else     z = 1'b0;      
    50     S0      : if (w_i) z = 1'b1;
    51               else     z = 1'b0;
    52     default :          z = 1'b0;
    53   endcase
    54 
    55 // mealy output to delay 1 clk for moore  
    56 always@(posedge clk or negedge rst_n)
    57   if (~rst_n) z_o <= 1'b0;
    58   else        z_o <= z;
    59     
    60 endmodule
    simple_fsm_mealy_3_always_best.v / Verilog

    Conclusion
    1.3个always与2个always (state register与next state logic合一)是两种推荐的写法,而且这两种写法无论要描述Moore FSM或者Mealy FSM都没问题,其他写法都不推荐,个人是比较喜欢2个always写法(state register + next state logic),因为这种写法最精简,各种需求都可描述,也不用担心是否要提前一个clk判断,最为直觉不易错。

    2.实务上不会特别拘泥使用Moore或者Mealy,只要符合需求即可,一般会以Moore FSM为正宗。

    3.实务上为了timing更好,会在Moore FSM的output logic多敲一级。

    4.Mealy会比Moore少1个state,且output会比Moore早1个clk。

    5.Moore与Mealy之间可以互换,只要在Mealy的output多敲一级即可。

  • 相关阅读:
    2.舵机
    1.呼吸灯
    Python学习笔记——Matplot库
    计算机仿真技术学习笔记(一)
    48、从堆和栈上建立对象哪个快?(考察堆和栈的分配效率比较)
    47、抖动你知道是什么吗?它也叫颠簸现象
    46、交换空间与虚拟内存的关系
    44、程序从堆中动态分配内存时,虚拟内存上怎么操作的
    43、一般情况下在Linux/windows平台下栈空间的大小
    42、一个由C/C++编译的程序占用的内存分为哪几个部分?
  • 原文地址:https://www.cnblogs.com/zlh840/p/3460908.html
Copyright © 2020-2023  润新知