一、篮球计分器的功能

按照篮球赛赛制进行设计。须具有24秒倒计时功能,十二分钟计时功能,暂停功能,进球计分功能(1分,2分,3分)等。

二、具体实现方法

这个篮球计分器的实现采用top-down思想,具体分为6个模块 分别为 控制模块、计分模块、计时模块、24s倒计时模块、按键消抖模块、数码管显示模块。

这个篮球计分器的输入根据功能分析有以下几个:系统时钟、复位信号、暂停信号、加分信号(one、two、three)、控制给哪个队伍加分的信号;输出信号由于只有在数码管上显示,所以输出信号就只有数码管的段选与位选

三、各个模块的实现方式

(1)、top模块

        top模块主要是要了解各个模块之间的连接方式,具体如下图所示:

根据上图所示,top模块代码应该为:

module top(input clk,    //系统时钟input rst,    //复位信号input stop,   //计时暂停 (拨码按键)input  team,   //选择加分的队伍 (拨码按键)input   ctrl,   //切换挡位  (按键)input one,    //加一分   (按键)input two,    //加两分   (按键)input three,  //加三分   (按键)output    wire [3:0] sel, //数码管位选output   wire [6:0] seg  //数码管段选);wire       key_one;wire        key_two;wire        key_three;wire [15:0] date1;wire [15:0] date2;wire [15:0] date3;wire            en;wire     key_ctrl;wire  [2:0] out_ctrl;//计分模块xiaodou s0 (.clk(clk), .rst(rst), .key_in(one), .key_flag(key_one));xiaodou s1 (.clk(clk), .rst(rst), .key_in(two), .key_flag(key_two));xiaodou s2 (.clk(clk), .rst(rst), .key_in(three), .key_flag(key_three));jifen s3 (.clk(clk), .rst(rst), .key_one(key_one), .key_two(key_two), .key_three(key_three), .team(team), .date2(date2));//计时模块jishi a0 (.clk(clk), .rst(rst), .stop(stop), .date1(date1));
//倒计时模块daojishi b0 (.clk(clk), .rst(rst), .en(en), .date3(date3));
//控制模块xiaodou c0 (.clk(clk), .rst(rst), .key_in(ctrl), .key_flag(key_ctrl));ctrl c1(.clk(clk), .rst(rst), .key_ctrl(key_ctrl), .en(en), .ctrl(out_ctrl));
//显示模块xianshi d0 (.clk(clk), .rst(rst), .ctrl(out_ctrl), .date1(date1), .date2(date2), .date3(date3), .sel(sel), .seg(seg));
endmodule

        (2)、控制模块

        控制模块主要功能是切换挡位,本模块他的输入是有:系统时钟、复位信号和经过按键消抖后的一个脉冲信号;其输出是一个控制数码管显示的一个信号和倒计时模块的使能信号en,由于我们要控制倒计时模块何时开始倒计时,所以要引入这个使能信号,也就是按下ctrl按钮切换到倒计时模块时就开始倒计时。

具体代码如下:

module ctrl(input    clk,input   rst,input   key_ctrl,output  reg    en,output   reg [2:0] ctrl);reg [1:0] cnt;always@(posedge clk or negedge rst) beginif(rst==0)cnt<=0;else if(cnt=='d2&&key_ctrl == 1) cnt<=0;else if(key_ctrl == 1)cnt<=cnt+1'd1;endalways@(posedge clk or negedge rst) beginif(rst==0) beginctrl<=0;en<=0;endelse if(cnt==0) beginctrl<=3'b000;en <=0;endelse if(cnt==1) beginctrl<=3'b001;en<=0;endelse if(cnt=='d2) beginctrl<=3'b010;en<=1;endend
endmodule

(3)、计时模块

       计时模块的主要功能是12分钟的计时并将现在所及的时间转化为16位的输出信号(输出信号为BCD码前八位表示分钟,后八位表示秒数), 计时模块的输入主要有:系统时钟、复位信号和一个暂停信号(stop)输出只有一个位宽为16位的数据信号;此模块中的暂停信号(stop)我们可以在一秒钟的计数器中加一个信号当stop拉高时停止记数,这样就可以将其暂停;

在此模块要注意如何将目前所及的时间转化为BCD码,在这里我使用的是BCD计数器,将分钟和秒数分开,分别用两个8位的数据来记录它们的数据,最后将其合并;

具体代码如下:

module jishi(input   clk,input   rst,input   stop,output [15:0] date1);localparam TIME_1S='d49_999_999;/* localparam TIME_1S='d4; */reg [25:0] cnt_1s;reg [7:0] dout_1;reg [7:0] dout_2;//一秒钟的计数器always@(posedge clk or negedge rst) beginif(rst==0)cnt_1s<='d0;else if(cnt_1s == TIME_1S)cnt_1s<='d0;else if(stop==0)cnt_1s<= cnt_1s + 1'd1;else cnt_1s<=cnt_1s;end//当前的秒数 并转化为bcd码always@(posedge clk or negedge rst)beginif(rst==0)dout_2<=1'd0;else if(dout_2[7:4]==4'b0101&&dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S)dout_2<=1'd0;else if(dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S) begindout_2[3:0]<=0;dout_2[7:4]<=dout_2[7:4]+1'd1;endelse if(cnt_1s == TIME_1S)dout_2[3:0]<=dout_2[3:0]+1'b1;end
//当前的分钟数并转化为bcd码always@(posedge clk or negedge rst)beginif(rst==0)dout_1<=1'd0;else if(dout_1[7:4]==4'b0001&&dout_1[3:0]==4'b0010&&cnt_1s == TIME_1S)dout_1<=1'd0;else if(dout_1[3:0]==4'b1001&&cnt_1s == TIME_1S) begindout_1[3:0]<=0;dout_1[7:4]<=dout_1[7:4]+1'd1;endelse if(dout_2[7:4]==4'b0101&&dout_2[3:0]==4'b1001&&cnt_1s == TIME_1S)dout_1[3:0]<=dout_1[3:0]+1'b1;endassign date1={dout_1[7:0],dout_2[7:0]};
endmodule

(4)、计分模块

计分模块的主要功能是计算并记录目前两队的分数并将其转化为16位的输出信号;本模块的输入有:系统时钟、复位信号和三个经过消抖后的计分信号(key_one、key_two、key_three)输出只有一个位宽为16位的数据信号

这里将数据转化为BCD码是要注意:由于我们不知道所加的分数是多少,所以有可能在加分后个位的分数大于9,所以此时BCD计数器在进位时要这要改写:

else if(dout_1[3:0] >= 4'b1001)     begindout_1[3:0] <= dout_1[3:0]-'d9;dout_1[7:4] <= dout_1[7:4] + 1'b1;end

此模块代码如下:

module jifen(input   clk,    //系统时钟input rst,    //复位信号input key_one,    //加一分input  key_two,    //加两分input  key_three,  //加三分input  team, //控制给那个队伍加分output wire    [15:0] date2    //输出的数据);/* reg [6:0] score1;   //目前该加几分reg [6:0] score2;   //目前该加几分 */reg [7:0] dout_1;reg [7:0] dout_2;//计算加分并将其转化为bcd码//第一队always@(posedge clk or negedge rst) beginif(rst==0)dout_1 <= 8'b00000000;else if(dout_1[3:0] >= 4'b1001)     begindout_1[3:0] <= dout_1[3:0]-'d9;dout_1[7:4] <= dout_1[7:4] + 1'b1;endelse  if(key_one == 1'b1 && team == 0)     begindout_1[7:4] <= dout_1[7:4];dout_1[3:0] <= dout_1[3:0] + 1'b1;endelse  if(key_two == 1'b1 && team == 0)     begin             dout_1[7:4] <= dout_1[7:4];dout_1[3:0] <= dout_1[3:0] + 'd2;endelse  if(key_three == 1'b1 && team == 0)     begindout_1[7:4] <= dout_1[7:4];dout_1[3:0] <= dout_1[3:0] + 'd3;endend//第二队always@(posedge clk or negedge rst) beginif(rst==0)dout_2 <= 8'b00000000;else if(dout_2[3:0] >= 4'b1001)       begindout_2[3:0] <= dout_2[3:0]-'d9;dout_2[7:4] <= dout_2[7:4] + 1'b1;endelse  if(key_one == 1'b1 && team == 1)     begindout_2[7:4] <= dout_2[7:4];dout_2[3:0] <= dout_2[3:0] + 1'b1;endelse  if(key_two == 1'b1 && team == 1)     begin             dout_2[7:4] <= dout_2[7:4];dout_2[3:0] <= dout_2[3:0] + 'd2;endelse  if(key_three == 1'b1 && team == 1)     begin             dout_2[7:4] <= dout_2[7:4];dout_2[3:0] <= dout_2[3:0] + 'd3;endend//将bcd码转为将要赋值的数据assign date2={dout_1[7:0],dout_2[7:0]};endmodule

        (5)、倒计时模块

        倒计时模块的主要功能是24s的倒计时并将目前的时间转化为BCD码;本模块的输入是系统时钟、复位信号和一个有控制模块输出的使能信号(用来控制何时开始倒计时);输出是一个16位的数据信号(BCD码)用来表示目前的时间

本模块中同样采用BCD计数器将数据信号转化为BCD码,不过与之前不同的是采用减法记数;

本模块代码如下:

module daojishi(input    clk,//系统时钟input rst,//复位信号input en,//判断何时开始倒计时 由控制模块输入output    [15:0]  date3   //输出的数据信号);localparam TIME_001S='d499999; /* localparam TIME_001S='d4; */reg [7:0] dout_1;reg [7:0] dout_2;reg [18:0] cnt_001s;always@(posedge clk or negedge rst) beginif(rst==0)cnt_001s<=0;else if(en==0)cnt_001s<=0;else if(cnt_001s == TIME_001S)cnt_001s<=0;elsecnt_001s<=cnt_001s +1;endalways@(posedge clk or negedge rst) beginif(rst==0)dout_2<=8'b0000_0000;else if(en==0)dout_2<=8'b0000_0000;else if(dout_1==0&&dout_2==0&&cnt_001s == TIME_001S) dout_2<=dout_2;else if(dout_2==0&&cnt_001s == TIME_001S)dout_2<=8'b1001_1001;else if(dout_2[3:0]==0&&cnt_001s == TIME_001S) begindout_2[7:4]<=dout_2[7:4] - 1'b1;dout_2[3:0]<=4'b1001;endelse if(cnt_001s == TIME_001S)dout_2[3:0]<=dout_2[3:0] - 1'b1;endalways@(posedge clk or negedge rst) beginif(rst==0)dout_1<=8'b0010_0100;else if(en==0)dout_1<=8'b0010_0100;else if(dout_1==0&&cnt_001s == TIME_001S)dout_1<=dout_1;else if(dout_1[3:0]==0&&cnt_001s == TIME_001S) begindout_1[7:4]<=dout_1[7:4] - 1'b1;dout_1[3:0]<=4'b1001;endelse if(dout_2==0&&cnt_001s == TIME_001S)dout_1[3:0]<=dout_1[3:0] - 1'b1;endassign date3={dout_1[7:0],dout_2[7:0]};
endmodule

(6)、按键消抖模块

        按键消抖模块的主要功能是将一个输入的按键信号滤波转化为一个脉冲信号;具体实现办法可以参见小梅哥《零基础轻松学习FPGA,小梅哥FPGA设计思想与验证方法视频教程》

        具体代码如下:

module xiaodou(input clk,input   rst,input   key_in,output   reg     key_flag        //滤波后的信号(脉冲信号));localparamIDEL    = 4'b0001,FILTER0 = 4'b0010,DOWN    = 4'b0100,FILTER1 = 4'b1000;reg [3:0] state;reg     key_tem0;reg    key_tem1;wire   nedge;wire  pedge;reg [19:0]    cnt;    //二十毫秒计数器reg            en_cnt; //计数器使能信号reg        cnt_full;//计数器记满信号//边沿检测    always@(posedge clk or negedge rst) beginif(rst==0) beginkey_tem0<=0;key_tem1<=0;endelse beginkey_tem0 <= key_in;key_tem1 <= key_tem0;endendassign   nedge = !key_tem0 & key_tem1;      //下降沿assign pedge =  key_tem0 & (!key_tem1);   //上升沿//一段式状态机always@(posedge clk or negedge rst )beginif(rst==0)  beginstate <= IDEL;en_cnt <= 1'b0;key_flag<=1'd0;endelse case(state)IDEL:beginkey_flag<=1'b0;if(nedge) beginstate <=    FILTER0;en_cnt <= 1'b1; //计数器记数endelse state <=    IDEL;endFILTER0:if(cnt_full) beginstate<= DOWN;en_cnt<=1'b0;key_flag<=1'b1;endelse if(pedge) beginstate<= IDEL;en_cnt <= 1'b0;endelsestate<= FILTER0;DOWN:beginkey_flag<=1'b0;if(pedge) beginstate<=FILTER1;en_cnt<=1'b1;endelsestate<= DOWN;endFILTER1:if(cnt_full) beginstate<= IDEL;en_cnt<=1'b0;key_flag<=1'b0;endelse if(nedge) beginstate<= DOWN;en_cnt <= 1'b0;endelsestate<= FILTER1;default: beginstate<=IDEL;en_cnt<=1'b0;key_flag<=1'b0;endendcase     end//二十毫秒计数器always@(posedge clk or negedge rst) beginif(rst==0)cnt <= 20'd0;else if(en_cnt)cnt <= cnt + 1'b1;elsecnt<= 20'd0;endalways@(posedge clk or negedge rst) beginif(rst==0)cnt_full <= 1'b0;else if(cnt == 'd999_999)cnt_full <= 1'b1;elsecnt_full <= 1'b0;endendmodule

        (7)、数码管显示模块

数码管显示模块的主要功能是将输入其中的16位数据信号通过动态扫描的方式输出在数码管上,本模块的输入有系统时钟、复位信号、由控制模块输入的控制信号和由计时、计分、倒计时三个模块输出的数据信号,输出也就是整个计分器的输出:4位的数码管位选sel和7位的数码管段选seg

本模块通过译码器的方式来实现数据选择:

always@(posedge clk or negedge rst) beginif(rst==0)disp_data<=0;else case(ctrl)3'b000:disp_data<=date1;3'b001:disp_data<=date2;3'b010:disp_data<=date3;default:disp_data<=0;endcaseend

本模块的代码如下:

module xianshi(input clk,input   rst,input   [2:0]   ctrl,input  [15:0] date1,//数据信号input    [15:0] date2,//数据信号input    [15:0] date3,//数据信号output   reg [3:0]  sel, // 数码管位选(选择当前要显示的数码管)output   reg [6:0]  seg // 数码管段选(选择当前要显示的内容));reg [14:0] cnt_1;    //分频记数的计数器reg          clk_out; //分频后的时钟信号/* reg [3:0]  sel_r;  //表示那个数码管亮 */reg [3:0]  date_tmp;reg [15:0] disp_data;localparam TIME='d24999;/* localparam TIME='d4; */always@(posedge clk or negedge rst) beginif(rst==0)disp_data<=0;else case(ctrl)3'b000:disp_data<=date1;3'b001:disp_data<=date2;3'b010:disp_data<=date3;default:disp_data<=0;endcaseend//cnt_1的记数模块always@(posedge clk or negedge rst) beginif(rst==0)cnt_1 <= 15'd0;else if(cnt_1 ==TIME)cnt_1 <= 15'd0;else cnt_1 <= cnt_1+1'd1;end//时钟分频模块always@(posedge clk or negedge rst) beginif(rst==0)clk_out<=1'b0;else if(cnt_1== TIME)clk_out<=~clk_out;else   clk_out<=clk_out;end//移位寄存器always@(posedge clk_out or negedge rst) beginif(rst==0)sel<=4'b0001;else if(sel==4'b1000)sel<=4'b0001;else   sel<=sel<<1;  /* if(rst==0)sel_r<=4'b0001;else sel_r<={sel_r[2:0],sel_r[3]}; */end//四选一多路器always@(*) begincase(sel)4'b0001 : date_tmp <= disp_data[3:0]; 4'b0010 : date_tmp <= disp_data[7:4]; 4'b0100 : date_tmp <= disp_data[11:8]; 4'b1000 : date_tmp <= disp_data[15:12]; default:date_tmp<=4'b0000;endcaseend//字典(译码器)always@(*) begincase(date_tmp)4'h0:seg<=7'b1000000;4'h1:seg<=7'b1111001;4'h2:seg<=7'b0100100;4'h3:seg<=7'b0110000;4'h4:seg<=7'b0011001;4'h5:seg<=7'b0010010;4'h6:seg<=7'b0000010;4'h7:seg<=7'b1111000;4'h8:seg<=7'b0000000;4'h9:seg<=7'b0010000;4'ha:seg<=7'b0001000;4'hb:seg<=7'b0000011;4'hc:seg<=7'b1000110;4'hd:seg<=7'b0100001;4'he:seg<=7'b0000110;4'hf:seg<=7'b0001110;endcaseend// endmodule

四、总结

本人是刚入门FPGA的一名在读大学生,由于初学代码也表现出冗长,凌乱等诸多问题,望见谅。

基于FPGA的篮球计分器相关推荐

  1. 基于FPGA的篮球计分器设计

    有谁会这个,叫我写一个下这个高级的系统结构框图和代码

  2. 51单片机 Proteus仿真 基于单片机的篮球计分器设计 LCD

    基于单片机的篮球计分器设计 设计LCD显示篮球比分牌 通过加分按钮可以给A队或B队加分 设计对调功能,A队和B队分数互换,意味着中场交换场地 显示比赛倒计时功能 创新内容:如显示第几小节

  3. 基于51单片机篮球计分器proteus仿真设计

    本设计是51单片机篮球计分器proteus仿真(源码+原理图+PCB+仿真+报告) 仿真:proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 编号C0004 资料文件下载 ...

  4. 基于单片机的篮球计分器设计

    1.设计任务 利用单片机AT89C51设计篮球计分器,设计LED显示比分牌,通过加分按钮可以给A队和B队加分. 2. 设计要求 2.1系统方案论证 根据设计任务,分析设计系统的组成,给出实现设计任务的 ...

  5. 基于单片机的篮球计分器系统设计(#0455)

    功能描述 1.采用51/52单片机作为主控芯片: 2.采用LCD1602显示双方比分.节数.12分/24秒倒计时: 3.采用按键控制比赛开始/暂停.24秒计时.加分操作: 4.采用蜂鸣器产生以下提示音 ...

  6. 基于单片机的篮球计分器系统设计(#0456)

    功能描述 1.采用51/52单片机作为主控芯片: 2.采用1个四位数码管显示比赛时间.2个三位数码管显示两方比分.1个两位数码管显示24秒倒计时: 3.可通过按键控制比赛开始/暂停.修改比赛时间.刷新 ...

  7. 单片机c语言篮球比分_基于单片机的篮球比赛计时计分器的设计

    摘 要:本系统是采用单片机AT89C51作为本设计的核心原件.利用7段共阴LED作为显示器件.在此设计中共接入了2个7段共阴LED显示器,用于记录得分和比赛时间,显示范围可以达到0到99分,基本满足赛 ...

  8. 基于51单片机的篮球计分器

    基于51单片机的篮球计分器 1)LCD1602液晶屏显示: 比赛双方队名.双方比分.12分钟倒计时.24s进攻倒计时.场次 2)24s倒计时结束蜂鸣器响 3)按键功能: 比赛开始/暂停.24s倒计时重 ...

  9. 单片机应用系统设计技术——基于51单片机篮球计时计分器的设计

    基于51单片机篮球计时计分器的设计 一.实验目的 二.实验内容 三.实验步骤 四.C代码如下 五.实验结果

  10. 用c语言编写篮球过程运行结果,基于单片机的篮球计时计分器设计(c语言编程、含proteus仿真图) 本科毕业论文.doc...

    基于单片机的篮球计时计分器设计(c语言编程.含proteus仿真图) 本科毕业论文 摘要 单片机,亦称单片微电脑或单片微型计算机.它是把中央处理器(CPU).随机存取存储器(RAM).只读存储器(RO ...

最新文章

  1. 线段树分裂与合并 ----- P2824 [HEOI2016/TJOI2016]排序 [线段树分裂合并 OR 01序列排序+二分线段树]
  2. 读写分离原来这么简单,一个小注解就够了
  3. 让页面先发送ajax,Ajax, 了解一下
  4. HALCON完全卸载重装
  5. sql 按 月份 结余_积累中沉淀,反思中提升——白霓镇幼儿园九月份工作总结会...
  6. es 使用ik停词_ES使用IK分词器
  7. Lintcode68 Binary Tree Postorder Traversal solution 题解
  8. Django中应用celery
  9. android黑色半透明dialog背景,Dialog背景半透明
  10. C语言 字符‘0‘和‘\0‘ 以及整数0的区别
  11. 大小写字母c语言,C语言 大小写字母转换
  12. 教你如何有效防止DDos攻击?
  13. 【听】红高粱,莫言经典诺贝尔文学奖小说
  14. 4只鸭子在同一个圆圈内游泳,问:4只鸭子出现在同一个半圆内的概率是多少?Python模拟
  15. HP打印机显示状态出错
  16. 清明节海报设计软件测试,PS清明节海报设计教程
  17. 获取电子面单号的API接口对比(中通、快宝、菜鸟)
  18. Emacs_快捷键列表
  19. MySQL8 设置自动创建时间和自动更新时间
  20. 一飞库房管理系统 v1.0 bt

热门文章

  1. 【数据采集】-目前比较流行的几种数据采集方式
  2. 用React实现基于Canvas的图片放大镜功能
  3. OpManager12——一个完整的网络管理解决方案
  4. rs485接口与计算机,电脑有USB接口就能连接RS485产品了
  5. 5.3 数据通路-专用通路
  6. 物联网无线技术蓝牙和WiFi的区别有哪些?
  7. 威联通_AMD YES!威联通高性价比9盘位TS-963N 5GbE NAS体验
  8. xbox手柄测试_【喂你播】苹果官网上架Xbox无线手柄,那么未来会有果牌手柄吗?...
  9. vue json对象转数组_Vue优秀表单组件,用Vue构建表单的最简单方法——Vue Formulate
  10. OpenCV C++安装和配置