1. 程式人生 > 其它 >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

就不模擬了,直接放實物圖。