源码系列:基于FPGA的计算器设计(附源工程)

原创 FPGA技术江湖 2024-12-27 08:08

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。


今天给大侠带来基于FPGA的计算器设计,附源码,获取源码,请在“FPGA技术江湖”公众号内回复“ 计算器设计源码”,可获取源码文件。话不多说,上货。



设计原理


在日常的生活和学习中,我们经常能用到计算器计算器的设计可以让我们加深对设计思想以及设计方法的理解,训练实操能力,紧密的联系各模块, 对我们的学习有很大的帮助和提升。下面咱们就来一起看一下。

本次的设计主要通过矩阵键盘来实现按键的加减乘除运算,通过按下有效键值来当被加数或者被除数等等,按下10 -- 13等数字来表示对应的运算符。按键键值15表示等于号。

此次的设计是通过数码管来实现显示的,通过按下对应的按键来显示到数码管上,百位十位个位等等。当按下运算算符的时候显示清0不显示东西,之后通过继续按下别的键值来显示出对应的加数和除数等等,之后通过按下对应的键值15表示等于后,然后数码管清0之后立马显示出对应的等于的数。


设计架构


设计框架图:


设计代码:

顶层模块calc代码:

module calc(clk,rst_n,row,col,sel,seg7);  //端口列表  input clk;    //时钟  input rst_n;  //复位  input [3:0] row;  //行信号
output [3:0] col; //列信号 output [2:0] sel; //数码管位选信号 output [7:0] seg7; //数码管段选信号
wire [23:0] data;
//例化数码管模,和矩阵键盘模块 key_borad key_borad_dut( .clk(clk), .rst_n(rst_n), .row(row), .col(col), .data(data) ); seg seg_dut( .clk(clk), .rst_n(rst_n), .sel(sel), .seg7(seg7), .data_in(data) );
endmodule


key_borad代码:

module key_borad(clk,rst_n,row,col,data);  input clk;      //时钟 50M  input rst_n;    //复位  input [3:0] row;      //输入行信号
output reg [3:0] col; //输出列信号 output reg [23:0] data;
//状态变量,表示 parameter s0 = 3'b00; parameter s1 = 3'b01; parameter s2 = 3'b10; parameter s3 = 3'b11; parameter s4 = 3'b100; parameter s5 = 3'b101;
//parameter T1ms = 50000; //扫描间隔 parameter T1ms = 2; //parameter T10ms= 500_000; //按键消抖时间 parameter T10ms = 20;
wire flag; reg [15:0] count; always @ (posedge clk or negedge rst_n) if(!rst_n) begin count <= 16'd0; end else begin if(count < T1ms - 1 ) //计数1K的频率时间 count <= count + 1'b1; else begin count <= 16'b0; end end
assign flag = (count == T1ms - 1) ? 1'b1 : 1'b0; //计数到了就给一个高脉冲,反之低脉冲
reg [2:0] state; reg [7:0] row_col; reg [18:0] cnt; reg data_flag; always @ (posedge clk or negedge rst_n) if(!rst_n) begin state <= 3'b0; row_col <= 8'b1111_1111; data_flag <= 1'b0; col <= 4'b0000; cnt <= 19'b0; end else begin case (state) s0: begin if(row == 4'b1111) //如果没有按下 begin data_flag <= 1'b0; col <= 4'b0000; end else //表示按下,跳转下一个状态 begin data_flag <= 1'b0; state <= s1; end end s1: begin if(row == 4'b1111) //如果是抖动跳转0状态 begin cnt <= 19'b0; state <= s0; end else begin if(cnt < T10ms - 1) //计数相应的时间,消抖处理 begin cnt <= cnt + 1'b1; end else begin cnt <= 19'b0; state <= s2; col <= 4'b0111; //消抖完表示按键有效 end end end s2: begin if (row != 4'b1111) //表示导通 begin state <= s3; //导通后跳转下一个状态 row_col <= {row,col}; //拼接行和列信号 end else //行信号不导通,开始进行列扫描 begin if(flag) begin col <= {col[2:0],col[3]}; //1ms进行一次列扫描 end else begin col <= col; end end end s3:begin if(row == 4'b1111) //按键抬起 begin state <= s0; data_flag <= 1'b1; //表示一次成功的按键,输出一个高脉冲 end else begin state <= s3; end end default: state <= s0; endcase end
reg [3:0] key_num; //键值的翻译模块的表示 always @ (posedge clk or negedge rst_n) if(!rst_n) key_num = 4'd0; else case ({row_col}) 8'b0111_0111:key_num = 4'hf; 8'b0111_1011:key_num = 4'he; 8'b0111_1101:key_num = 4'hd; 8'b0111_1110:key_num = 4'hc;
8'b1011_0111:key_num = 4'hb; 8'b1011_1011:key_num = 4'ha; 8'b1011_1101:key_num = 4'h9; 8'b1011_1110:key_num = 4'h8;
8'b1101_0111:key_num = 4'h7; 8'b1101_1011:key_num = 4'h6; 8'b1101_1101:key_num = 4'h5; 8'b1101_1110:key_num = 4'h4;
8'b1110_0111:key_num = 4'h3; 8'b1110_1011:key_num = 4'h2; 8'b1110_1101:key_num = 4'h1; 8'b1110_1110:key_num = 4'h0; default: ; endcase


//计算模块的表示 reg [2:0] state_s; //状态变量 reg [23:0] num1,num2,data_in,data_t; //信号变量 reg [3:0]flag_s; //运算符 always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin data <= 24'b0; state_s <= s0; num1 <= 24'b0; num2 <= 24'b0; data_t <= 24'b0; flag_s <= 4'b0; data_in <= 24'b0; end else begin case (state_s) s0:begin if(data_flag) //如果有一次按下 begin if(key_num < 4'd9) //键值小于9便是有效 begin num1 <= num1*10 + key_num; //BCD码转为2进制 data <= {data[19:0],key_num}; //数码管移位 end if(key_num > 4'd9 && key_num < 4'd14) //10 -- 13 表示运算符 begin data <= 24'b0; state_s <= s1; flag_s <= key_num; end else //否则无效信号 state_s <= s0; end end s1:begin if(data_flag)//如果有一次按下 begin if(key_num <4'd9 ) //键值小于9便是有效 begin num2 <= 10*num2 +key_num;//BCD码转为2进制 data <= {data[19:0],key_num};//数码管移位 end if(key_num > 4'd9 && key_num < 4'd14)//10 -- 13 表示运算符 begin state_s <= s1; end if(key_num == 15) //表示等于 begin state_s <= s2; end end end s2:begin state_s <= s3; case (flag_s)
4'd10 :begin //加运算 data_in <= num1 + num2; state_s <= s3; end
4'd13 :begin //乘运算 data_in <= num1 * num2; state_s <= s3; end endcase end s3:begin //二进制转为BCD码显示到对应的数码管上 data[3:0] = data_in % 10; data[7:4] = data_in / 10 % 10; data[11:8] = data_in / 100 % 10; data[15:12] = data_in / 1000 % 10; data[19:16] = data_in / 10000 % 10; data[23:20] = data_in / 100000; state_s <= s0; data_in <= 24'b0; end default: state_s <= s0; endcase end end
/* always @ (posedge clk or negedge rst_n) if(!rst_n) begin data <= 24'b0; end else begin if(data_flag) begin data <= {data[19:0],key_num};
if(key_num == 4'hf) data <= {data[15:0],4'hf,data[11:8] - data [3:0]}; end else begin data <= data; end end */endmodule

seg代码:

module seg(clk,rst_n,sel,seg7,data_in);
input clk; input rst_n; input [23:0] data_in;
output reg [2:0] sel; output reg [7:0] seg7;
parameter s0 = 3'b000; parameter s1 = 3'b001; parameter s2 = 3'b010; parameter s3 = 3'b011; parameter s4 = 3'b100; parameter s5 = 3'b101;
`define T1ms 50_000 //`define T1ms 5 reg [15:0] count; wire flag; always @ (posedge clk or negedge rst_n) if(!rst_n) begin count <= 15'b0; end else if(count == `T1ms - 1) begin count <= 15'b0; end else begin count <= count + 1'b1; end
assign flag =(count == `T1ms - 1) ? 1'b1 : 1'b0;
reg [2:0] state; reg [3:0] num; always @ (posedge clk or negedge rst_n) if(!rst_n) begin sel <= 3'b0; state <= 3'b0; num <= 4'b0; end else begin case (state) s0:begin if(flag) state <= s1; else begin sel <= 3'b000; num <= data_in[23:20]; end end s1:begin if(flag) state <= s2; else begin sel <= 3'b001; num <= data_in[19:16]; end end s2:begin if(flag) state <= s3; else begin sel <= 3'b010; num <= data_in[15:12]; end end s3:begin if(flag) state <= s4; else begin sel <= 3'b011; num <= data_in[11:8]; end end s4:begin if(flag) state <= s5; else begin sel <= 3'b100; num <= data_in[7:4]; end end s5:begin if(flag) state <= s0; else begin sel <= 3'b101; num <= data_in[3:0]; end end default:state <= s0; endcase end
always @ (*) begin case (num) 0:seg7 <= 8'b1100_0000; 1:seg7 <= 8'b1111_1001; 2:seg7 <= 8'b1010_0100; 3:seg7 <= 8'b1011_0000; 4:seg7 <= 8'b1001_1001; 5:seg7 <= 8'b1001_0010; 6:seg7 <= 8'b1000_0010; 7:seg7 <= 8'b1111_1000; 8:seg7 <= 8'b1000_0000; 9:seg7 <= 8'b1001_0000; 10:seg7 <= 8'b1000_1000; 11:seg7 <= 8'b1111_0111; // '-' 12:seg7 <= 8'b1100_0110; 13:seg7 <= 8'b1010_0001; 14:seg7 <= 8'b1000_0110; 15:seg7 <= 8'b1111_0110; // '= ' default:; endcase endendmodule


yingjian模块代码:
module yingjian(clk,rst_n,col,row,pressnum);
input clk; input rst_n; input [3:0] col; input [4:0] pressnum;
output reg [3:0] row;

always @ (*) begin case (pressnum) 0: row = {1'b1,1'b1,1'b1,col[0]}; 1: row = {1'b1,1'b1,1'b1,col[1]}; 2: row = {1'b1,1'b1,1'b1,col[2]}; 3: row = {1'b1,1'b1,1'b1,col[3]};
4: row = {1'b1,1'b1,col[0],1'b1}; 5: row = {1'b1,1'b1,col[1],1'b1}; 6: row = {1'b1,1'b1,col[2],1'b1}; 7: row = {1'b1,1'b1,col[3],1'b1};
8: row = {1'b1,col[0],1'b1,1'b1}; 9: row = {1'b1,col[1],1'b1,1'b1}; 10: row = {1'b1,col[2],1'b1,1'b1}; 11: row = {1'b1,col[3],1'b1,1'b1};
12: row = {col[0],1'b1,1'b1,1'b1}; 13: row = {col[1],1'b1,1'b1,1'b1}; 14: row = {col[2],1'b1,1'b1,1'b1}; 15: row = {col[3],1'b1,1'b1,1'b1};
16: row = {1'b1,1'b1,1'b1,1'b1}; default:; endcase endendmodule


仿真测试


测试模块calc_tb代码:
`timescale 1ns/1ps
module calc_tb(); reg clk; reg rst_n; reg [4:0] pressnum; wire [3:0] row;
wire [3:0] col; wire [3:0] key_num;
initial begin clk = 1'b1; rst_n = 1'b0; pressnum = 5'd16;
#200.1 rst_n = 1'b1; #2000 pressnum = 5'd16;
#1000 pressnum = 5'd5;
#1000 pressnum = 5'd16;
#1250 pressnum = 5'd10; #1250 pressnum = 5'd16; #1250 pressnum = 5'd2; #1250 pressnum = 5'd16; #1250 pressnum = 5'd15; #1250 pressnum = 5'd16; #2000 #2000 $stop;
end always #10 clk = ~clk;
calc calc_dut( .clk(clk), .rst_n(rst_n), .row(row), .col(col), .sel(sel), .seg7(seg7) ); yingjian yingjian_dut( .clk(clk), .rst_n(rst_n), .col(col), .row(row), .pressnum(pressnum) );endmodule


仿真图:

从仿真图中可以看出,在仿真中我们设置的是先按下5,再10,之后2,然后按下等于15.通过观察仿真正确,之后由于设计中我们10是表示加法,那么5 + 2 = 7 :结果显示正确。

END

福利】:QQ交流群173560979,进群备注名字+学校/企业。
淘宝店铺:https://shop588964188.taobao.com
论坛网址:www.sxznfpga.com
叁芯智能FPGA课程

往期精选 

 
 

【免费】FPGA工程师人才招聘平台

FPGA人才招聘,企业HR,看过来!

系统设计精选 | 基于FPGA的实时图像边缘检测系统设计(附代码)

基于原语的千兆以太网RGMII接口设计

时序分析理论和timequest使用_中文电子版

求职面试 | FPGA或IC面试题最新汇总篇

特惠 | FPGA图像处理专题课,Quartus、ISE、Vivado全涉及

特惠 | FPGA时序分析及约束专题课,Quartus、ISE、Vivado全涉及

资料汇总|FPGA软件安装包、书籍、源码、技术文档…(2024.11.14更新)

FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。


FPGA技术江湖微信交流群

加群主微信,备注姓名+学校/公司+专业/岗位进群


FPGA技术江湖QQ交流群

备注姓名+学校/公司+专业/岗位进群

FPGA技术江湖 任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。
评论
  • 采购与分销是企业运营中至关重要的环节,直接影响到企业的成本控制、客户满意度和市场竞争力。以下从多个方面介绍如何优化采购与分销:采购环节优化供应商管理供应商评估与选择:建立一套全面、科学的供应商评估体系,除了考虑价格因素,还要综合评估供应商的产品质量、交货期、信誉、研发能力、售后服务等。通过多维度评估,选择那些能够提供优质产品和服务,且与企业战略目标相契合的供应商。建立长期合作关系:与优质供应商建立长期稳定的合作关系,这种合作模式可以带来诸多好处。双方可以在信任的基础上进行深度沟通与协作,共同开展
    Jeffreyzhang123 2024-12-27 17:43 52浏览
  • 在当今科技飞速发展的时代,工业电子作为现代制造业的中流砥柱,正以前所未有的速度推动着各个行业的变革与进步。从汽车制造到航空航天,从智能家居到工业自动化,工业电子的身影无处不在,为我们的生活和生产带来了巨大的改变。工业电子的崛起与发展工业电子的发展历程可谓是一部波澜壮阔的科技进化史。追溯到上世纪中叶,电子技术开始逐渐应用于工业领域,最初主要是简单的电子控制装置,用于提高生产过程的自动化程度。随着半导体技术、计算机技术和通信技术的不断突破,工业电子迎来了爆发式的增长。集成电路的发明使得电子设备的体积
    Jeffreyzhang123 2024-12-27 15:40 67浏览
  • 一、引言无人机,作为近年来迅速崛起的新兴技术产物,正以前所未有的速度改变着众多行业的运作模式,从民用领域的航拍、物流,到工业领域的测绘、巡检,再到军事领域的侦察、打击等,无人机的身影无处不在。为了深入了解无人机的现状,本次调研综合了市场数据、行业报告、用户反馈等多方面信息,全面剖析无人机的发展态势。二、市场规模与增长趋势随着技术的不断进步和成本的逐渐降低,无人机市场呈现出爆发式增长。近年来,全球无人机市场规模持续扩大,预计在未来几年内仍将保持较高的增长率。从应用领域来看,消费级无人机市场依然占据
    Jeffreyzhang123 2024-12-27 17:29 74浏览
  • 在科技飞速发展的今天,汽车不再仅仅是一种交通工具,更是一个融合了先进技术的移动智能空间。汽车电子作为汽车产业与电子技术深度融合的产物,正以前所未有的速度推动着汽车行业的变革,为我们带来更加智能、安全、舒适的出行体验。汽车电子的发展历程汽车电子的发展可以追溯到上世纪中叶。早期,汽车电子主要应用于发动机点火系统和简单的电子仪表,功能相对单一。随着半导体技术的不断进步,集成电路被广泛应用于汽车领域,使得汽车电子系统的性能得到了显著提升。从电子燃油喷射系统到防抱死制动系统(ABS),从安全气囊到车载导航
    Jeffreyzhang123 2024-12-27 11:53 77浏览
  • 发明阶段(20世纪80年代至90年代)起源:当时ASIC设计成本高,周期长,流片失败率高,业界需要一种通用的半导体器件进行流片前测试和验证,可编程逻辑器件就此产生。诞生:1980年,Xilinx公司成立。1985年,Ross Freeman制造了第一片PFGA芯片XC2064,采用4输入,1输出的LUT和FF结合的基本逻辑单元。发展阶段(1992年至1999年)容量提升:FPGA容量不断上涨,芯片面积逐渐增大,为架构穿心提供空间,复杂功能可以实现。布线问题凸显:缩着芯片复杂度增加,片上资源的互连
    Jeffreyzhang123 2024-12-27 10:26 78浏览
  • 一、前言 回首2024,对于我而言,是充满挑战与收获的一年。在这一年里,我积极参与了论坛的众多活动,不仅拓宽了我的认知边界(有些东西不是你做不到,而是你想不到),还让我在实践中收获了宝贵的经验和。同时,多种多样的论坛活动让我们全方面的接受新东西,连接新知识,多种类型的的活动交织了你我的2024。在这里说一说对过去一年的活动经历,进行一次年终总结,并谈谈我的收获和感受,以及对2025年的展望。二、活动足迹(一)快速体验:机智云Gokit2.0开发板初体验 机智云Gokit2.0开发板的体验活动让大
    无言的朝圣 2024-12-27 14:50 47浏览
  • 在科技飞速发展的今天,医疗电子作为一个融合了医学与电子技术的交叉领域,正以前所未有的速度改变着我们的医疗模式和健康生活。它宛如一颗璀璨的明珠,在医疗领域绽放出耀眼的光芒,为人类的健康福祉带来了诸多惊喜与变革。医疗电子的神奇应用医疗电子的应用范围极为广泛,深入到医疗的各个环节。在诊断方面,各种先进的医学成像设备堪称医生的 “火眼金睛”。X 光、CT、MRI 等成像技术,能够清晰地呈现人体内部的结构和病变情况,帮助医生准确地发现疾病。以 CT 为例,它通过对人体进行断层扫描,能够提供比传统 X 光更
    Jeffreyzhang123 2024-12-27 15:46 54浏览
  • 在当今这个科技飞速发展的时代,物联网(IoT)已经不再是一个陌生的概念,它正以一种前所未有的速度改变着我们的生活和工作方式,像一股无形的力量,将世界紧密地连接在一起,引领我们步入一个全新的智能时代。物联网是什么简单来说,物联网就是通过感知设备、网络传输、数据处理等技术手段,实现物与物、人与物之间的互联互通和智能化管理。想象一下,你的家里所有的电器都能 “听懂” 你的指令,根据你的习惯自动调节;工厂里的设备能够实时监测自身状态,提前预警故障;城市的交通系统可以根据实时路况自动优化信号灯,减少拥堵…
    Jeffreyzhang123 2024-12-27 17:18 46浏览
  • 引言工程师作为推动科技进步和社会发展的核心力量,在各个领域发挥着关键作用。为深入了解工程师的职场现状,本次调研涵盖了不同行业、不同经验水平的工程师群体,通过问卷调查、访谈等方式,收集了大量一手数据,旨在全面呈现工程师的职场生态。1. 工程师群体基本信息行业分布:调研结果显示,工程师群体广泛分布于多个行业,其中制造业占比最高,达到 90%,其次是信息技术、电子通信、能源等行业。不同行业的工程师在工作内容、技术要求和职业发展路径上存在一定差异。年龄与经验:工程师群体以中青年为主,30 - 45 岁年
    Jeffreyzhang123 2024-12-27 17:39 64浏览
  • 起源与基础20 世纪 60 年代:可编程逻辑设备(PLD)的概念出现,一种被称为 “重构能力” 的芯片的可编程性吸引了许多工程师和学者。20 世纪 70 年代:最早的可编程逻辑器件 PLD 诞生,其输出结构是可编程的逻辑宏单元,它的硬件结构设计可由软件完成,设计比纯硬件的数字电路更灵活,但结构简单,只能实现小规模电路。诞生与发展20 世纪 80 年代中期:为弥补 PLD 只能设计小规模电路的缺陷,复杂可编程逻辑器件 CPLD 被推出,它具有更复杂的结构,能够实现较大规模的电路设计。1988 年:
    Jeffreyzhang123 2024-12-27 10:41 66浏览
  • 在当今这个数字化的时代,电子设备无处不在,从我们手中的智能手机、随身携带的笔记本电脑,到复杂的工业控制系统、先进的医疗设备,它们的正常运行都离不开一个关键的 “幕后英雄”—— 印刷电路板(Printed Circuit Board,简称 PCB)。PCB 作为电子设备中不可或缺的重要部件,默默地承载着电子元件之间的连接与信号传输,是整个电子世界的基石。揭开 PCB 的神秘面纱PCB,简单来说,就是一块由绝缘材料制成的板子,上面通过印刷、蚀刻等工艺形成了导电线路和焊盘,用于固定和连接各种电子元件。
    Jeffreyzhang123 2024-12-27 17:21 52浏览
  • 在当今竞争激烈的商业世界中,供应链管理已成为企业生存与发展的核心竞争力之一。它就像一条无形的纽带,将供应商、制造商、分销商、零售商直至最终消费者紧密相连,确保产品和服务能够高效、顺畅地流转。今天,就让我们一同深入探索供应链管理的奥秘。供应链管理是什么简单来说,供应链管理是对从原材料采购、生产制造、产品配送直至销售给最终用户这一整个过程中,涉及的物流、信息流和资金流进行计划、协调、控制和优化的管理活动。它不仅仅是对各个环节的简单串联,更是一种通过整合资源、优化流程,实现整体效益最大化的管理理念和方
    Jeffreyzhang123 2024-12-27 17:27 49浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦