实验五 数字系统的设计

本文档详细介绍了基于FPGA的数字系统设计,实现了从0到59秒的计时器,支持暂停、倒计时、复位和小时分钟秒的显示。设计中包含了分频器、计数器、7段码显示模块,并通过键盘控制各项功能。此外,还讨论了设计过程中遇到的挑战和注意事项,如变量宽度设置、命名规范和端口利用等。
摘要由CSDN通过智能技术生成

设计要求

1:能实现0到59秒的自动周而复始计时

2:通过键盘能暂停计时

3:通过键盘能倒计时59到0

4:  通过键盘能复位计时从0开始

5:  计时结果通过两位七段码显示

可选拓展设计

1:实现小时、分钟、秒的全部显示

2:能设置初始时间

3:整点报时

4:自行设计其他功能,如闪烁显示等

五、实验步骤与实验结果

1、编写一个程序,实现实验的要求,我们实现的功能如下,可以重置,可以计数(从0开始),可以倒计时(59到0),计时结束蜂鸣器会响,可以当电子表使用,用6个数码位显示,区分小时,分钟和秒数,可以通过按键进行调时间。实现的结果见附件一。

16代表的是小时

.用来分割时分秒

25代表的是分

32代表的是秒

可以根据图2-2给出的变量清单实现不同的操作

图1 测试1运行结果图

2、实验准备。变量声明和引脚声明,我将此系统定义为mysystem,定义了8个输入变量,3个输出变量,端口和变量声明清单见图2-1变量清单,mysystem的原理图见图2-2。

端口

引脚

作用

clkin

16

20mhz时钟的输入

rst_n

51

置0

zt

52

暂停计数和计时工作,此时可以调时间

jishu

52

计数开始

jishi

53

倒计时开始

thour

48

调小时0-23

tmin

49

调分钟0-59

tsecond

50

调秒0-59

fm

79

蜂鸣器,倒计时结束会响

dig_sel_n

111-114,129-132

控制数码位,只用1到6,7-8长暗,1和2代表秒,3和4代表分钟,5和6代表小时,中间有“.”来区分小时,分钟和秒数

seg_out

125-128,119-122

控制7段码

图2-1 变量清单

图2-2 mysystem的原理图

3、总体的实现过程。我们通过分块解决的方案,逐步实现所有功能,先实现的计数再实现的倒计时,再实现的计数结束后蜂鸣器响,再实现的计数器可以最大显示24小时再实现可以调时间,最后实现用“.“区分秒数分钟和小时。图3-1mysystem总体实现思路

图3-1 mysystem总体实现思路

4、分频器的实现。用到的需要分频成1s和1ms的两个分频器,前者给计数器使用,后者给7段码显示用,7段码显示的原理就是通过人眼的视觉停留快速刷新达到不动的效果。模块实现图4-1

图4-1 两个分频器的实现

5、计数器模块的实现。计数器内部分为计数和倒计时,实现的思路见图5-1。实现的时候会通过jishu和jishi这两个引脚的情况进行选择是倒计时还是计数,倒计时的时候数从59记到0的时候蜂鸣器会响。对于内部计数的时候要注意,计数的时候需要注意秒-分-小时之间的换算,当够60秒时分钟会进1,分钟够60的时候会进一,小时够24会清零,调时间的时候会搭配其余三个小模块进行工作。

图5-1 mysystem的原理图

6、段码显示模块。7段码译码器模块和输出模块并用,实现的思路见图6-1。

图6-1 7段码模块

六、实验讨论与总结

1.做数字系统设计的时候一定要注意系统和原理图设计的不同,本次实验是纯verilog代码,需要有完整的思路,学会的是自顶向下的设计思路,先从一个简单的小模块开始设计,逐步的增加功能

2.代码中的最需要注意的问题一定要设置好变量的宽度,尽量可以大一点但坚决不能小了,完美起见还是用多大设置多大,设计小了错误还不容易找错误

3.命名要符合代码的规范,要声明好输入的变量和输出的变量的,要设置好位数,位数匹配也是需要注意的

4.分频器模块的设置,1s的和1ms的异曲同工,区别在于分出来大小的不同

5.调时间的输入端口要连接在47-50这几个消抖的按钮上,不然调时间输入的时候会一下跳好几个数

6.计数器的设计是本实验的重点。在计数器设计上要明确设计的思路,倒计时和计数功能分开实现的同时要注意两者的共性

7.段码显示也是一个重点,需要用到译码器,附件一的代码通过设置一个译码器功能的函数,将数据的个位和十位分离进行调用处理,我还对段码显示的小点点进行了处理,也就是对小时分钟秒数进行了分割,便于观看

8.实验的优缺点:实验要求的基本功能全部实验,扩展功能也基本实现。后期会对写的Verilog程序进一步优化设计,进一步添加需要的功能,比如说在一个按键重复使用,我本次实验用到的端口比较多,解决这个问题会进一步节省端口。

附件一:程序源代码

1、mysystem程序清单如下:

//定义了一个模块系统,20mhz时钟脉冲,重置,暂停,蜂鸣器,计数(0-59),计时(倒计时),调时间,7段码,数码位

module mysystem (clkin,rst_n,zt,fm,jishu,jishi,thour,tmin,tsecond,seg_out,dig_sel_n);

//输入端口

input clkin,rst_n,zt,jishu,jishi,thour,tmin,tsecond;


//1ms的分频器

reg clk1ms;

//计数用

reg [17:0] cnt2;

//1ms----20MHZ入1000HZ输出

always @(posedge clkin or negedge rst_n)

begin

//如果重置的话

      if(!rst_n)

              cnt2 <=0;

//如果不重置的话

      else

         begin

                     if(cnt2 == 19_999)

                            cnt2 <=0;

                     else

                            cnt2 <= cnt2 + 1;

                     if (cnt2 <10_000)

                            clk1ms <= 1'b1;

                     else

                            clk1ms <= 1'b0;

           end

end


//分频得到1s的输出,七段码更替会用到

reg clk1S;

reg [24:0]cnt1;


//1s----20MHZ入1HZ输出

always @(posedge clkin or negedge rst_n)

begin

      if(!rst_n)

         cnt1 <= 0;

      else

         begin

                     if(cnt1 == 19_999_999)

                            cnt1 <=0;

                     else

                            cnt1 <= cnt1 + 1;

                     if (cnt1 <10_000_000)

                            clk1S <= 1'b1;

                     else

                            clk1S <= 1'b0;

               end

end


//6进制选择器,实现六个数码位的交替

reg [2:0]cnt22;

always @(posedge clk1ms)

begin

      if(!rst_n)

         cnt22 <= 0;

      else

         begin

                     if(cnt22 == 5)

                            cnt22 <=0;

                else

                            cnt22 <= cnt22 + 1;

                end

end



//时间调节

reg [5:0] cnt60_s;

reg [5:0] co1;

reg [4:0] myhour1;

always @(posedge thour or negedge rst_n)

begin

       if(!rst_n)

              myhour1<=0;

       else if(thour)

              begin

                     if(myhour1==23)

                            myhour1<=0;

                     else

                            myhour1<=myhour1+1;

              end


end




always @( posedge tmin or negedge rst_n)

begin

       if(!rst_n)

              co1<=0;

       else if(tmin)

       begin

              if(co1==59)

                     co1<=0;

              else

                     co1<=co1+1;

       end


end



always @(posedge tsecond or negedge rst_n)

begin

              if(!rst_n)

                     cnt60_s<=0;

              else if(tsecond)

                     begin

                            if(cnt60_s==59)

                                   cnt60_s<=0;

                            else

                            cnt60_s<=cnt60_s+1;

                     end

end

//******************计数器(0-59)秒(重复进行)******倒计时59-0(不重复)

output reg fm;//这是一个蜂鸣器

reg [5:0] rcnt60=6'b11_1011;//定义59

reg [5:0] cnt60;//记录秒数

reg [5:0] co;//记录分钟

reg [4:0] myhour;//记录小时

always @(posedge clk1S or negedge rst_n or posedge zt)

 begin

       //置零的时候会实现cnt60(0-59计数器)清0,实现rcnt60(计时器)恢复59,而且不响铃

      if(!rst_n)

           begin cnt60 <= 0;rcnt60<=6'b11_1011;fm<=0;co<=0;myhour<=0;end

   //暂停计时和计数

          else if(zt)

                     begin cnt60 <= cnt60; rcnt60<=rcnt60;

                            if(thour)

                                   myhour<=myhour1;

                            if(tmin)

                                   co<=co1;

                            if(tsecond)

                                   cnt60<=cnt60_s;

                                  

                                  

                      end

      else

              //看看是计时还是计数

              case({jishu,jishi})

              //当是00的时候处于暂停的状态,此时会把蜂鸣器fm设置为0,不响的状态

              2'b00:begin fm<=0;end

              //倒计时

       2'b01:begin

                            if(rcnt60 == 0)

                                   begin rcnt60<=0;fm<=1;cnt60<=rcnt60; end

                            else

                                   begin rcnt60 <= rcnt60 - 1;cnt60<=rcnt60; fm<=0;end

                      end

              //计数器

              2'b10: begin

                                   if(cnt60 == 59)

                                          begin cnt60<=0;

                                                 if(co==59)

                                                        begin

                                                               co<=0;

                                                               if(myhour==23)

                                                                      myhour<=0;

                                                               else

                                                                      myhour<=myhour+1;

                                                        end

                                                 else

                                                             co<=co+1;

      

                                       end

                                   else begin cnt60 <= cnt60 + 1; fm<=0; end

                        end

              endcase

end


//7段码译码器,这是定义了一个函数,4位的输入8位的输出

//4位会对应0到9,0000~1001,seg7就是七段码的输出,从后往前对应a,b,c,d,e,f,g,dp,fpga实验板是共阳极,也就是说输入0的时候才是有效的

output reg [7:0] seg_out;

output reg [7:0] dig_sel_n;

function [7:0] seg7;

       input [3:0] data;

       begin

       case(data)

               0:  seg7= 8'b11000000;

            1:  seg7= 8'b11111001;

            2:  seg7= 8'b10100100;

            3:  seg7= 8'b10110000;

            4:  seg7= 8'b10011001;

            5:  seg7= 8'b10010010;

            6:  seg7= 8'b10000010;

            7:  seg7= 8'b11111000;

            8:  seg7= 8'b10000000;

            9:  seg7= 8'b10010000; 

            default: seg7= 8'b11111111;

         endcase

    end

endfunction


//用来显示小点点,便于区分小时,分钟和秒

function [7:0] seg77;

       input [3:0] data_2;

       begin

       case(data_2)

               0:  seg77= 8'b01000000;

            1:  seg77= 8'b01111001;

            2:  seg77= 8'b00100100;

            3:  seg77= 8'b00110000;

            4:  seg77= 8'b00011001;

            5:  seg77= 8'b00010010;

            6:  seg77= 8'b00000010;

            7:  seg77= 8'b01111000;

            8:  seg77= 8'b00000000;

            9:  seg77= 8'b00010000; 

            default: seg77= 8'b01111111;

         endcase

    end

endfunction



always @(cnt22 ,cnt60,rst_n,myhour,co)

    begin

        if(!rst_n)

             begin    dig_sel_n <= 8'b11111111; seg_out <=8'b11111111; end       

        else

                     begin

                            case(cnt22)

//对计数器的十位和个位进行分离,交替闪烁

                            0:  begin dig_sel_n <= 8'b11111110; seg_out <= seg7(cnt60%10); end

                            1:  begin dig_sel_n <= 8'b11111101; seg_out <= seg7(cnt60/10);end

                            2:  begin dig_sel_n <= 8'b11111011; seg_out <= seg77(co%10); end

                            3:  begin dig_sel_n <= 8'b11110111; seg_out <= seg7(co/10);end

                            4:  begin dig_sel_n <= 8'b11101111; seg_out <= seg77(myhour%10); end

                            5:  begin dig_sel_n <= 8'b11011111; seg_out <= seg7(myhour/10);end

            default:

                begin dig_sel_n <= 8'b11111111; seg_out <= 8'b11111111;end

            endcase    

                     end

              end

             

endmodule


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简单点了

谢谢大佬

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值