Verilog描述有限状态机(一段式、二段式、三段式)

有限状态机(FSM)的输出取决于过去状态以及当前输入,是时序逻辑电路。适合描述那些发生有先后顺序或者有逻辑规律的事情,状态机的本质就是对具有逻辑顺序或时序规律的事件进行描述的一种方法,广泛用于多种场合。

因此,掌握有限状态机的Verilog描述方式至关重要;通过许多大神前辈的博客,我了解到状态机的描述具有三种方式,反思自己之前的描述深感逻辑混乱,毫无章法,因此重新对这方面进行学习与记录

一、FSM的组成

状态机:状态机描绘状态变迁的状态迁移图,体现了系统对外界事件的反应;
状态机组成六要素:状态集合,初态,终态,输入符号集,输出符号集,状态转移函数;
状态机工作四要素:现态 ,次态,输入,输出;

状态机主要分为三部分:

状态转移部分,描述状态机在时钟驱动下的状态转移这一过程(现态---次态);

状态转移条件,之前我们已经知道状态机会不断进行状态转移,但是由当前状态转移为何种状态?也就是次态的取值是什么,这个工作是状态转移条件部分来描述执行;

输出部分描述状态机的输出,即当前状态下的输出为什么;

这三部分的描述可以放在Verilog描述过程的不同部分,即对应FSM的三种描述方式;

二、FSM的三种描述方式

一段式FSM描述:状态机写在1个always块,既描述状态转移,又描述状态的输入输出;(但是其各部分杂糅,在功能比较复杂的场合会比较混乱,不建议使用)
二段式FSM描述:鉴于一段式描述的缺点,两段式描述使用2个always块,一个always块利用同步时序逻辑描述状态转移,一个always块利用组合逻辑描述状态转移条件以及输出;(但是输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素,并影响系统执行速率)
三段式FSM描述:三段式描述应运而生,通过使用3个always块,一个always块利用同步时序逻辑描述状态转移,一个always块利用组合逻辑描述状态转移条件,一个always块利用同步时序逻辑描述输出,避免了前两种描述方式的弊端;

更详细的描述见下连接:

基于Verilog HDL的有限状态机

【 FPGA 】状态机,FPGA的灵魂

三、仿真:

按照不同描述方式实现1011序列产生,序列产生的内容详见Verilog实现序列产生器(状态转移形,移位形,计数形)

而此处只关心状态机的描述方式:

一段式描述:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/21 15:30:18
// Design Name: 
// Module Name: seq_gen_fsm1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module seq_gen_fsm1(
    input clk,
    input rst_n,
    output reg seq
    );
 // state declaration
 parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
 reg [1:0]state;
// 状态转移+状态转移条件+输出
 always@(posedge clk or negedge rst_n)
 begin
    if(!rst_n)
        begin
            state <= s0;
            seq <= 1'b1;
        end
    else
        begin
            case(state)
            s0:begin
            state = s1;
            seq <= 1'b1;
            end
            s1:begin
            state = s2;
            seq <= 1'b0;
            end
            s2:begin
            state = s3;
            seq <= 1'b1;
            end
            s3:begin
            state = s0;
            seq <= 1'b1;
            end
            default:begin
            state = s0;
            seq <= 1'b1;
            end
            endcase
        end
 end
  
endmodule

二段式描述:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/21 15:30:49
// Design Name: 
// Module Name: seq_gen_fsm2
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module seq_gen_fsm2(
    input clk,
    input rst_n,
    output reg seq
    );
 // state declaration
 parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
 reg [1:0]c_state,n_state;
 // 状态转移
 always@(posedge clk or negedge rst_n)
 begin
    if(!rst_n)
        begin
            c_state <= s0;
        end
    else
        begin
            c_state <= n_state;
        end
 end
// 状态转移条件+输出
 always@(c_state or rst_n)
 begin
    if(!rst_n)
        begin
            n_state = s0;
        end
    else
        begin
            case(c_state)
            s0:begin
            n_state = s1;
            seq = 1'b1;
            end
            s1:begin
            n_state = s2;
            seq = 1'b0;
            end
            s2:begin
            n_state = s3;
            seq = 1'b1;
            end
            s3:begin
            n_state = s0;
            seq = 1'b1;
            end
            default:begin
            n_state = s0;
            seq = 1'b1;
            end
            endcase
        end
 end
 
endmodule

三段式描述:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/21 00:20:42
// Design Name: 
// Module Name: seq_gen_fsm
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module seq_gen_fsm(
    input clk,
    input rst_n,
    output reg seq
    );
 // state declaration
 parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
 reg [1:0]c_state,n_state;
 // 状态转移
 always@(posedge clk or negedge rst_n)
 begin
    if(!rst_n)
        begin
            c_state <= s0;
        end
    else
        begin
            c_state <= n_state;
        end
 end
// 状态转移条件
 always@(c_state or rst_n)
 begin
    if(!rst_n)
        begin
            n_state = s0;
        end
    else
        begin
            case(c_state)
            s0:n_state = s1;
            s1:n_state = s2;
            s2:n_state = s3;
            s3:n_state = s0;
            default:n_state = s0;
            endcase
        end
 end
 // 输出
 always@(posedge clk or negedge rst_n)
 begin
    if(!rst_n)
        begin
            seq <= 1'b0;
        end
    else
        begin
            case(n_state)
            s0:seq <= 1'b1;
            s1:seq <= 1'b0;
            s2:seq <= 1'b1;
            s3:seq <= 1'b1;
            default:seq <= 1'b0;
            endcase
        end
 end
 
endmodule

测试文件如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/21 00:35:17
// Design Name: 
// Module Name: seq_gen_tsb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module seq_gen_tsb(

    );
// port
reg clk;
reg rst_n;
wire seq1,seq2,seq3;
// clk
initial
begin
    clk = 1'b1;
    forever #10 clk = ~clk;
end
// 
initial
begin
    rst_n = 1'b1;
    #15 rst_n = 1'b0;
    #50 rst_n = 1'b1;
end
// instantation
//seq_gen_shift inst(
//seq_gen_count inst(
seq_gen_fsm1 inst(
    .clk(clk),
    .rst_n(rst_n),
    .seq(seq1)
);
seq_gen_fsm2 inst2(
    .clk(clk),
    .rst_n(rst_n),
    .seq(seq2)
);
seq_gen_fsm inst3(
    .clk(clk),
    .rst_n(rst_n),
    .seq(seq3)
);
endmodule

 输出结果如下:

可见,两段式与三段式描述输出一致,与理想波形一致;而一段式输出滞后一个时钟周期,原因在于一段式的描述特点,即根据当前状态进行输出的非阻塞赋值,因此输出必然滞后状态一个时钟周期;(二三段式描述为避免这一现象,按照次态选择输出,将非阻塞赋值的时间延迟通过这一方式补偿回来)

四、参考文献:

基于Verilog HDL的有限状态机

【 FPGA 】状态机,FPGA的灵魂

  • 13
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog是一种硬件描述语言,可以用于实现状态机。下面是三段式二段式一段状态机的Verilog实现示例: ## 三段式状态机 ```verilog module Three_State_Machine ( input clk, // 时钟信号 input reset, // 复位信号 input event, // 事件信号 output reg state_out // 输出状态信号 ); // 定义状态枚举类型 typedef enum logic [1:0] { STATE_IDLE, STATE_WAIT_EVENT, STATE_PROCESS_EVENT } state_type; // 定义状态变量和状态转移条件 reg [1:0] state, next_state; always @(*) begin case (state) STATE_IDLE: begin if (event) next_state = STATE_WAIT_EVENT; else next_state = STATE_IDLE; end STATE_WAIT_EVENT: begin next_state = STATE_PROCESS_EVENT; end STATE_PROCESS_EVENT: begin next_state = STATE_IDLE; end default: next_state = STATE_IDLE; endcase end // 状态机状态寄存器 always @(posedge clk, posedge reset) begin if (reset) state <= STATE_IDLE; else state <= next_state; end // 输出状态信号 always @(*) begin case (state) STATE_IDLE: state_out = 1'b0; STATE_WAIT_EVENT: state_out = 1'b1; STATE_PROCESS_EVENT: state_out = 1'b0; default: state_out = 1'b0; endcase end endmodule ``` ## 二段式状态机 ```verilog module Two_State_Machine ( input clk, // 时钟信号 input reset, // 复位信号 input event, // 事件信号 output reg state_out // 输出状态信号 ); // 定义状态枚举类型 typedef enum logic [0:0] { STATE_IDLE, STATE_PROCESS_EVENT } state_type; // 定义状态变量和状态转移条件 reg [0:0] state, next_state; always @(*) begin case (state) STATE_IDLE: begin if (event) next_state = STATE_PROCESS_EVENT; else next_state = STATE_IDLE; end STATE_PROCESS_EVENT: begin next_state = STATE_IDLE; end default: next_state = STATE_IDLE; endcase end // 状态机状态寄存器 always @(posedge clk, posedge reset) begin if (reset) state <= STATE_IDLE; else state <= next_state; end // 输出状态信号 always @(*) begin case (state) STATE_IDLE: state_out = 1'b0; STATE_PROCESS_EVENT: state_out = 1'b1; default: state_out = 1'b0; endcase end endmodule ``` ## 一段状态机 ```verilog module One_State_Machine ( input clk, // 时钟信号 input reset, // 复位信号 input event, // 事件信号 output reg state_out // 输出状态信号 ); // 定义状态枚举类型 typedef enum logic [0:0] { STATE_IDLE } state_type; // 定义状态变量和状态转移条件 reg [0:0] state, next_state; always @(*) begin next_state = STATE_IDLE; end // 状态机状态寄存器 always @(posedge clk, posedge reset) begin if (reset) state <= STATE_IDLE; else state <= next_state; end // 输出状态信号 always @(*) begin case (state) STATE_IDLE: state_out = 1'b0; default: state_out = 1'b0; endcase end endmodule ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值