基于PS2键盘的LCD计算器VHDL设计DE2-115 FPGA开发板
项目概述
名称: PS2键盘LCD计算器VHDL QuartusII
软件: Quartus II
语言: VHDL
目标平台: DE2-115 FPGA开发板
代码功能
本项目实现了一个基于FPGA的数字计算器系统,支持通过PS2键盘输入数字和运算符,并在LCD1602显示屏上显示计算过程和结果。系统支持四则运算(加、减、乘、除),能够处理单位数运算,除法运算还能显示余数。整个系统采用状态机设计,具有良好的用户交互体验和错误处理机制。
代码实现思路
整体架构设计
系统采用模块化设计思想,将功能分解为多个独立的功能模块:
输入处理模块:负责PS2键盘信号的接收、解码和按键识别状态控制模块:实现计算器的状态机逻辑,控制整个运算流程数值处理模块:处理数字输入、存储操作数并执行四则运算显示控制模块:控制LCD1602显示屏,实现运算过程和结果的可视化
核心算法流程
初始化状态:系统复位,等待第一个操作数输入操作数A输入:接收并存储第一个操作数运算符识别:检测加减乘除运算符,确定运算类型操作数B输入:接收并存储第二个操作数运算执行:根据运算符执行相应的算术运算结果显示:在LCD上显示完整的运算表达式和结果
关键技术特点
采用同步时序逻辑设计,确保系统稳定性实现PS2协议解析,支持标准键盘输入集成BCD码转换,便于数字显示处理
状态机控制确保运算流程的正确性
代码结构
顶层模块 (top.vhd)
系统的顶层模块,负责连接各个子模块并定义外部接口,包括时钟、复位、PS2键盘接口和LCD显示接口。
计算器核心模块 (calculator.vhd)
计算器的主控制模块,集成输入处理、状态控制和数值处理三个子模块,协调整个计算流程。
数据输入模块 (data_input.vhd)
处理PS2键盘输入,包含扫描码接收、ASCII转换和按键识别功能,输出数字和运算符的按键信号。
状态控制模块 (state_ctrl.vhd)
实现计算器的有限状态机,管理输入第一操作数、运算符、第二操作数、计算和显示结果等状态转换。
数值输入模块 (num_in.vhd)
负责数字的输入处理和四则运算的执行,包括操作数存储、运算类型判断和结果计算功能。
LCD显示模块 (lcd1602.vhd)
控制LCD1602显示屏,实现计算过程和结果的实时显示,包括LCD初始化、字符显示和格式控制。
BCD转换模块 (BCD.vhd)
将二进制数转换为BCD码,便于在LCD上以十进制形式显示数字结果。
PS2接口模块 (data_scanC.vhd & convert.vhd)
实现PS2键盘协议的硬件接口,包括扫描码接收和ASCII码转换功能。
工程文件图片
部分代码展示
LIBRARY ieee;USE ieee.std_logic_1164.all;--计算器ENTITY calculator ISPORT (clk : IN STD_LOGIC;--时钟500K--sys_clk : in STD_LOGIC; -- 系统时钟reset : IN STD_LOGIC;--低电平复位---rst_n-- L_row : IN STD_LOGIC_VECTOR(3 DOWNTO 0);----矩阵键盘行-- H_col : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);----矩阵键盘列k_data : in STD_LOGIC; -- PS2键盘数据线k_clock : in STD_LOGIC; -- PS2键盘时钟线OP_current_state :OUT STD_LOGIC_VECTOR(2 DOWNTO 0);OP_calcul : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);--计算方式,--00表示加--01表示减--10表示乘--11表示除OP_A : OUT integer;--输入的操作数AOP_B : OUT integer;--输入的操作数BOP_Result : OUT integer;--结果OP_reminder : OUT integer; --余数error : OUT STD_LOGIC--错误提示);END calculator;ARCHITECTURE trans OF calculator IS--输入模块COMPONENT data_input ISPORT (clk : IN STD_LOGIC;--500KHzreset : IN STD_LOGIC;-- L_row : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--行-- H_col : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--列k_data : in STD_LOGIC; -- PS2键盘数据线k_clock : in STD_LOGIC; -- PS2键盘时钟线key_0_rise : OUT STD_LOGIC;key_1_rise : OUT STD_LOGIC;key_2_rise : OUT STD_LOGIC;key_3_rise : OUT STD_LOGIC;key_4_rise : OUT STD_LOGIC;key_5_rise : OUT STD_LOGIC;key_6_rise : OUT STD_LOGIC;key_7_rise : OUT STD_LOGIC;key_8_rise : OUT STD_LOGIC;key_9_rise : OUT STD_LOGIC;key_add_rise : OUT STD_LOGIC;key_sub_rise : OUT STD_LOGIC;key_mul_rise : OUT STD_LOGIC;key_esc_rise : OUT STD_LOGIC;key_enter_rise : OUT STD_LOGIC;key_div_rise : OUT STD_LOGIC);END COMPONENT;COMPONENT state_ctrl ISPORT (clk : IN STD_LOGIC;esc : IN STD_LOGIC;add : IN STD_LOGIC;sub : IN STD_LOGIC;mul : IN STD_LOGIC;div : IN STD_LOGIC;enter : IN STD_LOGIC;current_state : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);calcul : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));END COMPONENT;COMPONENT num_in ISPORT (clk : IN STD_LOGIC;esc : IN STD_LOGIC;key_0 : IN STD_LOGIC;key_1 : IN STD_LOGIC;key_2 : IN STD_LOGIC;key_3 : IN STD_LOGIC;key_4 : IN STD_LOGIC;key_5 : IN STD_LOGIC;key_6 : IN STD_LOGIC;key_7 : IN STD_LOGIC;key_8 : IN STD_LOGIC;key_9 : IN STD_LOGIC;error : OUT STD_LOGIC;--错误提示current_state : IN STD_LOGIC_VECTOR(2 DOWNTO 0);calcul : IN STD_LOGIC_VECTOR(1 DOWNTO 0);OP_A : OUT integer;OP_B : OUT integer;OP_Result : OUT integer;reminder : OUT integer ---余数);END COMPONENT;SIGNAL esc : STD_LOGIC;--ESC键SIGNAL add : STD_LOGIC;--加SIGNAL sub : STD_LOGIC;--减SIGNAL mul : STD_LOGIC;--乘SIGNAL div : STD_LOGIC;--除SIGNAL enter : STD_LOGIC;--Enter键SIGNAL current_state : STD_LOGIC_VECTOR(2 DOWNTO 0);SIGNAL calcul : STD_LOGIC_VECTOR(1 DOWNTO 0);SIGNAL key_0_p : STD_LOGIC;SIGNAL key_1_p : STD_LOGIC;SIGNAL key_2_p : STD_LOGIC;SIGNAL key_3_p : STD_LOGIC;SIGNAL key_4_p : STD_LOGIC;SIGNAL key_5_p : STD_LOGIC;SIGNAL key_6_p : STD_LOGIC;SIGNAL key_7_p : STD_LOGIC;SIGNAL key_8_p : STD_LOGIC;SIGNAL key_9_p : STD_LOGIC;-- Declare intermediate signals for referenced outputsSIGNAL OP_A_buf : integer;SIGNAL OP_B_buf : integer;SIGNAL OP_Result_buf : integer;SIGNAL reminder : integer;BEGIN-- Drive referenced outputsOP_A <= OP_A_buf;OP_B <= OP_B_buf;OP_Result <= OP_Result_buf;OP_calcul <= calcul;OP_current_state <= current_state;--输入模块U_data_input: data_inputPORT MAP(clk => clk,--时钟reset =>reset,-- L_row =>L_row,--行-- H_col =>H_col,--列k_data =>k_data, -- PS2键盘数据线k_clock =>k_clock, -- PS2键盘时钟线key_0_rise =>key_0_p,key_1_rise =>key_1_p,key_2_rise =>key_2_p,key_3_rise =>key_3_p,key_4_rise =>key_4_p,key_5_rise =>key_5_p,key_6_rise =>key_6_p,key_7_rise =>key_7_p,key_8_rise =>key_8_p,key_9_rise =>key_9_p,key_esc_rise =>esc,key_add_rise =>add,key_sub_rise =>sub,key_mul_rise =>mul,key_div_rise =>div,key_enter_rise =>enter);--状态控制模块i_state_ctrl : state_ctrlPORT MAP (clk => clk,--时钟esc => esc,--ESC键add => add,--加sub => sub,--减mul => mul,--乘div => div,--除enter => enter,--Enter键current_state => current_state,--当前状态calcul => calcul--计算);--数字输入模块i_num_in : num_inPORT MAP (clk => clk,--时钟esc => esc,error => error,key_0 => key_0_p,key_1 => key_1_p,key_2 => key_2_p,key_3 => key_3_p,key_4 => key_4_p,key_5 => key_5_p,key_6 => key_6_p,key_7 => key_7_p,key_8 => key_8_p,key_9 => key_9_p,current_state => current_state,--当前状态calcul => calcul,--计算方式,--00表示加--01表示减--10表示乘--11表示除OP_A => OP_A_buf,--输入的操作数AOP_B => OP_B_buf,--输入的操作数BOP_Result => OP_Result_buf,--结果reminder => OP_reminder--结果);END trans;
713