目录
前言
本程序设计基于QuartusII 软件进行开发,使用VHDL语言编写了一个简易的全自动洗衣机控制器,并使用了Altera Cyclone II EP2C70896C6N进行了硬件实现。通过模块设计、代码编写、程序调测和原理图连接设计出了一个具有以下功能的全自动洗衣机控制程序:默认显示学号,主开关打开后进入待机状态,默认可自定义设置水位、浸泡时间、洗涤时间、洗涤力度和脱水时间,也可以切换若干固定的自动模式,如常用、记忆、自洁和强力等。运行开关打开后进入洗衣过程,各状态数据按流程顺序依次显示,并伴随LED提示。
1. 概述
1.1 VHDL语言
VHDL 的英文全名是VHSIC Hardware Description Language(VHSIC硬件描述语言)。VHDL 用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可视部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。
1.2 Quartus II 简介
Quartus II是Altera公司推出的综合性CPLD/FPGA开发软件,软件支持原理图、VHDL、VerilogHDL以及AHDL(Altera Hardware支持Description Language)等多种设计输入形式,内嵌自有的综合器以及仿真器,可以完成从设计输入到硬件配置的完整PLD设计流程。Quartus II可以在Windows、Linux以及Unix上使用,除了可以使用Tcl脚本完成设计流程外,提供了完善的用户图形界面设计方式。具有运行速度快,界面统一,功能集中,易学易用等特点。Quartus II支持Altera的IP核,包含了LPM/MegaFunction宏功能模块库,使用户可以充分利用成熟的模块,简化了设计的复杂性、加快了设计速度。对第三方EDA工具的良好支持也使用户可以在设计流程的各个阶段使用熟悉的第三方EDA工具。
2. 系统设计
2.1 整体设计

整体流程图

顶层原理图
2.2 功能要求
- 总开关:关闭时显示学号,打开后进入待机状态
- 运行开关:打开后程序运行,关闭时暂停
- 提示符:四个,显示档位/时间为共用
- 手动设置各项:水位、浸泡时间、洗涤时间、洗涤力度、脱水时间
- 手动设置时,默认为顺序设置,可改变开关状态使之为逆序
- 可供选择五种自动洗衣模式:默认、常用、脱水、自洁、强力
- 程序运行时,按次序执行加水、浸泡、洗涤、排水、脱水,结束的过程
2.3 引脚对应

引脚对应表
3. 模块设计
3.1 预置模块
预置模块主要包括三个:
XYKEY_1:洗衣各流程切换设置(数码管HEX0上的字符数值)
主要由三个开关对应的使能信号EN0、EN1、EN2作为约束条件,输入信号KEY1作为主要控制信号,调整输出信号CNT1[3..0]的值。还有一个输入信号CNT3[3..0],是另一个按键反馈的信号,用于清零重置并限制数据输出。

XYKEY_1
XYKEY_3:自动洗衣模式切换设置(数码管HEX2上的字符数值)
主要由两个开关对应的使能信号EN0、EN1作为约束条件,输入信号KEY3作为主要控制信号,调整输出信号CNT3[3..0]的值。还有一个输入信号K3,是洗衣结束后反馈的信号,用于清零重置。

XYKEY_3
XYSZ:设置洗衣各流程数据(数码管HEX5、HEX6上的字符数值)
主要由两个开关对应的使能信号EN0、EN1作为约束条件,输入信号KEY2作为主要控制信号调整输出信号C5[3..0]、C6[3..0]的值,KEY1作为辅助控制信号用于清零重置;输入信号CNT1[3..0]对应改变输出信号C1[3..0]的值,输入信号CNT3[3..0]对应改变输出信号STATE[3..0]及C3[3..0]的值。还有S51[3..0],S61[3..0]……等输出信号,这些也是由输入信号KEY2控制,用来将设置好的数据信号输出并存储到运行模块。

XYSZ
3.2 分频模块
XYGC_FD:主要用于洗衣过程运行暂停及加速的调节。
主要由四个开关对应的使能信号EN0、EN1、EN3、EN4作为约束条件,接收原始时钟信号CLK并通过改变使能信号EN3、EN4进而改变输出信号COUT,实现洗衣暂停和加速的功能。

XYGC_FD
3.3 状态机模块
XYZD:主要用于洗衣各流程数据设置的存储,并将存储好的数据传输到显示模块。
主要接收分频后的时钟信号CLK,同时由两个开关对应的使能信号EN0、EN1作为约束条件,接收并存储由预置模块XYSZ反馈的信号,并根据这些输入信号改变输出信号C0[3..0]、S1[3..0]、S3[3..0]、S5[3..0]、S6[3..0]的值。还有一个输出信号K3是反馈信号给预置模块XYKEY_3,用于重置自动洗衣模式。

XYZD
以下是对自动洗衣模式(常用,自洁,脱水,强力)的运行仿真:
常用模式
常用模式仿真
图示为常用模式的部分过程,其中S1表示加水、浸泡、洗涤、脱水和排水五个状态。S3代表此时处于1常用模式。S5和S6表示各状态下的参数:加水35L、浸泡15min、洗涤30min、脱水35min和排水35L。
自洁模式
自洁模式仿真
图示为自洁模式的全过程,其中S1表示加水、浸泡、洗涤、脱水和排水五个状态。S3代表此时处于2自洁模式。S5和S6表示各状态下的参数:加水10L、浸泡0min、洗涤20min、脱水0min和排水15L。
脱水模式仿真
脱水模式仿真
图示为脱水模式的部分过程,其中S1表示加水、浸泡、洗涤、脱水和排水五个状态。S3代表此时处于3脱水模式。S5和S6表示各状态下的参数:加水10L、浸泡20min、洗涤20min、脱水0min和排水10L。
强力模式仿真
强力模式仿真
图示为强力模式的部分过程,其中S1表示加水、浸泡、洗涤、脱水和排水五个状态。S3代表此时处于4强力模式。S5和S6表示各状态下的参数:加水45L、浸泡15min、洗涤20min、脱水0min和排水45L。
3.4 显示模块
显示模块主要包括两个:
XYXS_LED:主要用于洗衣过程中LED灯的相关显示。
主要接收分频后的时钟信号CLK,同时由三个开关对应的使能信号EN0、EN1、EN3作为约束条件,接收由按键模块XYSZ反馈的信号S54[3..0]、S64[3..0]以及运行模块反馈的信号C0[3..0],并根据这些信号数据和使能信号EN0、EN1、EN3的状态改变输出信号LEDR[17..0]、LEDG[7..0]的值,实现在LED灯上各个状态不同的显示。

XYXS_LED
以下是对洗衣过程中LEDR、LEDG显示的运行仿真:
洗衣过程LED仿真
其中C0为“0000”表示正在运行状态,S54、S64表示预置的洗涤力度(图示为“03”),LEDG、LEDR为输出信号。当使能信号EN3接收的信号为‘0’时,处于运行状态,LEDR自左向右“111”三位循环移动;当使能信号EN3接收的信号为‘1’时,进入暂停状态,图示LEDR始终保持为“00000000000111000000”。
XYXS_SEG:主要用于洗衣过程中数码管的相关显示。
主要接收分频后的时钟信号CLK,同时由两个开关对应的使能信号EN0、EN1作为约束条件,接收由按键模块XYSZ反馈的信号C1[3..0]、C3[3..0]、C5[3..0]、C6[3..0]以及运行模块反馈的信号S1[3..0]、S3[3..0]、S5[3..0]、S6[3..0],并根据这些信号数据和使能信号EN0、EN1的状态改变输出信号SEG_LED_1[6..0]、SEG_LED_2[6..0]……的值,实现在数码管上各个状态不同的显示。

XYXS_SEG
4. 整体运行结果演示
4.1 待机状态
在将代码导入到开发板中并接通电源后,洗衣机总开关即对应开发板的开关SW0处于置零状态,开发板上有且仅有数码管显示为学号(00151971),如图1所示。

图1 显示学号(待机状态)
4.2 设置状态
仅将洗衣机总开关SW0向上扳动,进入洗衣机的设置状态,此时数码管HEX0、HEX2、HEX5、HEX6均显示的字符为“0”,其他位无任何显示,如图2所示。

图2 设置状态(初始)
4.2.1 默认模式(记忆)
默认模式为自定义模式,同时具有记忆功能(即在自定义各流程数据的洗衣过程结束后,下一次洗衣仍按照上一次设置的各项数据重复洗衣过程)。
此时每次按下按键KEY0,则数码管HEX0显示的字符数值加‘1’,例如,若显示为初始字符“0”,则由“0”变为“1”(进入水位设置),如图3所示。

图3 水位设置状态(初始)
当数码管HEX0显示的字符为“1”,即进入水位设置后,此时第一次按下按键KEY1,则数码管HEX5显示的字符由“0”变为“5”、HEX6显示的字符由“0”变为“2”(表示初始水位为25L),如图4所示。之后在数码管HEX6显示的字符不为“5”的情况下,每次按下按键KEY1,则数码管HEX6显示的字符数值加‘1’,例如,若显示为字符“2”,则由“2”变为“3”;当数码管HEX6显示的字符为“5”时,再次按下按键KEY1,则数码管HEX6显示的字符又变回“2”(即水位设置的范围是25L到55L,每档为10L)。

图4 水位设置状态(水位为25L)
当再次按下按键KEY0后,数码管HEX0显示的字符数值加‘1’(即进入“2”浸泡时间设置状态)的同时,数码管HEX5、HEX6显示的字符均重置为“0”,如图5所示。(注:数码管HEX0显示的字符共对应五个状态:“1”水位设置状态、“2”浸泡时间设置状态、“3”洗涤时间设置状态、“4”力度设置状态、“5”脱水时间设置状态)。

图5 浸泡时间设置状态(初始)
如图6所示已经进入“3”洗涤时间设置状态,若想回到“1”水位设置状态或“2”浸泡时间设置状态,除了可以通过多次按下KEY0循环回到各状态以外,还可以将开关SW2向上扳动,进入洗衣各流程数据的回退设置状态,通过每次按下按键KEY0,实现数码管HEX0显示的字符数值减‘1’(即返回“2”浸泡时间设置状态),如图7所示。

图6 洗涤时间设置状态(初始)

图7 浸泡时间设置状态(初始)
对于洗衣其他各流程数据的设置同水位设置一致,均是在对应的各流程设置状态下,通过按键KEY1进行计数(注:浸泡时间设置的范围是0到60 min,每档为10 min;洗涤时间设置的范围是10 min到60min,每档为10 min;洗涤力度设置的范围是0到4,每档为1;脱水时间设置的范围是1 min到10 min,每档为1 min)。
4.2.2 自动洗衣模式(常用、自洁、脱水、强力)
在进入洗衣设置状态之后,按下按键KEY2,则数码管HEX2显示的字符数值加‘1’(即进入“1”常用模式),若此时数码管HEX1、HEX5、HEX6上有字符显示,则在按下按键KEY2后均会清零,如图8所示。

图8 设置状态(常用模式)(图中标错了,应该是“KEY2”)
注:自洁模式、脱水模式、强力模式的设置方式同常用模式一致。
4.3 洗衣过程状态
4.3.1 洗衣运行
在对洗衣各流程数据设置完成(或直接选择固定模式)后,将洗衣机运行开关SW1向上扳动,进入洗衣过程状态,如图9所示,图示为常用模式的洗衣过程。在洗衣运行过程状态中,LEDR灯会根据对应的时间频率从左至右三位移动循环显示,LEDG灯对应洗涤力度(0-4)显示,即洗涤力度为几档,从左到右就有几个LEDG灯亮。如图9所示,有2个LEDG灯亮,表示该次洗衣的洗涤力度为‘2’。

图9 洗衣运行状态(常用模式)
4.3.2 洗衣暂停
在洗衣过程进行时,将开关SW3向上扳动,进入洗衣暂停状态,该状态下,各数码管显示的字符数值不再随时间变动,如图10所示。

图10 洗衣暂停状态(常用模式)
4.3.3 洗衣加速(仅测试使用)
若将开关SW4向上扳动,进入洗衣加速状态,该状态下,时间频率变为0.2s(五倍速),如图11所示。

图11 洗衣加速状态(常用模式)
4.4 洗衣结束状态
在洗衣过程的各阶段结束后,自动进入洗衣结束状态,该状态下,各数码管和LEDG灯均不做任何显示,同时LEDR灯的单双位交替闪烁,如图12所示。在LEDR灯的单双位交替闪烁各5次之后,LEDR灯不再做任何显示,如图13所示。

图12 洗衣结束状态(闪烁)

图13 洗衣结束状态(熄灭)
5. 总结
该洗衣机控制程序整体设计符合需求,可以实现洗衣机的基本功能。本次程序设计的难点在于预置数据的清零、洗衣过程中状态的转换以及计时器的循环交替进行。在本次设计中,通过不断地学习,我更为深刻地掌握了对VHDL语言的运用,强化了自身模块设计能力,一次次的调测也让我不断发现新的改进思路,提高了创新思维。
附录
1.预置模块源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYKEY_1 IS
PORT( EN0 : IN STD_LOGIC;
EN1 : IN STD_LOGIC;
EN2 : IN STD_LOGIC;
KEY1 : IN STD_LOGIC;
CNT3 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
CNT1 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END ENTITY XYKEY_1;
ARCHITECTURE BHV OF XYKEY_1 IS
SIGNAL COUNT : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(EN0,EN1,EN2,KEY1)
BEGIN
IF EN0='0' THEN
COUNT <= "0000";
ELSE
IF EN1 = '0' THEN
IF CNT3 = "0000" THEN
IF FALLING_EDGE(KEY1) THEN
IF EN2 = '0' THEN
IF COUNT = "0101" THEN
COUNT <= "0000";
ELSE
COUNT <= COUNT + 1;
END IF;
ELSE
IF COUNT > "0000" THEN
COUNT <= COUNT - 1;
END IF;
END IF;
END IF;
ELSE
COUNT <= "0000";
END IF;
ELSE
COUNT <= "0000";
END IF;
END IF;
END PROCESS;
CNT1 <= COUNT;
END BHV;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYKEY_3 IS
PORT( EN0 : IN STD_LOGIC;
EN1 : IN STD_LOGIC;
KEY3 : IN STD_LOGIC;
K3 : IN STD_LOGIC;
CNT3 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END ENTITY XYKEY_3;
ARCHITECTURE BHV OF XYKEY_3 IS
SIGNAL COUNT : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(KEY3)
BEGIN
IF EN0='0' OR K3='1' THEN
COUNT <= "0000";
ELSE
IF EN1 = '0' THEN
IF FALLING_EDGE(KEY3) THEN
IF COUNT = "0100" THEN
COUNT <= "0000";
ELSE
COUNT <= COUNT + 1;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
CNT3 <= COUNT;
END BHV;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYSZ IS --洗衣设置
PORT( EN1 : IN STD_LOGIC;
EN0 : IN STD_LOGIC;
KEY1 : IN STD_LOGIC;
KEY2 : IN STD_LOGIC;
CNT1 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
CNT3 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
STATE : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S51 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S61 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S52 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S62 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S53 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S63 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S54 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S64 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S55 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S65 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
C3 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
C1 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
C5 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
C6 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END ENTITY XYSZ;
ARCHITECTURE BHV OF XYSZ IS
BEGIN
PROCESS(EN0,EN1,KEY1,KEY2)
VARIABLE CNT5 : STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT6 : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF EN0='1'THEN
IF EN1='0' THEN
IF CNT3 = "0000" THEN --默认模式(记忆模式)
IF KEY1='0' THEN
STATE <= "0001";
CNT5 := "0000";
CNT6 := "0000";
C1 <= CNT1;
C5 <= CNT5;
C6 <= CNT6;
ELSIF KEY2'EVENT AND KEY2='0' THEN
CASE CNT1 IS
WHEN "0001" => --状态1(水位)设置
IF CNT6 = "0000" THEN
CNT6 := CNT6 + 2;
CNT5 := "0101";
ELSE
CNT6 := CNT6 + 1;
IF CNT6 = "0110" THEN
CNT6 := "0010";
END IF;
END IF;
S51 <= CNT5;
S61 <= CNT6;
WHEN "0010" => --状态2(浸泡时间)设置
CNT6 := CNT6 + 1;
IF CNT6 = "0111" THEN
CNT6 := "0000";
END IF;
S52 <= CNT5;
S62 <= CNT6;
WHEN "0011" => --状态3(洗涤时间)设置
CNT6 := CNT6 + 1;
IF CNT6 = "0111" THEN
CNT6 := "0001";
END IF;
S53 <= CNT5;
S63 <= CNT6;
WHEN "0100" => --状态4(洗涤力度)设置
CNT5 := CNT5 + 1;
IF CNT5 = "0101" THEN
CNT5 := "0000";
END IF;
S54 <= CNT5;
S64 <= CNT6;
WHEN "0101" => --状态5(脱水时间)设置
IF CNT5 < "1001" THEN
CNT5 := CNT5 + 1;
IF CNT5 = "0001" THEN
CNT6 := "0000";
END IF;
ELSE
CNT5 := "0000";
CNT6 := CNT6 + 1;
END IF;
S55 <= CNT5;
S65 <= CNT6;
WHEN OTHERS => CNT5 := "0000"; CNT6 := "0000";
END CASE;
END IF;
ELSIF CNT3 = "0001" THEN --常用模式
STATE <= "0001";
CNT5 := "0000";
CNT6 := "0000";
S51 <= "0101"; S61 <= "0011"; --水位 35
S52 <= "0101"; S62 <= "0001"; --浸泡时间 15
S53 <= "0000"; S63 <= "0011"; --洗涤时间 30
S54 <= "0010"; S64 <= "0000"; --洗涤力度 2
S55 <= "0000"; S65 <= "0001"; --脱水时间 10
ELSIF CNT3 = "0010" THEN --脱水模式
STATE <= "0001";
CNT5 := "0000";
CNT6 := "0000";
S51 <= "0000"; S61 <= "0000"; --水位 0
S52 <= "0000"; S62 <= "0000"; --浸泡时间 0
S53 <= "0000"; S63 <= "0000"; --洗涤时间 0
S54 <= "0001"; S64 <= "0000"; --洗涤力度 1
S55 <= "0000"; S65 <= "0001"; --脱水时间 10
ELSIF CNT3 = "0011" THEN --自洁模式
STATE <= "0001";
CNT5 := "0000";
CNT6 := "0000";
S51 <= "0000"; S61 <= "0010"; --水位 20
S52 <= "0000"; S62 <= "0000"; --浸泡时间 0
S53 <= "0000"; S63 <= "0001"; --洗涤时间 10
S54 <= "0001"; S64 <= "0000"; --洗涤力度 1
S55 <= "0000"; S65 <= "0000"; --脱水时间 0
ELSIF CNT3 = "0100" THEN --强力模式
STATE <= "0001";
CNT5 := "0000";
CNT6 := "0000";
S51 <= "0101"; S61 <= "0100"; --水位 45
S52 <= "0101"; S62 <= "0001"; --浸泡时间 15
S53 <= "0000"; S63 <= "0010"; --洗涤时间 20
S54 <= "0100"; S64 <= "0000"; --洗涤力度 4
S55 <= "0000"; S65 <= "0001"; --脱水时间 10
END IF;
END IF;
ELSE
CNT5 := "0000";
CNT6 := "0000";
S51 <= "0000"; S61 <= "0000";
S52 <= "0000"; S62 <= "0000";
S53 <= "0000"; S63 <= "0000";
S54 <= "0000"; S64 <= "0000";
S55 <= "0000"; S65 <= "0000";
END IF;
C1 <= CNT1;
C3 <= CNT3;
C5 <= CNT5;
C6 <= CNT6;
END PROCESS;
END BHV;
2.分频模块源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYGC_FD IS
PORT( EN1 : IN STD_LOGIC;
EN3 : IN STD_LOGIC;
EN4 : IN STD_LOGIC;
EN0 : IN STD_LOGIC;
CLK : IN STD_LOGIC;
COUT : OUT STD_LOGIC
);
END ENTITY XYGC_FD;
ARCHITECTURE BHV OF XYGC_FD IS
SIGNAL Q: STD_LOGIC;
BEGIN
PROCESS(CLK,EN0,EN3,EN4)
VARIABLE TEMP1 : INTEGER RANGE 49999999 DOWNTO 0 := 0;
VARIABLE TEMP2 : INTEGER RANGE 9999999 DOWNTO 0 := 0;
BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF EN0 = '1' THEN
IF EN3 = '1' OR EN1 = '0' THEN
Q <= '0'; TEMP1 := 0; TEMP2 := 0;
ELSE
IF EN4 = '0' THEN
IF TEMP1 < 24999999 THEN
Q <= '0' ; TEMP1 := TEMP1 + 1;
ELSIF TEMP1 < 49999999 THEN
Q <= '1' ; TEMP1 := TEMP1 + 1;
ELSE
Q <= '1' ; TEMP1 := 0;
END IF;
ELSE
IF TEMP2 < 4999999 THEN
Q <= '0' ; TEMP2 := TEMP2 + 1;
ELSIF TEMP1 < 9999999 THEN
Q <= '1' ; TEMP2 := TEMP2 + 1;
ELSE
Q <= '1' ; TEMP2 := 0;
END IF;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
COUT <= Q;
END BHV;
3.状态机模块源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYZD IS --洗衣自动
PORT( EN1 : IN STD_LOGIC;
CLK : IN STD_LOGIC;
EN0 : IN STD_LOGIC;
STATE : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S51 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S61 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S52 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S62 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S53 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S63 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S55 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S65 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C3 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C0 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S1 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S3 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S5 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S6 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
K3 : OUT STD_LOGIC
);
END ENTITY XYZD;
ARCHITECTURE BHV OF XYZD IS
BEGIN
PROCESS(CLK,EN0,EN1)
VARIABLE CNT1: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT51: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT61: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT52: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT62: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT53: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT63: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT54: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT64: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT55: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT65: STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE CNT00: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF EN0='1' THEN
IF EN1='1' THEN
IF CLK'EVENT AND CLK='1' THEN
CASE CNT1 IS
WHEN "0001" => --状态1(加水)
IF CNT51 = S51 AND CNT61 = S61 THEN
CNT1 := CNT1 + "0001";
CNT52 := S52 + "0001";
CNT62 := S62;
ELSE
CNT51 := CNT51 + "0001";
IF CNT51 = "1001" THEN
CNT51 := "0000";
IF CNT61 < S61 THEN
CNT61 := CNT61 + "0001";
END IF;
END IF;
END IF;
C0 <= "0000";
S1 <= CNT1 ;
S3 <= C3 ;
S5 <= CNT51 ;
S6 <= CNT61 ;
WHEN "0010" => --状态2(浸泡)
IF CNT52 = "0000" AND CNT62 = "0000" THEN
CNT1 := CNT1 + "0001";
CNT53 := S53 + "0001";
CNT63 := S63;
ELSE
IF CNT52 > "0000" THEN
CNT52 := CNT52 - "0001";
ELSE
CNT52 := "1001";
IF CNT62 > "0000" THEN
CNT62 := CNT62 - "0001";
END IF;
END IF;
END IF;
C0 <= "0000";
S1 <= CNT1 ;
S3 <= C3 ;
S5 <= CNT52 ;
S6 <= CNT62 ;
WHEN "0011" => --状态3(洗涤)
IF CNT53 = "0000" AND CNT63 = "0000" THEN
CNT1 := CNT1 + "0001";
CNT54 := S51 + "0001";
CNT64 := S61;
ELSE
IF CNT53 > "0000" THEN
CNT53 := CNT53 - "0001";
ELSE
CNT53 := "1001";
IF CNT63 > "0000" THEN
CNT63 := CNT63 - "0001";
END IF;
END IF;
END IF;
C0 <= "0000";
S1 <= CNT1 ;
S3 <= C3 ;
S5 <= CNT53 ;
S6 <= CNT63 ;
WHEN "0100" => --状态4(排水)
IF CNT54 = "0000" AND CNT64 = "0000" THEN
CNT1 := CNT1 + "0001";
CNT55 := S55 + "0001";
CNT65 := S65;
ELSE
IF CNT54 > "0000" THEN
CNT54 := CNT54 - "0001";
ELSE
CNT54 := "1001";
IF CNT64 > "0000" THEN
CNT64 := CNT64 - "0001";
END IF;
END IF;
END IF;
C0 <= "0000";
S1 <= CNT1 ;
S3 <= C3 ;
S5 <= CNT54 ;
S6 <= CNT64 ;
WHEN "0101" => --状态5(脱水)
IF CNT55 = "0000" AND CNT65 = "0000" THEN
CNT1 := "0000";
CNT51 := "0000";
CNT61 := "0000";
CNT00 := "0101";
ELSE
IF CNT55 > "0000" THEN
CNT55 := CNT55 - "0001";
ELSE
CNT55 := "1001";
IF CNT65 > "0000" THEN
CNT65 := CNT65 - "0001";
END IF;
END IF;
END IF;
C0 <= "0000";
S1 <= CNT1 ;
S3 <= C3 ;
S5 <= CNT55 ;
S6 <= CNT65 ;
WHEN "0000" => --状态6(结束提示)
IF CNT00 = "0000" THEN
CNT1 := "1111";
C0 <= "0010";
ELSE
CNT00 := CNT00 - "0001";
C0 <= "0001";
END IF;
S1 <= "1111";
S3 <= "1111";
S5 <= "1111";
S6 <= "1111";
K3 <= '1';
WHEN "1111" => --状态7(重置)
CNT51 := "0000"; CNT61 := "0000";
CNT52 := "0000"; CNT62 := "0000";
CNT53 := "0000"; CNT63 := "0000";
CNT54 := "0000"; CNT64 := "0000";
CNT55 := "0000"; CNT65 := "0000";
K3 <= '0';
WHEN OTHERS =>
CNT51 := "0000"; CNT61 := "0000";
CNT52 := "0000"; CNT62 := "0000";
CNT53 := "0000"; CNT63 := "0000";
CNT54 := "0000"; CNT64 := "0000";
CNT55 := "0000"; CNT65 := "0000";
END CASE;
END IF;
ELSE
CNT1 := STATE;
END IF;
ELSE
CNT51 := "0000"; CNT61 := "0000";
CNT52 := "0000"; CNT62 := "0000";
CNT53 := "0000"; CNT63 := "0000";
CNT54 := "0000"; CNT64 := "0000";
CNT55 := "0000"; CNT65 := "0000";
END IF;
END PROCESS;
END BHV;
4.显示模块源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY XYXS_LED IS
PORT( EN3 : IN STD_LOGIC;
EN1 : IN STD_LOGIC;
EN0 : IN STD_LOGIC;
CLK : IN STD_LOGIC;
S54 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S64 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C0 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
LEDR : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
LEDG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END ENTITY XYXS_LED;
ARCHITECTURE BHV OF XYXS_LED IS
SIGNAL REG: STD_LOGIC_VECTOR(17 DOWNTO 0);
SIGNAL LDXS: STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
PROCESS (CLK,EN0,EN1,EN3,C0)
VARIABLE NUM : INTEGER RANGE 18 DOWNTO 0;
BEGIN
IF EN0 = '1' THEN
IF EN1 = '1' THEN
IF EN3 = '0' THEN
IF CLK'EVENT AND CLK='1' THEN
CASE C0 IS
WHEN "0000" =>
NUM := 0;
FOR n IN 0 TO 17 LOOP
IF REG(n) = '1' THEN
NUM := NUM + 1;
END IF;
END LOOP;
IF NUM /= 3 THEN
REG <= "000000000000000111";
ELSE
REG(17 DOWNTO 3) <= REG(14 DOWNTO 0);
REG(2 DOWNTO 0) <= REG(17 DOWNTO 15);
END IF;
IF S54 = "0001" THEN
LDXS <= "00000001";
ELSIF S54 = "0010" THEN
LDXS <= "00000011";
ELSIF S54 = "0011" THEN
LDXS <= "00000111";
ELSIF S54 = "0100" THEN
LDXS <= "00001111";
END IF;
WHEN "0001" =>
NUM := 0;
FOR n IN 0 TO 17 LOOP
IF REG(n) = '1' THEN
NUM := NUM + 1;
END IF;
END LOOP;
IF NUM /= 9 THEN
REG <= "010101010101010101";
ELSE
REG(17 DOWNTO 9) <= REG(8 DOWNTO 0);
REG(8 DOWNTO 0) <= REG(17 DOWNTO 9);
END IF;
LDXS <= "00000000";
WHEN "0010" => REG <= "000000000000000000"; LDXS <= "00000000";
WHEN OTHERS => REG <= "000000000000000000"; LDXS <= "00000000";
END CASE;
END IF;
END IF;
ELSE
REG <= "000000000000000000"; LDXS <= "00000000";
END IF;
ELSE
REG <= "000000000000000000"; LDXS <= "00000000";
END IF;
END PROCESS;
LEDR <= REG;
LEDG <= LDXS;
END BHV;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY XYXS_SEG IS
PORT( EN1 : IN STD_LOGIC; --运行开关
S1 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S3 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S5 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S6 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
CLK : IN STD_LOGIC;
EN0 : IN STD_LOGIC; --总开关
C3 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C1 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C5 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
C6 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG_LED_1 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX0
SEG_LED_2 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX1
SEG_LED_3 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX2
SEG_LED_4 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX3
SEG_LED_5 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX4
SEG_LED_6 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX5
SEG_LED_7 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --HEX6
SEG_LED_8 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0) --HEX7
);
END ENTITY XYXS_SEG;
ARCHITECTURE BHV OF XYXS_SEG IS
SIGNAL SEG_1 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_2 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_3 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_4 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_5 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_6 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_7 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SEG_8 : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(EN0,EN1)
BEGIN
IF EN0 = '0' THEN
SEG_8 <= "0000" ; --0
SEG_7 <= "0000" ; --0
SEG_6 <= "0001" ; --1
SEG_5 <= "0101" ; --5
SEG_4 <= "0001" ; --1
SEG_3 <= "1001" ; --9
SEG_2 <= "0111" ; --7
SEG_1 <= "0001" ; --1
ELSIF EN0 = '1' AND EN1 = '0' THEN
SEG_8 <= "1111" ;
SEG_7 <= "1111" ;
SEG_6 <= C6 ;
SEG_5 <= C5 ;
SEG_4 <= "1111" ;
SEG_3 <= C3 ;
SEG_2 <= "1111" ;
SEG_1 <= C1 ;
ELSIF EN0 = '1' AND EN1 = '1' THEN
SEG_8 <= "1111" ;
SEG_7 <= "1111" ;
SEG_6 <= S6 ;
SEG_5 <= S5 ;
SEG_4 <= "1111" ;
SEG_3 <= S3 ;
SEG_2 <= "1111" ;
SEG_1 <= S1 ;
END IF;
END PROCESS;
PROCESS (SEG_1)
BEGIN
CASE SEG_1 IS
WHEN "0000" => SEG_LED_1 <= "1000000";
WHEN "0001" => SEG_LED_1 <= "1111001";
WHEN "0010" => SEG_LED_1 <= "0100100";
WHEN "0011" => SEG_LED_1 <= "0110000";
WHEN "0100" => SEG_LED_1 <= "0011001";
WHEN "0101" => SEG_LED_1 <= "0010010";
WHEN "0110" => SEG_LED_1 <= "0000010";
WHEN "0111" => SEG_LED_1 <= "1111000";
WHEN "1000" => SEG_LED_1 <= "0000000";
WHEN "1001" => SEG_LED_1 <= "0010000";
WHEN OTHERS => SEG_LED_1 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_2)
BEGIN
CASE SEG_2 IS
WHEN "0000" => SEG_LED_2 <= "1000000";
WHEN "0001" => SEG_LED_2 <= "1111001";
WHEN "0010" => SEG_LED_2 <= "0100100";
WHEN "0011" => SEG_LED_2 <= "0110000";
WHEN "0100" => SEG_LED_2 <= "0011001";
WHEN "0101" => SEG_LED_2 <= "0010010";
WHEN "0110" => SEG_LED_2 <= "0000010";
WHEN "0111" => SEG_LED_2 <= "1111000";
WHEN "1000" => SEG_LED_2 <= "0000000";
WHEN "1001" => SEG_LED_2 <= "0010000";
WHEN OTHERS => SEG_LED_2 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_3)
BEGIN
CASE SEG_3 IS
WHEN "0000" => SEG_LED_3 <= "1000000";
WHEN "0001" => SEG_LED_3 <= "1111001";
WHEN "0010" => SEG_LED_3 <= "0100100";
WHEN "0011" => SEG_LED_3 <= "0110000";
WHEN "0100" => SEG_LED_3 <= "0011001";
WHEN "0101" => SEG_LED_3 <= "0010010";
WHEN "0110" => SEG_LED_3 <= "0000010";
WHEN "0111" => SEG_LED_3 <= "1111000";
WHEN "1000" => SEG_LED_3 <= "0000000";
WHEN "1001" => SEG_LED_3 <= "0010000";
WHEN OTHERS => SEG_LED_3 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_4)
BEGIN
CASE SEG_4 IS
WHEN "0000" => SEG_LED_4 <= "1000000";
WHEN "0001" => SEG_LED_4 <= "1111001";
WHEN "0010" => SEG_LED_4 <= "0100100";
WHEN "0011" => SEG_LED_4 <= "0110000";
WHEN "0100" => SEG_LED_4 <= "0011001";
WHEN "0101" => SEG_LED_4 <= "0010010";
WHEN "0110" => SEG_LED_4 <= "0000010";
WHEN "0111" => SEG_LED_4 <= "1111000";
WHEN "1000" => SEG_LED_4 <= "0000000";
WHEN "1001" => SEG_LED_4 <= "0010000";
WHEN OTHERS => SEG_LED_4 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_5)
BEGIN
CASE SEG_5 IS
WHEN "0000" => SEG_LED_5 <= "1000000";
WHEN "0001" => SEG_LED_5 <= "1111001";
WHEN "0010" => SEG_LED_5 <= "0100100";
WHEN "0011" => SEG_LED_5 <= "0110000";
WHEN "0100" => SEG_LED_5 <= "0011001";
WHEN "0101" => SEG_LED_5 <= "0010010";
WHEN "0110" => SEG_LED_5 <= "0000010";
WHEN "0111" => SEG_LED_5 <= "1111000";
WHEN "1000" => SEG_LED_5 <= "0000000";
WHEN "1001" => SEG_LED_5 <= "0010000";
WHEN OTHERS => SEG_LED_5 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_6)
BEGIN
CASE SEG_6 IS
WHEN "0000" => SEG_LED_6 <= "1000000";
WHEN "0001" => SEG_LED_6 <= "1111001";
WHEN "0010" => SEG_LED_6 <= "0100100";
WHEN "0011" => SEG_LED_6 <= "0110000";
WHEN "0100" => SEG_LED_6 <= "0011001";
WHEN "0101" => SEG_LED_6 <= "0010010";
WHEN "0110" => SEG_LED_6 <= "0000010";
WHEN "0111" => SEG_LED_6 <= "1111000";
WHEN "1000" => SEG_LED_6 <= "0000000";
WHEN "1001" => SEG_LED_6 <= "0010000";
WHEN OTHERS => SEG_LED_6 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_7)
BEGIN
CASE SEG_7 IS
WHEN "0000" => SEG_LED_7 <= "1000000";
WHEN "0001" => SEG_LED_7 <= "1111001";
WHEN "0010" => SEG_LED_7 <= "0100100";
WHEN "0011" => SEG_LED_7 <= "0110000";
WHEN "0100" => SEG_LED_7 <= "0011001";
WHEN "0101" => SEG_LED_7 <= "0010010";
WHEN "0110" => SEG_LED_7 <= "0000010";
WHEN "0111" => SEG_LED_7 <= "1111000";
WHEN "1000" => SEG_LED_7 <= "0000000";
WHEN "1001" => SEG_LED_7 <= "0010000";
WHEN OTHERS => SEG_LED_7 <= "1111111";
END CASE;
END PROCESS;
PROCESS (SEG_8)
BEGIN
CASE SEG_8 IS
WHEN "0000" => SEG_LED_8 <= "1000000";
WHEN "0001" => SEG_LED_8 <= "1111001";
WHEN "0010" => SEG_LED_8 <= "0100100";
WHEN "0011" => SEG_LED_8 <= "0110000";
WHEN "0100" => SEG_LED_8 <= "0011001";
WHEN "0101" => SEG_LED_8 <= "0010010";
WHEN "0110" => SEG_LED_8 <= "0000010";
WHEN "0111" => SEG_LED_8 <= "1111000";
WHEN "1000" => SEG_LED_8 <= "0000000";
WHEN "1001" => SEG_LED_8 <= "0010000";
WHEN OTHERS => SEG_LED_8 <= "1111111";
END CASE;
END PROCESS;
END BHV;