数字系统设计VHDL实验:洗衣机控制器的设计(简易版)

前言

学校布置的数字系统设计大作业,要求完成VHDL核心代码的设计,采用quartus II进行相关仿真并且在开发板上实现。由于本人能力有限,目的就是为了完成所要求的功能,就没有使用元件例化(同时也觉得作业中的要求比较简单),格式比较随便,代码仅供参考

设计目的与要求

  1. 洗衣机状态及其转换方式为:启动——正转20秒——反转20秒——浸泡10秒——脱水10秒——结束。
  2. 按键启动洗衣机控制程序,用6个LED灯指示洗衣机状态,其中启动指示灯按下启动按键后即点亮,直至结束;正转、反转、浸泡、脱水指示灯为闪烁方式,结束状态灯点亮持续5秒后自动熄灭。
  3. 用两个数码管显示洗涤剩余时间(启动时为60秒)。
  4. 设置一个暂停/恢复键,和一个暂停LED指示灯,暂停时停止计时,暂停指示灯亮;恢复时继续计时,暂停指示灯熄灭。

总体设计

  • 实验开发环境:QuartusII 9.0
  • 硬件资源:EDA-I(便携式)实验板
    资源布局:
    1. 主芯片:ALTERA 公司 EPF10K20TI144-4,提供 2 万逻辑门
    2. 配置芯片:ALTERA 公司 EPM240T100C5N
    3. USB 串并转换芯片:FTDI 公司的 FT245BL
    4. 通用时钟(时钟频率:0.9Hz-6MHz 范围内可调整):4 组
    5. 通用 LED 指示灯:24 个
    6. 通用电平输入/LED 指示:24 个
    7. 通用脉冲输入按键:8 个
    8. 动态数码管显示:8 个
    数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第1张图片
  • 数码管显示资源
    实验箱上共有 8 个数码管,其中 SEL7—SEL0 作为数码管选择信号,ABCDEFGH
    依次对应 7 段译码器及小数点的选通信号。
    8 个数码管共用 8 个段选择信号,在设计的时候,可以选择让 SEL7—SEL0 依次有效(SEL 信号低电平有效),然后对应的每个 SEL,ABCDEFGH有其相应的值(段选择信号高电平有效),只要扫描频率足够,由于人眼的视觉暂留,用户观察到 8 个数码管同时发光,且每个数码管显示的值互相不干扰。如某时刻 SEL0 的值为 0,ABCDEFGH 的值为 00001100,则最右边数码管显示的值为“1”。数码管的段选排列图如图所示:
    数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第2张图片
  • LED 输出显示资源
    一共有24个发光二极管当输出为高电平时,发光二极管导通,产生光源;当输出为低电平时,发光二极管无法导通,灯不亮。
  • 输入开关/输出显示复用资源
    实验箱上共有 24 个开关与 24 个发光二极管,当需要输入时,开关闭合(对于拨码开关向上),则对应输入值为逻辑“1”且发光二极管亮,若开关断开,则输入值为逻辑“0”,数码管不亮。当作为输出时,输出值为逻辑“1”,则发光二极管亮,当输出值为逻辑“0”时,发光二极管不亮。

基本原理

设计流程
EDA的设计流程主要包括设计输入、设计处理、设计验证、器件编程和硬件测试等5个步骤。
本次实验中,我采用通过硬件描述语言VHDL进行电路设计的方式;然后进行综合适配,对设计输入的文件进行逻辑化简,优化,对输入文件进行语法检查,最后产生编程文件;
设计验证即时序仿真和功能仿真。通常情况下,先进行功能仿真,验证其实现的功能是否满足原设计的要求。在功能仿真已经完成,确认设计文件表达的功能满足要求后,再进行综合适配和时序仿真。器件编程是指将设计处理中产生的编程数据下载到具体的可编程器件中,也就是所说的板载测试,将下载文件通过FPGA编程器载入目标芯片FPGA中。硬件测试是指将含有载入了设计的FPGA的硬件系统进行统一测试,便于在真实的环境中检验设计效果。

总体结构分析

洗衣机控制器总体上分为状态控制模块、指示灯、显像管控制模块。其中的核心模块是定时模块,应通过定时模块来决定洗衣机当前所在的状态和所控制的显像管。
洗衣机总共有6个状态,分别为启动、正转、反转、浸泡、脱水、结束;每个状态对应一个指示灯,当一个状态结束时,另一个状态及其对应的指示灯需要立即衔接上去。
定时模块主要用于确定剩余时间,首先将输入的CLK信号分频为1Hz,控制每个状态的运行过程,将实时时间显示在数码管上。当倒计时结束后发送结束信号,显示特定的信息。
显像管控制模块包括用于显示各过程的二极管,也包括显示时间的显像管。通过高频率地来回控制两个显像管,人用肉眼看上去就不会觉得有闪动,从而实时显示当前时间。

子模块设计

定时模块需用到两个CLK信号,其中一个用于控制倒计时,另一个用于控制时间在显像管上的显示。将用于倒计时的CLK信号设置成1Hz,每过1Hz,总时间减1,当个位数为0时,控制十位数减1,同时将个位的数重新置为9;十位减至0,此时若个位位置为0时,个位的数开始每经过1Hz加1,持续5秒,最后重新置0,整个状态结束。十位和个位的起始数值由用户选择的模式来决定,若是浸泡洗,则分别为6和5;若是快速洗,则分别为6和0;若是脱水模式,则分别置为1和0。
控制两个显像管分别显示十位和个位,需要输入极快的CLK信号,在极短的时间内来回显示两个显像管,从而使人们看上去像同时控制了两个显像管。
本次控制器设置了6个状态,实验要求是将所有状态运行一遍。但观察生活中的洗衣机我们可知道,洗衣机可以选择从任意一个状态开始,所以我添加了浸泡洗,分离出了脱水,该控制器总共有三种模式可选择;每个状态都有一个显像管所对应,包括暂停状态。

VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity led is
	port(clk: in std_logic;							--时间控制信号
		sjkz: in std_logic;							--数码管控制
		qidong: in std_logic;						--启动信号
		zanting:in std_logic; 						--暂停信号
		fenggan:in std_logic; 						--脱水信号
		jingpaoxi:in std_logic; 					-浸泡洗信号
		qidongdeng:out std_logic; 					--启动指示灯
		zhengzhuan:out std_logic; 					--正转指示灯
		fanzhuan:out std_logic; 					--反转指示灯
		jingpao:out std_logic; 						--浸泡指示灯
		tuoshui:out std_logic; 						--脱水指示灯
		jieshudeng:out std_logic; 					--结束指示灯
		zantingdeng:out std_logic; 					--暂停指示灯
		ledag:out std_logic_vector(7 downto 0);
		Bt:out std_logic_vector(7 downto 0));
end led;

architecture arc of led is
signal cnt1: integer range 0 to 8 :=6;
signal cnt2: integer range 0 to 9 :=0;
signal jsjs: integer range 0 to 5 :=0;				--结束倒计时控制信号
signal guan:integer range 0 to 1;
signal cntx:integer range 0 to 1;					--两个数码管控制信号
signal jieshu:std_logic :='0';
begin

--控制特定的数码管
P1:process(cnt1,cnt2)	
	begin 
	case cntx IS
		when 0=> BT<="11111101";guan<=0;			--显示十位的数码管
		when 1=> BT<="11111110";guan<=1;			--显示个位的数码管
		when others=>NULL;
	End case;
	end process p1;
	
--两个数码管来回显示控制
p2:process(sjkz)
	begin
	if sjkz='1' then 
		cntx<=1;
	else cntx<=0;
	end if;
	end process p2;
	
--倒计时进程控制
P3:process(clk) 									
	begin
	qidongdeng<='0';
	if fenggan='1' and jingpaoxi='0' and qidong='0' then
		cnt1<=1;
	elsif jingpaoxi='1' and fenggan='0' and qidong='0' then
		cnt2<=5;
	else
		if qidong='1' then
			qidongdeng<='1';
			if clk'event and clk='1' then			--每隔1Hz进行一次减1操作
					if zanting='0' then
						zantingdeng<='0';
						if jieshu='0' then
							if cnt2=0 and cnt1 /=0 then 
								cnt1<=cnt1-1;
								cnt2<=9;
							elsif cnt2=0 and cnt1=0 then
								cnt1<=0;
								cnt2<=0;
							else cnt1<=cnt1;
								cnt2<=cnt2-1;
							end if;
							if cnt1=5 or cnt1=4 then 
								if cnt2=9 or cnt2=7 or cnt2=5 or cnt2=3 or cnt2=1 then
									zhengzhuan<='1';
								else zhengzhuan<='0';
								end if;
							end if;
							if cnt1=3 or cnt1=2 then 
								if cnt2=9 or cnt2=7 or cnt2=5 or cnt2=3 or cnt2=1 then
									fanzhuan<='1';
								else fanzhuan<='0';
								end if;
							end if;
							if cnt1=1 then 
								if cnt2=9 or cnt2=7 or cnt2=5 or cnt2=3 or cnt2=1 then
									jingpao<='1';
								else jingpao<='0';
								end if;
							end if;
							if cnt1=0 then
								if cnt2=9 or cnt2=7 or cnt2=5 or cnt2=3 or cnt2=1 then
									tuoshui<='1';
								else tuoshui<='0';
								end if;
								if cnt2=0 then
									jieshudeng<='1';
									jieshu<='1';
								end if;
							end if;
						else 	cnt1<=0;
								cnt2<=0; 
							if jsjs=5 then
								jieshudeng<='0';
								cnt1<=8;
								cnt2<=0;
							 else
								jsjs<=jsjs+1;
								cnt2<=jsjs+1;
								jieshudeng<='1';	
							 end if;
						end if;
					else cnt1<=cnt1;
						cnt2<=cnt2;
						zantingdeng<='1';
					end if;
				end if;
			end if;
		end if;
	end process P3;
	
	--显像管显示资源控制
P4:process(guan,cnt1,cnt2) 								
	begin
		if guan=1 then
		case cnt2 is							--控制个位的数码管显示数字信息
			when 0 => ledag <="11111100";
			when 1 => ledag <="01100000";
			when 2 => ledag <="11011010";
			when 3 => ledag <="11110010";
			when 4 => ledag <="01100110";
			when 5 => ledag <="10110110";
			when 6 => ledag <="10111110";
			when 7 => ledag <="11100000";
			when 8 => ledag <="11111110";
			when 9 => ledag <="11110110";
			when others => null;
		end case;
		else
		case cnt1 is							--控制十位的数码管显示数字信息
			when 0 => ledag <="11111100";
			when 1 => ledag <="01100000";
			when 2 => ledag <="11011010";
			when 3 => ledag <="11110010";
			when 4 => ledag <="01100110";
			when 5 => ledag <="10110110";
			when 6 => ledag <="10111110";
			when 7 => ledag <="11100000";
			when 8 => ledag <="00000001";
			when others => null;
		end case;
		end if;
	end process P4;
end arc;

引脚分布

注意!一定要根据自己使用的开发板上的引脚来设置,下面我只能提供我所使用的开发板的引脚分布,设置不一定要一模一样,具体情况具体布局
数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第3张图片
数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第4张图片
输入信号主要分三大类型,第一类是左上角蓝色部分的通用时钟信号,用于发送固定时钟频率的波动信号,这里选择一个合适的频率来回切换当前一瞬间所控制的数码管,再选择一个合适的频率用来控制倒计时速度
第二类就是红色部分中的电平信号,将开关向上拨动表示该引脚输出高电平,向下
表示低电平
第三类就是黑色部分的脉冲信号,按一次表示输出一个高脉冲,不像电平信号会一直维持当前状态,所以可以用于电话按键等方面

开发板应该都具备这些基本输入信号类型,建议看看开发板相应的说明书

板载测试

  • 开始状态
    标准状态下,控制器从60秒开始倒计时,70端口代表开始信号,若将其置为1,程序开始运行。
  • 运行过程:
    启动指示灯在按下启动按键后即点亮,显像管根据题目要求,在规定时间内产生变化,根据倒计时时间来决定表示各个状态的二极管闪烁。
    数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第5张图片

运行结束:
5秒倒计时结束后,结束指示灯长亮,显像管显示规定数值。
数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第6张图片
数字系统设计VHDL实验:洗衣机控制器的设计(简易版)_第7张图片

分析与总结

本实验中系统设计已达成目的,完成了所要求的各功能,但还有一些地方可以进行优化,比如在程序中加入一部分对波形图显示进行优化的代码,使显像管对应的二进制表示改变成人们更习惯的十进制。
这次大作业,我收获最大的就是EDA操作的流程,VHDL语言的使用以及进程之间的通信都有了更深刻的认识,在实际操作中遇到了很多人都会遇到的问题,这些问题不会在书中讲述,只有靠平时的经验积累,才能为以后工作少走弯路。使用硬件描述语言需要我们学会从硬件的角度出发,理解信号传递之间的逻辑,在使代码精简的同时,确保系统运行的稳定性和正确性。

你可能感兴趣的:(数字系统设计,EDA,vhdl)