基于PS2键盘的LCD计算器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?IS ???PORT?( ??????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;--输入的操作数A ??????OP_B???????:?OUT?integer;--输入的操作数B ??????OP_Result??:?OUT?integer;--结果 OP_reminder?:?OUT?integer;?--余数 error???????:?OUT?STD_LOGIC--错误提示 ???); END?calculator; ARCHITECTURE?trans?OF?calculator?IS ??? --输入模块 COMPONENT?data_input?IS ???PORT?( ??????clk??:?IN?STD_LOGIC;--500KHz ??????reset???????:?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?IS ??????PORT?( ?????????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?IS ??????PORT?( ?????????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?outputs ???SIGNAL?OP_A_buf??????:?integer; ???SIGNAL?OP_B_buf??????:?integer; ???SIGNAL?OP_Result_buf?:?integer; SIGNAL?reminder??????:?integer; ? BEGIN ???--?Drive?referenced?outputs ???OP_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_input ???PORT?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_ctrl ??????PORT?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_in ??????PORT?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,--输入的操作数A ?????????OP_B???????????=>?OP_B_buf,--输入的操作数B ?????????OP_Result??????=>?OP_Result_buf,--结果 reminder????????=>?OP_reminder--结果 ??????); ??? END?trans;
217