半定制器件课程设计——基于FPGA的PS2键盘人机输入显示系统

寵の児 提交于 2019-12-13 05:14:40

本次半定制器件课程设计主要涉及FPGA逻辑设计Verilog HDL等方面的知识应用,根据课程设计要求完成了基于FPGA的人机输入显示系统,本系统目前还可以继续完善,目前实现的内容也相对来说较为基础,主要针对FPGA等逻辑器件设计的入门级玩家,有兴趣的旁友可以继续添加。


对于想要获取此课程设计报告word/PDF版本的同学,欢迎光顾小生寒舍 GitHub:https://github.com/ChromeWei?tab=repositories

特此感谢, 课程设计过程中任课老师张老师给予的指导和帮助!

第一部分 课程设计概述

1 课程设计的目的与任务

(1)熟练掌握EDA工具软件QuartusII的使用;
(2)熟练用Verilog HDL硬件描述语言描述数字电路;
(3)学会使用Verilog HDL进行大规模集成电路设计;
(4)学会用CPLD\FPGA使用系统硬件验证电路设计的正确性;
(5)初步掌握EDA技术并具备一定的可编程逻辑芯片的开发能力;

2 课程设计题目

人机输入显示系统:PS/2键盘输入, LCD显示

3 设计功能要求

(1)实现PS/2键盘的输入
(2)将键盘输入的内容显示在液晶显示器上;
(3)键盘的功能实现自定,例如是否考虑功能键,是否使用连击等;
(4)显示格式自定,例如是否使用多行,是否使用大小写等。

4 设计实现提示

方法是将PS/2模块与LCD模块连接
(1)问题是数据如何传递?
(2)利用LCD数据存储器?
(3)使用RAM宏模块?

5 课程设计的内容与要求

5.1 设计内容

(1)系统功能的分析;
(2)实现系统功能的实际方案;
(3)编写各功能模块的VHDL语言程序;
(4)对各功能模块进行编译、综合、仿真、分析;
(5)顶层文件设计
(6)对整个系统进行编译、综合、仿真、分析;
(7)在CPLD\FPGA实验开发系统试验箱上进行硬件验证;
(8)写课程设计报告;

5.2 设计要求

(1)按所布置的题目要求,每一位学生独立完成全过程;
(2)分模块层次化设计;
(3)各功能模块的底层文件必须用VHDL语言设计,顶层文件可用VHDL语言设计,也可以用原理图设计。


第二部分 实验仪器及平台

(1)PC机;
(2)QuartusII软件;
(3)黑金FPGA实验开发系统,芯片为Cyclone II的EP2C5Q208C8;



第三部分 设计方案

1 PS2解码

在这里插入图片描述
  图1为PS2的接口图。我使用的的右边的PS2接口,即1脚为数据脚,5脚为时钟脚,同时我编写的VHDL代码只对1脚和5脚操作。
在这里插入图片描述

图2 PS2协议时序图
  图2为PS2协议时序图。由图可以解读出,PS2协议对数据的读取时“CLK的下降沿”有效,而数据的放置时在“CLK的上升沿”。PS2频率比较慢,大概为10KHz。

第N位 属性
0 开始位
1~8 数据位
9 校验位
10 结束位
表1 PS2数据说明
  PS2的一帧数据时11位。对PS2进行解码,我们需要得到的是1~8位的数据位。其他的位,可以使用取巧的方法编写。
  键盘的编码有“通码(Make)”和“断码(Break)”之分。通码相当于某个按键按下了,断码相当于某个按键释放了。假设,我们按下了“Z”键不放,大约每秒有10个X“1A”的通码(10KHz),而当我们释放“Z”键,就会输出断码X“F0”和X“1A”。同时,键盘编码一次只能有一个输出,即多个按键同时按下时,只有一个有效。
  下表为第二套PC键盘扫描码。

在这里插入图片描述

在这里插入图片描述

表2 PC键盘第二套扫描码

2 设计思路

(1)PS2时钟的检测;
(2)PS2数据的接受并提取需要的8位数据;
(3)对PS2提取的8位数据进行解码,确定按键;
(4)通过LED灯显示按键的解码的结果;
(5)设置多个按键,多种LED显示方式;
  对于PS2键盘扫描程序,我的设计思路是一个模块一个功能,这样能清晰分辨模块,同时易于修改代码。代码条理清晰,便于解读。而对于多个模块则使用层次化的形式来编写,顶层文件并不包含功能的设定,只包含各个子功能模块。

3 模块设计

  PS2键盘扫描分为:电平检测,PS2解码,PS2组合,LED控制和总PS组合六个模块。下面为各个模块的简易模块图。

3.1 PS2时钟检测模块:

在这里插入图片描述

图3 电平检测模块图

3.2 PS2解码模块:

在这里插入图片描述

图4 PS2解码模块图

3.3 PS2组合模块:

在这里插入图片描述

图5 PS2组合模块图

3.4 控制LED模块:

在这里插入图片描述

图6 LED控制模块图

3.5 PS2总的组合模块:

在这里插入图片描述

图7 PS2模块图

4 各模块分析

4.1 PS2时钟检测模块

  PS2电平检测模块主要的作用是检测PS2接口键盘的时钟信号,因为PS2的协议规定数据是在时钟的下降沿读取的。所以电平检测模块要检测PS2时钟的下降沿,有下降沿来临时,要做相应的数据读取动作。下面是代码的分析。

LIBRARY IEEE;										--库
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2_detect_module IS							--实体声明
	PORT(
			CLK,RSTn        : IN STD_LOGIC;
			PS2_CLK_Pin_In  : IN STD_LOGIC;
			H_L_Sig         : OUT STD_LOGIC;		--电平由高变低,输出一个信号
			L_H_Sig         : OUT STD_LOGIC		    --电平由低变高,输出一个信号	
		);
END ENTITY PS2_detect_module;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2_detect OF PS2_detect_module IS			--结构体声明
	SIGNAL H_L_F1 : STD_LOGIC :='1';					--声明4个信号,用于电平输入的变化
	SIGNAL H_L_F2 : STD_LOGIC :='1';					--4个信号都赋了初值
	SIGNAL L_H_F1 : STD_LOGIC :='0';
	SIGNAL L_H_F2 : STD_LOGIC :='0';		
	BEGIN
			PROCESS(CLK,RSTn)
			BEGIN
				IF (CLK'event AND CLK='1') THEN		--同步进行
					IF (RSTn='0') THEN				--同步复位动作
						 H_L_F1 <= '1';H_L_F2 <= '1';L_H_F1 <= '0';L_H_F2 <= '0';
					ELSE
						 H_L_F1 <= PS2_CLK_Pin_In;H_L_F2 <= H_L_F1;
						 L_H_F1 <= PS2_CLK_Pin_In;L_H_F2 <= L_H_F1;
					END IF;
				END IF;
			END PROCESS;
			H_L_Sig <= H_L_F2 AND (NOT H_L_F1);		--输出信号
			L_H_Sig <= L_H_F1 AND (NOT L_H_F2);		
END ARCHITECTURE PS2_detect;						--结构体结束

  在结构体中声明了4个信号,用于电平的检测F2信号是接着F1信号的,如果F1信号变化了,F2信号还不会立即变化,F2还会保持F1的前一个状态,以两者的逻辑关系,可以判断输入的是上升沿还是下降沿。结果如表格3。

时间 H_L_F1 H_L_F2 H_L_Sig <= H_L_F2 AND (NOT H_L_F1)
Initial 1 1 0
T1 0 1 1
T2 0 0 0
时间 L_H_F1 L_H_F2 L_H_Sig <= L_H_F1 AND (NOT L_H_F2);
Initial 0 0 0
T1 1 0 1
T2 1 1 0
表3 电平检测变化表

4.2 PS2解码模块

LIBRARY IEEE;											--库
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2_decode_module IS								--实体声明
	PORT(
			CLK,RSTn        : IN STD_LOGIC;
			H_L_Sig         : IN STD_LOGIC;				
			PS2_Data_Pin_In  : IN STD_LOGIC;
			PS2_Done_Sig    : OUT STD_LOGIC;
			PS2_Data        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)			
		);
END ENTITY PS2_decode_module;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2_decode OF PS2_decode_module IS
SIGNAL Done : STD_LOGIC :='0';							--声明一个完成信号
SIGNAL i    : STD_LOGIC_VECTOR(4 DOWNTO 0) :="00001";	--声明步骤i
SIGNAL Data : STD_LOGIC_VECTOR(7 DOWNTO 0) :=X"32";
BEGIN
PROCESS(CLK,RSTn,i)
BEGIN
IF (CLK'event AND CLK='1') THEN
IF (RSTn='0') THEN
				i <= "00001";Done <= '0';Data <= X"00";
ELSE
				CASE i IS
WHEN "00000" => i <= "00001";
		WHEN "00001" => IF (H_L_Sig='1') THEN i <= "00010";Data(0) <= PS2_Data_Pin_In;END IF;
		WHEN "00010" => IF (H_L_Sig='1') THEN i <= "00011";Data(1) <= PS2_Data_Pin_In;END IF;
		WHEN "00011" => IF (H_L_Sig='1') THEN i <= "00100";Data(2) <= PS2_Data_Pin_In;END IF;
		WHEN "00100" => IF (H_L_Sig='1') THEN i <= "00101";Data(3) <= PS2_Data_Pin_In;END IF;
		WHEN "00101" => IF (H_L_Sig='1') THEN i <= "00110";Data(4) <= PS2_Data_Pin_In;END IF;
		WHEN "00110" => IF (H_L_Sig='1') THEN i <= "00111";Data(5) <= PS2_Data_Pin_In;END IF;
		WHEN "00111" => IF (H_L_Sig='1') THEN i <= "01000";Data(6) <= PS2_Data_Pin_In;END IF;
		WHEN "01000" => IF (H_L_Sig='1') THEN i <= "01001";Data(7) <= PS2_Data_Pin_In;END IF;
		WHEN "01001" => IF (H_L_Sig='1') THEN i <= "01010";END IF;
		WHEN "01010" => IF (H_L_Sig='1') THEN i <= "01011";END IF;
		WHEN "01011" => IF (Data=X"F0")  THEN i <= "01100";ELSE i <= "10110";END IF;
		WHEN "01100" => IF (H_L_Sig='1') THEN i <= "01101";END IF;
		WHEN "01101" => IF (H_L_Sig='1') THEN i <= "01110";END IF;
		WHEN "01110" => IF (H_L_Sig='1') THEN i <= "01111";END IF;
		WHEN "01111" => IF (H_L_Sig='1') THEN i <= "10000";END IF;
		WHEN "10000" => IF (H_L_Sig='1') THEN i <= "10001";END IF;
		WHEN "10001" => IF (H_L_Sig='1') THEN i <= "10010";END IF;
		WHEN "10010" => IF (H_L_Sig='1') THEN i <= "10011";END IF;
		WHEN "10011" => IF (H_L_Sig='1') THEN i <= "10100";END IF;
		WHEN "10100" => IF (H_L_Sig='1') THEN i <= "10101";END IF;
		WHEN "10101" => IF (H_L_Sig='1') THEN i <= "10110";END IF;
		WHEN "10110" => IF (H_L_Sig='1') THEN i <= "10111";Done <= '1';END IF;
		WHEN "10111" => IF (H_L_Sig='1') THEN i <= "00001";Done <= '0';END IF;
		WHEN OTHERS  => i <= "00001";
				END CASE;
			END IF;
		END IF;
END PROCESS;
	PS2_Data <= Data;
	PS2_Done_Sig <= Done;
END ARCHITECTURE PS2_decode;

  这个模块我有点偷懒,只对键盘输入的8位有效数据进行了提取,其他位基本是忽略了,第一位开始位忽略了,然后是读取8位有效数据,第9步和第10步跳过了检测位和结束位,然后是判断。如果是0XF0,则证明是断码,断码的话后面的直接跳过,如果不是0XF0,则证明是有效的数据,立即跳到步骤22,向顶层的模块回馈一个完成信号,并将有效数据输出。

4.3 PS2组合模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2 IS
	PORT(
			CLK,RSTn        : IN STD_LOGIC;
			PS2_Data_Pin_In :  IN STD_LOGIC;
			PS2_CLK_Pin_In  : IN STD_LOGIC;
			PS2_Done_Sig    : BUFFER STD_LOGIC;
			PS2_Data        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)		
		);
END ENTITY PS2;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2_behave OF PS2 IS
	COMPONENT PS2_detect_module
		PORT(
				CLK,RSTn       : IN STD_LOGIC;
				PS2_CLK_Pin_In : IN STD_LOGIC;
				H_L_Sig        : OUT STD_LOGIC;
				L_H_Sig        : OUT STD_LOGIC
			);
	END COMPONENT;
	COMPONENT PS2_decode_module	
		PORT(
				CLK,RSTn        : IN STD_LOGIC;
				H_L_Sig         : IN STD_LOGIC;
				PS2_Data_Pin_In  : IN STD_LOGIC;
				PS2_Done_Sig    : OUT STD_LOGIC;
				PS2_Data        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)			
			);
	END COMPONENT;
	
	COMPONENT PS2_code_module 
		PORT(
				CLK,RSTn         : IN STD_LOGIC;
				L_H_Sig          : IN STD_LOGIC;
				PS2_Done_Sig     : IN STD_LOGIC;
				PS2_Data_Pin_Out : OUT STD_LOGIC
			);
	END COMPONENT;
	SIGNAL H_L : STD_LOGIC;
	SIGNAL L_H : STD_LOGIC;
	SIGNAL PS2_Data_Pin_Out : STD_LOGIC;
	BEGIN
		U1:PS2_detect_module PORT MAP(CLK,RSTn,PS2_CLK_Pin_In,H_L,L_H);
		U2:PS2_decode_module PORT MAP(CLK,RSTn,H_L,PS2_Data_Pin_In,PS2_Done_Sig,PS2_Data);
		U2:PS2_decode_module PORT MAP(CLK,RSTn,H_L,PS2_Data_Pin_Out,PS2_Done_Sig,PS2_Data);
		U3:PS2_code_module   PORT MAP(CLK,RSTn,L_H,PS2_Done_Sig,PS2_Data_Pin_Out);
END ARCHITECTURE PS2_behave;

  这是一个组合例化的模块,是对PS2时钟电平检测和PS2解码的一个简单模块。这一个模块初步实现了PS2的解码功能。上面的是代码的方法实现例化功能,同时也可以使用原理图的方式来实现例化,下面为原理图例化的图。
 PS2例化原理图

图8 PS2例化原理图

4.4 控制LED模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2_contorl_module IS
	PORT(
			CLK,RSTn        : IN STD_LOGIC;
			PS2_Done_Sig    : IN STD_LOGIC;
			PS2_Data        : IN STD_LOGIC_VECTOR(7 DOWNTO 0);	
			Data_Out        : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)	
		);
END ENTITY PS2_contorl_module;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2_contorl OF PS2_contorl_module IS
SIGNAL Data : STD_LOGIC_VECTOR(3 DOWNTO 0);
	BEGIN
		PROCESS(CLK,RSTn)
		BEGIN
			IF (CLK'event AND CLK='1') THEN
				IF (RSTn='0') THEN
					Data <= "0001";
				ELSIF(PS2_Done_Sig='1') THEN
					CASE PS2_Data IS
						WHEN X"22" => Data <= (Data(2 DOWNTO 0)&Data(3));
						WHEN X"1A" => Data <= (Data(0)&Data(3 DOWNTO 1));
						WHEN X"14" => Data <= (Data(0)&Data(1)&Data(2)&Data(3));
						WHEN X"21" => Data <= "1111";WHEN X"2A" => Data <= "0000";
						WHEN X"5A" => Data <= "0001";WHEN X"32" => Data <= "0001";
						WHEN X"31" => Data <= "0011";WHEN X"3A" => Data <= "0111";
						WHEN OTHERS => Data <= Data;
					END CASE;
				END IF;
			END IF;
		END PROCESS;
		Data_Out <= Data;			
END ARCHITECTURE PS2_contorl;

  LED控制模块主要的作用是用于显示结果。在PS2键盘扫描后,得到的8位有效结果,使用4盏LED灯作为检查结果的输出,使用不用的LED闪亮方式来表示不同的按键按下了。本程序只做了11个按键,分别是“Z”,“X”,“C”,“V”,“B”,“N”,“M”,“Entet”和“Ctrl”。“Z”按下后,LED向左移一个单位,“X”是向右移一个单位,“Ctrl”是LED灯互换,“B”是点亮一盏LED,“N”是点亮两盏LED,“M”是点亮三盏LED,“Entet”是复原LED灯的情况。

4.5 PS2总的组合模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2_module IS
	PORT(
			CLK,RSTn        : IN STD_LOGIC;
			PS2_Data_Pin_In   : IN STD_LOGIC;
			PS2_CLK_Pin_In  : IN STD_LOGIC;
			Data_Out        : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)			
		);
END ENTITY PS2_module;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2 OF PS2_module IS
	COMPONENT PS2 
		PORT(
				CLK,RSTn        : IN STD_LOGIC;
				PS2_Data_Pin_In   : IN STD_LOGIC;
				PS2_CLK_Pin_In  : IN STD_LOGIC;
				PS2_Done_Sig    : OUT STD_LOGIC;
				PS2_Data        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)		
			);
	END COMPONENT;
COMPONENT PS2_contorl_module 
		PORT(
				CLK,RSTn        : IN STD_LOGIC;
				PS2_Done_Sig    : IN STD_LOGIC;
				PS2_Data        : IN STD_LOGIC_VECTOR(7 DOWNTO 0);	
				Data_Out        : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)	
			);
	END COMPONENT;
	SIGNAL Done_Sig    : STD_LOGIC;
	SIGNAL Data        : STD_LOGIC_VECTOR(7 DOWNTO 0);		
	BEGIN		
      	U1:PS2 			PORT MAP(CLK,RSTn,PS2_Data_Pin_In,PS2_CLK_Pin_In,Done_Sig,Data);
--		U1:PS2 			PORT MAP(CLK,RSTn,PS2_CLK_Pin_In,Done_Sig,Data);
		U2:PS2_contorl_module  PORT MAP(CLK,RSTn,Done_Sig,Data,Data_Out);		
END ARCHITECTURE PS2;

  这是一个组合例化的模块,是对PS2功能模块和LED控制的一个简单组合的模块。这一个模块是PS2键盘扫描的最顶层文件,只做例化作用,不包含其他功能代码。上面的是代码的方法实现例化功能,同时也可以使用原理图的方式来实现例化,下面为原理图例化的图。
PS2_module总例化原理图

图9 PS2_module总例化原理图


第四部分 综合与仿真

1 综合

  对编写好的源程序进行综合,同时生成RTL电路图,RTL电路图如下。
PS2_module模块RTL图

图10 PS2_module模块RTL图

2 综合仿真

  在本次设计中,仿真工作只对电平检测模块,LED灯控制模块和PS2 _module总模块进行了仿真。对于前两个模块,采用的仿真方法是使用Quartus II自带的波形仿真软件进行仿真,而对于PS2_module总模块的仿真则使用了编写代码的方式进行仿真。因为PS2_module总模块对键盘按键的波形设置很麻烦,而且仿真效果不好,所以直接使用代码的方式产生一个键盘按键,同时观察波形来检测。

2.1 电平检测模块仿真

电平检测模块原理图如下:
电平检测原理图

图11 电平检测原理图

仿真波形如下:
 电平检测模块仿真波形

图12 电平检测模块仿真波形
  系统时钟给了10ns,PS2_CLK_Pin_In给了100ns,RSTn复位一直为高电平,可以观察波形得到,在PS2_CLK_Pin_In时钟的上升沿发生后,L_H_Sig发出了一个高脉冲的信号,大概相隔两个系统时钟;在PS2_CLK_Pin_In时钟的下降沿发生后,H_L_Sig也发出了一个高脉冲,也是相隔两系统时钟,而高脉冲大概是两个系统时钟左右。

2.2 LED灯控制模块仿真

LED灯控制模块原理图如下:
LED灯控制模块原理图

图13 LED灯控制模块原理图
仿真波形如下:

LED灯控制模块仿真波形

图14 LED灯控制模块仿真波形

  系统时钟给了10ns,RSTn复位在一开始的时候给了‘0’,进行了一次复位,PS2 _Done_Sig完成信号则是100ns一次,PS2_Data给的是X“22”(即X被按下)。复位后Data_Out输出的是“0001”,第一盏LED灯点亮,然后在PS2_Done_Sig信号后,Data_Out输出变化了,变为了“0010”,LED第二盏给点亮了,LED灯移位了。因为一直是X被按下,所以信号不断移位,LED分别为1,2,4,8。在最后那里,由于PS2_Data给的是X“20”,并没有在控制那设置这个按键,所以LED没反应,一直保持在2(即第二盏灯点亮)。


2.3 PS2_module总模块仿真

  由于PS2总仿真的时候需要键盘的通码输入,但使用波形的改变来作为通码输入的方式太麻烦了,而且很容易出错,得不到想要的波形。所以为了克服这个问题,我使用了另外的一种方法来仿真,直接写键盘编码来给整个模块,然后开输出波形就可以观察。
  PS2_module总模块仿真点简单方框图如下:
在这里插入图片描述

图15 PS2_module总模块方框图

  PS2_code_module键盘编码模块代码如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------------------------------------------------------------------------------------------
ENTITY PS2_code_module IS
	PORT(
			CLK,RSTn         : IN STD_LOGIC;
			L_H_Sig          : IN STD_LOGIC;
			PS2_Done_Sig     : IN STD_LOGIC;
			PS2_Data_Pin_Out : OUT STD_LOGIC
		);
END ENTITY PS2_code_module;
------------------------------------------------------------------------------------------------------------------------------------------
ARCHITECTURE PS2_code OF PS2_code_module IS	
	CONSTANT n_0:STD_LOGIC_VECTOR:=X"22";CONSTANT n_1:STD_LOGIC_VECTOR:=X"1A";
	CONSTANT n_2:STD_LOGIC_VECTOR:=X"14";CONSTANT n_3:STD_LOGIC_VECTOR:=X"21";
	CONSTANT n_4:STD_LOGIC_VECTOR:=X"2A";CONSTANT n_n:STD_LOGIC_VECTOR:=X"F0";
	SIGNAL data : STD_LOGIC :='0';
	SIGNAL i    : STD_LOGIC_VECTOR(4 DOWNTO 0) :="00000";
	BEGIN
		PROCESS(CLK,RSTn,i)
BEGIN
			IF (CLK'event AND CLK='1') THEN
				IF (RSTn='0') THEN
					i <= "00000";
					data <= '0';
				ELSE
					CASE i IS
				WHEN "00000" => i <= "00001";
				WHEN "00001" => IF (L_H_Sig='1') THEN i <= "00010";data <= n_1(0);END IF;
				WHEN "00010" => IF (L_H_Sig='1') THEN i <= "00011";data <= n_1(1);END IF;
				WHEN "00011" => IF (L_H_Sig='1') THEN i <= "00100";data <= n_1(2);END IF;
				WHEN "00100" => IF (L_H_Sig='1') THEN i <= "00101";data <= n_1(3);END IF;
				WHEN "00101" => IF (L_H_Sig='1') THEN i <= "00110";data <= n_1(4);END IF;
				WHEN "00110" => IF (L_H_Sig='1') THEN i <= "00111";data <= n_1(5);END IF;
				WHEN "00111" => IF (L_H_Sig='1') THEN i <= "01000";data <= n_1(6);END IF;	
				WHEN "01000" => IF (L_H_Sig='1') THEN i <= "01001";data <= n_1(7);END IF;
				WHEN "01001" => IF (L_H_Sig='1') THEN i <= "01010";END IF;
				WHEN "01010" => IF (L_H_Sig='1') THEN i <= "01011";END IF;
				WHEN "01011" => IF (PS2_Done_Sig='1')  THEN i <= "01100";END IF;
				WHEN "01100" => IF (L_H_Sig='1') THEN i <= "01101";data <= n_n(0);END IF;
				WHEN "01101" => IF (L_H_Sig='1') THEN i <= "01110";data <= n_n(1);END IF;
				WHEN "01110" => IF (L_H_Sig='1') THEN i <= "01111";data <= n_n(2);END IF;
				WHEN "01111" => IF (L_H_Sig='1') THEN i <= "10000";data <= n_n(3);END IF;					WHEN "10000" => IF (L_H_Sig='1') THEN i <= "10001";data <= n_n(4);END IF;
				WHEN "10001" => IF (L_H_Sig='1') THEN i <= "10010";data <= n_n(5);END IF;
				WHEN "10010" => IF (L_H_Sig='1') THEN i <= "10011";data <= n_n(6);END IF;
				WHEN "10011" => IF (L_H_Sig='1') THEN i <= "10100";data <= n_n(7);END IF;
				WHEN "10100" => IF (L_H_Sig='1') THEN i <= "10101";END IF;
				WHEN "10101" => IF (L_H_Sig='1') THEN i <= "10110";END IF;
				WHEN "10110" => IF (L_H_Sig='1') THEN i <= "10111";END IF;
				WHEN "10111" => IF (L_H_Sig='1') THEN i <= "00000";END IF;
						WHEN OTHERS  => i <= "00000";
					END CASE;
				END IF;
			END IF;
		END PROCESS;
		PS2_Data_Pin_Out <= data;		
END ARCHITECTURE PS2_code;

  代码实现的功能就是每一个PS2_CLK_Pin_In的上升沿来临的时候,设置好数据给S2_CLK_Pin_In的下降沿时后面模块的读取,时间要与PS2_decode_module模块同步。

仿真出来的波形图如下:
在这里插入图片描述

图16 输入为“Z”的波形图

在这里插入图片描述

图17 输入为“X”的波形图
  由图16和图17可以看出整个模块的仿真结果。“X”和“Z”按键的作用是一个向左移,一个向右移,在上图中能很清晰地看出他们的变化。



第五部分 硬件下载

  先设置好芯片类型,因为我是使用自己的FPGA开发板,所以我用的芯片是Cyclone II的EP2C5Q208C8,如下图。

在这里插入图片描述

图18 设置芯片型号

  设置芯片后,接着的是设置不用到引脚位,将不用的引脚设置为三态输入,以防芯片烧坏,设置方式如下图:

在这里插入图片描述

图19 设置没有用到的引脚

  成功编译后,是引脚分配,将需要用到的端口分配到FPGA的引脚上关联起来,引脚分配如下图:

在这里插入图片描述

图20 引脚分配图

  最后的操作是硬件下载,在PROGRAMMER中进行,要设置好USB仿真口,FPGA下载方式是JTAG,下载图如下:

在这里插入图片描述

图21 文件下载图
  最后是在讲PC键盘接在FPGA开发板上,按下按键来试调观察结果。



第六部分 心得体会



第七部分 参考文献

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!