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

这篇具有很好参考价值的文章主要介绍了Verilog基础:三段式状态机与输出寄存。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相关阅读

Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html


        对于Verilog HDL而言,有限状态机(FSM)是一种重要而强大的模块,常见的有限状态机书写方式可以分为一段式,二段式和三段式,笔者强烈建议使用三段式因为这样能使状态机逻辑清晰且易于维护。

        有限状态机有两种基本类型:Mealy机和Moore机。两者的区别在于:Mealy机的下一状态和输出都取决于当前状态和当前输入,而Moore机的下一状态取决于当前状态和当前输入,输出只取决于当前状态。这两类有限状态机的下一状态和输出都是组合逻辑的形式的(指输出不直接来自寄存器的输出),两类状态机的结构如图1、图2所示。

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发

图1 Mealy型状态机

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发

图2 Moore型状态机

        下面以一个简单的例子说明三段式Moore型状态机的书写方式。图3是一个有两个状态的异步复位的Moore机。

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发

图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型状态机,虽然没有输出毛刺的问题,但也可以使用寄存器采集输出以避免大段组合逻辑输出。图4和图5分别给出了寄存输出的Mealy型状态机和Moore型状态机的结构。

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发图4 寄存输出的Mealy型状态机

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发图5 寄存输出的Moore型状态机

        上面两图不难理解,但是一个新的问题出现了,即输出会延后一个周期得到,如果既需要当前周期给出输出,又需要对输出寄存,就不能使用当前状态和输入确定输出,而是应该使用下一状态组合逻辑和输入确定输出。图6和图7给出了这种情况下的Mealy型状态机和Moore型状态机。

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发图6 寄存输出的Mealy型状态机(下一状态)

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发 图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 = 3'd0;
    parameter S_0 = 3'd1;
    parameter S_1 = 3'd2;
    parameter S_2 = 3'd3;
    parameter S_3 = 3'd4;

    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

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发图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 = 3'd0;
    parameter S_0 = 3'd1;
    parameter S_1 = 3'd2;
    parameter S_2 = 3'd3;
    parameter S_3 = 3'd4;

    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

Verilog基础:三段式状态机与输出寄存,Verilog基础,数字IC,硬件工程,fpga开发 图9 Mealy状态机仿真截图 

一个简单的testbench如下所示,图9的仿真截图显示了如果使用寄存输出,而输入无法维持到下个时钟沿,则会丢失寄存输出信号。文章来源地址https://www.toymoban.com/news/detail-759836.html

`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

到了这里,关于Verilog基础:三段式状态机与输出寄存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【零基础玩转BLDC系列】无刷直流电机无位置传感器三段式启动法详细介绍及代码分享

    无刷直流电动机基本转动原理等内容请参考《基于霍尔传感器的无刷直流电机控制原理》、《基于反电动势过零检测法的无刷直流电机控制原理》与《以GD32F30x为例定时器相关功能详解》,BLDC基本原理及基础知识本篇不再赘述。 直流无刷电机由于定子绕组的反电动势与电机的

    2023年04月08日
    浏览(91)
  • Flutter BottomSheet 三段式拖拽

    前面倒是有讲过Android原生的BottomSheetBehavior,使用场景还是蛮多的,最近在用Flutter做一款地图App,有用到BottomSheet的功能,但是 Flutter 自带的BottomSheet有点拉,只能显示和隐藏销毁,不支持折叠为最小高度状态也不支持三段式拖动 ,那就自己撸一个吧: 既然是基于系统的Bot

    2024年02月09日
    浏览(45)
  • [Daimayuan] 三段式(C++,数组前缀和)

    有一个长度为 n n n 的序列,现在我们想把它切割成三段(每一段都是连续的),使得每一段的元素总和都相同,请问有多少种不同的切割方法 输入描述 第一行给出一个数 n n n ,( 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1 ≤ n ≤ 1 0 5 ) 第二行给出序列 a 1 a_1 a 1 ​ , a 2 a_2 a 2 ​ , a 3 a_3 a 3 ​

    2024年02月05日
    浏览(36)
  • 电力系统电流三段式保护MATLAB仿真模型

    完整资源请查看主页置顶博客(专享优惠) 整体模型如下: Matlab/Simulink搭建的电力系统电流保护模型采用辐射型单电源供电的运行方式 Ⅰ段保护的搭建 Ⅰ段保护为瞬时速断保护,根据Ⅰ段整定原则确定整定值。线路发生短路故障时,短路电流急剧增大;超过设置的整定值时

    2024年02月14日
    浏览(47)
  • 三段式电流保护与自动重合闸MATLAB仿真模型

    微 ❤ 关注“电气仔推送”获得资料(专享优惠) 前加速、后加速的区别: 前加速是保护装置不判别是永久性故障还是瞬时故障,直接跳闸,然后经重合闸装置来纠正;后加速是保护装置是先判别故障类型有选择性跳闸 以下只叙述后加速的相关内容,前加速不在赘述!!!

    2024年02月02日
    浏览(37)
  • verilog 3段式状态机

    3段式状态机写法,写出下图状态转换图。 1 确定输入输出信号,及其类型(是wire还是reg); 2 声明内部信号,一般需要定义current_state和next_state; 3 用3个always语句描述状态机。第一个用来次态和现态的转换,第二个always用于现态在输入情况下转换为次态的组合逻辑;第三个

    2024年02月15日
    浏览(50)
  • 【FPGA零基础学习之旅#10】按键消抖模块设计与验证(一段式状态机实现)

    🎉欢迎来到FPGA专栏~按键消抖模块设计与验证 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 🥝 模块设计: 🥝 按键消

    2024年02月12日
    浏览(45)
  • FOC:【2】SVPWM(七段式)的Verilog实现与仿真

    碎碎念: 经过近一周的调试与查错(不好意思我实在太菜了),才终于从MATLAB代码的基础上,实现了Verilog对SVPWM算法的实现,同时给出仿真的结果。 2022年10月20日更新 :实在抱歉,由于之前在算法中没有考虑到输入电压值量化以及死区时间的问题,我也是在电路测试过程中

    2023年04月08日
    浏览(82)
  • 【verilog基础】用状态机解决交通灯问题

    思路:计数器加状态机 1、状态组合 light1 light2 状态 状态转移条件 跳转至 红 (100) 绿 (001) S0

    2024年02月11日
    浏览(38)
  • 状态机与序列机

    状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。 一、线性序列机 序列机是什么 :用计数器对时钟个数计数,根据相应时钟周期下的单个周期时间和计数个数可以确定某个时刻

    2024年02月08日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包