洗衣机控制系统 VHDL语言 状态机实现

来源:互联网 发布:origin8.0软件下载 编辑:程序博客网 时间:2024/04/28 14:46

题目要求如下:

一、设计任务

洗衣机有注水、洗涤、排水、脱水和漂洗等功能,每个功能均有对应的显示灯,运行在某种工作状态时,其对应显示灯一直亮,直到此功能工作结束。其中,注水功能提供低,中,高三个水位等级供用户选择;洗涤功能有弱洗,普通,强洗三个洗涤等级可供选择。注水,洗涤,排水,脱水,漂洗状态的转变分别由各自的使能端控制。

系统有六个工作模式。其中,模式1=洗涤+漂洗+脱水,模式2=洗涤+漂洗,模式3=漂洗+脱水,模式4=洗涤,模式5=漂洗,模式6=脱水。

二、需求分析

(1)系统所有操作均有统一的时钟信号,统一的复位端。

(2)系统设有暂停端,当处于某一工作状态时,若按下暂停端,则停在此工作状态。

(3)在当前的运行状态时,有数码显示当前剩余时间;

(4)所有操作完成之后,有响铃提示。

三、设计方案

该系统由输入模块、控制模块和输出模块构成。输入模块完成洗涤时间的预置与编码,控制模块完成洗涤时间计时以及对电机运行状态的控制,输出模块完成电机运行状态的指示。

四、必须用状态机实现(为后续课程组原做准备),经典状态机代码如下:

1. Moore型状态机:

library ieee;

use ieee.std_logic_1164.all;

 

entity Moore is

port(

     Reset:in std_logic;

     Clock:in std_logic; 

     DIN:in std_logic;

     DOUT:out std_logic_vector(2 downto 0)

    );

end Moore;

 

architecture Mooremachine of Moore is

type State_type is(S0,S1,S2,S3);

signal PresenState:State_type;     

signal NextnState:State_type;      

begin

 

State_Reg:                

   process(Reset,Clock)      

   begin

      if Reset='1'then

         PresenState<=S0;

      elsif rising_edge(Clock)then

         PresenState<=NextnState;

      end if;

   end process;

 

Change_State:      

   process(PresenState,DIN)

   begin

      case PresenState is

         when S0=>

            if DIN='1'then

               NextnState<=S1;

            else

               NextnState<=S0;

            end if;

            DOUT<="001";

         when S1=>

            if DIN='1'then

               NextnState<=S2;

            else

               NextnState<=S1;

            end if;

            DOUT<="011";

         when S2=>

            if DIN='1'then

               NextnState<=S3;

            else

               NextnState<=S2;

            end if;

            DOUT<="101";

         when S3=>

            if DIN='1'then

               NextnState<=S0;

            else

               NextnState<=S1;

            end if;

            DOUT<="111";

      end case;

   end process;

end Mooremachine;


2. Mealy型状态机:

library ieee;

use ieee.std_logic_1164.all;

 

entity Mealy is

port(

     Reset:in std_logic;                     

     Clock:in std_logic;                     

     DIN:in std_logic;                       

     DOUT:out std_logic_vector(2 downto 0)   

    );

end Mealy;

 

architecture Statemachine of Mealy is

type State_type is(S0,S1,S2,S3);           

signal State:State_type;

 

begin

 

Change_State:                              

   process(State,DIN)

   begin

      if Reset='1'then

         State<=S0;

      elsif rising_edge(Clock)then           

         case State is

            when S0=>

               if DIN='1' then

                  State<=S1;

               end if;

            when S1=>

               if DIN='1' then

                  State<=S2;

               end if;

            when S2=>

               if DIN='1' then

                  State<=S3;

               end if;

            when S3=>

               if DIN='1' then

                  State<=S0;

               else

                  State<=S1;

               end if;

         end case;

      end if;

   end process;

 

Output_Process:                

   process(State,DIN)

   begin

      case State is

         when S0=>

            if DIN='0' then

               DOUT<="000";    

            else

               DOUT<="001";       

            end if;

         when S1=>

            if DIN='0' then

               DOUT<="010";

            else

               DOUT<="011";

            end if;

         when S2=>

            if DIN='0' then

               DOUT<="100";

            else

               DOUT<="101";

            end if;

         when S3=>

            if DIN='0' then

               DOUT<="110";

            else

               DOUT<="111";

            end if;

      end case;

   end process;

end Statemachine;

——————————————————————————————————————————————

以下是设计及实现:

一、设计思路

先确定输入有哪些,通过观察题目可知,“系统的所有操作均有统一时钟信号,统一的复位端”,“系统有六个工作模式。模式1=洗涤+漂洗+脱水….”,“系统设有暂停端”,“注水功能提供低,中,高三个水位等级供用户选择;洗涤功能有弱洗,普通,强洗三个洗涤等级可供选择”。综上可得出输入有以下几个:clk:时钟信号;reset:复位端,相当于开关,为‘1’时复位,为‘0’时洗衣机才可正常工作;user_input:用户输入的模式选择001—110分别为模式1—模式6;zanting:暂停端,为‘1’时暂停;zs_time:注水有低中高三个水位等级,可用注水时间长短来表示(当注水3s表示低水位,4s表示中水位,5s表示高水位);px_time:漂洗时间(当漂洗水3s表示弱洗,4s表示普通,5s表示强洗)。其余功能时间设置均为5s。

再确定输出,仍分析题目:“每个功能均有对应的显示灯,运行在某种工作状态时,其对应显示灯一直亮,直到此功能工作结束”,“在当前的运行状态时,有数码显示当前剩余时间”,“所有操作完成之后,有响铃提示”。综上得输出有以下几个:light1,light2...light5:每个功能所对应的显示灯,当该功能被运行时,显示灯会一直亮;time_3s:3s倒计时显示器;time_4s:4s倒计时显示器;time_5s:5s倒计时显示器;ring:铃。

 整个系统由三个模块组成,第一个模块是输入模块,在这个模块,需要用户输入所选择的模式,以及注水漂洗的时间,若选择的模式为3,4或6,则可略去洗涤时间,然后把模式编码,编码对应如下:

1. 模式1=漂洗+洗涤+脱水001->001 010 011 100 101 110  (注水+漂洗+洗涤+脱水+排水+响铃)

2. 模式2=漂洗+洗涤          010->001 010 011 000 101 110  (注水+漂洗+洗涤+ 空  +排水+响铃)

3. 模式3=漂洗+脱水          011->001 000 011 100 101 110  (注水+漂洗+ 空   +脱水+排水+响铃)

4. 模式4=漂洗                   100->001 010 000 000 101 110  (注水+漂洗+ 空   +  空  +排水+响铃)

5. 模式5=洗涤                   101->001 000 011 000 101 110  (注水+ 空   +洗涤+  空  +排水+响铃)

6. 模式6=脱水                   110->001 000 000 100 101 110  (注水+ 空   + 空   +脱水+排水+响铃)

第二个模块为计时模块,包含3部分:3s计时器,4s计时器和5s计时器;

第三个模块为控制模块,本次课设选用的是米里机,这个模块需要进行状态转换,一共有6个状态,当reset为‘1’时是S0状态,否则当上升沿到来时,转为S1状态(注水),此时读取注水时间,激活相应计时器,当计时器到时候反馈回一个计时结束的信号时,转为S2状态(漂洗)或S3状态(洗涤)或S4状态(脱水),视读取的编码而定....直至S6状态响铃,然后转为S7灯灭铃熄。具体见下文代码。


二、具体实现

输入文件:

LIBRARY ieee;
USE ieee.std_logic_1164.all;


ENTITY shuru IS
PORT
(
user_input  :INSTD_LOGIC_vector(2 downto 0);
reset : INSTD_LOGIC;
clk : INSTD_LOGIC;
user_output : OUT STD_LOGIC_vector(17 downto 0)
);
END shuru;


ARCHITECTURE b OF shuru IS 
BEGIN
PROCESS (reset,clk)
BEGIN
  IF reset = '1' then
     user_output <= "000000000000000000"; 
  elsif (clk'EVENT AND clk = '1') THEN
if user_input = "001" then          --模式一
user_output <= "001010011100101110";
elsif user_input = "010" then       --模式二
user_output <= "001010011000101110";
        elsif user_input = "011" then       --模式三
user_output <= "001000011100101110";
elsif user_input = "100" then       --模式四
user_output <= "001010000000101110";
elsif user_input = "101" then       --模式五
user_output <= "001000011000101110";
elsif user_input = "110" then       --模式六
user_output <= "001000000100101110";
else user_output <= "000000000000000000";
end if;  --user_input
  END IF;    --reset
END PROCESS;
END b;


状态转换文件:

library ieee;
use ieee.std_logic_1164.all;


entity Mealy_control is
port(
reset : in std_logic;
clk : in std_logic;

zs_time : in std_logic_vector(2 downto 0);     --注水时间(100: 4s, 011: 3s, 101: 5s)
px_time : in std_logic_vector(2 downto 0);     --漂洗时间(100: 4s, 011: 3s, 101: 5s)

time_4s : in std_logic;     --从计时器反馈过来的信号,为'1'时表示4s已经结束
time_3s : in std_logic;    
time_5s : in std_logic;
enable_4s : out std_logic;  --为'1'时启动4s计时器
enable_3s : out std_logic;
enable_5s : out std_logic;
light1 : out std_logic;
light2 : out std_logic;
light3 : out std_logic;
light4 : out std_logic;
light5 : out std_logic;
ring : out std_logic;

transfer : in std_logic_vector(17 downto 0);
DOUT : out std_logic_vector(2 downto 0)
);
end Mealy_control;


architecture a of Mealy_control is
type State_type is(s0, s1, s2, s3, s4, s5, s6, s7);
signal State : State_type;
signal DIN : std_logic_vector(2 downto 0);
signal DIN_DIN : std_logic_vector(2 downto 0);


--signal DIN : std_logic_vector(2 downto 0);
begin 


process(State, transfer)
begin

if reset='1' then
State<=s0;
elsif(clk'event and clk='1')then
case State is
when s0=>                      --s0到s1状态的转换经过了两个上升沿????????????????
DIN <= transfer(17)&transfer(16)&transfer(15);
if DIN="001" then 
State<=s1;                                                         
if zs_time="100" then enable_4s<='1';enable_3s<='0';enable_5s<='0';
elsif zs_time="011" then enable_4s<='0';enable_3s<='1';enable_5s<='0';
elsif zs_time="101" then enable_4s<='0';enable_3s<='0';enable_5s<='1';
end if;
else State<=s0;
end if;
when s1=>   
DIN<=transfer(14)&transfer(13)&transfer(12);   
DIN_DIN<=transfer(11)&transfer(10)&transfer(9);   
if DIN="010" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s2;
if px_time="100" then enable_4s<='1';enable_3s<='0';enable_5s<='0';
elsif px_time="011" then enable_4s<='0';enable_3s<='1';enable_5s<='0';
elsif px_time="101" then enable_4s<='0';enable_3s<='0';enable_5s<='1';
end if;
elsif DIN="000" and DIN_DIN="000" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s4;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
elsif DIN="000" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s3;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
else State<=s1;
end if;
when s2=>
DIN<=transfer(11)&transfer(10)&transfer(9);
DIN_DIN<=transfer(8)&transfer(7)&transfer(6);             --模式四
if DIN="011" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s3;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
elsif DIN="000" and DIN_DIN="000" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s5;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
elsif DIN="000" and (time_4s='1' or time_3s='1' or time_5s='1') then
State<=s4;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
else State<=s2;
end if;
when s3=>
DIN<=transfer(8)&transfer(7)&transfer(6);
if DIN="100" and time_5s='1' then 
State<=s4;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
elsif DIN="000" and time_5s='1' then
State<=s5;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
else State<=s3;
end if;
when s4=>
DIN<=transfer(5)&transfer(4)&transfer(3);
if DIN="101" and time_5s='1' then
State<=s5;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
else State<=s4;
end if;
when s5=>
DIN<=transfer(2)&transfer(1)&transfer(0);
if DIN="110" and time_5s='1' then
State<=s6;
enable_4s<='0';enable_3s<='0';enable_5s<='1';
else State<=s5;
end if;
when s6=>                        --当响铃时刻
if time_5s='1' then
State<=s7;               --s0之后的状态--错误!
else State<=s6;
end if; 
when s7=>
enable_4s<='0';enable_3s<='0';enable_5s<='0';
end case;                      
end if;
end process;

process(State, transfer)
begin
case State is 
when s0=>
light1<='0';light2<='0';light3<='0';light4<='0';light5<='0';ring<='0';
DOUT<="000";
when s1=>
light1<='1';light2<='0';light3<='0';light4<='0';light5<='0';ring<='0';
DOUT<="001";
when s2=>
light1<='0';light2<='1';light3<='0';light4<='0';light5<='0';ring<='0';
DOUT<="010";
when s3=>
light1<='0';light2<='0';light3<='1';light4<='0';light5<='0';ring<='0';
DOUT<="011";
when s4=>
light1<='0';light2<='0';light3<='0';light4<='1';light5<='0';ring<='0';
DOUT<="100";
when s5=>
light1<='0';light2<='0';light3<='0';light4<='0';light5<='1';ring<='0';
DOUT<="101";
when s6=>
light1<='0';light2<='0';light3<='0';light4<='0';light5<='0';ring<='1';
DOUT<="110";
when s7=>
light1<='0';light2<='0';light3<='0';light4<='0';light5<='0';ring<='0';
DOUT<="000";
end case;
end process;
end a;

计时器文件

(1)3s计时器文件

library ieee;
use ieee.std_logic_1164.all;
entity jishi_3s is
port(
clk              : in std_logic;
reset_enable     : in std_logic;   --重置
zanting          : in std_logic;  --暂停端 1为暂停
output_3s        : out STD_LOGIC_vector(1 downto 0);
time_3s          : out std_logic     --反馈给控制模块,为'1'时表示1s倒计时结束
);
end jishi_3s;
architecture d of jishi_3s is
begin
process(reset_enable,clk)
variable count : integer range 0 to 3;
begin
if(reset_enable='0')then
count:=3;
--output_3s<="00";
output_3s<="11";
time_3s<='0';
elsif(clk'event and clk='1')then
 if zanting='0' then --未暂停
count:=count-1;
if(count=2)then output_3s<="10";time_3s<='0';
elsif(count=1)then output_3s<="01";time_3s<='0';
elsif(count=0)then output_3s<="00";time_3s<='1';count:=3;
end if;  --if count=0
 end if;  --zanting
end if; --if reset
end process;
end d;

(2)4s计时器文件

library ieee;
use ieee.std_logic_1164.all;
entity jishi_4s is
port(
clk              : in std_logic;
reset_enable     : in std_logic;   --重置
zanting          : in std_logic;  --暂停端 1为暂停
output_4s        : out STD_LOGIC_vector(2 downto 0);
time_4s          : out std_logic     --反馈给控制模块,为'1'时表示4s倒计时结束
);
end jishi_4s;
architecture d of jishi_4s is
begin
process(reset_enable,clk)
variable count : integer range 0 to 4;
begin
if(reset_enable='0')then
count:=4;
output_4s<="100";
time_4s<='0';
elsif(clk'event and clk='1')then
 if zanting='0' then --未暂停
count:=count-1;
if(count=3)then output_4s<="011";time_4s<='0';
elsif(count=2)then output_4s<="010";time_4s<='0';
elsif(count=1)then output_4s<="001";time_4s<='0';
elsif(count=0)then output_4s<="000";time_4s<='1';count:=4;
end if;  --if count=0
 end if;  --zanting
end if; --if reset
end process;
end d;

(3)5s计时器文件

library ieee;
use ieee.std_logic_1164.all;
entity jishi_5s is
port(
clk              : in std_logic;
reset_enable     : in std_logic;   --重置
zanting          : in std_logic;  --暂停端 1为暂停
output_5s        : out STD_LOGIC_vector(2 downto 0);
time_5s          : out std_logic     --反馈给控制模块,为'1'时表示1s倒计时结束
);
end jishi_5s;
architecture d of jishi_5s is
begin
process(reset_enable,clk)
variable count : integer range 0 to 5;
begin
if(reset_enable='0')then
count:=5;
output_5s<="101";
time_5s<='0';
elsif(clk'event and clk='1')then
 if zanting='0' then --未暂停
count:=count-1;
if(count=4)then output_5s<="100";time_5s<='0';
elsif(count=3)then output_5s<="011";time_5s<='0';
elsif(count=2)then output_5s<="010";time_5s<='0';
elsif(count=1)then output_5s<="001";time_5s<='0';
elsif(count=0)then output_5s<="000";time_5s<='1';count:=5;
end if;  --if count=0
 end if;  --zanting
end if; --if reset
end process;
end d;

三个文件连接的bdf图如下所示


得到的仿真结果如下,第一张是模式一,第二张是模式5,其余略。




哈哈,仔细看仿真结果你就会发现其实是有错误的,但是一个个分别运行这三个文件得出的仿真结果又正确,所以说问题就出在控制部分的时钟沿和计时器的时钟沿没有协调好,这个错误 我现在还没想到解决方法,如果众位大神知道如何做最少的修改能改掉这个错误,恳请一定要告诉我,在此谢过!

0 1
原创粉丝点击