洗衣机控制器设计

设计题目

洗衣机控制器设计

任务要求

  1. 设计一个电子定时器,控制洗衣机作如下运转:定时启动--正转20秒--暂停10秒--反转20秒--暂停10秒--定时未到回到“正转20秒--暂停10秒循环”,定时到则停止;
  2. 若定时到,则停机发出音响信号;
  3. 用两个数码管显示洗涤的预置时间(分钟数),按倒计时方式对洗涤过程作计时显示,直到时间到停机;洗涤过程由“开始”信号开始;
  4. 三只LED灯表示“正转”、“反转”、“暂停”三个状态。

实验设备及软件

实验设备:21EDA EPM240-CPLD

软件:Quartus II 13.0 (64-bit)

      ModelSim-Altera

VHDL软件设计报告

一、设计任务及要求

1)  设计一个电子定时器,控制洗衣机作如下运转:设计一个电子定时器,控制洗衣机作如下运转:定时启动--正转20秒--暂停10秒--反转20秒--暂停10秒--定时未到回到“正转20秒--暂停10秒循环”,定时到则停止;

2)  若定时到,则停机发出音响信号;

3)  用两个数码管显示洗涤的预置时间(分钟数),按倒计时方式对洗涤过程作计时显示,直到时间到停机;洗涤过程由“开始”信号开始;

4)  三只LED灯表示“正转”、“反转”、“暂停”三个状态。

二、设计原理简介

2.1 洗衣机控制器原理

全自动洗衣机具有时间预置及状态显示等功能。其工作流程为:定时启动 正转20秒 暂停10秒 反转20秒 暂停10秒 定时未到,重复上述过程,若定时已到,停止发出音响。状态控制模块的设计主要是定时器的设计,利用减法计数器,时序控制电路和工作状态控制电路等组成,可以实现正转、反转和暂停等洗衣机的工作过程,并且用两个数码管可以显示预置洗涤时间,按倒计时方式对洗涤过程进行计数显示,直到时间到停机。其工作过程图如下图:

图1.1 自动洗衣机工作流程

2.2 状态控制模块原理(washing_state.vhd)

洗衣机控制器要求有启动按键、三种状态(正转、暂停、反转)以及结束信号功能。每个功能都由时钟信号驱动,当时钟信号为1Hz时,利用CLK周期为1秒,可以实现60秒的秒计时循环。在此基础上,又可以实现预置时间分钟数的递减。记录启动按键的单脉冲信号的上边沿,并将其设为IF条件,控制计时器归0以及状态变化起始位置。三种状态由60秒倒计时改变状态灯,依次为(20s, 10s, 20s, 10s)的(正转、暂停、反转、暂停)。最后,按照预置时间归0,发出结束信号即可实现所有功能。

图1.2 流程图

2.3 倒计时显示模块原理(BCD.vhd)

        利用循环将预置时间的十位依次减“0000 1010”,同时十位TENS依次加“0000 0001”,之后将余下的时间直接赋值给个位ONES,即是将预置时间改写到两位上,方便后续接入两个数码管显示时间。

2.4顶层设计模块(washing_machine.vhd)

          将控制模块和显示模块的端口接入顶层设计模块,使其协同工作。分别输出“状态”(正转“100”、暂停“010”、反转“001”);倒计时十位“TENS”和倒计时个位“ONES”;以及结束信号。

三、设计方案与实现

3.1 设计软件环境搭建

本设计使用软件QUARTUS II 13.0开发,使用VHDL语言编写,采用ModelSi Altera进行仿真。新建工程文件命名为washing_machine,并新建BCD.vhd、washing_machine.vhd、washing_state.vhd等文件。

之后按照Processing--Start--Start Test Bench Template Writer运行,编写好.tbh仿真模板的文件,进入Assignments--setting导入仿真模板。

注:设置仿真工具路径:Tools--options--EDA Tool Options

3.2 代码实现方案

要求设计洗衣机控制器,可分为以下两个部分:代码基础部分,以及基于基础部分实现设计要求的功能实现部分。

代码基础部分包括状态机(控制洗衣机的工作状态与结束状态)与秒钟计时器(每一分钟产生一个计时脉冲);

功能实现部分,大致分为基于状态机实现结束状态时结束信号灯发光;以及基于一分钟定时脉冲实现倒计时功能(每分钟减一);最后,还有基于60秒计时器实现(20s正转、10s暂停、20s反转、10s暂停)的状态循环功能。

时钟显示功能。具体解释如下:

一分钟脉冲:每次秒钟计时器计时到59s时,一分钟脉冲信号变为高电平,在一个时钟周期之后恢复低电平。

时钟显示功能:首先规定一个输入信号,用于存储预定洗衣机工作时间,例如15分钟,每当一分钟脉冲产生,便将倒计时减一,并将其显示在输出上,即将倒计时分钟数分别以十位和个位显示为输出。

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;
--二进制转BCD码,将输入binary以分钟数十位和个位显示
ENTITY BCD IS
   PORT (
      clk     : IN STD_LOGIC;
      binary  : IN STD_LOGIC_VECTOR(7 DOWNTO 0);--二进制输入
      Tens    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--十位
      Ones    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)--个位
   );
END BCD;--定义端口

ARCHITECTURE RTL OF BCD IS
   
   SIGNAL state     : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00";
   SIGNAL data_buf  : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
   SIGNAL Tens_buf : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
   SIGNAL Ones_buf : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";
BEGIN
   PROCESS (clk)
	--该过程由clk时钟触发。当clk上升沿(从'0'到'1')发生时,IF (clk'EVENT AND clk = '1') THEN条件为真,并执行内部的CASE语句。
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         CASE state IS
            WHEN "00" =>
               data_buf <= binary;
               Tens_buf <= "00000000";
               Ones_buf <= "0000";
               state <= "01";
            WHEN "01" =>
               IF (data_buf >= "00001010") THEN--是否大于10
                  data_buf <= data_buf - "00001010";--减10
                  Tens_buf <= Tens_buf + "00000001";--十位加1
                  Ones_buf <= Ones_buf;
                  state <= "01";
						--当你输入预置时间binary,将会赋值data_buf,此时利用循环将十位赋值给Tens_buf
               ELSE
                  data_buf <= data_buf;
                  Tens_buf <= Tens_buf;--十位
                  Ones_buf <= data_buf(3 DOWNTO 0);--个位
                  state <= "10";
						--跳出上一个循环后,赋值Oens_buf
               END IF;
            WHEN "10" =>
               data_buf <= binary;
               Tens <= Tens_buf(3 DOWNTO 0);
               Ones <= Ones_buf;
               state <= "00";
            WHEN OTHERS =>
         END CASE;
      END IF;
   END PROCESS;
   
   
END RTL;


结束信号功能。具体解释如下:

状态机:为了实现洗衣机工作状态和结束状态的切换,增加一个中间状态—等待状态。即是等待状态、倒计时状态与结束状态。检测到启动信号则状态机从等待状态进入倒计时状态,否则停在等待状态;倒计时状态由洗衣机倒计时控制,倒计时归零,则进入结束状态;进入结束状态后,在下一个时钟周期自动进入等待状态。

结束功能:在状态机进入结束状态时,结束信号变为高电平。

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;

--实现功能,led灯显示工作状态,结束亮灯报警,以及显示剩余时间(顶层设计)
ENTITY washing_machine IS
   PORT (
      clk_in     : IN STD_LOGIC;--1Hz
      start_key  : IN STD_LOGIC;--启动按键
      led        : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);--正转,反转,暂停
      end_led    : OUT STD_LOGIC;--洗衣结束信号
      minute_Tens    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--分钟十位BCD码
      minute_Ones    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)--分钟个位BCD码
   );
END washing_machine;

ARCHITECTURE behaveral OF washing_machine IS

--两个component将另外两个vhd代码置于本模块内
component washing_state IS
   PORT (
      clk_in     : IN STD_LOGIC;--1Hz
      start_key  : IN STD_LOGIC;--启动按键
      led        : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);--正转,反转,暂停
      end_led    : OUT STD_LOGIC;--洗衣结束信号
      time_out   : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)--分钟时间
   );
END component;


component BCD IS
   PORT (
      clk      : IN STD_LOGIC;
      binary  : IN STD_LOGIC_VECTOR(7 DOWNTO 0);--二进制输入,预定时间
      Tens    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--十位
      Ones    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)--个位
   );
END component;

--这里由于本模块没有time_out,只有tens和ones,故再此引入
signal time_out:STD_LOGIC_VECTOR(7 DOWNTO 0);--分钟时间
   
BEGIN
--洗衣机状态控制模块
U_washing_state:washing_state
   PORT MAP(
      clk_in     =>clk_in,--1Hz
      start_key  =>start_key,--启动按键
      led        =>led,--正转,反转,暂停
      end_led    =>end_led,--洗衣结束信号
      time_out   =>time_out--分钟时间
   );

--实例化了washing_state组件,并将其命名为U_washing_state。通过PORT MAP子句将washing_state组件的端口连接到当前实体的相应信号上。

--二进制转BCD码
U_BCD: BCD 
   PORT MAP(
      clk     =>clk_in,
      binary  =>time_out,--二进制输入
      Tens    =>minute_Tens,--十位
      Ones    =>minute_Ones--个位
   );
   
END behaveral;

60s计时器基础和(正转、暂停、反转、暂停)的状态循环控制,具体介绍如下:

60s计时器:采用1Hz的时钟周期,即每一个时钟周期时长为1s,介于此,每逢一个时钟周期的上升沿信号,就在60s计时器上加1,从0开始,到59为一循环,即在59之后一个时钟周期将60s计时器复位。同时,为一分钟脉冲作基础。

(正转、暂停、反转、暂停)的状态循环控制:题设要求为20s正转、10s暂停、20s反转、10s暂停,恰好为60s,基于60s计时器实现状态循环控制,每当遇到时钟信号上升沿,检测60s计时器的值,若介于0到19之间,令状态为正转;若介于20到29之间,令状态为暂停;若介于30到49,令状态为反转;若介于50到59之间,令状态为暂停。

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;
--洗衣机状态控制模块
ENTITY washing_state IS
   PORT (
      clk_in     : IN STD_LOGIC;--1Hz
      start_key  : IN STD_LOGIC;--启动按键
      led        : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);--正转,反转,暂停
      end_led    : OUT STD_LOGIC;--洗衣结束信号
      time_out   : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)--分钟时间
   );
END washing_state;

ARCHITECTURE behaveral OF washing_state IS
   
	--此处定义了大量输入输出以外的信号,用于后续功能实现
   SIGNAL state               : STD_LOGIC_VECTOR(1 DOWNTO 0) := "01";
	--启动按键与相关信号
   SIGNAL start_key_rise      : STD_LOGIC;
   SIGNAL start_key_1         : STD_LOGIC := '0';
   SIGNAL start_key_2         : STD_LOGIC := '0';
	--预置洗衣时间15分钟
   SIGNAL washing_time        : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00001111";
	--结束时亮的led
   SIGNAL end_led_buf         : STD_LOGIC := '1';
	--秒 计时脉冲 60秒一循环 同时 用于正转,暂停,反转三个状态
   SIGNAL second_cnt          : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
   --分钟计时脉冲
	SIGNAL min_en              : STD_LOGIC := '0';
	--同步
	SIGNAL synchronization     : STD_LOGIC := '0';
	
   SIGNAL second_en_1s        : STD_LOGIC := '0';
   SIGNAL second_en           : STD_LOGIC;
   SIGNAL second_div_cnt      : STD_LOGIC_VECTOR(9 DOWNTO 0) := "0000000000";
-- SIGNAL minute_cnt          : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";

----------------------------------------------------------------------
	BEGIN
   time_out <= washing_time;  --连续不断地将右侧的值赋值给左侧的输出信号

   PROCESS (clk_in) --时钟敏感
   BEGIN
	   IF (clk_in'EVENT AND clk_in = '1') THEN  --时钟上升沿变化
         start_key_1 <= start_key;
         start_key_2 <= start_key_1;-- 启动按钮寄存器缓存
      END IF;
   END PROCESS;
   
   start_key_rise <= start_key_1 AND (NOT(start_key_2));--确保 信号start_key_rise 在启动按键上升沿触发,且变为1
--启动按键部分
-----------------------------------------------------------------------
	
	
-----------------------------------------------------------------------
   PROCESS (clk_in)--状态机
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN  --上升沿
         CASE state IS
            WHEN "00" =>--状态00,等待状态,若有启动信号则到状态01
               IF (start_key_rise = '1') THEN
                  state <= "01";
               ELSE
                  state <= "00";
               END IF;
            WHEN "01" =>--状态01,倒计时状态,直到计时到0,到状态10,即结束
               IF (washing_time > "00000000") THEN
                  state <= "01";
               ELSE
                  state <= "10";
               END IF;
            WHEN "10" =>--结束状态,返回00
               state <= "00";
            WHEN OTHERS =>
               state <= "00";
         END CASE;
      END IF;
   END PROCESS;
--状态机(有启动按键进入倒计时状态,没有就等待)
-----------------------------------------------------------------------
	
	
-----------------------------------------------------------------------
   PROCESS (clk_in)  --上升沿
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN  --上升沿
         IF (state = "00") THEN
            end_led_buf <= '1';	--状态00,提示洗衣结束
         ELSE
            end_led_buf <= '0';
         END IF;
      END IF;
   END PROCESS;

   end_led <= end_led_buf;
--结束提醒部分
-----------------------------------------------------------------------

 PROCESS (start_key)
   BEGIN
	   IF (start_key'EVENT AND start_key = '1' ) THEN  
         synchronization <= '1';
      END IF;
   END PROCESS;
	

-----------------------------------------------------------------------
PROCESS (clk_in)
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN  --上升沿
         IF (start_key_rise = '1') THEN  --启动键只有一个时钟周期的脉冲,启动则赋予秒计时器0值
            second_cnt <= "00000000";
         ELSE
            IF (second_cnt >= "00111011") THEN  --秒计时到59返回0
               second_cnt <= "00000000";
            ELSE
               second_cnt <= second_cnt + "00000001";
            END IF;
         END IF;
      END IF;
   END PROCESS;
--秒计时器--60秒一循环
-----------------------------------------------------------------------
   

-----------------------------------------------------------------------
   PROCESS (clk_in)
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN  --上升沿
         IF (second_cnt = "00111011") THEN  --秒计时到59,生成分计时脉冲
            min_en <= '1';
         ELSE
            min_en <= '0';
         END IF;
      END IF;
   END PROCESS;
--60秒倒计时记录
-----------------------------------------------------------------------


-----------------------------------------------------------------------
   PROCESS (clk_in)
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN  --上升沿
         IF (start_key_rise = '1') THEN
            washing_time <= "00001111";  --预置计时时间15分钟 --可修改
         ELSIF (min_en = '1') THEN  --分钟脉冲到了,分钟时间减1
            IF (washing_time > "00000000") THEN
               washing_time <= washing_time - "00000001";
            ELSE
               washing_time <= "00000000";
            END IF;
         ELSE
            washing_time <= washing_time;
         END IF;
      END IF;
   END PROCESS;
   
   second_en <= second_en_1s;
--分钟倒计时,结合秒钟倒计时运行
-----------------------------------------------------------------------

-----------------------------------------------------------------------
--   PROCESS (clk_in)
--   BEGIN
--     IF (clk_in'EVENT AND clk_in = '1') THEN --上升沿
--         IF (start_key_rise = '1') THEN
--            minute_cnt <= "00000000";--复位
--				ELSIF (min_en = '1') THEN
--            IF (minute_cnt = "00000101") THEN
--               minute_cnt <= "00000000";
--            ELSE
--               minute_cnt <= minute_cnt + "00000001";
--            END IF;
--         ELSE
--            minute_cnt <= minute_cnt;
--         END IF;
--      END IF;
--   END PROCESS;
--5分钟 一循环,用于(正转、暂停、反转)的时间控制  可修改

   

-----------------------------------------------------------------------
   PROCESS (clk_in)
   BEGIN
      IF (clk_in'EVENT AND clk_in = '1') THEN --上升沿
         IF (washing_time > "00000000" AND synchronization = '1') THEN
            IF (second_cnt < "00010100") THEN--20秒,正转灯(100)亮
               led <= "100";
            ELSIF (second_cnt >= "00010100" AND second_cnt < "00011110") THEN--10秒,暂停灯(010)亮
               led <= "010";
            ELSIF (second_cnt >= "00011110" AND second_cnt < "00110010") THEN--20秒,反转灯(001)亮
               led <= "001";
            ELSE
               led <= "010";--最后10秒,暂停灯(010)亮
            END IF;
         ELSE
            led <= "000";
         END IF;
      END IF;
   END PROCESS;
-----------------------------------------------------------------------
   
END behaveral;

3.2  RTL图

图2.1 RTL图

四、仿真结果分析

4.1 仿真模板(vht文件)

LIBRARY ieee;                                               
USE ieee.std_logic_1164.all;                                

ENTITY washing_machine_vhd_tst IS
END washing_machine_vhd_tst;
ARCHITECTURE washing_machine_arch OF washing_machine_vhd_tst IS
                                                 
-- signals                                                   
SIGNAL clk_in : STD_LOGIC;--时钟信号
SIGNAL end_led : STD_LOGIC;--结束信号
SIGNAL led : STD_LOGIC_VECTOR(2 DOWNTO 0);--状态(正转,暂停,反转)信号
SIGNAL minute_Ones : STD_LOGIC_VECTOR(3 DOWNTO 0);--倒计时分钟个位
SIGNAL minute_Tens : STD_LOGIC_VECTOR(3 DOWNTO 0);--倒计时分钟十位
SIGNAL start_key : STD_LOGIC;--启动按键
COMPONENT washing_machine
	PORT (
	clk_in : IN STD_LOGIC;
	end_led : OUT STD_LOGIC;
	led : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
	minute_Ones : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
	minute_Tens : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
	start_key : IN STD_LOGIC
	);
END COMPONENT;
BEGIN
	i1 : washing_machine
	PORT MAP (
-- 列出主端口和信号之间的连接
	clk_in => clk_in,
	end_led => end_led,
	led => led,
	minute_Ones => minute_Ones,
	minute_Tens => minute_Tens,
	start_key => start_key
	);

----------------------------------------------------------------------
init : PROCESS                                               
-- 使得启动信号产生一个脉冲                                     
BEGIN                                                        
start_key<='0';--启动按键初始为低电平
wait for 500 ns;--500ns后
start_key<='1';--开始信号
wait for 500 ns; 
start_key<='0';
wait for 500 ns;                  
WAIT;                                                       
END PROCESS init;      
----------------------------------------------------------------------

--此处以100ns一个时钟来模拟,是为了快速得到仿真
--正常情况下应该使用1Hz,如此使得秒钟计时器正常运作
--产生时钟                          
always : PROCESS                                                                                  
BEGIN                                                         
clk_in<='1';
wait for 50 ns;
clk_in<='0';
wait for 50 ns;                                                     
END PROCESS always;                                          
END washing_machine_arch;

图3.1 仿真模板代码

4.2 仿真图

图3.2 状态变化仿真

图3.3 倒计时仿真

图3.4 状态变化仿真

图3.4 暂停状态仿真—观察运行时间

4.3 仿真结果分析

由仿真图可见,本次实验目标已完成,已知预置时间为15分钟。倒计时显示正常。

可以看到,状态显示在启动信号上边沿后一个时钟周期开始显示,并且以20s(20个时钟周期,之后所说秒数也是由时钟周期数仿真代替的)正转、10s暂停、20s反转、10s暂停循环。

结束信号在状态变化归0后一个时钟周期电压值变为高电平。

可见所要求的功能已全部实现。

 

  • 26
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值