其他分享
首页 > 其他分享> > FPGA学习之秒表

FPGA学习之秒表

作者:互联网

1、资源

   a、FPGA控制板;

   b、两个级联的74HC595控制 8段8位共阳极数码管;

        c、两个按键;

2、想法

  实现秒表功能;

  初始状态,秒表零。

  按下按键1:开始跑秒;

  再次按下按键1,停止跑秒;---->往后分两种情况:

    ---->a、再次按下按键1,继续跑秒;

    ---->b、再次按下按键2,秒表清零。

3、实现

3.1、模块划分

  a、时间模块:计时功能

  b、BCD码转换模块:将2进制转换成10进制;

  c、数码管动态显示模块;

  d、按键检测模块;

  e、整合模块。

3.2、具体实现

  此处补模块图

3.2.1、时间模块 

  板载时钟20ns周期,计算计数值如下表。

  输入:

    开始计时、停止计时、计时清零

  输出:

    1ms计时完成、时间值

  模块图

    

  代码:

  1 `timescale 1ns/10ps
  2 module ShiJian_JiShuQi(
  3     clk,                            
  4     rst_n,
  5     JiShuQi_KaiShi, 
  6     JiShuQi_TingZhi,
  7     JiShuQi_QingLing,
  8     JiShu_1ms_WanCheng,
  9     ShiJianZhi
 10 );
 11     input clk;
 12     input rst_n;
 13     input JiShuQi_KaiShi;           //开始计数
 14     input JiShuQi_TingZhi;            //暂停计数
 15     input JiShuQi_QingLing;          //清零计数器
 16     output JiShu_1ms_WanCheng;        //计数1ms完成
 17     output reg [22:0]ShiJianZhi;    //输出时间值 精确到ms
 18     
 19     reg JiShuQi_ZhuangTai;            //计时状态,计时置1,停止计时置0
 20     reg [5:0]JiShuQi_ns ;            //ns计数器
 21     reg [9:0]JiShuQi_us ;            //us计数器
 22     reg [9:0]JiShuQi_ms ;            //ms计数器
 23     reg [5:0]JiShuQi_s  ;            //s计数器
 24     reg [6:0]JiShuQi_min;            //分钟计数器
 25     
 26     wire JiShu_1us_WanCheng;        //完成1us计数,时间进位标志
 27 //    wire JiShu_1ms_WanCheng;      //完成1ms计数,时间进位标志
 28     wire JiShu_1s_WanCheng;       //完成1s计数,时间进位标志
 29     wire JiShu_1min_WanCheng;     //完成1min计数,时间进位标志
 30     wire JiShu_max;                    //记满120分钟,时间清零
 31     
 32     localparam                             //系统时钟20ns
 33         JiShuQi_ns_max     =    6'd49,        //1000ns    
 34         JiShuQi_us_max     =    10'd999,        //1000us
 35         JiShuQi_ms_max     =    10'd999,        //1000ms
 36         JiShuQi_s_max     =    6'd59,        //1s
 37         JiShuQi_min_max =    7'd120;        //120min
 38     //仿真     
 39 /*     localparam 
 40         JiShuQi_ns_max     =    6'd5,
 41         JiShuQi_us_max     =    10'd5,
 42         JiShuQi_ms_max     =    10'd5,
 43         JiShuQi_s_max     =    6'd5,
 44         JiShuQi_min_max =    7'd120; */
 45 
 46     assign  JiShu_1us_WanCheng    = JiShuQi_ns == JiShuQi_ns_max?1'b1:1'b0;//ns计数器记满时进位标志1
 47     assign  JiShu_1ms_WanCheng    = (JiShuQi_us == JiShuQi_us_max)&&JiShu_1us_WanCheng?1'b1:1'b0;//us
 48     assign  JiShu_1s_WanCheng    = (JiShuQi_ms == JiShuQi_ms_max)&&JiShu_1ms_WanCheng?1'b1:1'b0;
 49     assign  JiShu_1min_WanCheng = (JiShuQi_s     == JiShuQi_s_max)&&JiShu_1s_WanCheng?1'b1:1'b0;
 50     assign  JiShu_max               = (JiShuQi_min== JiShuQi_min_max)&&JiShu_1min_WanCheng?1'b1:1'b0;
 51     
 52     always@(posedge clk or negedge rst_n)
 53         if(!rst_n)
 54         #1     JiShuQi_ZhuangTai <= 1'b0;
 55         else if(JiShuQi_KaiShi)                //开始置1
 56         #1     JiShuQi_ZhuangTai <= 1'b1;
 57         else if(JiShuQi_TingZhi)            //停止置0
 58         #1     JiShuQi_ZhuangTai <= 1'b0;
 59         else
 60         #1     JiShuQi_ZhuangTai <= JiShuQi_ZhuangTai;
 61     //ns计数器
 62     always@(posedge clk or negedge rst_n)
 63         if(!rst_n)
 64         #1     JiShuQi_ns <= 6'd0;
 65         else if(JiShu_1us_WanCheng || JiShuQi_QingLing)
 66         #1     JiShuQi_ns <= 6'd0;
 67         else if(JiShuQi_ZhuangTai)
 68         #1     JiShuQi_ns <= JiShuQi_ns + 1'b1;
 69         else                                        //无计时状态时时间值保持
 70         #1     JiShuQi_ns <= JiShuQi_ns;
 71     //us计数器
 72     always@(posedge clk or negedge rst_n)
 73         if(!rst_n)
 74         #1     JiShuQi_us <= 10'd0;
 75         else if((JiShu_1ms_WanCheng&&JiShu_1us_WanCheng) || JiShuQi_QingLing)
 76         #1     JiShuQi_us <= 10'd0;
 77         else if(JiShuQi_ZhuangTai && JiShu_1us_WanCheng)
 78         #1     JiShuQi_us <= JiShuQi_us + 1'b1;
 79         else
 80         #1     JiShuQi_us <= JiShuQi_us;    
 81     //ms计数器
 82     always@(posedge clk or negedge rst_n)
 83         if(!rst_n)
 84         #1     JiShuQi_ms <= 10'd0;
 85         else if((JiShu_1s_WanCheng&&JiShu_1ms_WanCheng) || JiShuQi_QingLing)
 86         #1     JiShuQi_ms <= 10'd0;
 87         else if(JiShuQi_ZhuangTai && JiShu_1ms_WanCheng)
 88         #1     JiShuQi_ms <= JiShuQi_ms + 1'b1;
 89         else
 90         #1     JiShuQi_ms <= JiShuQi_ms;                
 91     //s计数器
 92     always@(posedge clk or negedge rst_n)
 93         if(!rst_n)
 94         #1     JiShuQi_s <= 6'd0;
 95         else if((JiShu_1min_WanCheng && JiShu_1s_WanCheng) || JiShuQi_QingLing)
 96         #1     JiShuQi_s <= 6'd0;
 97         else if(JiShuQi_ZhuangTai && JiShu_1s_WanCheng)
 98         #1     JiShuQi_s <= JiShuQi_s + 1'b1;
 99         else
100         #1     JiShuQi_s <= JiShuQi_s;        
101     //min计数器
102     always@(posedge clk or negedge rst_n)
103         if(!rst_n)
104         #1     JiShuQi_min <= 7'd0;
105         else if((JiShu_max&&JiShu_1min_WanCheng) || JiShuQi_QingLing)
106         #1     JiShuQi_min <= 7'd0;
107         else if(JiShuQi_ZhuangTai && JiShu_1min_WanCheng)
108         #1     JiShuQi_min <= JiShuQi_min + 1'b1;
109         else
110         #1     JiShuQi_min <= JiShuQi_min;
111     //输出时间值
112     always@(posedge clk or negedge rst_n)
113         if(!rst_n)
114         #1 ShiJianZhi <= 23'd0;
115         else if(JiShu_1ms_WanCheng)
116          #1 ShiJianZhi <= {JiShuQi_min,JiShuQi_s,JiShuQi_ms}; 
117         else
118         #1    ShiJianZhi <= ShiJianZhi;
119             
120 endmodule

 仿真:

 1 `timescale 1ns/10ps
 2 `define clk_period 20
 3 module ShiJian_JiShuQi_tb();
 4     reg clk ;
 5     reg rst_n;
 6     reg JiShuQi_KaiShi;
 7     
 8     initial clk = 0;
 9     always#(`clk_period/2) clk = ~clk;
10     
11     initial begin
12         JiShuQi_KaiShi = 0;
13         rst_n = 0;
14         #(`clk_period*2); rst_n = 1;
15         #(`clk_period*2);JiShuQi_KaiShi = 1;
16         #(`clk_period*1);JiShuQi_KaiShi = 0;
17                 
18         #(`clk_period*1000*10);
19         $stop;
20     end
21 ShiJian_JiShuQi ShiJian_JiShuQi(
22     .clk(clk),
23     .rst_n(rst_n),
24     .JiShuQi_KaiShi(JiShuQi_KaiShi), 
25     .JiShuQi_TingZhi(),
26     .JiShuQi_QingLing(),
27     .JiShu_1ms_WanCheng(),
28     .ShiJianZhi()
29 );
30 endmodule

仿真图:

 3.2.2 BCD转换模块

  此处参考:https://blog.csdn.net/xs20180801/article/details/84716098

  BCD转换模块作用是将输入的时间值【分-分-分-秒-秒-毫秒-毫秒-毫秒】转换成BCD码,共32位。

  BCD转换模块在此处分BCD转换模块和BCD控制模块。

  a、BCD转换模块:

  功能:即将输入的10位2进制数(此处去值最大的毫秒值,最大值为999)转换为【11:0】的BCD码--->【11:8】、【7:4】、【3:0】。

  输入:

    转换使能、待转换数值【9:0】

  输出:

    转换完成使能、BCD转换值【11:0】。

  b、BCD转换控制模块:

  功能:也就是依次将需要转换的数值【分分分】、【秒秒】、【毫秒毫秒毫秒】送入BCD转换模块,并取出BCD转换值组合后输出。此处也可以例化成3个BCD转换模块,同时转换。时间重要还是面积重要来取舍。

  输入:

    BCD转换使能(此处将计时器1ms计时完成信号做使能)

    待转换数值【22:0】(时间值)

  输出:

    转换完成使能

    BCD转换值【31:0】(完整值)。

    

  BCD转换模块代码

    

 1 `timescale 1ns/10ps
 2 module BCD_ZhuanHuan_module(
 3     clk,
 4     rst_n,
 5     BCD_KaiShi,
 6     BCD_DaiZhuanZhi,
 7     BCD_WanCheng,
 8     BCD_Zhi
 9 );
10     input clk;
11     input rst_n;
12     input BCD_KaiShi;                    //开始转换
13     input [9:0]BCD_DaiZhuanZhi;    //待转换数值
14     output reg BCD_WanCheng;        //本次转换完成
15     output reg [11:0]BCD_Zhi;        //BCD转换值
16     
17     reg [21:0]BCD_YiWei;                //10 + 3 * 4 = 22 位 结构【BCD值 + 原始值】
18     reg [3:0]BCD_JiShuQi;            //移位次数
19     reg ZhuanHuan_ZhuangTai;        //BCD转换状态
20     
21     localparam YiWeiZhi = 4'd10;    //计数10次:0~9移位;10值输出
22     wire ZhuanHuan_WanCheng;        //转换完成标志
23     
24     assign ZhuanHuan_WanCheng = BCD_JiShuQi == YiWeiZhi ? 1'b1:1'b0;//计数器计数10时使能
25     //
26     always@(posedge clk or negedge rst_n)
27         if(!rst_n)
28         #1    ZhuanHuan_ZhuangTai <= 1'b0;
29         else if(BCD_KaiShi)
30         #1    ZhuanHuan_ZhuangTai <= 1'b1;
31         else if(ZhuanHuan_WanCheng)
32         #1    ZhuanHuan_ZhuangTai <= 1'b0;
33         else
34         #1    ZhuanHuan_ZhuangTai <= ZhuanHuan_ZhuangTai;
35     //移位计数器
36     always@(posedge clk or negedge rst_n)
37         if(!rst_n)
38         #1    BCD_JiShuQi <= 4'd0;
39         else if(ZhuanHuan_WanCheng)
40         #1    BCD_JiShuQi <= 4'd0;
41         else if(ZhuanHuan_ZhuangTai)
42         #1    BCD_JiShuQi <= BCD_JiShuQi + 1'b1;
43         else 
44         #1    BCD_JiShuQi <= 4'd0;
45     //左移加3 此处用阻塞赋值
46     always@(posedge clk or negedge rst_n)
47         if(!rst_n)
48         #1    BCD_YiWei = 22'd0;
49         else if(BCD_KaiShi)                            //开始只能是一个脉冲
50         #1    BCD_YiWei = {12'd0,BCD_DaiZhuanZhi};//装载初始值
51         else if(ZhuanHuan_ZhuangTai && BCD_JiShuQi < YiWeiZhi)begin//0~9移位
52         #1    if(BCD_YiWei[21:18] >= 3'd5)  BCD_YiWei[21:18] = BCD_YiWei[21:18] + 2'd3;
53         #1    if(BCD_YiWei[17:14] >= 3'd5)  BCD_YiWei[17:14] = BCD_YiWei[17:14] + 2'd3;
54         #1    if(BCD_YiWei[13:10] >= 3'd5)  BCD_YiWei[13:10] = BCD_YiWei[13:10] + 2'd3;
55         #1    BCD_YiWei = BCD_YiWei << 1'b1;
56         end
57         else                        //清零
58         #1    BCD_YiWei = 22'd0;
59     //
60     always@(posedge clk or negedge rst_n)
61         if(!rst_n)
62         #1    BCD_Zhi <= 12'd0;
63         else if(ZhuanHuan_WanCheng)
64         #0.5    BCD_Zhi <= BCD_YiWei[21:10];
65         else
66         #1    BCD_Zhi <= 12'd0;
67     //
68     always@(posedge clk or negedge rst_n)//此处延迟一个时钟周期,与值一起送出去
69         if(!rst_n)
70         #1    BCD_WanCheng <= 1'b0;
71         else
72         #1    BCD_WanCheng <= ZhuanHuan_WanCheng;
73 endmodule

  BCD转换模块仿真

 1 `timescale 1ns/10ps
 2 `define clk_period 20
 3 module BCD_ZhuanHuan_module_tb();
 4     reg clk;
 5     reg rst_n;
 6     reg BCD_KaiShi;
 7     reg [9:0]BCD_DaiZhuanZhi;
 8     
 9     initial clk = 0;
10     always#(`clk_period/2) clk = ~clk;
11     
12     initial begin
13         rst_n = 0;
14         BCD_KaiShi = 0;
15         BCD_DaiZhuanZhi = 10'd0;
16         #(`clk_period*3) rst_n = 1;
17         #(`clk_period*3) ;
18         BCD_KaiShi = 1;    
19         BCD_DaiZhuanZhi = 10'd999;
20         #(`clk_period*1) ;
21         BCD_KaiShi = 0;
22         
23         #(`clk_period*20) ;
24         $stop;
25         
26         
27     end
28     
29     
30 BCD_ZhuanHuan_module BCD_ZhuanHuan_module(
31     .clk(clk),
32     .rst_n(rst_n),
33     .BCD_KaiShi(BCD_KaiShi),
34     .BCD_DaiZhuanZhi(BCD_DaiZhuanZhi),
35     .BCD_WanCheng(),
36     .BCD_Zhi()
37 );
38 endmodule

  BCD转换模块仿真图

     BCD控制模块代码

  1 `timescale 1ns/10ps
  2 module BCD_KongZhi_module(
  3     clk,
  4     rst_n,
  5     BCD_KongZhi_KaiShi,
  6     ShiJianZhi,
  7     BCD_ZhuanHuanZhi,
  8     BCD_ZhuanHuan_WanCheng
  9 );
 10     input clk;
 11     input rst_n;
 12     input BCD_KongZhi_KaiShi;            //此处接1ms转换完成信号
 13     input [22:0]ShiJianZhi;            
 14     output reg [31:0]BCD_ZhuanHuanZhi;
 15     output reg BCD_ZhuanHuan_WanCheng;
 16     
 17     localparam KongXian_ZhuangTai            =        2'b00,        //空闲状态
 18                  BCD_FuZhi_ZhuangTai       =         2'b01,        //给BCD转换模块赋值
 19         DengDaiZhuanHuan_ZhuangTai            =        2'b10;        //等待BCD转换模块转换完成
 20     reg[1:0]CS;
 21     reg[1:0]NS;
 22     reg[1:0]JiShuQi;
 23     wire BCD_WanCheng;
 24     wire [11:0]BCD_Zhi;
 25     reg BCD_KaiShi;
 26     reg[9:0]BCD_DaiZhuanZhi;
 27     reg[22:0]ShiJianZhi_JiCunQi;
 28     //1
 29     always@(posedge clk or negedge rst_n)
 30         if(!rst_n)
 31         #1    CS <= 2'd0;
 32         else
 33         #1    CS <= NS;
 34     //2
 35     always@(BCD_KongZhi_KaiShi,BCD_WanCheng,CS,JiShuQi)begin
 36         NS = 2'bxx;
 37         case(CS)
 38             KongXian_ZhuangTai            :
 39                 if(BCD_KongZhi_KaiShi)                //开始使能、状态改变
 40                     NS = BCD_FuZhi_ZhuangTai;
 41                 else
 42                     NS = KongXian_ZhuangTai;
 43             BCD_FuZhi_ZhuangTai         :
 44                 NS = DengDaiZhuanHuan_ZhuangTai;    //赋值后,直接进入等待转换状态
 45             DengDaiZhuanHuan_ZhuangTai    :begin
 46                 if(BCD_WanCheng && JiShuQi == 2'd2)//共需转换3次,若转换完,直接进入空闲状态
 47                     NS = KongXian_ZhuangTai;
 48                 else if(BCD_WanCheng && JiShuQi < 2'd2)//未转换完,再次进入赋值状态
 49                     NS = BCD_FuZhi_ZhuangTai;
 50                 else
 51                     NS = DengDaiZhuanHuan_ZhuangTai;
 52                 end
 53             default:NS = KongXian_ZhuangTai;
 54         endcase
 55     end
 56     //3
 57     always@(posedge clk or negedge rst_n)
 58         if(!rst_n)begin
 59             BCD_KaiShi <= 1'b0;
 60             JiShuQi <= 2'd0;                //计数器也在此处赋值
 61             BCD_ZhuanHuanZhi <= 32'd0;    //值整合也在此处实现
 62             BCD_ZhuanHuan_WanCheng <= 1'b0;
 63         end
 64         else begin
 65             case(CS)
 66                 KongXian_ZhuangTai:begin
 67                 #1    JiShuQi <= 2'd0;
 68                     BCD_KaiShi <= 1'b0;
 69                     BCD_ZhuanHuanZhi <= 32'd0;             //BCD转换值每次都清零
 70                     BCD_ZhuanHuan_WanCheng <= 1'b0;
 71                 end
 72                 BCD_FuZhi_ZhuangTai:begin
 73                 #1    BCD_KaiShi <= 1'b1;
 74                 end
 75                 DengDaiZhuanHuan_ZhuangTai:begin
 76                 #1    BCD_KaiShi <= 1'b0;
 77                     if(BCD_WanCheng && JiShuQi == 2'd0)begin
 78                         JiShuQi <= JiShuQi + 1'b1;
 79                         BCD_ZhuanHuanZhi[11:0] <= BCD_Zhi;
 80                     end
 81                     else if(BCD_WanCheng && JiShuQi == 2'd1)begin
 82                         JiShuQi <= JiShuQi + 1'b1;
 83                         BCD_ZhuanHuanZhi[19:12] <= BCD_Zhi[7:0];
 84                     end
 85                     else if(BCD_WanCheng && JiShuQi == 2'd2)begin
 86                         BCD_ZhuanHuanZhi[31:20] <= BCD_Zhi;
 87                         BCD_ZhuanHuan_WanCheng <= 1'b1;
 88                     end
 89                     else begin
 90                         JiShuQi <= JiShuQi;
 91                         BCD_ZhuanHuanZhi <= BCD_ZhuanHuanZhi;
 92                     end
 93                 end
 94                 default:begin 
 95                     BCD_KaiShi <= 1'b0;
 96                     JiShuQi <= 2'd0;
 97                     BCD_ZhuanHuanZhi <= 32'd0;
 98                     BCD_ZhuanHuan_WanCheng <= 1'b0;
 99                 end
100             endcase
101         end        
102     //时间值寄存
103     always@(posedge clk or negedge rst_n)
104         if(!rst_n)
105         #1    ShiJianZhi_JiCunQi <= 22'd0;
106         else if(BCD_KongZhi_KaiShi)
107         #1    ShiJianZhi_JiCunQi <= ShiJianZhi;
108         else
109         #1    ShiJianZhi_JiCunQi <= ShiJianZhi_JiCunQi;
110     //待转换数值,直接用查找表实现的。个人感觉比较直观些
111     always@(*)
112         case(JiShuQi)
113             2'd0:BCD_DaiZhuanZhi = ShiJianZhi_JiCunQi[9:0];        //转ms
114             2'd1:BCD_DaiZhuanZhi = {4'b0000,ShiJianZhi_JiCunQi[15:10]};
115             2'd2:BCD_DaiZhuanZhi = {3'b000,ShiJianZhi_JiCunQi[22:16]};
116             default:BCD_DaiZhuanZhi = 10'd0;
117         endcase
118 BCD_ZhuanHuan_module BCD_ZhuanHuan_module(
119     .clk(clk),
120     .rst_n(rst_n),
121     .BCD_KaiShi(BCD_KaiShi),
122     .BCD_DaiZhuanZhi(BCD_DaiZhuanZhi),
123     .BCD_WanCheng(BCD_WanCheng),
124     .BCD_Zhi(BCD_Zhi)
125 );
126 endmodule

  BCD控制模块仿真代码

 1 `timescale 1ns/10ps
 2 `define clk_period 20
 3 module BCD_KongZhi_module_tb();
 4     reg clk;
 5     reg rst_n;
 6     reg KaiShi;
 7     reg [22:0]ShiJianZhi;
 8     initial clk = 1;
 9     always#(`clk_period/2) clk = ~clk;
10     
11     initial begin
12         rst_n = 0;
13         KaiShi = 0;
14         ShiJianZhi = 23'd0;
15         #(`clk_period*2) rst_n = 1;                //时间值:12:58:332
16         #(`clk_period*5) ;KaiShi = 1; ShiJianZhi = 23'b000_1100_11_1010_01_0100_1100;
17         #(`clk_period*1) KaiShi = 0;
18         #(`clk_period*80);
19         
20         KaiShi = 1; ShiJianZhi = 23'b000_1101_1010_1001_0100_1111;
21         #(`clk_period*1) KaiShi = 0;
22         #(`clk_period*80);
23         
24         $stop;
25     end
26     
27     
28 BCD_KongZhi_module tt(
29     .clk(clk),
30     .rst_n(rst_n),
31     .BCD_KongZhi_KaiShi(KaiShi),
32     .ShiJianZhi(ShiJianZhi ),
33 
34     .BCD_ZhuanHuanZhi(),
35     .BCD_ZhuanHuan_WanCheng()
36 );
37 endmodule

  BCD控制模块仿真图

 转换周期860ns,满足计时器的要求的  

 3.2.3、数码管动态显示模块

  74hc595本身有两个时钟频率,一个是移位时钟的频率,一个是寄存器(显示)时钟的频率。

  数据输入的频率是1000HZ,也就是BCD转换完成频率

  几个显示频率计算如下

  

  模块划分

  a、单数码管显示;

  b、多数码管动态显示;

  单数码管显示:(74HC595单字符显示)

  条件:

  74HC595

        8个位置

        单字符显示。

  输入:

  待显示字符;

        待显示位置。

  输出:

        移位时钟

        显示时钟

        串行值

        显示完成,也就是动态显示时,需要知道的一个信号 

  需要处理的:

  上级系统输入信号

        待显示字符

        待显示位置

  上面两个上级系统输入信息要求

  1、  上级系统需要将值一直保持;

  2、  寄存该值,一直到完成一次显示,再次取值。

  如果采用第二种方式,就要有个取值时机。在模块内部加一个计数器,或者利用移位时钟,在完成16次移位后,也是完成一次移位后,再重新取值。

  输出信号

         两个时钟的信号

         由上表获得的信息(芯片信息表,不插图):

         移位时钟的频率最大是4mhz(按最小的算)。时长也就是250ns 且高电平需要保持110ns的时间。

         显示时钟:因为我们这里要完整的显示一次,需要先移位16次,再显示,就是和移位时钟保持16倍的关系即可,也就是16*4mhz,且高电平也要有110ns的保持时间。

         移位时钟置高之前,待移位的数值应该保持75ns至少

         更新时钟置高之前,移位时钟至少需要走过半个时钟周期。

         移位时钟:查数据表直到移位频率最大值 至少有4MHZ

   这里有个想法,计数移位时钟,计数到17,再送一个显示时钟。

 直接贴代码:

  

 1 module SuMaGuan_XianShi(
 2     clk,
 3     rst_n,
 4     XinXi,
 5     XianShi_WanCheng,
 6     YiWeiShiZhong,
 7     XianShiShiZhong,
 8     ChuanHangZhi
 9 );
10     input clk;
11     input rst_n;
12     input [15:0]XinXi;                //段选编码+位选值顺序也是这样
13     output XianShi_WanCheng;        //完成一次编码值的显示
14     output YiWeiShiZhong;
15     output XianShiShiZhong;
16     output reg ChuanHangZhi;
17 
18     reg[7:0]JiShuQi_YWPL;            //移位时钟频率计数器,计数值12,频率=4mhz(稍微小)
19     reg[4:0]JiShuQi_YWCS;            //移位时钟次数计数器,记录移位时钟的次数。
20     reg[15:0]XinXi_JCQ;                //一次移位操作前,先寄存一次信息值
21     
22     localparam YWPL   =  8'd12;    //移位时钟频率 4mhz(稍微小),高低电平1:1
23 /*     wire [7:0]YWPL;
24     wire [31:0]ttt;
25     assign YWPL = ttt[7:0]; */
26     localparam YWCS   =  5'd18;    //18次为一个字符的显示频率,0.222mhz 
27     wire YWPL_JM;                        //JiShuQi_YWPL计数器记满标记
28     wire YWCS_JM;                        //JiShuQi_YWCS计数器记满标记
29     assign YWPL_JM = JiShuQi_YWPL == YWPL ? 1'b1:1'b0;//记满标记1
30     assign YWCS_JM = JiShuQi_YWCS == YWCS ? 1'b1:1'b0;//记满标记1
31     //
32     always@(posedge clk or negedge rst_n)//移位计数器记满置0,持续计数
33         if(!rst_n)
34             JiShuQi_YWPL <= 8'd0;    
35         else if(YWPL_JM) 
36             JiShuQi_YWPL <= 8'd0;
37         else
38             JiShuQi_YWPL <= JiShuQi_YWPL + 1'b1;
39     //        
40     always@(posedge clk or negedge rst_n)//计数器记满置0,持续计数
41         if(!rst_n)
42             JiShuQi_YWCS <= 5'd0;    
43         else if(YWCS_JM)//最大计数值也要持续一个移位频率后才清零 
44             JiShuQi_YWCS <= 5'd0;
45         else if(JiShuQi_YWPL == (YWPL >>1'b1)) 
46             JiShuQi_YWCS <= JiShuQi_YWCS + 1'b1;
47         else
48             JiShuQi_YWCS <= JiShuQi_YWCS;        
49     //
50     always@(posedge clk or negedge rst_n)
51         if(!rst_n)
52             XinXi_JCQ <= 16'd0;
53         else if(!(JiShuQi_YWPL||JiShuQi_YWCS))    //取值时机,在双计数器都是0时取新值
54             XinXi_JCQ <= XinXi;
55         else
56             XinXi_JCQ <= XinXi_JCQ;
57     //
58     assign YiWeiShiZhong = (JiShuQi_YWPL <= (YWPL >>1'b1))&&(JiShuQi_YWCS <= 4'd15) ? 1'b1:1'b0;
59     assign XianShiShiZhong = (JiShuQi_YWCS == 5'd17) ? 1'b1:1'b0;
60     assign XianShi_WanCheng = (YWCS_JM ) ?1'b1:1'b0;
61     //串行值 做一个查找表吧
62     always@(*)
63         case(JiShuQi_YWCS)
64             4'd00:ChuanHangZhi = XinXi_JCQ[15];    //段选编码dp h
65             4'd01:ChuanHangZhi = XinXi_JCQ[14]; //段选编码g
66             4'd02:ChuanHangZhi = XinXi_JCQ[13]; //段选编码f
67             4'd03:ChuanHangZhi = XinXi_JCQ[12]; //段选编码e
68             4'd04:ChuanHangZhi = XinXi_JCQ[11]; //段选编码d
69             4'd05:ChuanHangZhi = XinXi_JCQ[10]; //段选编码c
70             4'd06:ChuanHangZhi = XinXi_JCQ[09]; //段选编码b
71             4'd07:ChuanHangZhi = XinXi_JCQ[08]; //段选编码a
72             4'd08:ChuanHangZhi = XinXi_JCQ[07]; //位选信号8
73             4'd09:ChuanHangZhi = XinXi_JCQ[06]; //位选信号7
74             4'd10:ChuanHangZhi = XinXi_JCQ[05]; //位选信号6
75             4'd11:ChuanHangZhi = XinXi_JCQ[04]; //位选信号5
76             4'd12:ChuanHangZhi = XinXi_JCQ[03]; //位选信号4
77             4'd13:ChuanHangZhi = XinXi_JCQ[02]; //位选信号3
78             4'd14:ChuanHangZhi = XinXi_JCQ[01]; //位选信号2
79             4'd15:ChuanHangZhi = XinXi_JCQ[00]; //位选信号1
80             default:ChuanHangZhi = 1'b0;            //默认情况置0
81         endcase    
82         
83 /* tz tz(
84     .probe(),
85     .source(ttt)
86     );  */
87 endmodule
  1 module DongTai_ShuMaGuan(
  2     clk,
  3     rst_n,
  4     XianShiZhi,
  5     XianShiZhi_En,
  6     XianShiShiZhong,
  7     ChuanHangZhi,
  8    YiWeiShiZhong
  9 );
 10     input clk;
 11     input rst_n;
 12     input[31:0]XianShiZhi;        //8个数码管依次待显示的BCD值 从【高位-->低位】
 13     input XianShiZhi_En;            //取待显示值的使能
 14     output XianShiShiZhong;
 15     output ChuanHangZhi;
 16     output YiWeiShiZhong;
 17 
 18     wire XianShi_WanCheng;        //完成一个数码管的显示
 19     wire [15:0]XinXi;                //段选编码+位选值顺序也是这样    
 20 
 21     reg [2:0]JiShuQi;                    //循环记录显示了几个数码管
 22     reg [31:0]XianShiZhi_r1;        //显示值存储器1
 23     wire[31:0]XianShiZhi_r2;        //显示值存储器2
 24     wire XianShi_1Lun;                //数码管显示完一轮 JiShuQi== 3'd7 && XianShi_WanCheng
 25     reg [7:0]DuanXuanXinHao;        //待显示数码管编码
 26     reg [7:0]WeiXuanXinHao;            //待显示数码管位置信号
 27     reg[3:0]DaiXianShiZhi;            //待显示数值
 28     //
 29     always@(posedge clk or negedge rst_n)
 30         if(!rst_n)
 31             XianShiZhi_r1 <= 32'd0;        
 32         else if(XianShiZhi_En)//取值使能来的时候先存值
 33             XianShiZhi_r1 <= XianShiZhi;        
 34         else
 35             XianShiZhi_r1 <= XianShiZhi_r1;
 36     //
 37     assign XianShi_1Lun =  (JiShuQi== 3'd7 && XianShi_WanCheng) ? 1'b1:1'b0;
 38     //
 39     assign XianShiZhi_r2 = XianShi_1Lun ? XianShiZhi_r1:XianShiZhi_r2;//判断有无显示完一轮,若显示完一轮,就取XianShiZhi_r1,若没有,就先将一轮显示完,初始时会出现未知
 40     //
 41     always@(posedge clk or negedge rst_n)
 42         if(!rst_n)
 43             JiShuQi <= 3'd0;
 44         else if(XianShi_WanCheng) //显示完一个数码管记一次值
 45             JiShuQi <= JiShuQi + 1'b1;
 46         else                                //此处未记满清零是因为刚好只能记到7
 47             JiShuQi <= JiShuQi;
 48     
 49     //位选查找表
 50     always@(*)
 51         case(JiShuQi)
 52              4'd 0: WeiXuanXinHao = 8'b0000_0001;
 53              4'd 1: WeiXuanXinHao = 8'b0000_0010;
 54              4'd 2: WeiXuanXinHao = 8'b0000_0100;
 55              4'd 3: WeiXuanXinHao = 8'b0000_1000;
 56              4'd 4: WeiXuanXinHao = 8'b0001_0000;
 57              4'd 5: WeiXuanXinHao = 8'b0010_0000;
 58              4'd 6: WeiXuanXinHao = 8'b0100_0000;
 59              4'd 7: WeiXuanXinHao = 8'b1000_0000;
 60              default:WeiXuanXinHao = 8'b0000_0000;
 61         endcase
 62     //时间值查找表
 63     always@(*)
 64         case(JiShuQi)
 65              4'd 0: DaiXianShiZhi = XianShiZhi_r2[3:0];
 66              4'd 1: DaiXianShiZhi = XianShiZhi_r2[7:4];
 67              4'd 2: DaiXianShiZhi = XianShiZhi_r2[11:8]; 
 68              4'd 3: DaiXianShiZhi = XianShiZhi_r2[15:12];
 69              4'd 4: DaiXianShiZhi = XianShiZhi_r2[19:16];
 70              4'd 5: DaiXianShiZhi = XianShiZhi_r2[23:20];
 71              4'd 6: DaiXianShiZhi = XianShiZhi_r2[27:24];
 72              4'd 7: DaiXianShiZhi = XianShiZhi_r2[31:28];
 73              default:DaiXianShiZhi = 4'd0;
 74         endcase
 75     always@(*)
 76         case(DaiXianShiZhi)
 77                 4'h0 : DuanXuanXinHao = 8'hc0 ;
 78                 4'h1 : DuanXuanXinHao = 8'hf9 ;
 79                 4'h2 : DuanXuanXinHao = 8'ha4 ;
 80                 4'h3 : DuanXuanXinHao = 8'hb0 ;
 81                 4'h4 : DuanXuanXinHao = 8'h99 ;
 82                 4'h5 : DuanXuanXinHao = 8'h92 ;
 83                 4'h6 : DuanXuanXinHao = 8'h82 ;
 84                 4'h7 : DuanXuanXinHao = 8'hf8 ;
 85                 4'h8 : DuanXuanXinHao = 8'h80 ;
 86                 4'h9 : DuanXuanXinHao = 8'h90 ;
 87                 4'ha : DuanXuanXinHao = 8'h88 ;
 88                 4'hb : DuanXuanXinHao = 8'h83 ;
 89                 4'hc : DuanXuanXinHao = 8'hc6 ;
 90                 4'hd : DuanXuanXinHao = 8'ha1 ;
 91                 4'he : DuanXuanXinHao = 8'h86 ;
 92                 4'hf : DuanXuanXinHao = 8'h8e ;
 93             default:DuanXuanXinHao = 8'hff;
 94         endcase
 95     
 96     assign XinXi = {DuanXuanXinHao,WeiXuanXinHao};
 97 SuMaGuan_XianShi SuMaGuan_XianShi(
 98     .clk(clk),
 99     .rst_n(rst_n),
100     .XinXi(XinXi),
101     .XianShi_WanCheng(XianShi_WanCheng),
102     .YiWeiShiZhong(YiWeiShiZhong),
103     .XianShiShiZhong(XianShiShiZhong),
104     .ChuanHangZhi(ChuanHangZhi)
105 );
106 endmodule

//此模块只为测试数码管仿真用
1 module top( 2 clk, 3 rst_n, 4 YiWeiShiZhong, 5 XianShiShiZhong, 6 ChuanHangZhi 7 ); 8 input clk; 9 input rst_n; 10 output YiWeiShiZhong; 11 output XianShiShiZhong; 12 output ChuanHangZhi; 13 14 // wire [15:0]XinXi; //段选编码+位选值顺序也是这样 15 // wire XianShi_WanCheng; //完成一次编码值的显示 16 17 // wire [31:0]XianShiZhi; 18 19 DongTai_ShuMaGuan DongTai_ShuMaGuan( 20 .clk(clk), 21 .rst_n(rst_n), 22 .XianShiZhi(32'h12345678), 23 .XianShiZhi_En(1'b1), 24 .XianShiShiZhong(XianShiShiZhong), 25 .ChuanHangZhi(ChuanHangZhi), 26 .YiWeiShiZhong(YiWeiShiZhong) 27 ); 28 /* SuMaGuan_XianShi SuMaGuan_XianShi( 29 .clk(clk), 30 .rst_n(rst_n), 31 .XinXi(16'h0010), 32 .XianShi_WanCheng(), 33 .YiWeiShiZhong(YiWeiShiZhong), 34 .XianShiShiZhong(XianShiShiZhong), 35 .ChuanHangZhi(ChuanHangZhi) 36 ); */ 37 /* tz tz( 38 .probe(), 39 .source(XianShiZhi) 40 ); */ 41 42 /* input [0:0] probe; 43 output [15:0] source; */ 44 45 endmodule

仿真:

 1 `timescale 1ns/10ps
 2 `define clk_period 20
 3 module top_tb();
 4     reg clk;
 5     reg rst_n;
 6     
 7     initial clk = 1;
 8     always#(`clk_period/2) clk = ~clk;
 9     
10     initial begin
11         rst_n = 0;
12         #(`clk_period*2) rst_n = 1;
13         #(`clk_period*1000*8);
14         $stop;
15     end
16     
17 top top(
18     .clk(clk),
19     .rst_n(rst_n),
20     .YiWeiShiZhong(),
21     .XianShiShiZhong(),
22     .ChuanHangZhi()
23 );
24 endmodule

仿真图如下

 

 3.2.4 按键检测模块 (省略)

 3.2.5整合模块

  此模块一个连接整合的作用,还有个就是状态机

直接贴代码

  

  1 `timescale 1ns/10ps
  2 module ZhengHe(
  3     clk,
  4     rst_n,
  5     AnJian_ShuRu1,
  6     AnJian_ShuRu2,
  7     ChuanHangZhi,
  8     YiWeiShiZhong,
  9     XianShiShiZhong
 10  );
 11 
 12     input clk;
 13     input rst_n;
 14     input AnJian_ShuRu1;
 15     input AnJian_ShuRu2;
 16     output ChuanHangZhi;
 17     output YiWeiShiZhong;
 18     output XianShiShiZhong;    
 19 
 20     wire AnJian_YouXiao1;
 21     wire AnJian_YouXiao2;
 22     wire AnJian_ZhuangTai1;
 23     wire AnJian_ZhuangTai2;
 24     reg KaiShi_JiShi;
 25     reg TingZhi_JiShi;
 26     reg QingLing_ShiJian;
 27     wire JiShu_1ms_WanCheng;
 28     wire [22:0]ShiJianZhi;
 29     wire [31:0]BCD_ZhuanHuanZhi;  //时机情况
 30     wire BCD_ZhuanHuan_WanCheng;
 31     
 32     reg [2:0]CS;
 33     reg [2:0]NS;
 34     localparam     KongXian_ZhuangTai    = 3'b000,
 35                     JiShi_ZhuangTai        = 3'b001,
 36                     ZanTing_ZhuangTai        = 3'b010,
 37                     QingLing_ZhuangTai    = 3'b100;
 38 //
 39     always@(posedge clk or negedge rst_n)
 40         if(!rst_n)
 41             CS <= 3'd0;    
 42         else 
 43             CS <= NS;
 44 //
 45     always@(CS,AnJian_YouXiao1,AnJian_YouXiao2,AnJian_ZhuangTai1,AnJian_ZhuangTai2)begin
 46         NS = 3'bxxx;
 47         case(CS)
 48             KongXian_ZhuangTai    :
 49                 if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 50                     NS = JiShi_ZhuangTai;
 51                 else
 52                     NS = KongXian_ZhuangTai;
 53             JiShi_ZhuangTai        :
 54                 if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 55                     NS = ZanTing_ZhuangTai;
 56                 else
 57                     NS = JiShi_ZhuangTai;
 58             ZanTing_ZhuangTai        :begin
 59                 if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 60                     NS = JiShi_ZhuangTai;
 61                 else if(AnJian_YouXiao2&&AnJian_ZhuangTai2)
 62                     NS = QingLing_ZhuangTai;
 63                 else
 64                     NS = ZanTing_ZhuangTai;
 65             end
 66             QingLing_ZhuangTai    :
 67                 NS = KongXian_ZhuangTai;
 68             default:NS = KongXian_ZhuangTai;
 69         endcase
 70     end
 71 //3
 72     always@(posedge clk or negedge rst_n)
 73         if(!rst_n)begin
 74             KaiShi_JiShi <= 1'b0;
 75             TingZhi_JiShi <= 1'b0;
 76             QingLing_ShiJian <= 1'b0;
 77         end
 78         else begin
 79             case(CS)
 80                 KongXian_ZhuangTai    :begin
 81                     QingLing_ShiJian <= 1'b0;
 82                     if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 83                         KaiShi_JiShi <= 1'b1;
 84                     else
 85                         ;
 86                 end
 87                 JiShi_ZhuangTai        :begin
 88                     KaiShi_JiShi <= 1'b0;
 89                     if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 90                         TingZhi_JiShi <= 1'b1;
 91                     else
 92                         ;
 93                 end
 94                 ZanTing_ZhuangTai        :begin
 95                     TingZhi_JiShi <= 1'b0;
 96                     if(AnJian_YouXiao1&&AnJian_ZhuangTai1)
 97                         KaiShi_JiShi <= 1'b1;
 98                     else if(AnJian_YouXiao2&&AnJian_ZhuangTai2)
 99                         QingLing_ShiJian <= 1'b1;
100                     else
101                         ;
102                 end
103                 QingLing_ZhuangTai    :
104                     QingLing_ShiJian <= 1'b0;
105                 default:begin
106                     KaiShi_JiShi <= 1'b0;
107                     TingZhi_JiShi <= 1'b0;
108                     QingLing_ShiJian <= 1'b0;
109                 end
110             endcase
111         end
112             
113     
114     
115     
116 DanAnJianJianCe_module AnJian1(
117     .clk(clk),
118     .rst_n(rst_n),
119     .JianCe_En(1'b1),
120     .AnJian_ShuRu(AnJian_ShuRu1),
121     .AnJian_YouXiao(AnJian_YouXiao1),
122     .AnJian_ZhuangTai(AnJian_ZhuangTai1)
123 );
124 DanAnJianJianCe_module AnJian2(
125     .clk(clk),
126     .rst_n(rst_n),
127     .JianCe_En(1'b1),
128     .AnJian_ShuRu(AnJian_ShuRu2),
129     .AnJian_YouXiao(AnJian_YouXiao2),
130     .AnJian_ZhuangTai(AnJian_ZhuangTai2)
131 );
132 
133 ShiJian_JiShuQi ShiJian_JiShuQi(
134     .clk(clk),
135     .rst_n(rst_n),
136     .JiShuQi_KaiShi(KaiShi_JiShi), 
137     .JiShuQi_TingZhi(TingZhi_JiShi),
138     .JiShuQi_QingLing(QingLing_ShiJian),
139     .JiShu_1ms_WanCheng(JiShu_1ms_WanCheng),
140     .ShiJianZhi(ShiJianZhi)
141 );
142 
143 BCD_KongZhi_module BCD_KongZhi_module(
144     .clk(clk),
145     .rst_n(rst_n),
146     .BCD_KongZhi_KaiShi(JiShu_1ms_WanCheng),
147     .ShiJianZhi(ShiJianZhi ),
148     .BCD_ZhuanHuanZhi(BCD_ZhuanHuanZhi),
149     .BCD_ZhuanHuan_WanCheng(BCD_ZhuanHuan_WanCheng)
150 );
151     wire [31:0]BCD_ZhuanHuanZhi_r;
152     assign BCD_ZhuanHuanZhi_r = QingLing_ShiJian ? 32'd0: BCD_ZhuanHuan_WanCheng ? BCD_ZhuanHuanZhi :BCD_ZhuanHuanZhi_r;
153 
154 DongTai_ShuMaGuan DongTai_ShuMaGuan(
155     .clk(clk),
156     .rst_n(rst_n),
157     .XianShiZhi(BCD_ZhuanHuanZhi_r),
158     .XianShiZhi_En(BCD_ZhuanHuan_WanCheng||QingLing_ShiJian),
159     .XianShiShiZhong(XianShiShiZhong),
160     .ChuanHangZhi(ChuanHangZhi),
161    .YiWeiShiZhong(YiWeiShiZhong)
162 );
163 endmodule

就不仿真了,直接放实物图。

 

标签:FPGA,clk,BCD,学习,WanCheng,rst,秒表,reg,JiShuQi
来源: https://www.cnblogs.com/wxh8821/p/15107587.html