FSM是电路设计中很是常见的结构,对于这样常见的结构的正确输写很是重要, 良好的代码风格对于阅读理解以及后期维护也很是重要。本文总结了目前常见的两种输写FSM的方法html
FSM目前主要有两种架构后端
要让电路顺序地执行计算,最简单的方法就是生成一个counter, 而后根据counter值去执行相应的操做或计算。但这种方法只能用于很是简单的控制,且很是不容易维护以及后期功能修改。因此实际上你们都会用标准的FSM来实现复杂控制。架构
Moore FSM是目前的主流写法, 它由三块组成:编码
假设输入为w_i, 输出为z_o, 当输入连续2个cycle为高时,则输出为1个cycle高spa
下面是state diagram设计
/********************************************** Description : 3 always block for moore fsm (BEST) **********************************************/ module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; parameter S1 = 2'b10; reg [1:0] curr_state; reg [1:0] next_state; reg z_o; // state reg always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else curr_state <= next_state; end // next state logic always@(*) begin case (curr_state) IDLE : if (w_i) next_state = S0; else next_state = IDLE; S0 : if (w_i) next_state = S1; else next_state = IDLE; S1 : if (w_i) next_state = S1; else next_state = IDLE; default : next_state = IDLE; endcase end // output logic always@(*) begin case (curr_state) IDLE : z_o = 1'b0; S0 : z_o = 1'b0; S1 : z_o = 1'b1; default : z_o = 1'b0; endcase end endmodule
下面是相应的TBcode
/********************************************** Description : testbench for FSM **********************************************/ module simple_fsm_tb; reg clk = 1'b1; reg rst_n = 1'b1; reg w_i = 1'b0; wire z_o; // clk always #10 clk = ~clk; event after_rst; // rst_n initial begin #6; // 6ns rst_n = 1'b0; #30; // 36ns rst_n = 1'b1; ->after_rst; end // w_i initial begin @(after_rst); repeat(2)@(posedge clk); // 60ns w_i <= 1'b1; @(posedge clk); // 80 ns w_i <= 1'b0; @(posedge clk); // 100 ns w_i <= 1'b1; repeat(2)@(posedge clk); // 140 ns w_i <= 1'b0; @(posedge clk); // 160 ns w_i <= 1'b1; repeat(3)@(posedge clk); // 220 ns w_i <= 1'b0; end initial begin $fsdbDumpfile("simple_fsm.fsdb"); $fsdbDumpvars(0, simple_fsm_tb); end simple_fsm u_simple_fsm ( .clk (clk), .rst_n (rst_n), .w_i (w_i), .z_o (z_o) ); endmodule
仿真波形以下:htm
代码以下:blog
module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; parameter S1 = 2'b10; reg [1:0] curr_state; reg z_o; // state reg + next state logic always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else case (curr_state) IDLE : if (w_i) curr_state <= S0; else curr_state <= IDLE; S0 : if (w_i) curr_state <= S1; else curr_state <= IDLE; S1 : if (w_i) curr_state <= S1; else curr_state <= IDLE; default : curr_state <= IDLE; endcase end // output logic always@(*) begin case (curr_state) IDLE : z_o = 1'b0; S0 : z_o = 1'b0; S1 : z_o = 1'b1; default : z_o = 1'b0; endcase end endmodule
还有其余二段式,或者一段式,但都不推荐使用。
从条理上讲三段式是最清晰的, 易于理解,便于维护ip
架构以下
默认它的输出行为与Moore有点不同,输出会早一拍
原来Moore FSM须要3个state, 改用Mealy FSM只须要2个State
注意上图中z_o与w_i有关, 因此上图在s0是不存在w_i/~z_o的状态
为了使输出与Moore FSM相同,须要打一拍
module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; reg [1:0] curr_state; reg [1:0] next_state; reg z; reg z_o; // state reg always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else curr_state <= next_state; end // next state logic always@(*) begin case (curr_state) IDLE : if (w_i) next_state = S0; else next_state = IDLE; S0 : if (w_i) next_state = S0; else next_state = IDLE; default : next_state = IDLE; endcase end // output logic always@(*) case (curr_state) IDLE : if (w_i) z = 1'b0; else z = 1'b0; S0 : if (w_i) z = 1'b1; else z = 1'b0; default : z = 1'b0; endcase // mealy output to delay 1 clk for moore always@(posedge clk or negedge rst_n) begin if (~rst_n) z_o <= 1'b0; else z_o <= z; end endmodule
module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; reg [1:0] curr_state; reg z; reg z_o; // state reg + next state logic always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else case (curr_state) IDLE : if (w_i) curr_state <= S0; else curr_state <= IDLE; S0 : if (w_i) curr_state <= S0; else curr_state <= IDLE; default : curr_state <= IDLE; endcase end // output logic always@(*) begin case (curr_state) IDLE : if (w_i) z = 1'b0; else z = 1'b0; S0 : if (w_i) z = 1'b1; else z = 1'b0; default : z = 1'b0; endcase end // mealy output to delay 1 clk for moore always@(posedge clk or negedge rst_n) begin if (~rst_n) z_o <= 1'b0; else z_o <= z; end endmodule
为了timing更好,常会在Moore FSM的输出端加一级DFF
架构以下
module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; parameter S1 = 2'b10; reg [1:0] curr_state; reg z_o; // state reg + next state logic always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else case (curr_state) IDLE : if (w_i) curr_state <= S0; else curr_state <= IDLE; S0 : if (w_i) curr_state <= S1; else curr_state <= IDLE; S1 : if (w_i) curr_state <= S1; else curr_state <= IDLE; default : curr_state <= IDLE; endcase end // output logic always@(posedge clk or negedge rst_n) begin if (~rst_n) z_o <= 1'b0; else case (curr_state) IDLE : z_o <= 1'b0; S0 : z_o <= 1'b0; S1 : z_o <= 1'b1; default : z_o <= 1'b0; endcase end endmodule
代码以下:
module simple_fsm ( clk, rst_n, w_i, z_o ); input clk; input rst_n; input w_i; output z_o; parameter IDLE = 2'b00; parameter S0 = 2'b01; parameter S1 = 2'b10; reg [1:0] curr_state; reg [1:0] next_state; reg z_o; // state reg always@(posedge clk or negedge rst_n) begin if (~rst_n) curr_state <= IDLE; else curr_state <= next_state; end // next state logic always@(*) begin case (curr_state) IDLE : if (w_i) next_state = S0; else next_state = IDLE; S0 : if (w_i) next_state = S1; else next_state = IDLE; S1 : if (w_i) next_state = S2; else next_state = IDLE; default : next_state = IDLE; endcase end // output logic always@(posedge clk or negedge rst_n) begin if (~rst_n) z_o <= 1'b0; else case (curr_state) IDLE : z_o <= 1'b0; S0 : z_o <= 1'b0; S1 : z_o <= 1'b1; default : z_o <= 1'b0; endcase end endmodule
注: 本文是在真OO无双原版上的简化,如须要了解更详细信息,请阅读原文