第1章 概述

1.1 EDA技术及其发展

EDA技术的含义、发展历程、与其他设计技术的比较。

电子设计自动化,“自顶向下”设计思想。
EDA技术用软件工具自动化地设计硬件电路。
发展历程:CAD -> CAE -> EDA

1.2 EDA技术四要素

软件开发工具、几种常用硬件描述语言、可编程逻辑器件的演化、实验开发系统简介。

1.3 EDA流程及工具

文本与原理图两种输入方式、综合与优化、布线/适配、下载、硬件测试以及贯穿设计始终的仿真

1.4 IP核

IP核的优势以及种类

1.5 EDA技术应用展望

第2章 CPLD/FPGA结构与工作原理

概述——可编程逻辑器件结构的演进

自20世纪60年代初集成电路诞生以来, 经历了SSI、 MSI、LSI、 VLSI、 ULSI几个发展阶段,同时,数字系统设计技术也随之发生了崭新的变化。

(1)最初是只有与—或单元结构的简单PLD(SPLD), 随着集成技术的进一步发展,出现了集成规模更大、密度更高的PLD(HDPLD)。

(2)HDPLD又可分为复杂PLD(CPLD)和FPGA两类: 在有效扩展SPLD和吸取标准单元阵列的构思基础上,构成了复杂PLD(CPLD),它已不再完全局限于由两级与—或电路构成的阵列; 在门阵列的基础上诞生了现场可编程门阵列(FPGA)。

(3)随着集成电路技术的发展, 电路的集成规模越来越大, 在一颗芯片上已经可以集成一个独立的系统,完成特定的功能(SOC),ASIC和FPGA是实现SOC的两大途径。

(4)由于FPGA在可编程、设计成本、上市速度方面具有ASIC不可比拟的优点,而ASIC在价格以及实现系统的某些特定物理特性上又有FPGA无法实现的优势, 为了解决这方面的矛盾,人们创造性地提出了将两种技术融合在一起, 研发了具有FPGA功能模块的ASIC芯片和具有ASIC功能模块的PLD芯片。

2.1 CPLD

随着微电子技术和数字系统应用需求的发展,小规模的PLD器件已不适合用户的设计需求,于是,以CPLD和FPGA为代表的大规模PLD器件应运而生。美国Altera公司发明的EPLD/CPLD就是其中之一。逻辑块间的可编程连接和I/O单元与GAL器件类似,可实现多种配置方式:专用组合输出、专用输入、组合I/O、 寄存器时序输出和寄存器I/O等,用来实现电路的灵活的输入输出。

CPLD的内部一般由数个到数十个可编程逻辑块(LAB)阵列组成, LAB的逻辑资源相对较大,一般包含十多个至数十个触发器和可实现数位到数十位的宽位译码组合逻辑资源。相对而言,内部连线资源较少,主要由集中分布的可编程内联线的布线池构成器件的内连线资源。由于单元逻辑资源大,布线相对集中,因而灵活性较低。CPLD器件在应用设计中很难使器件的资源利用率提高, 一般都小于80%。

但是,由于该器件的内部连线资源比较固定, 因此其连线延时是可以预测的,从而为电路设计的时延控制带来了方便; 同时, 该器件的所有I/O脚均可根据需要实现输入或输出的定义。

2.2 FPGA

1985年,美国Xilinx公司发明了现场可编程阵列器件——FPGA, 从而开创了大规模数字逻辑系统可以现场集成、现场实现的新纪元。Xilinx公司的FPGA采用SRAM编程,主要由可配置逻辑块(CLB)、可编程输入输出模块(IOB)和可编程连线(PI)组成,如果将EPLD/CPLD也归入现场可编程门阵列器件计算, 则现场可编程阵列器件按其编程方式, 基本分为3种: 基于SRAM编程的FPGA, 基于E2PROM、 Flash编程的FPGA,基于反熔丝编程的FPGA。

目前多数FPGA属于基于SRAM编程的FPGA,这个类型的器件内部结构主要有3个部分:可编程阵列基本单元(CLB),可编程I/O和可编程内连线。在所有可编程的阵列分布的单元和布线中, 其可编程点阵接通和关断是由阵列分布的SRAM编程开关控制的。 这些开关分布于芯片的各可编程单元,在芯片功能定义的数据下载网表的作用下,实现资源调用和布局布线的物理实现。

FPGA在结构方面有它自身的独特之处。它的逻辑块的逻辑资源相对小,而其连线资源相对丰富,这就使得它在实现逻辑功能时有很大的灵活性,可以实现很复杂的运算逻辑功能。但同时,其在设计布线过程中无法控制每一根线的布置方式,布线的可控性降低, 延时特性很难预测,这样给其电路实现的时序控制带来一定困难。

小结:2.3 CPLD和FPGA的比较

第3章 VHDL结构与要素

3.1 VHDL概述

以与门电路为例,将代码划分为3个层次——库语句与包语句,实体,结构体。

3.2 VHDL结构

3.2.1库、程序包与配置

(1)库

在利用VHDL进行工程设计中,为了提高设计效率以及使设计遵循某些统一的语言标准或数据格式,有必要将一些有用的信息汇集在一个或几个库中以供调用。

库(LIBRARY)的语句格式如下:

            LIBRARY 库名;

库的种类、库的用法

1) IEEE库
2) STD库
3) WORK库

(2)程序包

1) STD_LOGIC_1164程序包
2) STD_LOGIC_ARITH程序包
3) STD_LOGIC_UNSIGNED和STD_LOGIC_SIGNED程序包
4) STANDARD和TEXTIO程序包

(3)配置

3.2.2实体

实体:语句结构、端口说明语句与端口类型

实体是一个设计实体的表层设计单元,其功能是对这个设计实体与外部电路进行接口描述。它规定了设计单元的输入/输出接口信号或引脚,是设计实体经封装后对外的一个通信界面。

实体说明单元的一般语句结构:

    ENTITY  实体名  IS

    [GENERIC ( 参数名:数据类型 );]--------例GENERIC ( n : INTEGER );                
    --定义类属参量及其数据类型

    [PORT ( 端口表 );]

    END ENTITY 实体名;

其中:

PORT ( 端口名 : 端口模式  数据类型 ;

      { 端口名 : 端口模式  数据类型} ) ;   

端口说明语句

3.2.3结构体

结构体是用于描述设计实体的内部结构以及实体端口间的逻辑关系。一般地,一个完整的结构体由两个基本层次组成:

   对数据类型、常数、信号、子程序和元件等元素的说明部分。

   描述实体逻辑行为的,以各种不同的描述风格表达的功能描述语句。

3.3 端口模式

IN:输入,只读模式,将变量或信号信息通过该端口读入

OUT:输出,单向赋值模式,将信号通过该端口输出

BUFFER:具有读功能的输出模式,可以读或写,只能有一个驱动源。

INOUT:双向,可以通过该端口读入或写出信息

3.4数据类型

(1)VHDL预定义数据类型

(2)IEEE预定义标准逻辑位与矢量

(3)其它预定义标准逻辑数据类型

(4)枚举类型、数组类型(本次课略讲,在6.5节状态机的VHDL设计中详讲)

3.5数据对象

3.5.1常量(CONSTANT)

在程序中,常量是一个恒定不变的值,一旦作了数据类型的赋值定义后,在程序中不能再改变,因而具有全局意义。

3.5.2变量(VARIABLE)

在VHDL语法规则中,变量是一个局部量,只能在进程和子程序中使用。变量不能将信息带出对它作出定义的当前设计单元。变量的赋值是一种理想化的数据传输,是立即发生,不存在任何延时的行为。VHDL语言规则不支持变量附加延时语句。

3.5.3信号(SIGNAL)

信号是描述硬件系统的基本数据对象,它类似于连接线。信号可以作为设计实体中并行语句模块间的信息交流通道。

3.5.4信号与变量的比较

举例分析

3.5.5信号与变量的赋值

(1)同一信号多个赋值源

(2)单个变量赋值语句与单个信号赋值语句的比较

(3)多个变量传递赋值与多个信号传递赋值的比较

3.6操作符

并置操作符“&”、移位操作符举例详讲

VHDL的各种表达式由操作数和操作符组成,其中,操作数是各种运算的对象,而操作符则规定运算的方式。

(1)并置连接操作符

(2)逻辑操作符

(3)关系操作符

(4)算术操作符

3.7文字规则

数字、字符串、标识符、下标名

第4章 QuartusII应用指南

4.1 VHDL文本输入设计流程

示例程序:模8计数器

4.1.1 建立工作库文件夹和编辑设计文件

4.1.2 创建工程

4.1.3 全程编译

4.1.4 时序仿真

4.1.5 应用RTL电路图观察器

4.1.6 引脚锁定

4.2 原理图输入设计方法

按所示逻辑电路图,用FPGA器件设计完成电路。

第5章 VHDL基本语句

  1. 提出项目目标——设计动态扫描显示电路

(1)讲解静态和动态扫描显示的工作原理以及二者优劣,划分设计模块,厘清各模块间关系。

(2)带着目标进行新课学习

  1. 新课

5.1顺序语句

5.1.1赋值语句

赋值语句由3个基本部分组成——赋值目标、赋值符号、赋值源。

赋值目标是赋值的受体,它的基本元素只能是信号或变量。

赋值符号有信号赋值符号和变量赋值符号。

5.1.2 IF语句

IF语句是一种条件语句,它根据语句中所设置的一种或多种条件,有选择地执行指定的顺序语句。

IF语句概述及应用举例

小练习

  1. 用IF语句设计8-1MUX、组合逻辑设计。
  2. 编译、仿真练习

5.1.3 CASE语句
语句格式、应用举例和练习

CASE语句

CASE语句根据满足的条件直接选择多项顺序语句中的一项执行。

            CASE语句的结构如下:

            CASE  表达式  IS

            WHEN   选择值  =>顺序语句; 

            WHEN   选择值  =>顺序语句;

             …

             [ WHEN   OTHERS =>顺序语句;]

     END CASE;

使用CASE语句的注意事项。

小练习——

  1. 用CASE语句设计8-1MUX等组合逻辑设计。
  2. 动态扫描显示电路设计初步

5.1.4 LOOP语句

LOOP语句就是循环语句,它可以使所包含的一组顺序语句被循环执行,其执行次数可由设定的循环参数决定.

 FOR  循环变量 IN  循环次数范围  LOOP                        

讲解8位奇偶校验的工作原理及用途

小练习:
8位串入/并出移位寄存器、8位并入/串出移位寄存器、左移和右移两种移位模式的实现。

与并置语句实现移位的比较:

Q(7 downto 0)<=DIN &  q(7 downto 1) ---右移

Q(7 downto 0)<= q(6 downto 0) &  DIN---左移

5.1.5 NEXT语句
NEXT语句主要用在LOOP语句执行中有条件的或无条件的转向控制。它的语句格式为

             NEXT  [LOOP  标号] [WHEN  条件表达式];      

示例程序讲解

5.1.6EXIT语句

EXIT语句也是LOOP语句的内部循环控制语句,其语句格式如下:

                 EXIT [LOOP 标号] [WHEN 条件表达式];                                         

这种语句格式与前述的NEXT 语句的格式和操作功能非常相似,惟一的区别是NEXT语句是跳向LOOP语句的起始点,而EXIT语句则是跳向LOOP语句的终点。

示例程序讲解

5.1.7WAIT语句

在进程中(包括过程中),当执行到WAIT等待语句时,运行程序将被挂起(Suspension),直到满足此语句设置的结束挂起条件后,将重新开始执行进程或过程中的程序。但VHDL规定,已列出敏感量的进程中不能使用任何形式的WAIT语句。WAIT语句的语句格式如下:

 WAIT[ON   信号表][UNTI  条件表达式][FOR  时间表达式];

示例程序讲解

  1. “动态扫描显示”项目设计的实现

运用所学顺序语句,完成项目各模块。

思考:如果显示的数据是未知且变化的,将怎样完成显示?

5.2.3 元件例化语句(第11课)

元件例化就是将预先设计好的设计实体定义为一个元件,然后利用特定的语句将此元件与当前的设计实体中的指定端口相连接,从而为当前设计实体引入一个新的低一级的设计层次。

元件例化语句由两部分组成,前一部分是将一个现成的设计实体定义为一个元件的语句,第二部分则是此元件与当前设计实体中的连接说明,它们的语句格式如下:

元件定义语句:

COMPONENT  例化元件名  IS                         

GENERIC (类属表);                                  

PORT(例化元件端口名表);

ENDCOMPONENT  例化元件名;

元件例化语句:

元件例化名:例化元件名 PORT MAP(   

[例化元件端口名=>] 连接实体端口名,…);

案例:

5.2.4 生成语句

练习:用元件例化语句设计节拍脉冲发生器

第6章 状态机

6.5状态机的VHDL设计(第12课)

6.5.1状态机设计的优势

状态机克服了纯硬件数字系统顺序方式控制不灵活的缺点;

状态机可以定义符号化枚举类型的状态;

状态机容易构成性能良好的同步时序逻辑模块;

状态机的VHDL表述丰富多样、程序层次分明,易读易懂;

在高速运算和控制方面,状态机更有其巨大的优势;

高可靠性;

※例如:机械手工作、交通灯控制系统、自动售货机、A/D转换控制系统。

6.5.2状态机的形式

重点讲解米利型与摩尔型、单进程与双进程

6.5.3状态机的基本结构

主控时序进程、主控组合进程、辅助进程

6.5.4一般状态机的VHDL设计

为了能获得可综合的,高效的VHDL状态机描述,建议使用枚举类数据类型来定义状态机的状态,并使用多进程方式来描述状态机的内部逻辑。——此处介绍3.4节 数据类型中的“枚举类数据类型”

(1)双进程基本结构

TYPESTATES IS (ST0,ST1,ST2,ST3);      

                          --定义STATES为枚举型数据类型

SIGNALCURRENT_STATE,NEXT_STATE:STATES;

BEGIN


REG:PROCESS (RESET,CLK)IS        

                      --时序逻辑进程

BEGIN

IFRESET=‘1’THEN

CURRENT_STATE<=ST0;                     --异步复位

ELSIF(CLK=‘1’ AND CLK’EVENT) THEN

CURRENT_STATE<=NEXT_STATE;   

                          --当测到时钟上升沿时转换至下一状态

END IF;

ENDPROCESS REG;  

--由CURRENT_STATE将当前状态值带出此进程,进入进程COM

COM:PROCESS(CURRENT_STATE,STATE_INPUTS) IS          --组合逻辑进程

BEGIN

CASECURRENT_STATE IS          --确定当前状态的状态值

WHENST0=>COMB_OUTPUTS<=“00”;

--初始态译码输出“00”

进程间一般是并行运行的,但由于敏感信号的设置不同以及电路的延迟,在时序上,进程间的动作是有先后的。

(2)单进程基本结构

TYPE ST_TYPE IS (ST0, ST1, ST2,ST3,ST4); 

  SIGNAL C_ST : ST_TYPE ;

   BEGIN                  

   PROCESS(CLK,RST)

    BEGIN   

   IF RST ='1' THEN  C_ST <= ST0 ;Q<= "0000" ;

     ELSIF CLK'EVENT AND CLK='1' THEN              

CASE C_ST IS        

        WHEN ST0 => IF DATAIN ="10" THEN C_ST <= ST1 ;

               ELSE C_ST <= ST0 ; END IF;

               Q <= "1001" ;

练习:
设计模5可控计数器,要求:外输入M=0,则计数器保持原状态;M=1,则加1计数。设计状态图并用状态机设计法实现。

课程练习

移位寄存器设计

“FOR-LOOP语句”和“信号并置与赋值语句”任选其一,设计8位移位寄存器。

要求:(1)在时钟CLK上升沿触发下,M=00,实现并行置数;M=01,实现左移;M=10实现右移。

(2)串行输入数据为DIN,并行8位预置数为data,串行输出端为output。

(3)rst为使能端:rst=0,则寄存器清零,否则将正常工作。

写出代码,给出编译通过截图。

我的答案:(没有右移输出)

library ieee;

use ieee.std_logic_1164.all;



entity shift_reg_8 is

    port( CLK : in std_logic;

          RST : in std_logic;

          M : in std_logic_vector(1 downto 0);

          --00    load

          --01    left

          --10    right

          DIN : in std_logic;

          DATA : in std_logic_vector(7 downto 0);

          TEST : out std_logic_vector(7 downto 0);

          OUTPUT : out std_logic);

end shift_reg_8;



architecture BHV of shift_reg_8 is

    signal REG : std_logic_vector(7 downto 0) := (others => '0');

begin

    process(CLK, RST)

    --variable REG : std_logic_vector(7 downto 0) := (others => '0');

    begin

        if (RST = '0') then

            REG <= (others => '0');

        elsif rising_edge(CLK) then

            case M is

                when "00" =>

                    --load

                    REG <= DATA;

                when "01" =>

                    --left

                    REG <= REG(6 downto 0) & DIN;

                when "10" =>

                    --right

                    REG <= DIN & REG(7 downto 1);

                when "11" =>

                    --hold

                    REG <= REG;

                when others =>

                    null;

            end case;

        end if;

        OUTPUT <= REG(7);

        TEST <= REG;

    end process;

end BHV;

动态扫描显示电路设计

设计8位动态扫描显示电路,8位显示字型自选。

要求写出代码,给出仿真波形。

我的答案:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



entity scan is

    port( CLK : in std_logic;



          DATA : in std_logic_vector(31 downto 0);

          

          POINT_CTL : in std_logic_vector(7 downto 0);

          POINT_OUT : out std_logic;

          --test output

          TEST : out std_logic_vector(2 downto 0);

          

          SEG_OUT : out std_logic_vector(6 downto 0);

          SEG_CTL : out std_logic_vector(7 downto 0));

end scan;

          

architecture BHV of scan is

    signal CNT : std_logic_vector(2 downto 0);

    signal DATA_BUF : std_logic_vector(3 downto 0);

begin

    COUNT : process(CLK)

    begin

        if rising_edge(CLK) then

            CNT <= CNT + 1;

        end if;

        TEST <= CNT;

    end process COUNT;



    SELECT_SEG : process(CLK)

    begin

        if rising_edge(CLK) then

            case CNT is

                when "000" =>

                    SEG_CTL <= "11111110";

                    POINT_OUT <= POINT_CTL(0);

                    DATA_BUF <= DATA(3 downto 0);

                when "001" =>

                    SEG_CTL <= "11111101";

                    POINT_OUT <= POINT_CTL(1);

                    DATA_BUF <= DATA(7 downto 4);

                when "010" =>

                    SEG_CTL <= "11111011";

                    POINT_OUT <= POINT_CTL(2);

                    DATA_BUF <= DATA(11 downto 8);

                when "011" =>

                    SEG_CTL <= "11110111";

                    POINT_OUT <= POINT_CTL(3);

                    DATA_BUF <= DATA(15 downto 12);

                when "100" =>

                    SEG_CTL <= "11101111";

                    POINT_OUT <= POINT_CTL(4);

                    DATA_BUF <= DATA(19 downto 16);

                when "101" =>

                    SEG_CTL <= "11011111";

                    POINT_OUT <= POINT_CTL(5);

                    DATA_BUF <= DATA(23 downto 20);

                when "110" =>

                    SEG_CTL <= "10111111";

                    POINT_OUT <= POINT_CTL(6);

                    DATA_BUF <= DATA(27 downto 24);

                when "111" =>

                    SEG_CTL <= "01111111";

                    POINT_OUT <= POINT_CTL(7);

                    DATA_BUF <= DATA(31 downto 28);

                when others =>

                    null;

            end case;

        end if;

    end process SELECT_SEG;



    DISPLAY : process(DATA_BUF)

    begin

        --display 0-9

        case DATA_BUF is

            when "0000" =>

                --display 0

                SEG_OUT <= "1111110";

            when "0001" =>

                --display 1

                SEG_OUT <= "0000110";

            when "0010" =>

                --display 2

                SEG_OUT <= "1101101";

            when "0011" =>

                --display 3

                SEG_OUT <= "1111001";

            when "0100" =>

                --display 4

                SEG_OUT <= "0110011";

            when "0101" =>

                --display 5

                SEG_OUT <= "1011011";

            when "0110" =>

                --display 6

                SEG_OUT <= "1011111";

            when "0111" =>

                --display 7

                SEG_OUT <= "1110000";

            when "1000" =>

                --display 8

                SEG_OUT <= "1111111";

            when "1001" =>

                --display 9

                SEG_OUT <= "1111011";

            when others =>

                null;

        end case;

    end process DISPLAY;

end BHV;

波形图:

编译界面:

电机的PWM控制

设计电机转速与转向控制电路,要求该控制电路能够实现电机转向控制、转速控制,该综合设计包含如下模块的设计工作:

1.计数器、比较器模块。

2.电机速度控制电路:要求电机速度能够四档可调。

3.电机方向控制电路。

写出设计代码,给出仿真波形。

我的答案:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



entity MOTOR_PWM is

    port( CLK : in std_logic;

          speed : in std_logic_vector(3 downto 0);

          direction_control : in std_logic;

          positive : out std_logic;

          negative : out std_logic);

end MOTOR_PWM;



architecture BHV of MOTOR_PWM is

signal T, CNT : std_logic_vector(4 downto 0);

signal PWM : std_logic;

begin

    process(CLK)

    begin

        if rising_edge(CLK) then

            CNT <= CNT + 1;

        end if;

    end process;



    process(speed)

    begin

        case speed is 

            when "0111"=>

                T <= "00001";

            when "1011"=>

                T <= "00011";

            when "1101"=>

                T <= "00111";

            when "1110"=>

                T <= "01111";

            when others=>

                T <= "00000";

        end case;

    end process;



    process(T, CNT)

    begin

        if (CNT <= T) then

            PWM <= '0';

        else

            PWM <= '1';

        end if;

    end process;



    process(PWM, direction_control)

    begin

        if (direction_control = '0') then

            positive <= PWM;

            negative <= '0';

        else

            positive <= '0';

            negative <= PWM;

        end if;

    end process;

end BHV;

编译界面:

波形图:

元件例化语句应用

用元件例化语句描述图示的电路结构,给出代码,给出编译成功截图。

我的答案:

底层设计:

library ieee;

use ieee.std_logic_1164.all;



entity and1 is

    port ( a, b : in std_logic;

           c : out std_logic);

end and1;



architecture bhv1 of and1 is

begin

    c <= a and b;

end bhv1;
library ieee;

use ieee.std_logic_1164.all;



entity or1 is

    port ( a, b : in std_logic;

           c : out std_logic);

end or1;



architecture bhv2 of or1 is

begin

    c <= a or b;

end bhv2;

顶层设计:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



entity TASK is

    port( A : in std_logic;

          B : in std_logic;

          C : in std_logic;

          D : in std_logic;

          F : out std_logic);

end TASK;



architecture BHV of TASK is

component and1

    port( A, B : in std_logic;

          C : out std_logic);

end component;



component or1

    port( A, B : in std_logic;

          C : out std_logic);

end component;


signal y1, y2 : std_logic;

begin

    u1 : and1 port map(a, b, y1);

    u2 : or1 port map(c, d, y2);

    u3 : and1 port map(y1, y2, f);

end BHV;

编译界面:

RTL视图:

状态机设计

用状态机设计法设计实现下面任意一个状态示意图,要求给出代码,给出程序生成的状态图。

我的答案:

图1代码:

library ieee;

use ieee.std_logic_1164.all;



entity FSM is

    port( CLK, RST : in std_logic;

          CIN : in std_logic;

          COUT : out std_logic);

end FSM;



architecture BHV of FSM is

    type state_type is (s0, s1, s2, s3);

    signal new_state, current_state : state_type;

begin

    process(CLK, RST)

    begin

        if(RST = '1') then

            current_state <= s0;

        elsif(rising_edge(CLK)) then

            current_state <= new_state;

        end if;

    end process;



    process(CIN, current_state)

    begin

        case current_state is

            when s0 =>

                if (CIN = '0') then

                    COUT <= '0';

                    new_state <= s0;

                else

                    COUT <= '0';

                    new_state <= s1;

                end if;

            when s1 =>

                if (CIN = '1') then

                    COUT <= '1';

                    new_state <= s1;

                else

                    COUT <= '1';

                    new_state <= s2;

                end if;

            when s2 =>

                if (CIN = '1') then

                    COUT <= '0';

                    new_state <= s2;

                else

                    COUT <= '0';

                    new_state <= s3;

                end if;

            when s3 =>

                if (CIN = '0') then

                    COUT <= '0';

                    new_state <= s1;

                else

                    COUT <= '0';

                    new_state <= s0;

                end if;

            when others =>

                null;

        end case;

    end process;

end BHV;

图2代码:

library ieee;

use ieee.std_logic_1164.all;



entity FSM is

    port( CLK, RST : in std_logic;

          CIN : in std_logic;

          COUT : out std_logic);

end FSM;



architecture BHV of FSM is

    type state_type is (s0, s1, s2, s3);

    signal new_state, current_state : state_type;

begin

    process(CLK, RST)

    begin

        if(RST = '1') then

            current_state <= s0;

        elsif(rising_edge(CLK)) then

            current_state <= new_state;

        end if;

    end process;



    process(CIN, current_state)

    begin

        case current_state is

            when s0 =>

                if (CIN = '0') then

                    COUT <= '0';

                    new_state <= s0;

                else

                    COUT <= '1';

                    new_state <= s1;

                end if;

            when s1 =>

                if (CIN = '1') then

                    COUT <= '1';

                    new_state <= s1;

                else

                    COUT <= '0';

                    new_state <= s2;

                end if;

            when s2 =>

                if (CIN = '1') then

                    COUT <= '0';

                    new_state <= s2;

                else

                    COUT <= '1';

                    new_state <= s3;

                end if;

            when s3 =>

                if (CIN = '0') then

                    COUT <= '0';

                    new_state <= s1;

                else

                    COUT <= '1';

                    new_state <= s0;

                end if;

            when others =>

                null;

        end case;

    end process;

end BHV;

编译界面:

状态图:




扫一扫在手机打开当前页