2021-07-06

ANSHUN UNIVERSITY
数 字 逻 辑 电 路 实 验 论 文

(2021~2021年)

题 目: 有限状态机的设计实验

院 别: 数学与计算机科学学院
专业班级: 2020级计算机(1)班
学生姓名: 曹端庆 学号: 202003024011
学生姓名: 黄毓 学号: 202003024036

 指导教师:        阳瑞新      职称:    教师     
 起讫日期:      2021年6月——2021年7月            

安顺学院本科毕业论文原创性声明
本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果。对本文的研究作出重要贡献的个人和集体,均已在文中以明确方式表明。本人完全意识到本声明的法律后果由本人承担。

作者签名: 曹端庆、黄毓 日期:2021年6月28日

安顺学院本科毕业论文版权使用授权书
本毕业论文作者完全了解学校有关保留、使用论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权安顺学院可以将本论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本论文。

作者签名:曹端庆、黄毓 日期:2021年6月28日

导师签名:阳瑞新 日期:2021年6月28日
有限状态机的设计实验
专业:计算机科学与技术 指导教师:阳瑞新
姓名:曹端庆、 学 号:202003024011
姓名:黄毓 学 号:202003024036
摘 要

本课题研究的是利用Modelsim软件进行独立仿真,Verilog HDL(第二版)数字系统设计及仿真 十一章 实验7,一是为了掌握有限状态机的写法,二是为了理解三段式与两段式的写法和区别,最后完成有限状态机的仿真实验。
我们需要了解及掌握Modelsim软件的基本操作,根据教材书得知的实验要求、实验目的和实验代码通过Modelsim软件来实现。
本实验的内容由五大部分组成:完成一个序列检测器、编写测试代码、仿真部分。其中完成一个序列检测器为本实验重点,主要有编写设计代码和测试代码,再进行仿真。
本实验为mealy型有限状态机,它的输出不仅与当前状态有关系,而且与它的输入也有关系,因而在状态图中每条转移边需要包含输入和输出的信息。需要先画出状态图或写出状态转换表。但是状态转换图不利于编写代码,而状态转换表要更直观,可直接修改成代码形式。
关键词:Modelsim独立仿真 Verilog 有限状态机(三段式写法) 行为级建模
Design experiment of finite State Machine
This topic is to use Modelsim software to independently simulate, Verilog HDL (second edition) Digital system design and simulation Chapter 11 experiment 7, one is to master the writing method of finite state machine, the other is to understand the writing method and difference between three-stage and two-stage, and finally complete the simulation experiment of finite state machine.
We need to understand and master the basic operation of Modelsim software, and realize the experimental requirements, experimental purposes and experimental codes through Modelsim software according to the textbook.
The content of this experiment consists of five parts: completing a sequence detector, writing test code, and simulation. Among them, the completion of a sequence detector is the focus of this experiment, mainly writing design code and test code, and then simulation. This experiment is a Mealy finite state machine, and its output is not only related to the current state, but also to its input, so each transition edge in the state diagram needs to contain input and output information. You need to draw a state diagram or write a state transition table first. However, the state transition diagram is not conducive to writing code, and the state transition table is more intuitive and can be directly modified into code form.
Key words: Modelsim independent simulation Verilog finite state machine (three-stage writing) behavioral level modeling

目 录

1 总论 1
1.1绪论…8
1.1.1Modelsim的简介及使用流程 …11
1.2实验范围… 13
1.3实验依据 …13
1.4有限状态机…14
1.4.1Moore状态机…16
1.4.2Mealy状态机…16
1.4.3状态编码…17
1.4.4状态机的描述…18
1.4.5行为建模…30
2 实验部分 …30
2.1 实验目的…31
2.2 实验步骤…31
2.3实验注意事项…35
2.4 实验代码 …35
2.5 实验截图 39
2.6 实验视频 39
3 问题分析及解决方案 39
3.1 ModelSim的操作过程中常见错误类型及解决方法 40
4 实验博客网址 49
4.1 平时实验的博客网址 49
4.2 考试实验的博客网址 50
5结论 54
参考文献 51
致谢 53
1 总论

1 总论
1.1绪论
数字电路的发展与模拟电路一样经历了由电子管、半导体分立器件到集成电路等几个时代。但其发展比模拟电路发展的更快。从60年代开始,数字集成器件以双极型工艺制成了小规模逻辑器件。随后发展到中规模逻辑器件;70年代末,微处理器的出现,使数字集成电路的性能产生质的飞跃。
数字集成器件所用的材料以硅材料为主,在高速电路中,也使用化合物半导体材料,例如砷化镓等。
逻辑门是数字电路中一种重要的逻辑单元电路。TTL逻辑门电路问世较早,其工艺经过不断改进,至今仍为主要的基本逻辑器件之一。随着CMOS工艺的发展,TTL的主导地位受到了动摇,有被CMOS器件所取代的趋势。
近年来,可编程逻辑器件PLD特别是现场可编程门阵列FPGA的飞速进步,使数字电子技术开创了新局面,不仅规模大,而且将硬件与软件相结合,使器件的功能更加完善,使用更灵活。
数字逻辑电路分类
按功能来分:
1、组合逻辑电路
简称组合电路,它由最基本的逻辑门电路组合而成。特点是:输出值只与当时的输入值有关,即输出惟一地由当时的输入值决定。电路没有记忆功能,输出状态随着输入状态的变化而变化,类似于电阻性电路,如加法器、译码器、编码器、数据选择器等都属于此类。
2、时序逻辑电路
简称时序电路,它是由最基本的逻辑门电路加上反馈逻辑回路(输出到输入)或器件组合而成的电路,与组合电路最本质的区别在于时序电路具有记忆功能。时序电路的特点是:输出不仅取决于当时的输入值,而且还与电路过去的状态有关。它类似于含储能元件的电感或电容的电路,如触发器、锁存器、计数器、移位寄存器、储存器等电路都是时序电路的典型器件。
按电路有无集成元器件来分,可分为分立元件数字电路和集成数字电路。
按集成电路的集成度进行分类,可分为小规模集成数字电路(SSI)、中规模集成数字电路(MSI)、大规模集成数字电路(LSI)和超大规模集成数字电路(VLSI)。
按构成电路的半导体器件来分类,可分为双极型数字电路和单极型数字电路。
数字电路的特点
1、同时具有算术运算和逻辑运算功能
数字电路是以二进制逻辑代数为数学基础,使用二进制数字信号,既能进行算术运算又能方便地进行逻辑运算(与、或、非、判断、比较、处理等),因此极其适合于运算、比较、存储、传输、控制、决策等应用。
2、实现简单,系统可靠
以二进制作为基础的数字逻辑电路,可靠性较强。电源电压的小的波动对其没有影响,温度和工艺偏差对其工作的可靠性影响也比模拟电路小得多。
3、集成度高,功能实现容易
集成度高,体积小,功耗低是数字电路突出的优点之一。电路的设计、维修、维护灵活方便,随着集成电路技术的高速发展,数字逻辑电路的集成度越来越高,集成电路块的功能随着小规模集成电路(SSI)、中规模集成电路(MSI)、大规模集成电路(LSI)、超大规模集成电路(VLSI)的发展也从元件级、器件级、部件级、板卡级上升到系统级。电路的设计组成只需采用一些标准的集成电路块单元连接而成。对于非标准的特殊电路还可以使用可编程序逻辑阵列电路,通过编程的方法实现任意的逻辑功能。
数字电路的应用
数字电路与数字电子技术广泛的应用于电视、雷达、通信、电子计算机、自动控制、航天等科学技术各个领域。
数字电路的分类:
包括数字脉冲电路和数字逻辑电路。
前者研究脉冲的产生、变换和测量;后者对数字信号进行算术运算和逻辑运算。
数字电路的划分:
1.按功能分为组合逻辑电路和时序逻辑电路两大类。
前者在任何时刻的输出,仅取决于电路此刻的输入状态,而与电路过去的状态无关,它们不具有记忆功能。常用的组合逻辑器件有加法器、译码器、数据选择器等。
后者在任何时候的输出,不仅取决于电路此刻的输入状态,而且与电路过去的状态有关,它们具有记忆功能。
2.按结构分为分立元件电路和集成电路。
前者是将独立的晶体管、电阻等元器件用导线连接起来的电路。
后者将元器件及导线制作在半导体硅片上,封装在一个壳体内,并焊出引。

1.1.1 Modelsim的简介及使用流程
Modelsim简介:
Mentor公司的ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业界唯一的单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术、和单一内核仿真技术,编译仿真速度快,编译的代码与平台无关,便于保护IP核,个性化的图形界面和用户接口,为用户加快调错提供强有力的手段,是FPGA/ASIC设计的首选仿真软件。
使用流程:
modelsim 使用
1、打开modelsim
2、新建项目File-New-project,选择工作路径(建议先建一个文件夹来保存自己的工程)和设置工程名。
3、添加文件(这里可以根据自己所用的硬件语言而定,我使用的是Verilog,所用我选择Verilog,如果是用VHDL就选择VHDL)

4、编写代码,这里打了一个16加法器,里面缺了一个else分支就不要计较了。
module adder(clk,rst,q,p);
input clk;
input rst;
input p;
output reg[3:0]q;
always @(posedge clk or negedge rst)
if(!rst)
q <= 4’b0;
else if§
q <= q + 1’b1;
endmodule
5、编译代码,右键adder.v文件 Compile–Compile Select,看到下面提示successful就说明代码没问题了。
6、建立测试平台testbench
`include “adder.v”
module adder_test();
reg clk;
reg rst;
reg p;
wire [3:0]q;
//实例化adder
adder U0(clk,rst,q,p);
always #10 clk = ~clk;
initial begin
clk = 0;
rst = 1;
p = 0;
#10 rst = 0;
#10 rst = 1;
#10 p = 1;
end
endmodule
7、保存testbench文件,testbench后缀名可以是.v也可以是.vt
8、添加testbench文件到项目,到最后,一定要有一个testbench的文件
9、再一次编译两个文件
10、可以开始仿真了,工具栏-Simulate-Start Simulation,找到work,展开,选择testbench文件,然后点击ok
11、添加观察信号,观察信号可以更加自己的情况添加信号
12、设置仿真时间并开始仿真(点设置时间旁边那颗按键),之后会出现波形图
13、波形图里面的数值为二进制数值,不便观察,我们可以设置格式让波形变得容易观察,波形也可以放大缩小
设置好之后
14、好了可以观察波形是否符合自己的设计,这里的波形符合我的设计,我前面随便打的一个16位进制加法器,到了数字f(也就是数字15),则从数字0开始。如果不符合自己的设计,则需要修改代码了,这个根据自己的情况修改。
15、以上就是modelsim的使用流程。

1.2实验范围
Mealy和Moore状态机建模方法。还设计并实现了序列检测器、序列生成器和编码转换器,实践了两段和三段式的状态机。
1.3实验依据
  依据行为级建模的部分语法,有限状态机的三段式写法来实现。有限状态机的下一个状态不但取决于各个输入值,还取决于当前所在状态。这里指的是米里Mealy型有限状态机,而莫尔Moore型有限状态机的下一个状态只决于当前状态。
状态机的描述方法多种多样,将整个状态机写到1个always 模块里,在该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为一段式FSM 描述方法;还有一种写法是使用两个always 模块,其中一个always 模块采用同步时序的方式描述状态转移,而另一个模块采用组合逻辑的方式判断状态转移条件,描述状态转移规律,这种写法被称为两段式FSM 描述方法;还有一种写法是在两段式描述方法的基础上发展而来的,这种写法使用3 个always模块,一个always 模块采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件,描述状态转移规律,第三个always 模块使用同步时序电路描述每个状态的输出,这种写法称为三段式写法。

1.4有限状态机
有限状态机是由寄存器组和组合逻辑构成的硬件时序电路。有限状态机的状态(即由寄存器组的1和0的组合状态所构成的有限个状态)只可能在同一时钟跳变沿的情况下才能从一个状态转向另一个状态。有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。在计算机科学中,有限状态机被广泛用于建模应用行为、硬件电路系统设计、软件工程,编译器、网络协议、和计算与语言的研究。比如下图非常有名的TCP协议状态机。

其实我们在编程时实现相关业务逻辑时经常需要处理各种事件和状态切换,写各种switch/case 和if/else ,所以我们其实可能一直都在跟有限状态机打交道,只是可能没有意识到。在处理一些业务逻辑比较复杂的需求时,可以先看看是否适合用一个有限状态机来描述,如果可以把业务模型抽象成一个有限状态机,那么代码就会逻辑特别清晰,结构特别规整。
下面我们就来聊聊所谓的状态机,以及它如何在代码中实现。
1、状态机的要素
状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:
①现态:是指当前所处的状态。
②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
我们可以用状态表了表示整个过程,如下图所示。

状态表
这里需要注意的两个问题:
1、避免把某个“程序动作”当作是一种“状态”来处理。那么如何区分“动作”和“状态”?“动作”是不稳定的,即使没有条件的触发,“动作”一旦执行完毕就结束了;而“状态”是相对稳定的,如果没有外部条件的触发,一个状态会一直持续下去。
2、状态划分时漏掉一些状态,导致跳转逻辑不完整。
所以维护上述一张状态表就非常必要,而且有意义了。从表中可以直观看出那些状态直接存在跳转路径,那些状态直接不存在。如果不存在,就把对应的单元格置灰。 每次写代码之前先把表格填写好,并且对置灰的部分重点review,看看是否有“漏态”,然后才是写代码。QA拿到这张表格之后,写测试用例也是手到擒来。
2、状态机在object-C的代码实现。
我在开发百度地图导航过程页以及百度CarLife的反控手机识别中都用到了有些状态机编程,下面我结合个人的经验,给大家分享一个iOS程序中实现有限状态机的写法。
先回顾一下上面那个状态表,其中状态变迁时执行的动作,可能是由一系列的元动作组成,并且通常都是跟现态和次态强相关的,所以,我把状态表做一个改进,如下所示:

其中:FSM_FUN(stateA,stateB) 就表示,从状态stateA跳转到stateB时要执行的所有元动作的有序集。

1.4.1Moore型状态机

最大特点是输出只由当前状态确定,与输入无关。Moore状态机的状态图中的每一个状态都包含一个输出信号。这是一个典型的Moore状态机的状态跳转图,x、y、z是输入,a、b、c是输出。
1.4.2Mealy型状态机

它的输出不仅与当前状态有关系,而且与它的输入也有关系,因而在状态图中每条转移边需要包含输入和输出的信息。
1.4.3状态编码
数字逻辑系统状态机设计中常见的编码方式有:二进制码(Binary码)、格雷码(Gray码)、独热码(One-hot码)以及二一十进制码(BCD码)。
  格雷码的特点:相邻的两个码组之间仅有一位不同。
普通二进制码与格雷码之间可以相互转换。
  二进制码转换为格雷码:从最右边一位起,一次与左边一位“异或”,作为对应格雷码该位的值,最左边的一位不变(相当于最左边是0)。
  格雷码转换为二进制码:从左边第二位起,将每一位与左边一位解码后的值“异或”,作为该解码后的值(最左边的一位依然不变)。
  独热码又分为独热1码和独热0码,是一种特殊的二进制编码方式。当任何一种状态有且仅有一个1时,就是独热1码,相反任何一种状态有且仅有一个0时,就是独热0码。

1.4.4状态机的描述
一段式状态机
当把整个状态机卸载一个always模块中,并且这个模块既包含状态转移,又含有组合逻辑输入/输出时,称为一段式状态机。不推荐采用这种状态机,因为从代码风格方面来讲,一般都会要求把组合逻辑和时序逻辑分开;从代码维护和升级来说,组合逻辑和书序逻辑混合在一起不利于代码维护和修改,也不利于约束。
一段式即将“状态转移、状态输出和状态转移条件”写在一块。
//一段式状态机
reg [3:0] state;
localparam S0 = 4’b0001, //采用独热码
S1 = 4’b0010,
S2 = 4’b0100,
S3 = 4’b1000;

//共一段 采用时序逻辑完成状态机的转移、输出等
always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset
        dout    <=  1'b0;
        state   <=  S0;
    end
    else begin
        case(state)
            S0:begin
               dout    <=  1'b0;   //输出0
                if (din == 1'b1) begin
                    state   <=  S1;
                end
                else begin

state <= S0;
end
end

            S1:begin
               dout    <=  1'b0;   //输出0
                if (din == 1'b1) begin
                    state   <=  S1;
                end
                else begin
                    state   <=  S2;
                end
            end

            S2:begin
               dout    <=  1'b0;   //输出0
                if (din == 1'b1) begin
                    state   <=  S3;
                end
                else begin
                    state   <=  S0;
                end
            end

S2:begin
dout <= 1’b0; //输出0
if (din == 1’b1) begin
state <= S3;
end
else begin
state <= S0;
end
end

            S3:begin
               dout    <=  1'b1;   //输出1
                if (din == 1'b1) begin
                    state   <=  S1;
                end
                else begin
                    state   <=  S2;
                end
            end

            default:begin
                dout    <=  1'b0;
                state   <=  S0;

end
endcase
end
end

一段式的状态机的RTL如下图所示:

一段式状态机RTL
一段式的状态机的RTL综合后的结果如下图所示:

一段式状态机RTL综合后的结果

两段式状态机
所谓的两段式状态机就是采用一个always语句来实现时序逻辑,另外一个always语句来实现组合逻辑,提高了代码的可读性,易于维护。不同于一段式状态机的是,它需要定义两个状态----现态和次态,然后通过现态和次态的转换来实现时序逻辑。
两段式即将“状态转移”、“状态输出和状态转移条件”分成两部分写,容易理解,便于维护。(组合逻辑不用复位)
//两段式状态机 reg [3:0] current_state; //当前状态 reg [3:0] next_state; //下一状态 localparam S0 = 4’b0001, //采用独热码 S1 = 4’b0010,
S2 = 4’b0100,
S3 = 4’b1000;

//第一段 采用时序逻辑完成状态转移    always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset            current_state   <=  S0;
    end
    else begin
        current_state   <=  next_state;
    end
end

//第二段 采用组合逻辑完成转移条件判断和状态输出    always @(*) begin
    case(current_state)
        S0:begin
            dout    =  1'b0;   //输出0                if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S0;
            end
        end

        S1:begin
            dout    =  1'b0;   //输出0                if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        S2:begin
            dout    =  1'b0;   //输出0                if (din == 1'b1) begin
                next_state   =  S3;
            end
            else begin
                next_state   =  S0;
            end
        end

        S3:begin
            dout    =  1'b1;   //输出1                if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        default:begin
            dout        =  1'b0;
            next_state  =  S0;
        end
    endcase
end

两段式的状态机的RTL如下图所示:

两段式状态机RTL
两段式的状态机的RTL综合后的情况如下图所示:

两段式状态机RTL综合后的结果

三段式状态机
  三段式状态机与两段式状态机的区别:两段式直接采用组合逻辑输出,而三段式则通过在组合逻辑后再增加一级寄存器来实现时序逻辑输出。这样做的好处是可以有效地滤去租个逻辑输出的毛刺,同时可以有效地进行时序计算与约束,另外对于总线形式的输出信号来说,容易使总线数据对其,从而减小总线数据间的偏移,减小接收端数据采样出错的频率。
三段式状态机的基本格式是:第一个always语句实现同步状态跳转;第二个always语句实现组合逻辑;第三个always语句实现同步输出。
三段式即将“状态转移”、“转移条件”、“状态输出”分三部分写,可能在看起来会比较的难写,但是了解结构之后感觉就像八股文或是填空题一样。但需要注意的是:第三段不一定是采用一个always完成,如果输出的信号较多可以采用多个。(组合逻辑不用复位)
//三段式状态机 reg [3:0] current_state; //当前状态 reg [3:0] next_state; //下一状态 localparam S0 = 4’b0001, //采用独热码 S1 = 4’b0010,
S2 = 4’b0100,
S3 = 4’b1000;

//第一段 采用时序逻辑完成状态转移    always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset            current_state   <=  S0;
    end
    else begin
        current_state   <=  next_state;
    end
end

//第二段 采用组合逻辑完成转移条件判断    always @(*) begin
    case(current_state)
        S0:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S0;
            end
        end

        S1:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        S2:begin
            if (din == 1'b1) begin
                next_state   =  S3;
            end
            else begin
                next_state   =  S0;
            end
        end

        S3:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        default:next_state  =  S0;
    endcase
end

//第三段 采用时序逻辑状态输出    always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset            dout    <=  1'b0;
    end
    else begin
        case(next_state)    //采用next state,提前一拍                S0:begin
                dout    <=  1'b0;   //输出0                end

            S1:begin
                dout    <=  1'b0;   //输出0                end

            S2:begin
                dout    <=  1'b0;   //输出0                end

            S3:begin
                dout    <=  1'b1;   //输出1                end

            default:dout    <=  1'b0;
        endcase
    end
end

三段式的状态机的RTL如下图所示:
三段式即将“状态转移”、“转移条件”、“状态输出”分三部分写,可能在看起来会比较的难写,但是了解结构之后感觉就像八股文或是填空题一样。但需要注意的是:第三段不一定是采用一个always完成,如果输出的信号较多可以采用多个。(经评论区提醒组合逻辑不用复位)
//三段式状态机 reg [3:0] current_state; //当前状态 reg [3:0] next_state; //下一状态 localparam S0 = 4’b0001, //采用独热码 S1 = 4’b0010,
S2 = 4’b0100,
S3 = 4’b1000;

//第一段 采用时序逻辑完成状态转移    always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset            current_state   <=  S0;
    end
    else begin
        current_state   <=  next_state;
    end
end

//第二段 采用组合逻辑完成转移条件判断    always @(*) begin
    case(current_state)
        S0:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S0;
            end
        end

        S1:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        S2:begin
            if (din == 1'b1) begin
                next_state   =  S3;
            end
            else begin
                next_state   =  S0;
            end
        end

        S3:begin
            if (din == 1'b1) begin
                next_state   =  S1;
            end
            else begin
                next_state   =  S2;
            end
        end

        default:next_state  =  S0;
    endcase
end

//第三段 采用时序逻辑状态输出    always @(posedge clk or posedge rst) begin
    if (rst) begin
        // reset            dout    <=  1'b0;
    end
    else begin
        case(next_state)    //采用next state,提前一拍                S0:begin
                dout    <=  1'b0;   //输出0                end

            S1:begin
                dout    <=  1'b0;   //输出0                end

            S2:begin
                dout    <=  1'b0;   //输出0                end

            S3:begin
                dout    <=  1'b1;   //输出1                end

            default:dout    <=  1'b0;
        endcase
    end
end

三段式的状态机的RTL如下图所示:

三段式状态机RTL
三段式的状态机的RTL综合后的结果如下图所示:

三段式状态机RTL综合后的结果
1.4.5行为建模
Verilog支持结构级和行为级建模。结构级建模就是把基本与/或门的功能单元进行连接,产生某一特定的功能器件(如加法器),就像部件在芯片或电路板互连一样。但是,门级模型不- -定是电路最简单或最容易理解的模型,特别是当设计包含较多逻辑门的时候。许多现代专用集成电路( ASIC)在一一个芯片上就可能有几百万个逻辑门。同样,当电路有多个输人端的时候,真值表也变得不再实用,而且也限制了Verilog用户自定义原语的应用。在当今设计ASIC和现场可编程门阵列(FPGA)的方法中,大规模的电路被分割以形成一-个架构一即通过端口进行通信的功能单元组成的结构,这样就可以用一个能表示其功能的行为级模型来描述每-一个单元。尽管架构是由比整个设计简单的多个功能单元构成的,但是设计者仍然不能直接完成它们的门级实现。他们只是写出所谓的行为模型,而这些模型可以被自动地综合成]级电路结构。
传统情况下,设计者通过采用原理图输人工具把逻辑门连接起来形成门电路,完成门级(结构级)设计。但是现代设计方法则是将一个 设计在抽象级别上进行分解和表述,然后再将其综合为对应的门级电路。综合工具将硬件描述语言( HDL)翻译并映射到物理工艺,如ASIC标准单元库,或者FPGA的可编程器件库。
行为级建模是工业上采用的一- 种非常重要的描述方式,可以用来进行大型芯片设计。行为级建模描述设计的功能特性,即所设计的电路是干什么的,而不用考虑怎样实现它的硬件设计。行为级模型描述的是逻辑电路的输入输出模型,忽略了电路的低层次内部结构和物理实现的细节。传播延时不包含在电路的行为级模型中,但是,当对逻辑的物理实现施加了时序约束后,综合工具将对目标工艺库单元的传播延时予以考虑。行为建模鼓励设计者去做如下的事情:
(1)快速地创建该设计的行为模型(不要将模型与硬件细节联系起来);
(2)验证其功能;
(3)用综合工具将设计优化并映射到所选择的物理工艺,使其满足时序和/或面积的约束条件。
如果行为级模型是以一-种易综合的方式描述的D,那么综合工具将去除冗余逻辑,并在可供选择的电路结构和/或多级等效电路之间进行分析权衡,最终完成-一个面积和时序约束都达到要
求的设计。由于设计者将注意力集中到所实现的电路功能上,而不是具体逻辑门和它们的连接上,因而在将设计投产之前行为级建模为电路结构的选择提供了较大的*度。
除了在综合中的重要性以外,行为级建模还允许将部分设计在不同的抽象层次和完整性级别上进行建模,这就为完成设计项目提供了灵活性。Verilog语言适用于混合级别的抽象层次描述,使得在门级(即结构上)实现的设计部分能够与行为级描述设计部分同步,并能进行综合和仿真。

2 实验部分
2.1实验目的

  1. 进一步学习时序逻辑电路
  2. 了解有限状态机的工作原理
  3. 有限状态机三段式写法

2.2实验步骤
(1)在硬盘里新建一个文件夹,建议把建的文件夹和modelsim,放在同一个盘里,然后在桌面或者任意一个盘里建立一个.v文件可以把设计代码和测试代码放在一个文件里,也可以分开放。

(2)打开modelsim软件之后,先点击close关闭弹出窗口,然后新建一个项目设置一个工程名称,这个工程名称也可以跟模块名同名,点击OK

(3)添加现有文件,即添加我们之前已经编写好的,装有设计代码和测试代码的.v文件

(4)添加完成之后,直接关闭Add items to the project窗口,然后右键单击compile选择compile All,进行编译,如果后面还要添加别的.v文件进行仿真,可以右键点击Add to Project,然后添加现有文件,或者自己临时编写代码。

(5)可以点击Simulate,然后再点击start simulation 进行仿真,也可以直接点击右边的小图进行仿真。

(6)先点击sim窗口右键单击添加波形,再回到wave窗口。

(7)开始运行,得到最终结果波形图(这里我把信号调到了700)

2.3实验注意事项
注意敲代码时,代码中大小写的区别,符号都要在英文状态下。

2.4实验代码
设计代码:
module s7 (x,z,clk,reset) ;
input x,clk,reset;
output z;
reg z;
reg [2: 0] state,nstate;
parameter s0='d0,s1='d1,s2='d2,s3='d3,s4='d4,s5='d5;
always @ (posedge clk or posedge reset)
begin
if (reset)
state <=s0;
else
state <=nstate;
end
always@ (state or x)
begin
casex (state)
s0:begin
if (x1)
nstate=s1;
else
nstate=s0;
end
s1:begin
if (x
0)
nstate=s2;
else
nstate=s1;
end
s2:begin
if (x0)
nstate=s3;
else
nstate=s1;
end
s3:begin
if (x
0)
nstate=s0;
else
nstate=s4;
end
s4:begin
if (x0)
nstate=s5;
else
nstate=s1;
end
s5:begin
if (x
0)
nstate=s0;
else
nstate=s1;
end
default:nstate=s0;
endcase
end
always@ (posedge clk)
begin
casex (nstate)
s0:z <=0;
s1:z <=0;
s2:z <=0;
s3:z <=0;
s4:z <=0;
s5:z <=1;
default:z <=0;
endcase
end
endmodule

module tbs7;
reg x,clk,reset;
wire z;
integer seed=9;

initial clk=0;
always #5 clk=~clk;
initial
begin
reset=0;
#15 reset=1;
#15 reset=0;
end

always
#10 x={$random(seed)}%2;
s7 mys7(x,z,clk,reset);

endmodule

测试代码:
module tbs7;
reg x,clk,reset;
wire z;
integer seed=9;

initial clk=0;
always #5 clk=~clk;

initial
begin
reset=0;
#15 reset=1;
#15 reset=0;
end

always
#10 x={$random(seed)}%2;
s7 mys7(x,z,clk,reset);
endmodule

2.5实验截图

2.6实验视频
【有限状态机-哔哩哔哩】https://b23.tv/WWfhk6

3问题分析及解决方案
3.1 ModelSim的操作过程中常见错误类型及解决方法
一、Error deleting “msim_transcript”
Error deleting “msim_transcript”:permission denied.
Check the NativeLink log file

问题原因
同一工程Modelsim窗口多开。
解决方法
关闭正在运行的modelsim软件,再启动仿真。
二、Error: (vsim-3170) Could not find
** Error: (vsim-3170) Could not find ‘……simulation/modelsim/rtl_work.HEX4_tb’.
Error loading design

问题原因
testbench文件名与其中module 后紧跟的名称不匹配,如下图文件名为HEX4_tb,而实际文件中的module名为HEX_tb:

而在设置testbench链接设置时,却将Testbench name和Top level module in test bench的名字都设置为了HEX4_tb,导致modelsim仿真时无法找到时找top level (HEX4_tb),因为testbench中命名的是HEX_tb,而通过脚本告诉modelsim的时候却是告诉的HEX4_tb,当然找不到。

解决方法
方法1:将Testbench中的module名改为HEX4_tb,仿真即可通过,如下图所示:

方法2:在quartus 的testbench设置部分将Top level module in test bench部分设置为testbench中命名的名字,即不更改testbench中的module名字,让其依旧保持为HEX_tb,而在设置部分如下设置:

然后运行仿真,也可以正常进行仿真。如下图:

三、You selected Modelsim-Altera as Simulation Software in EDA Tool Settings,however……
You selected ModelSim-Altera as Simulation Software in EDA Tool Settings,however NativeLink found ModelSim in the pata – correct path or change EDA Tool Settings and try again.

问题原因
该工程设置的仿真工具名称与在Quartus II软件中指定的该软件路径不匹配。例如,本来设置的仿真工具是modelsim–altera,结果在Quartus II软件的modelsim-altera路径下设定的是Tools下设置的是modelsim-se的路径,导致软件版本不匹配而报错。

设置的仿真工具为modelsim-altera

Modelsim-altera路径却指向了modelsim-se版本。
解决方法
1、 如果你电脑装的是modelsim-se版本,请按照如下图所示的设置进行工程和工具路径设置:

2、 如果你的电脑装的是modelsim-altera版本,请按照如下图所示的设置进行工程和工具路径设置:

四、Unable to checkout a license

问题原因
使用了非免费版本的Modelsim软件,却没有获得软件使用许可证
解决方法
方法1:使用免费版本的modelsim软件,如modelsim altera stater edition。
方法2:购买软件许可证。
方法3: 破解modelsim软件,破解方法见如下链接(altera收费版和se版本破解思路相同,破解工具通用):
modelsim-win64-10.1c 下载、安装、破解全攻略
http://bbs.elecfans.com/jishu_433057_1_1.html
(出处: 中国电子技术论坛)
获得许可后最好重启Quartus II软件
五、Error loading design

问题原因
提示信息中提示没有Verilog的仿真许可证,表明是没有获得软件使用许可。

即使用了非免费版本的Modelsim软件,却没有获得软件使用许可证
解决方法
方法1:使用免费版本的modelsim软件,如modelsim altera stater edition。
方法2:购买软件许可证。
方法3: 破解modelsim软件,破解方法见如下链接(altera收费版和se版本破解思路相同,破解工具通用):
modelsim-win64-10.1c 下载、安装、破解全攻略
http://bbs.elecfans.com/jishu_433057_1_1.html
(出处: 中国电子技术论坛)
获得许可后最好重启Quartus II软件
六、Analysis and Synthesis should be completed
Analysis and Synthesis should be completed successfully before starting RTL NativeLink Simulation

问题原因
仿真前需要在Quartus II中执行一次分析和综合。
解决方法
仿真前需要在Quartus II中执行一次分析和综合。

七、关于Modesim闪退错误
如下图所示:

1、运行CMD调出命令窗口。运行命令msconfig

出现如下窗口

2、选择启动栏,查看电脑的启动项都有那些,这是系统级的禁用~

4 实验博客网址
4.1 平时实验的博客网址:
曹端庆:
https://blog.csdn.net/yycya/article/details/118102570?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/117564324?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/117362607?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/117170684?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/116500669?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/116499897?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/115444824?spm=1001.2014.3001.5501
https://blog.csdn.net/yycya/article/details/114840803?spm=1001.2014.3001.5501(勾题实验)
黄毓:
https://blog.csdn.net/qq_54046303/article/details/114840506?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/115742697?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/117134156?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/117135514?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/117136721?spm=1001.2014.3001.5501(93页勾题实验)
https://blog.csdn.net/qq_54046303/article/details/117364020?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/117560235?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/117817372?spm=1001.2014.3001.5501

4.2 考试实验的博客网址:
黄毓:
https://blog.csdn.net/qq_54046303/article/details/118047867?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/118219727?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_54046303/article/details/118219875?spm=1001.2014.3001.5501

曹端庆:
https://blog.csdn.net/yycya/article/details/118102570?spm=1001.2014.3001.5501

5结论
三段式状态机是较为常用的写法。

参考文献

[1] 于斌 黄海编著作.Verilog HDL(第二版)数字系统设计及仿真. 电子工业出版社
[2]Michael D.Ciletti 著.Verilog HDL 高级数字设计(第二版).电子工业出版社
[3]斯蒂芬·布朗 斯万克·瓦拉纳西 著.数字逻辑基础与Verilog设计 (原书第三版).机械工业出版社
[4]百度百科
[5]CSDN
[6]知乎

格式: “参考文献”标题用黑体、三号、较粗、居中、与正文空一行;下文用宋体小四,顶格,行距1.5倍。参考文献中的标点符号均在英文输入状态下输入。

致 谢

这部分内容主要是表达对作者的论文写作中提供指导与帮助的老师、同学、朋友、亲人等的感谢。

毕业论文(设计)一律采取A4纸张打印,页边距:上2.7cm、下2.5cm,左2.5cm,右2.5cm,行间距1.5倍;字符间距为默认值(缩放100%,间距:标准);单面或双面打印形式由各二级学院自行统一。

上一篇:FPGA 的笔记总结(未完结。。。)


下一篇:关于Verilog 中的for语句的探讨