verilog 中的三段式状态机
抄的: https://zhuanlan.zhihu.com/p/431143109
一段式状态机
特点:
最主要的特征是只有一个always块。在这个always块内既描述状态转移,又含有组合逻辑输入/输出,当前状态用寄存器输出;在这种状态机的写法中,组合逻辑电路和时序逻辑电路都在一起,没有分开;因此这种写法增加了代码的复杂度且不利于代码的维护和修改,同时也不利于后期约束;
module simple( input clk, input rst_n, input w, output reg[1:0] z ); localparam A = 2'b00; localparam B = 2'b01; localparam C = 2'b10; reg [1:0] state; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin state <= A; z <= 0; end else case (state) A: begin if (w) begin state <= B; z <= 2'd1; end else begin state <= A; z <= 2'd0; end end B: begin if (w) begin state <= C; z <= 2'd2; end else begin state <= A; z <= 2'd1; end end C: begin if (w) begin state <= C; z <= 2'd2; end else begin state <= A; z <= 2'd0; end end default: begin state <= A; z <= 2'd0; end endcase end endmodule
二段式状态机
特点
最主要的特征是有两个always块,将组合逻辑和时序逻辑分开。其中一个always块采用同步时序描述状态转移,而另一个always块采用组合逻辑来判断状态转移的条件,描述状态转移规律及输出;在这种写法下,需要定义两个状态,分别是现态和次态,通过现态和次态的转换来实现状态转移;两段式状态机可以清晰完整的显示出状态机的结构,有利于代码的维护和后期修改,同时也降低编写复杂度;
module simple( input clk, input rst_n, input w, output reg[1:0] z ); localparam A = 2'b00; localparam B = 2'b01; localparam C = 2'b10; reg [1:0] current_state; reg [1:0] next_state; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= A; end else current_state <= next_state; end always @(*) begin case (current_state) A: begin if (w) begin next_state = B; z = 2'd1; end else begin next_state = A; z = 2'd0; end end B: begin if (w) begin next_state = C; z = 2'd2; end else begin next_state <= A; z = 2'd1; end end C: begin if (w) begin next_state = C; z = 2'd2; end else begin next_state = A; z = 2'd0; end end default: begin next_state = A; z = 2'd0; end endcase end endmodule
三段式状态机
特点
最主要的特征是有三个always块。区别于两段式状态机的关键在于两段式状态机直接采用组合逻辑输出,而三段式状态机则通过在组合逻辑后再增加一级寄存器实现逻辑输出——即一个always块采用同步时序描述状态转移,一个always块采用组合逻辑判断转移条件、转移状态规律,最后一个always块采用同步时序描述状态的输出;这种三段式状态机的写法代码非常清晰,极大降低了编写维护代码的复杂度,最大程度清晰完整的显示出状态机的结构。同时可以有效地滤除两段式状态机组合逻辑输出可能产生的毛刺信号;另外对于总线形式的输出来说,容易使总线数据对齐,从而减小总线数据间的偏移,减小接收端数据采样出错的频率;但是代码量会长
module simple( input clk, input rst_n, input w, output reg[1:0] z ); localparam A = 2'b00; localparam B = 2'b01; localparam C = 2'b10; reg [1:0] current_state; reg [1:0] next_state; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= A; end else current_state <= next_state; end always @(*) begin case (current_state) A: begin if (w) begin next_state = B; end else begin next_state = A; end end B: begin if (w) begin next_state = C; end else begin next_state <= A; end end C: begin if (w) begin next_state = C; end else begin next_state = A; end end default: begin next_state = A; end endcase end always @(posedge clk or negedge rst_n) begin if (rst_n) begin z <= 2'd0; end else begin case (next_state) A: z <= 2'd0; B: z <= 2'd1; C: z <= 2'd2; default: z <= 2'd0; endcase end end endmodule
本文来自博客园踩坑狭,作者:韩若明瞳,转载请注明原文链接:https://www.cnblogs.com/han-guang-xue/p/16643280.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人