tag 标签: 一段式,两段式,三段式状态机

相关博文
  • 热度 15
    2016-4-17 16:54
    771 次阅读|
    0 个评论
      本次笔记我们使用"电子男特有的方式向我们最亲爱的人说一句"I LOVE YOU"."为例,分别比较一下 一段式,两段式,三段式状态机的区别         有限状态机(finite statemachine,FSM)广泛应用于数字系统的控制器设计中.由于设计方法不同,综合出来的电路结构、速度、面积和时延特性都会有很大的差别, 甚至某些臃肿的电路还会产生难以预料的问题.      1.“一段式”   特点:将当前状态向量和输出向量用同一时序always块进行描述。  缺点:代码冗长,不易修改和调试,可维护性较差且占用资源多;通过case语句对输出向量的赋值应是下一个状态的输出,这点容易出错;状态向量和输出向量都是由寄存器逻辑实现,面积较大;不能实现异步mealy有限状态机。  优点:寄存器输出,输出向量不会产生毛刺。  结构: 例程: module FSM( clk, rst_n, data_cap,// data_low, out_flow ); input clk,rst_n; input  data_cap,data_low;//大写,小写字母数据流 output reg  out_flow; reg  state; localparam //独热码 CHECK_I  = 8'b0000_0001, CHECK_L  = 8'b0000_0010, CHECK_o1 = 8'b0000_0100, CHECK_v  = 8'b0000_1000, CHECK_e  = 8'b0001_0000, CHECK_Y  = 8'b0010_0000, CHECK_o2 = 8'b0100_0000, CHECK_u  = 8'b1000_0000; always @(posedge clk or negedge rst_n) if(!rst_n)begin out_flow = 0; state = CHECK_I; end else begin case(state) CHECK_I : if(data_cap == "I")begin state = CHECK_L; out_flow = data_cap; end else state = CHECK_I; CHECK_L : if(data_cap == "L")begin state = CHECK_o1; out_flow = data_cap; end else state = CHECK_L; CHECK_o1 : if(data_low == "o")begin state = CHECK_v; out_flow = data_low; end else state = CHECK_o1; CHECK_v : if(data_low == "v")begin state = CHECK_e; out_flow = data_low; end else state = CHECK_v; CHECK_e : if(data_low == "e")begin state = CHECK_Y; out_flow = data_low; end else state = CHECK_e; CHECK_Y : if(data_cap == "Y")begin state = CHECK_o2; out_flow = data_cap; end else state = CHECK_Y; CHECK_o2 : if(data_low == "o")begin state = CHECK_u; out_flow = data_low; end else state = CHECK_o2; CHECK_u : if(data_low == "u")begin state = CHECK_I; out_flow = data_low; end else state = CHECK_u; default : begin out_flow = 0; state = CHECK_I; end endcase end endmodule RTL: 资源使用: 仿真效果:   2.“两段式”  特点:(第一段)一个时序always块给当前状态向量赋值,(第二段)一个组合always块给下一个状态向量和输出向量赋值。  缺点:(1)组合逻辑输出会使输出向量产生毛刺;               (2)从速度角度而言,由于这种状态机的输出向量必须由状态向量经译码得到,因此加大了从状态向量到输出向量的延时。               (3)从综合角度而言,组合输出消耗了一部分时钟周期,即增加了由它驱动的下一个模块的输入延时。 结构: 例程: module FSM( clk, rst_n, data_cap,// data_low, out_flow ); input clk,rst_n; input  data_cap,data_low;//大写,小写字母数据流 output reg  out_flow; reg  state,NS; localparam //独热码 CHECK_I  = 8'b0000_0001, CHECK_L  = 8'b0000_0010, CHECK_o1 = 8'b0000_0100, CHECK_v  = 8'b0000_1000, CHECK_e  = 8'b0001_0000, CHECK_Y  = 8'b0010_0000, CHECK_o2 = 8'b0100_0000, CHECK_u  = 8'b1000_0000; always @(posedge clk or negedge rst_n) if(!rst_n) begin state = CHECK_I; end else begin state = NS; end always @(rst_n or state or data_cap or data_low) begin NS = 8'bx; out_flow = 8'bx; case(state) CHECK_I : if(data_cap == "I") begin NS = CHECK_L; out_flow = data_cap; end else NS = CHECK_I; CHECK_L : if(data_cap == "L")begin NS = CHECK_o1; out_flow = data_cap; end else NS = CHECK_L; CHECK_o1 : if(data_low == "o")begin NS = CHECK_v; out_flow = data_low; end else NS = CHECK_o1; CHECK_v : if(data_low == "v")begin NS = CHECK_e; out_flow = data_low; end else NS = CHECK_v; CHECK_e : if(data_low == "e")begin NS = CHECK_Y; out_flow = data_low; end else NS = CHECK_e; CHECK_Y : if(data_cap == "Y")begin NS = CHECK_o2; out_flow = data_cap; end else NS = CHECK_Y; CHECK_o2 : if(data_low == "o")begin NS = CHECK_u; out_flow = data_low; end else NS = CHECK_o2; CHECK_u : if(data_low == "u")begin NS = CHECK_I; out_flow = data_low; end else NS = CHECK_u; default : begin out_flow = 8'bx; NS = CHECK_I; end endcase end endmodule RTL: 资源占用: 仿真:     3.“三段式”  特点:两个时序always块,分别产生当前状态向量和输出向量,再用一个组合逻辑always块产生下一个状态向量。    代码主要包含以下三部分:  状态转移部分(时序逻辑)  状态转移条件部分(即产生下个状态向量的模块,组合逻辑)   输出逻辑部分(时序逻辑) 优点:  三段式描述方法虽然代码结构复杂了一些,但是 换来的优势是:使 FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。 结构: 例程: module FSM( clk, rst_n, data_cap,// data_low, out_flow ); input clk,rst_n; input  data_cap,data_low;//大写,小写字母数据流 output reg  out_flow; reg  state,NS; localparam //独热码 CHECK_I  = 8'b0000_0001, CHECK_L  = 8'b0000_0010, CHECK_o1 = 8'b0000_0100, CHECK_v  = 8'b0000_1000, CHECK_e  = 8'b0001_0000, CHECK_Y  = 8'b0010_0000, CHECK_o2 = 8'b0100_0000, CHECK_u  = 8'b1000_0000; always @(posedge clk or negedge rst_n) if(!rst_n) begin state = CHECK_I; end else begin state = NS; end always @(rst_n or state or data_cap or data_low) begin NS = 8'bx; case(state) CHECK_I : if(data_cap == "I")  NS = CHECK_L; else NS = CHECK_I; CHECK_L : if(data_cap == "L") NS = CHECK_o1; else NS = CHECK_L; CHECK_o1: if(data_low == "o") NS = CHECK_v; else NS = CHECK_o1; CHECK_v : if(data_low == "v") NS = CHECK_e; else NS = CHECK_v; CHECK_e : if(data_low == "e") NS = CHECK_Y; else NS = CHECK_e; CHECK_Y : if(data_cap == "Y") NS = CHECK_o2; else NS = CHECK_Y; CHECK_o2: if(data_low == "o") NS = CHECK_u; else NS = CHECK_o2; CHECK_u : if(data_low == "u") NS = CHECK_I; else NS = CHECK_u; default : NS = CHECK_I; endcase end always @(posedge clk or negedge rst_n) if(!rst_n) begin out_flow = 8'b0; end else begin case(NS) CHECK_I : out_flow = "I";//I                                   CHECK_L : out_flow = "L";//L                                CHECK_o1 : out_flow = "o";//o                        CHECK_v : out_flow = "v";//v                             CHECK_e : out_flow = "e";//e                                CHECK_Y : out_flow = "Y";//Y                                CHECK_o2 : out_flow = "o";//o                                CHECK_u : out_flow = "u";//u endcase end endmodule RTL: 资源占用:   以上的仿真代码: `timescale 1ns/1ns `define clock_period 20 module FSM_tb; reg clk; reg rst_n; reg  data_cap,data_low; wire  out_flow; FSM FSM( .clk(clk), .rst_n(rst_n), .data_cap(data_cap),// .data_low(data_low), .out_flow(out_flow) ); always @(posedge clk) begin #(`clock_period) data_cap = 65 + {$random}%26; #(`clock_period) data_low = 97 + {$random}%26; end initial clk = 1; always #(`clock_period/2)clk = ~clk; initial begin rst_n = 0; //ASCII = 0; #(`clock_period*5); rst_n = 1; #(`clock_period*500 ); //forever begin $stop; end endmodule           一般而言, 推荐的FSM 描述方法是后两种 。这是因为:FSM和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,状态转移部分是同步时序电路而状态的转移条件的判断是组合逻辑。 第二种描述方法同第一种描述方法相比,将同步时序和组合逻辑分别放到不同的always模块中实现,这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在第二种方式的描述中,描述当前状态的输出用组合逻辑实现,组合逻辑很容易产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计。 为了使FSM 描述清晰简介,易于维护,易于附加时序约束,使综合器和布局布线器更好的优化设计,推荐使用两段式FSM 描述方法 。   由于Augus能力有限,笔记如有错误,请大家之处帮忙指出!十分感谢,一起学习!