基于mealy状态机的密码锁系统设计

应学院课程安排学习了verilog语言并在Xilinx vivado下用寄存器传输级的verilog 代码做功能实现,最后在basys3开发板上作验证与测试。

一、FPGA基本介绍

FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。在一些特殊场景(如运行中的卫星等)中,可编程是极大的优势。

FPGA在民用中最大的优点是成本与时间:自定制ASIC设计的非经常性工程(NRE)费用远远超过基于FPGA的硬件解决方案所产生的费用。ASIC设计初期的巨大投资表明了原始设备制造商每年需要运输数千种芯片,但更多的最终用户需要的是自定义硬件功能,从而实现数十至数百种系统的开发。可编程芯片的特性意味着用户可以节省制造成本以及漫长的交货组装时间。这也大大加快了开发过程,快速验证现有思路和实现,快速改进、定型,继而送去生产相应的ASIC,从而实现设计花费和产品功效的平衡。

二、本项目要求

这次利用Verilog语言在FPGA开发板basys3上实现密码锁的具体要求如下:

1 密码锁接受任意长度的密码,只有密码为123 时开锁,其余情况拒绝开锁。
2 以开关为输入密码信号,以LED 灯为开锁信号。
3 密码输入完毕应进入等待状态,等待确认信号。
4 以按键为确认信号,输入确认信号后显示是否开锁。
5 开关拨动一个来回,按键按下又弹起作为一次有效输入。
6 应有复位信号。
7 请根据mealy 状态机的规范设计密码锁的状态图,并用寄存器传输级的verilog 代码做功能实现。
8 在basys3 板上作验证与测试。

三、分析设计

设计所要实现的功能为:

1、手动用0~9的拨码开关设计三位密码。

2、当输入密码开锁时,输入密码后还需要按确认键才进行判断

3、当密码输入错误时,错误指示灯亮,表示开锁失败。

4、应有复位信号。

首先,实验要求是基于mealy状态机的,故输出不仅与存储电路的当前状态有关,还与输入有关。

确定基本要求和模式如下

1、输出为2位LED灯,第一个作为正确解锁LED灯,第二个作为错误&重置LED灯

2、输入为10位数字键(0~9)、1位确认键和1位重置键。然后化归,将确认键和数字键作为一组(即代码中的inKey),重置键无法化归,另算。由于是同步时序逻辑电路,还需要时钟信号。

将确认信号和数字输入信号化归,相当于“1、2、3、确认”4次按键,但又有“开关拨动一个来回、按键按下又弹起作为一次有效输入”的要求,可将其视为8个状态(1个基本状态+7个中间状态),再搭配两个错误状态:一个是基本错误状态,另一个是在错误状态的基础上再拨动一次开关(未拨回)的状态,这样可以满足要求。

进一步构思得:10种状态(基本初态s0,中间状态s1~s7,错误状态serror和serror1)搭配5种输入(Put0:00000000000(正常状态)、Put1:00000000010(输入1)、Put2:00000000100(输入2)、Put3:00000001000(输入3)、PutOK:10000000000(输入确认键)),复位信号直接强制将任意状态转化为基本初态s0且LED灯置为01(错误&重置指示灯亮)。

流程图如下:

基于mealy状态机的密码锁系统设计_第1张图片


四、代码实现

由于整个实验要求不是太难,整个流程结构比较紧凑、简单,故只用一个模块实现所有功能。

module mima(
	output [1:0] led,
	input [10:0] inKey,
	input reset,
	input clk
	);
	
	reg [1:0] led;
	reg [3:0] state;
	
	parameter led_begin = 2'b00;
	parameter led_true = 2'b10;
	parameter led_false = 2'b01;
	
	parameter put0 = 11'b00000000000;
	parameter put1 = 11'b00000000010;
	parameter put2 = 11'b00000000100;
	parameter put3 = 11'b00000001000;
	parameter putOK = 11'b10000000000;
	
	parameter s0 = 4'b0000;
	parameter s1 = 4'b0001;
	parameter s2 = 4'b0010;
	parameter s3 = 4'b0011;
	parameter s4 = 4'b0100;
	parameter s5 = 4'b0101;
	parameter s6 = 4'b0110;
	parameter s7 = 4'b0111;
	parameter serror = 4'b1000;
	parameter serror1 = 4'b1001;
	
	always @(posedge clk)
		if (reset) // 重置
		begin
		    led <= led_false;
			state <= s0;
		end
		else
			case (state) // mealy有限状态机
			s0:
			begin
				if (inKey == put1)
				begin
					led <= led_begin;
					state <= s1;
				end
				else if (inKey == put0)
				begin
					led <= led_begin;
					state <= s0;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s1:
			begin
				if (inKey == put0)
				begin
					led <= led_begin;
					state <= s2;
				end
				else if (inKey == put1)
				begin
					led <= led_begin;
					state <= s1;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s2:
			begin
				if (inKey == put2)
				begin
					led <= led_begin;
					state <= s3;
				end
				else if (inKey == put0)
				begin
					led <= led_begin;
					state <= s2;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s3:
			begin
				if (inKey == put0)
				begin
					led <= led_begin;
					state <= s4;
				end
				else if (inKey == put2)
				begin
					led <= led_begin;
					state <= s3;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s4:
			begin
				if (inKey == put3)
				begin
					led <= led_begin;
					state <= s5;
				end
				else if (inKey == put0)
				begin
					led <= led_begin;
					state <= s4;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s5:
			begin
				if (inKey == put0)
				begin
					led <= led_begin;
					state <= s6;
				end
				else if (inKey == put3)
				begin
					led <= led_begin;
					state <= s5;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s6:
			begin
				if (inKey == putOK)
				begin
					led <= led_begin;
					state <= s7;
				end
				else if (inKey == put0)
				begin
					led <= led_begin;
					state <= s6;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			s7: // 根据输入put0(开关拨回)来决定输出led正确灯亮
			begin
				if (inKey == put0)
				begin
					led <= led_true;
					state <= s7;
				end
				else if (inKey == putOK)
				begin
					led <= led_begin;
					state <= s7;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			serror: // 基本错误状态,输入putOK进入下一错误状态
			begin
				if (inKey == putOK)
				begin
					led <= led_begin;
					state <= serror1;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
			serror1: // 错误状态2,输入put0(开关拨回)输出led错误灯亮
			begin
				if (inKey == put0)
				begin
					led <= led_false;
					state <= serror1;
				end
				else if (inKey == putOK)
				begin
					led <= led_begin;
					state <= serror1;
				end
				else
				begin
					led <= led_begin;
					state <= serror;
				end
			end
		endcase
endmodule

五、测试

运行SyathesisàSynthesized DesignàReport Power,查看用电估计功率报告如下:

基于mealy状态机的密码锁系统设计_第2张图片

之后进行输入信号(序列)测试,测试数据及结果如下:

信号测试数据表
信号测试数据 结果(正确灯、错误&重置灯)
重置 01
1、2、 00
1、2、3、确认 10
1、2、5 00
1、2、5、确认 01
7、1、2 00
7、1、2、确认 01
1、8、2、3 00
1、8、2、3、确认 01
1、2、3、9 00
1、2、3、9、确认 01
1、2、3、重置 01
4、1、2、重置 01
1、2、7、3、重置 01
1、2、3、8、重置 01
   

由此表可判断,此设计和实现没有问题,完全达到设计要求、圆满完成设计任务。

下为两张运行时图



六、end

如有需要代码,直接在csdn上搜索

基于mealy状态机的密码锁系统设计_全工程.rar

就好了

你可能感兴趣的:(FPGA)