基于FPGA的计算器设计---第一版

fpga · 浏览次数 : 0

小编点评

Sure, here is the summary you requested: **Code Explanation:** The code you provided is an implementation of a calculator using a 4x4 matrix keyboard. It uses a state machine to handle different operations and displays results on a seven-segment display. **Key Features:** * The code supports addition, subtraction, multiplication, and division operations. * It also handles equal sign and comparison operations. * The code uses a state machine to track the current operation and display results accordingly. * The simulation allows you to input numbers and perform operations to see results on the seven-segment display. **Additional Information:** * The code uses a 4x4 matrix keyboard simulation model. * The simulation allows you to input numbers and perform operations to see results on the seven-segment display. * The code is divided into several sections for clarity. **Resources:** * Video explanation and demonstration: BV1ew4m1S7Av * Code link: s0f8 * Design description link: Not provided in the context * Simulation link: Not provided in the context **Conclusion:** This code provides a functional calculator using a 4x4 matrix keyboard simulation model. The code uses a state machine to handle different operations and displays results on a seven-segment display.

正文

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于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的计算器设计---第一版

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的计算器设计 第一版。 功能说明: 1. 计算器的显示屏幕为数码管。 2. 4x4矩阵键盘作为计算器的输入设备。 3. 计算任意两位正整数的加减乘除。 4. 当减法结果出现负数时(一个小的数字减去一个大的数字),数码管需要显示负数

基于FPGA的4x4矩阵键盘驱动设计---第一版

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的4x4矩阵键盘驱动设计 第一版 功能说明: 1. 驱动4x4矩阵键盘:按下任意一个按键,解析出对应按键信息,并给出标志 使用平台:纯代码形式 使用语言:Verilog HDL 作者QQ:746833924 说明:本篇设计中不涉及

基于FPGA的数字钟设计---第三版

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的数字钟设计 第三版。 功能说明: 1. 在数码管上面显示时分秒(共计六个数码管,前两个显示小时;中间两个显示分钟;最后两个显示秒)。 2. 利用按键可以切换24/12小时制(默认24小时制)。 3. led1的亮灭表示24小时制

基于FPGA的电子琴设计(按键和蜂鸣器)----第一版

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的电子琴设计(按键和蜂鸣器) 第一版。 功能说明: 外部输入七个按键,分别对应音符的“1、2、3、4、5、6、7”,唱作do、re、mi、fa、sol、la、si。当某个按键按下时,蜂鸣器发出对应的声音 1. 默认发出0.2秒(可

基于FPGA的贪吃蛇游戏 之代码解析

基于FPGA的贪吃蛇游戏 之代码解析 1. 代码结构 代码结构包含7格.v文件。 下面依次解析。 2. 代码解析 (1) seg_display.v 数码管的译码模块是最熟悉,最简单的模块了。这里是共阳极的数码管,用case语句编码即可。从上图可以看到,这个模块被例化了3次,分别驱动3个数码管显示,

ZynqMP PL固件通过U-BOOT从指定位置加载FPGA BIT

原因 PL固件可能经常修改,而BOOT.BIN和文件系统、内核实际上基本不会变,在一个平台上可以用同一份。如果每次修改都要重新打包PL 固件到BOOT.BIN,操作起来非常麻烦。所以希望PL 的固件可以直接从指定位置加载。典型的可以从SD卡的FAT32分区加载。 https://xilinx-wik

基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示

之前也分享过 Swashbuckle.AspNetCore 的使用,不过版本比较老了,本次演示用的示例版本为 .net core 8.0,从安装使用开始,到根据命名空间分组显示,十分的有用

跟我一起学习和开发动态表单系统-前端用vue、elementui实现方法(3)

基于 Vue、Element UI 和 Spring Boot + MyBatis 的动态表单系统前端实现解析 在现代企业信息系统中,动态表单是一种非常常见的功能。它可以根据业务需求灵活地调整表单结构,以满足不同的数据收集和展示需求。在本文中,我们将探讨一种基于 Vue、Element UI 和 S

基于Bootstrap Blazor开源的.NET通用后台权限管理系统

前言 今天大姚给大家分享一个基于Bootstrap Blazor开源的.NET通用后台权限管理系统,后台管理页面兼容所有主流浏览器,完全响应式布局(支持电脑、平板、手机等所有主流设备),可切换至 Blazor 多 Tabs 模式,权限控制细化到网页内任意元素(按钮、表格、文本框等等):Bootstr

基于Chrome扩展的浏览器可信事件与网页离线PDF导出

基于Chrome扩展的浏览器可信事件与网页离线PDF导出 Chrome扩展是一种可以在浏览器中添加新功能和修改浏览器行为的软件程序,我们可以基于Manifest规范的API实现对于浏览器和Web页面在一定程度上的修改,例如广告拦截、代理控制等。Chrome DevTools Protocol则是Ch