篮球计分器设计VHDL代码Quartus DE2-115开发板

名称:篮球计分器设计VHDL代码Quartus  DE2-115开发板(文末获取)

软件:Quartus

语言:VHDL

代码功能:

任务与要求:

1、具有24s(也可假定30s)计时、显示;

2、可对计时器清零、置数、启动和暂停

3、30秒倒计时;

4、两个数码管显示两队比分

5、超时报警并可解除报警。

要求--都不够价钱50.jpg

本代码已在DE2-115开发板验证,DE2-115开发板如下,其他开发板可以修改管脚适配:

DE2-115开发板.png

要求

第三部分 详细设计过程

整体设计分析:顶层电路包括输入端口有:clk_in(50MHz时钟输入端口),reset_p(复位信号),start(开始、继续信号),stop(暂停信号),score_1(1队分数),score_2(2队分数输入端口),其中reset_p高电平有效,start、stop端口均为低电平有效。

输出端口有:LED(闪烁报警),HEX0(显示秒个位)、HEX1(显示秒十位)、HEX2(显示1队分数)、HEX3(显示2队分数)。

图2 顶层模块

图形分析:顶层模块由分频模块,倒计时模块,数码管显示模块3个模块组成。其中,分频模块输入50MHz时钟,输出1Hz信号;倒计时模块在开始、暂停按键控制下输出秒倒计时信号和LED报警信号;数码管显示模块将两队分数和秒倒计时信号通过数码管显示。

3.1分频模块

3.1.1 模块功能描述

在这个模块中主要实现50MHz的时钟转换为1Hz的信号,DE2-115板子上的晶振为50MHz,而倒计时为一秒一次,即1Hz,故需要将50MHz的信号转换为1Hz的信号。50MHz对应周期为20ns,1Hz对应周期为1s,两者相差50000000倍。

为到达分频的目的,可以使用计数器来设计,即将50MHz的信号进行计数,一共计数5000000次后就是1s,计数到50000000后计数器清零,重新开始计数,这样循环往复就能的带周期性的1Hz信号。

3.1.2模块设计思想

设计分频模块时,我设计了1个进程,定义time_count为一个32位的计数器,使用50MHz的clk_in信号作为时钟,在时钟上升沿进行计数,当计数到“00000010111110101111000010000000”时清零,重新开始计数。“00000010111110101111000010000000”表示二进制的50000000。当计数到50000000时,控制clk_1Hz输出高电平,否则输出低电平。这样得到的clk_1Hz信号就是1秒钟输出一次脉冲的1Hz信号。

电路模块图如下所示:

图4 分频模块

图4所示为分频模块框图,clk_in为时钟信号输入,clk_1Hz为输出。

3.1.3设计关键知识点

在进程设计种使用了一个32位的计数器信号time_count,需要计数到“00000010111110101111000010000000”,该计数值是一个很大得

数,在进行模块仿真时会耗费大量时间,因此仿真时可以将改计数器改小,本设计改小为"00000000000000000000000000010000",即仿真时用这个小的计数器,用于仿真验证功能。实际需要上板调试时再改为大数。在该模块中调用ieee.std_logic_1164.all库和ieee.std_logic_unsigned.all库,并且确定输入输出信号的类型[4]。

实体部分如下:

LIBRARY ieee;

   USE ieee.std_logic_1164.all;

   USE ieee.std_logic_unsigned.all;

--分频模块,分频到1Hz

ENTITY fenping IS

   PORT (

      clk_in   : IN STD_LOGIC;

      clk_1Hz  : OUT STD_LOGIC--输出1Hz

   );

END fenping;

3.2倒计时模块

3.2.1模块功能描述

在这个模块中主要实现秒钟倒计时功能且倒计时结束后LED闪烁报警。当按下reset_p信号时,模块复位,按下start信号时开始倒计时,按下stop信号暂停,再次按下start信号时继续倒计时,直到倒计时为0后,LED闪烁报警。

该模块输入信号有系统时钟信号clk_in,倒计时时钟clk_1Hz,复位清零信号reset_p,启动、继续信号start,暂停信号stop。

输出有闪烁报警信号LED,秒信号second_time。

该模块使用状态机实现,一共分为s_idle,s_down_cnt,s_stop,s_end这4个状态。系统复位时处于s_idle状态,表示空闲。当按下start信号时,系统启动,进入s_down_cnt状态,该状态为倒计时状态,在这个状态下second信号按每秒一次递减,当second减为0时,进入s_end状态,表示结束。当second未减到0时,按下stop按键,则进入s_stop状态,表示暂停。在暂停状态下,按下start信号,进入s_down_cnt状态继续倒计时。状态机的状态转移图如下:

图5 倒计时模块状态机图

3.2.2模块设计思想

该模块用于倒计时控制及结束LED报警闪烁,模块输入信号有系统时钟信号clk_in,倒计时时钟clk_1Hz,复位清零信号reset_p,启动、继续信号start,暂停信号stop。输出有闪烁报警信号LED,秒信号second_time。输入信号start、stop控制倒计时的启动和暂停,reset_p控制计数器复位。通过状态机控制s_idle,s_down_cnt,s_stop,s_end这4个状态的切换。在s_down_cnt状态下,控制second信号倒计时。倒计时采用clk_1Hz为计时信号,每来一次clk_1Hz信号倒计时一次。在s_end状态时输出LED报警信号,LED闪烁频率为2Hz,也是采用分频思路,产生一个2Hz的信号。倒计时模块电路如下:

图6 倒计时模块

3.2.3设计关键知识点

本模块的关键在于状态机的设计,状态机在实现流程控制方面是首选的方法。倒计时控制信号包括启动。暂停按键以及倒计时的second信号。在这些信号控制下,状态机会进入不同的状态,然后在不同的状态下,我们可以控制信号倒计时以及LED闪烁。实体部分如下:

LIBRARY ieee;

   USE ieee.std_logic_1164.all;

   USE ieee.std_logic_unsigned.all;

--倒计时模块

ENTITY jishi IS

   PORT (

      clk_in       : IN STD_LOGIC;

      clk_1Hz      : IN STD_LOGIC;--1Hz信号

      reset_p      : IN STD_LOGIC;--复位清零

      start        : IN STD_LOGIC;--启动、继续

      stop         : IN STD_LOGIC;--暂停

      LED          : OUT STD_LOGIC;--闪烁报警

      second_time  : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)--秒

   );

END jishi;

   

3.3数码管显示模块

3.2.1模块功能描述

在这个模块中主要实现数码管的显示,本模块显示秒倒计时以及1队分数和2队分数。输入信号有clk时钟,second_time秒倒计时,score_1为1队分数,score_2为2队分数。输出为HEX0(显示秒个位)、HEX1(显示秒十位)、HEX2(显示1队分数)、HEX3(显示2队分数)。数码管显示实际上是实现译码器,数码管为8段数码管,即有8个段组成,如下图:

如要显示数字1,则上图中的1,2段点亮即可。若要显示数字2,则需要点亮0、1、6、4、3段,以此类推。本模块就是将十进制数字转换为数码管需要点亮的段。

3.2.2模块设计思想

该模块用于显示倒计时以及2队分数。倒计时为30s倒计时到0,因此需要2个数码管显示,一个显示十位,一个显示个位。因此需要将second_time信号转换为十位和个位,转换方法为将second_time除以10,得到的商即为十位数据,然后再将second_time减去商除以10,得到的就是个位。最后再通过一个case语句将十进制数据转换为对应数码管段的点亮信号。即实现数码管译码。

倒计时模块电路如下:

图6 显示模块

3.2.3设计关键知识点

本模块的关键在于计算倒计时的十位和个位,以及数码管译码器。将

second_time除以10,得到的商即为十位数据,然后再将second_time减去商除以10,得到的就是个位,译码器采用case语句实现。实体部分如下:

LIBRARY ieee;

   USE ieee.std_logic_1164.all;

   USE ieee.std_logic_unsigned.all;

    USE ieee.std_logic_arith.all;

--数码管显示模块

ENTITY display IS

   PORT (

      clk         : IN STD_LOGIC;

      

      second_time  : IN STD_LOGIC_VECTOR(7 DOWNTO 0);--秒钟

      score_1    : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--1队分数

      score_2  : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--2队分数

      

      HEX0        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

      HEX1        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

      HEX2        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

      HEX3        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)

   );

END display;

第四部分 功能仿真

4.1分频模块仿真波形

上图为分频模块仿真图,图中clk_in为输入50MHz的时钟,输出clk_1Hz为1Hz的脉冲信号。程序种设计种使用了一个32位的计数器信号time_count,需要计数到“00000010111110101111000010000000”,该计数值是一个很大得数,在进行模块仿真时会耗费大量时间,因此仿真时将改计数器改小,本设计改小为"00000000000000000000000000010000"。可以看到clk_1Hz信号每个一段时间输出一个脉冲信号,因此功能仿真正确。

4.2倒计时模块仿真波形

图中输入为clk_in,clk_1Hz,reset_p,start,stop,输出为second_time和LED。复位后,按下start信号,开始倒计时,可以看到图上second_time从30开始减小,减小按clk_1Hz的频率变化。按下stop信号后,暂停倒计时,second_time信号保持9不。再次按下start信号后,继续倒计时,second_time继续减小直到0。此时LED开始闪烁,即高低电平变化。按下stop后,LED停止报警。

4.3数码管显示模块仿真波形

图中输入为clk,score_1,score_1,second_time,输出为HEX0~3.其中秒钟个位对应HEX0,秒

钟十位对应HEX1,1对分数对应HEX2,2队分数对应HEX3。可以看到图中1队分数为0001,即1分,对应的数码管译码值为11111001,2队分数为0010,即2分,对应的数码管译码值为10100100,数码管为共阴极,即低电平亮,故11111001对应显示为1,10100100对应显示为2。秒钟十位和个位的显示类似,对应HEX0和HEX1。

4.4整体仿真

仿真分析:

图中clk_in为输入50MHz的时钟,在start按下后,HEX0为1Hz变化一次,即按分频模块的1Hz信号的频率变化。                                       ---分频模块

图中复位后,按下start信号,开始倒计时,可以看到图上HEX1初始为10110000(对应数字3),HEX0初始为11000000(对应数字0),表示秒从30开始减小,减小按clk_1Hz的频率变化。按下stop信号后,暂停倒计时,HEX0和HEX1信号保持不变。再次按下start信号后,继续倒计时,继续减小直到11000000(对应数字0)。此时LED开始闪烁,即高低电平变化。按下stop后,LED停止报警。                           ---倒计时模块

其中秒钟个位对应HEX0,秒钟十位对应HEX1,1对分数对应HEX2,2队分数对应HEX3。按共阴极的7段数码管方式译码,例如10110000(对应数字3),11000000(对应数字0)。最终1队分数显示1,2队分数显示2,倒计时数码管显示“00”。 ---显示模块

1. 工程文件

2. 程序文件

3. 程序编译

4. RTL图

状态图

5. 管脚图

6. 仿真图

整体仿真图

分频模块仿真图

倒计时模块仿真图

显示模块仿真图

部分代码展示:

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
--篮球计时器
ENTITY Basketball_clock IS
   PORT (
      clk_in   : IN STD_LOGIC;
      reset_p  : IN STD_LOGIC;--复位清零
      start    : IN STD_LOGIC;--开始、继续
      stop     : IN STD_LOGIC;--暂停
      score_1  : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--1队分数
      score_2  : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--2队分数
      LED      : OUT STD_LOGIC;--闪烁报警
      HEX0     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--数码管段选
      HEX1     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--数码管段选
      HEX2     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--数码管段选
      HEX3     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) --数码管段选
   );
END Basketball_clock;
ARCHITECTURE behave OF Basketball_clock IS
--50M分频到1hz
   COMPONENT fenping IS
      PORT (
         clk_in   : IN STD_LOGIC;
         clk_1Hz  : OUT STD_LOGIC
      );
   END COMPONENT;
 --倒计时模块  
   COMPONENT jishi IS
      PORT (
         clk_in   : IN STD_LOGIC;
         clk_1Hz  : IN STD_LOGIC;
         reset_p  : IN STD_LOGIC;
         start    : IN STD_LOGIC;
         stop     : IN STD_LOGIC;
         LED      : OUT STD_LOGIC;
         second_time : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
      );
   END COMPONENT;
   
--数码管显示模块
COMPONENT display IS
   PORT (
      clk         : IN STD_LOGIC;
      
      second_time  : IN STD_LOGIC_VECTOR(7 DOWNTO 0);--秒钟
      score_1    : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--1队分数
      score_2  : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--2队分数
      
      HEX0        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
      HEX1        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
      HEX2        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
      HEX3        : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
   );
END COMPONENT;
   
   SIGNAL clk_1Hz     : STD_LOGIC;
   SIGNAL second_time : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
--50M分频到1hz
   i_fenping : fenping
      PORT MAP (
         clk_in   => clk_in,
         clk_1Hz  => clk_1Hz--1Hz
      );
   
   
--倒计时模块   
   i_jishi : jishi
      PORT MAP (
         clk_in       => clk_in,
         clk_1Hz      => clk_1Hz,
         reset_p      => reset_p,--复位
         start        => start,--开始
         stop         => stop,--暂停
         LED          => LED,--闪烁报警
         second_time  => second_time--秒
      );
源代码

点击下方的公众号卡片获取

// // Permission: // // Terasic grants permission to use and modify this code for use // in synthesis for all Terasic Development Boards and Altera Development // Kits made by Terasic. Other use of this code, including the selling // ,duplication, or modification of any portion is strictly prohibited. // // Disclaimer: // // This VHDL/Verilog or C/C++ source code is intended as a design reference // which illustrates how these types of functions can be implemented. // It is the user's responsibility to verify their design for // consistency and functionality through the use of formal // verification methods. Terasic provides no warranty regarding the use // or functionality of this code. // // -------------------------------------------------------------------- // // Terasic Technologies Inc // 356 Fu-Shin E. Rd Sec. 1. JhuBei City, // HsinChu County, Taiwan // 302 // // web: http://www.terasic.com/ // email: support@terasic.com // // -------------------------------------------------------------------- // // Major Functions: DE2_115_PS2 Mouse Controller // // -------------------------------------------------------------------- // // Revision History : // -------------------------------------------------------------------- // Ver :| Author :| Mod. Date :| Changes Made: // V1.0 :| Johnny FAN,HdHuang :| 05/16/10 :| Initial Revision // -------------------------------------------------------------------- module ps2( iSTART, //press the button for transmitting instrucions to device; iRST_n, //FSM reset signal; iCLK_50, //clock source; PS2_CLK, //ps2_clock signal inout; PS2_DAT, //ps2_data signal inout; oLEFBUT, //left button press display; oRIGBUT, //right button press display; oMIDBUT, //middle button press display; oX_MOV1, //lower SEG of mouse displacement display for X axis. oX_MOV2, //higher SEG of mouse displacement display for X axis. oY_MOV1, //lower SEG of mouse displacement display for Y axis. oY_MOV2 //higher SEG of mouse displacement display for Y axis. ); //interface; //======================================================= // PORT declarations //======================================================= input iSTART; input iRST_n; input iCLK_50; inout PS2_CLK; inout PS2_DAT; output oLEFBUT; output oRIGBUT; output oMIDBUT; output [6:0] oX_MOV1; output [6:0] oX_MOV2; output [6:0] oY_MOV1; output [6:0] oY_MOV2; //instantiation SEG7_LUT U1(.oSEG(oX_MOV1),.iDIG(x_latch[3:0])); SEG7_LUT U2(.oSEG(oX_MOV2),.iDIG(x_latch[7:4])); SEG7_LUT U3(.oSEG(oY_MOV1),.iDIG(y_latch[3:0])); SEG7_LUT U4(.oSEG(oY_MOV2),.iDIG(y_latch[7:4])); //instruction define, users can charge the instruction byte here for other purpose according to ps/2 mouse datasheet. //the MSB is of parity check bit, that's when there are odd number of 1's with data bits, it's value is '0',otherwise it's '1' instead. parameter enable_byte =9'b011110100; //======================================================= // REG/WIRE declarations //======================================================= reg [1:0] cur_state,nex_state; reg ce,de; reg [3:0] byte_cnt,delay; reg [5:0] ct; reg [7:0] x_latch,y_latch,cnt; reg [8:0] clk_div; reg [9:0] dout_reg; reg [32:0] shift_reg; reg leflatch,riglatch,midlatch; reg ps2_clk_in,ps2_clk_syn1,ps2_dat_in,ps2_dat_syn1; wire clk,ps2_dat_syn0,ps2_clk_syn0,ps2_dat_out,ps2_clk_out,flag; //======================================================= // PARAMETER declarations //======================================================= //state define parameter listen =2'b00, pullclk=2'b01, pulldat=2'b10, trans =2'b11; //======================================================= // Structural coding //======================================================= //clk division, derive a 97.65625KHz clock from the 50MHz source; always@(posedge iCLK_50) begin clk_div <= clk_div+1; end assign clk = clk_div[8]; //tristate output control for PS2_DAT and PS2_CLK; assign PS2_CLK = ce?ps2_clk_out:1'bZ; assign PS2_DAT = de?ps2_dat_out:1'bZ; assign ps2_clk_out = 1'b0; assign ps2_dat_out = dout_reg[0]; assign ps2_clk_syn0 = ce?1'b1:PS2_CLK; assign ps2_dat_syn0 = de?1'b1:PS2_DAT; // assign oLEFBUT = leflatch; assign oRIGBUT = riglatch; assign oMIDBUT = midlatch; //multi-clock region simple synchronization always@(posedge clk) begin ps2_clk_syn1 <= ps2_clk_syn0; ps2_clk_in <= ps2_clk_syn1; ps2_dat_syn1 <= ps2_dat_syn0; ps2_dat_in <= ps2_dat_syn1; end //FSM shift always@(*) begin case(cur_state) listen :begin if ((!iSTART) && (cnt == 8'b11111111)) nex_state = pullclk; else nex_state = listen; ce = 1'b0; de = 1'b0; end pullclk :begin if (delay == 4'b1100) nex_state = pulldat; else nex_state = pullclk; ce = 1'b1; de = 1'b0; end pulldat :begin nex_state = trans; ce = 1'b1; de = 1'b1; end trans :begin if (byte_cnt == 4'b1010) nex_state = listen; else nex_state = trans; ce = 1'b0; de = 1'b1; end default : nex_state = listen; endcase end //idle counter always@(posedge clk) begin if ({ps2_clk_in,ps2_dat_in} == 2'b11) begin cnt <= cnt+1; end else begin cnt <= 8'd0; end end //periodically reset ct; ct counts the received data length; assign flag = (cnt == 8'hff)?1:0; always@(posedge ps2_clk_in,posedge flag) begin if (flag) ct <= 6'b000000; else ct <= ct+1; end //latch data from shift_reg;outputs is of 2's complement; //Please treat the cnt value here with caution, otherwise wrong data will be latched. always@(posedge clk,negedge iRST_n) begin if (!iRST_n) begin leflatch <= 1'b0; riglatch <= 1'b0; midlatch <= 1'b0; x_latch <= 8'd0; y_latch <= 8'd0; end else if (cnt == 8'b00011110 && (ct[5] == 1'b1 || ct[4] == 1'b1)) begin leflatch <= shift_reg[1]; riglatch <= shift_reg[2]; midlatch <= shift_reg[3]; x_latch <= x_latch+shift_reg[19 : 12]; y_latch <= y_latch+shift_reg[30 : 23]; end end //pull ps2_clk low for 100us before transmit starts; always@(posedge clk) begin if (cur_state == pullclk) delay <= delay+1; else delay <= 4'b0000; end //transmit data to ps2 device;eg. 0xF4 always@(negedge ps2_clk_in) begin if (cur_state == trans) dout_reg <= {1'b0,dout_reg[9:1]}; else dout_reg <= {enable_byte,1'b0}; end //transmit byte length counter always@(negedge ps2_clk_in) begin if (cur_state == trans) byte_cnt <= byte_cnt+1; else byte_cnt <= 4'b0000; end //receive data from ps2 device; always@(negedge ps2_clk_in) begin if (cur_state == listen) shift_reg <= {ps2_dat_in,shift_reg[32:1]}; end //FSM movement always@(posedge clk,negedge iRST_n) begin if (!iRST_n) cur_state <= listen; else cur_state <= nex_state; end endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值