基于FPGA的计算器设计---第一版
欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的计算器设计---第一版。
功能说明:
1. 计算器的显示屏幕为数码管。
2. 4x4矩阵键盘作为计算器的输入设备。
3. 计算任意两位正整数的加减乘除。
4. 当减法结果出现负数时(一个小的数字减去一个大的数字),数码管需要显示负数。
5. 除法计算时,结果只输出商的整数,小数自动抹去。
注:矩阵键盘输入0-9,表示0-9;10表示加号(数码管显示A);11表示减号(数码管显示b);12表示乘号(数码管显示C);13表示除号(数码管显示d);14表示等于号。
使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。
作者QQ:746833924
说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;
设计思想如下:
keyboard4x4_drive模块为4x4矩阵键盘的驱动模块,负责检测4x4矩阵键盘被按下的按键信息;cal_logic模块为计算逻辑和控制显示信息的逻辑,负责根据矩阵键盘传递的按键信息进行计算,根据计算的过程控制输出需要显示的信息;seven_tube_drive(七段数码管驱动)模块负责将产生的数字逻辑显示到数码管上。
keyboard4x4_drive模块的设计思想和具体设计可以参考本公众号,获取方式:关注本公众号,发送“FPGA矩阵键盘驱动第一版”。
cal_logic模块的设计思想:利用状态机设计进行实现。共有八个状态。
- localparam STATE_IDLE = 8'b0000_0001;
- localparam STATE_NUM1_1 = 8'b0000_0010;
- localparam STATE_NUM1_2 = 8'b0000_0100;
- localparam STATE_OPCODE = 8'b0000_1000;
- localparam STATE_NUM2_1 = 8'b0001_0000;
- localparam STATE_NUM2_2 = 8'b0010_0000;
- localparam STATE_EQUAL = 8'b0100_0000;
- localparam STATE_RESULT = 8'b1000_0000;
STATE_IDLE :空闲初始化状态;
STATE_NUM1_1 :输入第一个操作数的第一位。
STATE_NUM1_2 :输入第一个操作数的第二位。
STATE_OPCODE :输入操作符。
STATE_NUM2_1 :输入第二个操作数的第一位。
STATE_NUM2_2 :输入第二个操作数的第二位。
STATE_EQUAL :输入等于号。
STATE_RESULT :计算输出结果。
复位结束后,在IDLE状态,初始化所有的中间变量和输出,之后进入STATE_NUM1_1。
- STATE_IDLE : begin
- state <= STATE_NUM1_1;
- num1 <= 8'd0;
- num2 <= 8'd0;
- opcode <= 4'd0;
- show_data <= 24'hfffff0;
- end
在STATE_NUM1_1状态中,当输入的数字0-9,认为是第一个操作数的第一位(显示到最后的数码管),然后进入STATE_NUM1_2,准备接收第一个操作数的第二位;如果输入数字10-13,认为是第一个操作数为0(数码管显示第一个操作数0和操作符),并且存储好操作符,进入STATE_NUM2_1,准备接收第二个操作数的第一位;如果输入为其他数字,则认为无效输入。
- STATE_NUM1_1 : begin
- if (flag == 1'b1)
- if (press_num < 4'd10) begin
- state <= STATE_NUM1_2;
- num1 <= {4'd0, press_num};
- show_data <= {20'hfffff, press_num};
- end
- else
- if (press_num > 4'd9 && press_num < 4'd14) begin
- num1 <= 8'd0;
- state <= STATE_NUM2_1;
- opcode <= press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- state <= STATE_NUM1_1;
- else
- state <= STATE_NUM1_1;
- end
在STATE_NUM1_2状态中,当输入的数字0-9,认为是第一个操作数的第二位(将第一个操作数的第一位和第二位都显示到数码管上)(计算得出num1),然后进入STATE_OPCODE,准备接收操作符;如果输入数字10-13,认为是第一个操作数为STATE_NUM1_1输入的数字(数码管显示第一个操作数和操作符),并且存储好操作符,进入STATE_NUM2_1,准备接收第二个操作数的第一位;如果输入为其他数字,则认为无效输入。
- STATE_NUM1_2 : begin
- if (flag == 1'b1)
- if (press_num < 4'd10) begin
- state <= STATE_OPCODE;
- num1 <= num1 * 10 + press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- if (press_num > 4'd9 && press_num < 4'd14) begin
- state <= STATE_NUM2_1;
- opcode <= press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- state <= STATE_NUM1_2;
- else
- state <= STATE_NUM1_2;
- end
在STATE_OPCODE状态中,如果输入数字10-13,认为是第一个操作数为STATE_NUM1_1和STATE_NUM1_2输入的数字(数码管显示第一个操作数和操作符),并且存储好操作符,进入STATE_NUM2_1,准备接收第二个操作数的第一位;如果输入为其他数字,则认为无效输入。
- STATE_OPCODE : begin
- if (flag == 1'b1)
- if (press_num > 4'd9 && press_num < 4'd14) begin
- state <= STATE_NUM2_1;
- opcode <= press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- state <= STATE_OPCODE;
- else
- state <= STATE_OPCODE;
- end
在STATE_NUM2_1状态中,如果输入数字0-9,认为是第二个操作数的第一个数字(数码管显示第一个操作数、操作符和第二个操作数的第一个数字),进入STATE_NUM2_2,准备接收第二个操作数的第二位;如果输入为其他数字,则认为无效输入。
- STATE_NUM2_1 : begin
- if (flag == 1'b1)
- if (press_num < 4'd10) begin
- state <= STATE_NUM2_2;
- num2 <= press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- state <= STATE_NUM2_1;
- else
- state <= STATE_NUM2_1;
- end
在STATE_NUM2_2状态中,当输入的数字0-9,认为是第二个操作数的第二位(将第一个操作数、操作符和第二个操作数显示到数码管上)(计算得出num2),然后进入STATE_EQUAL,准备接收等于号;如果输入数字14,认为是等于号,进入STATE_RESULT状态。如果输入为其他数字,则认为无效输入。
- STATE_NUM2_2 : begin
- if (flag == 1'b1)
- if (press_num < 4'd10) begin
- state <= STATE_EQUAL;
- num2 <= num2 * 10 + press_num;
- show_data <= {show_data[19:0], press_num};
- end
- else
- if (press_num == 4'd14) begin
- state <= STATE_RESULT;
- end
- else
- state <= STATE_NUM2_2;
- else
- state <= STATE_NUM2_2;
- end
在STATE_EQUAL状态中,如果输入数字14,认为是等于号,进入STATE_RESULT状态。如果输入为其他数字,则认为无效输入。
- STATE_EQUAL : begin
- if (flag == 1'b1)
- if (press_num == 4'd14) begin
- state <= STATE_RESULT;
- end
- else
- state <= STATE_EQUAL;
- else
- state <= STATE_EQUAL;
- end
在STATE_RESULT状态中,只有按下复位才可以再次进行计算;在本状态中根据第一个操作数、操作符和第二个操作数进行计算,并且将计算的结果作为输出。
- STATE_RESULT : begin
- state <= STATE_RESULT;
- show_data[23:20] <= result[15] ? 4'he : 4'h0;
- show_data[19:16] <= result[15] ? (-result)/10000 : result/10000;
- show_data[15:12] <= result[15] ? (-result)/1000 % 10 : result/1000 % 10;
- show_data[11:8] <= result[15] ? (-result)/100 % 10 : result/100 % 10;
- show_data[7:4] <= result[15] ? (-result)/10 % 10 : result/10 % 10;
- show_data[3:0] <= result[15] ? (-result) % 10 : result % 10;
- end
七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。
仿真时,需要利用4x4矩阵键盘的仿真模型,否则不容易仿真(相关代码,下方链接提供)。
- calculator calculator_inst(
- .clk (clk ),
- .rst_n (rst_n ),
- .keyboard4x4_row (keyboard4x4_row),
- .keyboard4x4_col (keyboard4x4_col),
- .sel (sel ),// 数码管位选信号
- .seg (seg ) // 数码管段选信号
- );
- keyboard4x4 keyboard4x4_inst(
- .press_num (press_num ),
- .keyboard4x4_col (keyboard4x4_col),
- .keyboard4x4_row (keyboard4x4_row)
- );
模拟2+8;
- press_data(5'd2);
- press_data(5'd10);
- press_data(5'd8);
- press_data(5'd14);
模拟55-8;
- press_data(5'd5);
- press_data(5'd5);
- press_data(5'd11);
- press_data(5'd8);
- press_data(5'd14);
其他模拟情况,可以根据设计者自由模拟;
注意在计算一次完成后,需要进行一次复位(相当于计算器中的清除),然后才可以进行下一次计算。
讲解和演示视频链接如下:
https://www.bilibili.com/video/BV1ew4m1S7Av/?vd_source=b5405faeab8632f02533bcbfc5e52e55
本设计所有内容(设计代码、设计工程)链接为:
链接:https://pan.baidu.com/s/1WKkfXU7XInPBNCUSvgs5Pw
提取码:s0f8
本篇内容中有部分资源来源于网络,如有侵权,请联系作者。
如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!
基于FPGA的计算器设计---第一版的更多相关文章
- 基于FPGA的DDS设计(一)
最近在学习基于FPGA的DDS设计,借此机会把学习过程记录下来,当作自己的学习笔记也希望能够帮助到学习DDS的小伙伴. DDS(Direct Digital Synthesizer)直接数字合成器,这 ...
- 基于FPGA的DDS设计(二)
在DDS设计中,如果相位累加器每个时钟周期累加1,就会输出频率为195.313KHz的波形.如果每个时钟周期累加2,就会输出频率为2*195.313KHz的波形·······,如果每两个时钟周期累加1 ...
- 38.基于FPGA的FIR设计二
利用fdatool工具生成的滤波器系数与用代码生成的系数不一致,在网上查询得知,fdatool生成的滤波器系数是有符号小数,而且是浮点型,而代码生成的滤波器系数是定点型有符号数,故不一样. 浮点型数据 ...
- 优化基于FPGA的深度卷积神经网络的加速器设计
英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...
- 自己动手写CPU(基于FPGA与Verilog)
大三上学期开展了数字系统设计的课程,下学期便要求自己写一个单周期CPU和一个多周期CPU,既然要学,就记录一下学习的过程. CPU--中央处理器,顾名思义,是计算机中最重要的一部分,功能就是周而复始地 ...
- 基于FPGA的XPT2046触摸控制器设计
基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com 发 ...
- 基于FPGA的HDMI显示设计(三)
上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间实习,令我万万没想到的是实习题目是 “便携式高清电视显示屏测试系统原型设计” 也就是 “基于FPGA的视频显示”. 实习要求用 ...
- 基于FPGA的VGA显示设计(二)
上一篇:基于FPGA的VGA显示设计(一) 参照 CrazyBingo 的 基于FPGA的VGA可移植模块终极设计代码 的工程代码风格,模块化处理了上一篇的代码,并增加了一点其它图形. 顶层 ...
- 基于FPGA的VGA可移植模块终极设计【转】
本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯 基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...
- 基于FPGA的SPI FLASH控制器设计
1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...
随机推荐
- nginx重新整理——————http请求的11个阶段中的find_config[十三]
前言 简单介绍一下find_config 与 preaccess 阶段. 正文 find_config 很大一部分工作是进行location的匹配. 来一张图看下location指令和merge_sl ...
- CentOS 7.9编译安装Python-3.10.13
目录 查看CentOS版本.系统默认gcc版本.Python版本和pip版本 部署Python-3.10.13 测试 将yum中的Python版本修改为系统原来的2.7.5版本 查看CentOS版本. ...
- 国内首家!百度智能云宣布支持Llama3全系列训练推理
继18日Llama3的8B.70B大模型发布后,百度智能云千帆大模型平台19日宣布在国内首家推出针对Llama3全系列版本的训练推理方案,便于开发者进行再训练,搭建专属大模型,现已开放邀约测试. 目前 ...
- echarts使用与踩坑
0.踩坑点 1.当图表不显示在页面(display:none)执行resize可能会导致图表样式混乱 1. 官网示例 import * as echarts from 'echarts'; // 基于 ...
- 这10款VS Code神仙插件,嵌入式程序员必备
大家好,我是知微! 嵌入式软件开发工程师平时可能更多的是使用Source Insight.Keil.IAR来阅读代码,写代码. VSCode大家都听说过,功能十分强大,而且免费! 或许是因为这款软件上 ...
- 蚂蚁一面:GC垃圾回收时,内存分配和回收策略有哪些?
文章首发于公众号:腐烂的橘子 蚂蚁面试主要为电话面试,期间也会要求使用编辑器手写算法题.作为一线互联网大厂,Java 基础知识是必备的,其中垃圾回收也是面试过程中的重中之重. Java 内存的自动管理 ...
- 斩获大奖|阿里云PolarDB-X引领云原生分布式数据库新时代
简介:阿里云原生分布式数据库PolarDB-X荣获"2021年度最佳分布式数据库". 12月15-16日,以"引领分布式云变革 助力湾区数字经济"为主题的全球分 ...
- [FAQ] swagger-php 支持 Authorization Bearer token 校验的用法
@OA\SecurityScheme 可以是 Controller 层面也可以是 Action 层面. 类型 type="apiKey". in="header" ...
- 通过WebRTC简单实现媒体共享
通过WebRTC简单实现媒体共享 媒体协商 在设置本地描述符(offer/answer)前,我们总是需要将媒体添加到连接中,只有这样在描述符中才能包含需要共享的媒体信息,除非你不需要共享媒体. 在实际 ...
- WPF 简单判断主线程界面是否卡顿的方法
本文来告诉大家如何使用简单的代码判断当前的软件的 UI 线程或界面是否卡顿 在后台线程调用如下代码即可用来判断是否卡顿 private static async Task<bool> Ch ...