资讯动态

Verilog基础:三段式状态机与输出寄存

发布时间:2026/10/27 9:24:41 来源:尧图企业网站定制
相关阅读Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html对于Verilog HDL来说有限状态机(FSM, Finite State Machine)是一类非常重要且功能强大的时序逻辑模块。常见的状态机写法通常分为一段式、二段式和三段式。从可读性、可维护性以及工程实践的角度来看更推荐使用三段式状态机因为这种写法结构清晰状态转移逻辑与输出逻辑分工明确后期修改和调试也更加方便。有限状态机主要可以分为两种基本类型Mealy型状态机和Moore型状态机。两者最核心的区别在于输出信号的决定方式不同Mealy型状态机的下一状态和输出都由当前状态和当前输入共同决定而Moore型状态机的下一状态由当前状态和当前输入决定而输出只由当前状态决定。这两类有限状态机的下一状态和输出都是组合逻辑的形式的指输出不直接来自寄存器的输出两类状态机的结构如图1、图2所示。图1 Mealy型状态机图2Moore型状态机下面以一个简单的例子说明三段式Moore型状态机的书写方式。图3是一个有两个状态的异步复位的Moore型状态机。图3 一个简单的Moore型状态机module top_module ( input clk, input in, input rst_n, output reg out ); parameter A 0 parameter B 1 reg state, next_state; //定义寄存器变量保存状态信息 //第一段下一状态组合逻辑 always(*) begin case (state) //根据不同的状态和输入决定下一时钟周期的状态 A: next_state in ? A : B; B: next_state in ? B : A; endcase end //第二段状态转移时序逻辑 always (posedge clk, negedge rst_n) begin if (!rst_n) state B; //异步复位到状态B else state next_state; end //第三段输出组合逻辑 always(*) begin if(state B) out 1; else out 0; end //因为输出比较简单这里的第三段的输出组合逻辑也可以用assign连续赋值 //但out此时不能定义为reg //assign out (state B); endmodule对于Mealy型状态机由于输出直接受到输入信号影响因此在某些场景下可能会出现毛刺也就是输出在非时钟边沿发生跳变。这种现象在某些对输出稳定性要求较高的场合是不希望看到的因此常常会考虑对输出进行寄存。而对于Moore型状态机由于输出只与当前状态有关通常不会像Mealy型状态机那样天然存在输出毛刺问题。不过即使如此在工程设计中也依然可能选择对Moore型状态机的输出进行寄存原因在于这样可以避免输出端接入过长的组合逻辑路径改善时序使输出更规整便于后级模块采样。图4和图5分别给出了寄存输出的Mealy型状态机和Moore型状态机的结构。图4 寄存输出的Mealy型状态机图5 寄存输出的Moore型状态机上面两图不难理解但是一个新的问题出现了即输出会延后一个周期得到如果既需要当前周期给出输出又需要对输出寄存就不能使用当前状态和输入确定输出而是应该使用下一状态组合逻辑和输入确定输出。图6和图7给出了这种情况下的Mealy型状态机和Moore型状态机。图6 寄存输出的Mealy型状态机下一状态图7 寄存输出的Moore型状态机下一状态对于Mealy状态机因为需要状态转移和相应状态的输出同时出现输出寄存器需要保存由下一状态组合逻辑和的输入推导的输出。对于Moore状态机输出寄存器需要保存由下一状态组合逻辑推导的输出。下面用一个更加复杂的有限状态机为例说明寄存输出的具体写法。这是一个序列检测器用于检测输入序列中三个连续的1信号首先给出Moore型序列检测器的Verilog描述。module Seq_Rec_Moore(output reg D_out, D_out_r1, D_out_r2, input D_in, En, clk, rst_n); parameter S_idle 3d0; parameter S_0 3d1; parameter S_1 3d2; parameter S_2 3d3; parameter S_3 3d4; reg [2:0] state, next_state; //下一状态组合逻辑 always(*)begin case(state) S_idle: if((En 1)(D_in 1)) next_state S_1; else if((En 1)(D_in 0)) next_state S_0; else next_state S_idle; S_0: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_1; else next_state S_idle; S_1: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_2; else next_state S_idle; S_2: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_3; else next_state S_idle; S_3: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_3; else next_state S_idle; default: next_state S_idle; endcase end //状态转移时序逻辑 always(posedge clk, negedge rst_n)begin if(!rst_n) state S_idle; else state next_state; end //输出组合逻辑 always(*) begin D_out (state S_3); end //寄存输出 always (posedge clk, negedge rst_n) begin if(!rst_n) D_out_r1 0; else D_out_r1 D_out; end //寄存输出(下一状态) always(posedge clk, negedge rst_n)begin if(!rst_n) D_out_r2 0; else D_out_r2 (next_state S_3); end endmodule一个简单的testbench如下所示图8所示的仿真截图显示了三种不同形式的输出。timescale 1ns / 1ns module t_Seq(); reg D_in, clk, rst_n,En; wire D_out, D_out_r1, D_out_r2; Seq_Rec_Moore Seq_Rec_Moore_1 (.D_in(D_in), .clk(clk), .rst_n(rst_n), .D_out(D_out), .En(En), .D_out_r1(D_out_r1), .D_out_r2(D_out_r2)); initial begin D_in 0; clk 0; rst_n 1; En 0; end initial begin #5 rst_n 0; #4 rst_n 1; end always begin #5 clk 0; #5 clk 1; end initial begin #5 En 1; end initial begin #5 D_in 1; end endmodule图8 Moore状态机仿真截图下面是Mealy型序列检测器的Verilog描述。module Seq_Rec_Mealy(output reg D_out, D_out_r1, D_out_r2, input D_in, En, clk, rst_n); parameter S_idle 3d0; parameter S_0 3d1; parameter S_1 3d2; parameter S_2 3d3; parameter S_3 3d4; reg [2:0] state, next_state; //下一状态组合逻辑 always(*)begin case(state) S_idle: if((En 1)(D_in 1)) next_state S_1; else if((En 1)(D_in 0)) next_state S_0; else next_state S_idle; S_0: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_1; else next_state S_idle; S_1: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_2; else next_state S_idle; S_2: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_3; else next_state S_idle; S_3: if(D_in 0) next_state S_0; else if(D_in 1) next_state S_3; else next_state S_idle; default: next_state S_idle; endcase end //状态转移时序逻辑 always(posedge clk, negedge rst_n)begin if(!rst_n) state S_idle; else state next_state; end //输出组合逻辑 always(*) begin D_out (state S_3)(D_in 1); end //寄存输出 always (posedge clk, negedge rst_n) begin if(!rst_n) D_out_r1 0; else D_out_r1 D_out; end //寄存输出(下一状态) always(posedge clk, negedge rst_n)begin if(!rst_n) D_out_r2 0; else D_out_r2 (next_state S_3)(D_in 1); end endmodule图9 Mealy状态机仿真截图一个简单的testbench如下所示图9的仿真截图显示了如果使用寄存输出而输入无法维持到下个时钟沿则会丢失寄存输出信号。timescale 1ns / 1ns module t_Seq(); reg D_in, clk, rst_n,En; wire D_out, D_out_r1, D_out_r2; Seq_Rec_Mealy Seq_Rec_Mealy_1 (.D_in(D_in), .clk(clk), .rst_n(rst_n), .D_out(D_out), .En(En), .D_out_r1(D_out_r1), .D_out_r2(D_out_r2)); initial begin D_in 0; clk 0; rst_n 1; En 0; end initial begin #5 rst_n 0; #4 rst_n 1; end always begin #5 clk 0; #5 clk 1; end initial begin #5 En 1; end initial begin #5 D_in 1; #30 D_in 0; #10 D_in 1; #37 D_in 0; end endmodule

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑