基于FPGA的数字秒表设计

硬件平台:DE2-115

软件环境:Quartus II 15.1

      采样了较为简单的计数方法,详细代码就不讲解了,分为三个模块,一个是计数模块 count.v,一个是显示模块 disp.v,还有一个是顶层模块 miaobiao.v。有清零按键和暂停拨码开关。

顶层模块:

 1 module miaobiao(
 2   clk,
 3   rst_n,
 4   pause,
 5   
 6   Hex0,
 7   Hex1,
 8   Hex2,
 9   Hex3,
10   Hex4,
11   Hex5,
12 );
13 
14 input clk;
15 input rst_n;
16 input pause;
17 
18 output[6:0] Hex0;
19 output[6:0] Hex1;
20 output[6:0] Hex2;
21 output[6:0] Hex3;
22 output[6:0] Hex4;
23 output[6:0] Hex5;
24 
25  wire[3:0]h_sec_h;
26  wire[3:0]h_sec_l;
27  
28  wire[3:0]sec_h;
29  wire[3:0]sec_l;
30 
31  wire[3:0]fen_h;
32  wire[3:0]fen_l;
33 
34 count u0(
35   .clk(clk),
36   .rst_n(rst_n),
37   .pause(pause),
38   
39   .h_sec_h(h_sec_h),
40   .h_sec_l(h_sec_l),
41   
42   .sec_h(sec_h),
43   .sec_l(sec_l),
44   
45   .fen_h(fen_h),
46   .fen_l(fen_l)
47 );
48 
49 disp u1(
50   
51   .h_sec_l(h_sec_l),
52   .h_sec_h(h_sec_h),
53   
54   .sec_l(sec_l),
55   .sec_h(sec_h),
56   
57   .fen_l(fen_l),
58   .fen_h(fen_h),
59   
60   .Hex0(Hex0),
61   .Hex1(Hex1),
62   .Hex2(Hex2),
63   .Hex3(Hex3),
64   .Hex4(Hex4),
65   .Hex5(Hex5)
66 );
67 
68 endmodule
miaobiao.v

计数模块:

  1 module count(
  2   clk,
  3   rst_n,
  4   pause,
  5   
  6   h_sec_h,
  7   h_sec_l,
  8   
  9   sec_h,
 10   sec_l,
 11   
 12   fen_h,
 13   fen_l
 14 );
 15 
 16 input clk;
 17 input rst_n;
 18 input pause;              //pause为0时正常计数,为1时暂停计数
 19 
 20 output reg[3:0] h_sec_h;  //百分秒低位
 21 output reg[3:0] h_sec_l;  //百分秒高位
 22 
 23 output reg[3:0] sec_h;    //秒高位
 24 output reg[3:0] sec_l;    //秒低位
 25 
 26 output reg[3:0] fen_h;    //分低位
 27 output reg[3:0] fen_l;    //分高位
 28 
 29 reg flag1;       //flag1为百分秒向秒的进位
 30 reg flag2;       //flag2为秒向分的进位
 31 reg[27:0] cnt;   //
 32 reg clk_100hz;
 33 
 34 /*  100hz 分频  */
 35 always@(posedge clk or negedge rst_n)
 36   if(!rst_n)
 37     cnt <= 28'd0;
 38   else if(cnt == 249999)
 39     cnt <= 28'd0;
 40   else
 41     cnt <= cnt + 1'b1;
 42      
 43 always@(posedge clk or negedge rst_n)
 44   if(!rst_n)
 45     clk_100hz <= 1'b0;
 46   else if(cnt == 249999)
 47     clk_100hz <= !clk_100hz;
 48   else
 49     clk_100hz <= clk_100hz;
 50 
 51 /* 百分秒计数进程,每计满100,flag1产生一个进位 */
 52 always@(posedge clk_100hz or negedge rst_n)
 53   begin
 54     if(!rst_n) begin  
 55        {h_sec_h,h_sec_l} <= 8'h00;
 56         flag1 <= 1'b0;
 57         end
 58      else if(!pause) begin      
 59        if(h_sec_l == 9) begin
 60           h_sec_l <= 4'd0;
 61           if(h_sec_h == 9) begin
 62             h_sec_h <= 4'd0;
 63              flag1 <= 1'b1;
 64              end
 65           else
 66             h_sec_h <= h_sec_h + 1'b1;
 67         end
 68      else begin
 69        h_sec_l <= h_sec_l + 1'b1;
 70        flag1 <= 1'b0;
 71        end
 72      end
 73   end
 74   
 75 /* 秒计数进程,每计满60,flag2产生一个进位 */
 76 always@(posedge flag1 or negedge rst_n)
 77   begin
 78     if(!rst_n) begin
 79        {sec_h,sec_l} <= 8'h00;
 80         flag2 <= 0;
 81         end
 82      else if(sec_l == 9) begin
 83        sec_l <= 4'd0;
 84         if(sec_h == 5) begin
 85           sec_h <= 4'd0;
 86           flag2 <= 1'b1;
 87           end
 88         else
 89           sec_h <= sec_h + 1'b1;
 90        end
 91      else begin
 92        sec_l <= sec_l + 1'b1;
 93         flag2 <= 1'b0;
 94      end
 95   end
 96   
 97 /* 分计数进程,每计数满60,系统自动清零 */
 98 always@(posedge flag2 or negedge rst_n)
 99   begin
100     if(!rst_n) begin
101        {fen_h,fen_l} <= 8'h00;
102         end
103      else if(fen_l == 9) begin
104        fen_l <= 4'd0;
105         if(fen_h == 5)
106           fen_h <= 4'd0;
107         else
108           fen_h <= fen_h + 1'b1;
109         end
110      else
111        fen_l <= fen_l + 1'b1;
112     end
113 endmodule
114 
115     
116     
117        
118       
count.v

显示模块:

  1 module disp(
  2   
  3   h_sec_l,
  4   h_sec_h,
  5   
  6   sec_l,
  7   sec_h,
  8   
  9   fen_l,
 10   fen_h,
 11   
 12   Hex0,
 13   Hex1,
 14   Hex2,
 15   Hex3,
 16   Hex4,
 17   Hex5,
 18 );
 19 
 20 input[3:0] h_sec_h;
 21 input[3:0] h_sec_l;
 22 
 23 input[3:0] sec_h;
 24 input[3:0] sec_l;
 25 
 26 input[3:0] fen_h;
 27 input[3:0] fen_l;
 28 
 29 output reg[6:0] Hex0;
 30 output reg[6:0] Hex1;
 31 output reg[6:0] Hex2;
 32 output reg[6:0] Hex3;
 33 output reg[6:0] Hex4;
 34 output reg[6:0] Hex5;
 35 
 36 always@(*)    //百分秒个位控制
 37   begin
 38     case(h_sec_l)
 39        0:Hex0 <= 7'b1000000;  //0
 40       1:Hex0 <= 7'b1111001;  //1
 41       2:Hex0 <= 7'b0100100;  //2
 42       3:Hex0 <= 7'b0110000;  //3
 43       4:Hex0 <= 7'b0011001;  //4
 44       5:Hex0 <= 7'b0010010;  //5
 45       6:Hex0 <= 7'b0000010;  //6
 46       7:Hex0 <= 7'b1111000;  //7
 47       8:Hex0 <= 7'b0000000;  //8
 48       9:Hex0 <= 7'b0010000;  //9
 49         default:Hex0 <= 7'b1000000;  //0
 50      endcase
 51   end
 52 
 53 always@(*)    //百分秒十位控制
 54   begin
 55     case(h_sec_h)
 56        0:Hex1 <= 7'b1000000;  //0
 57       1:Hex1 <= 7'b1111001;  //1
 58       2:Hex1 <= 7'b0100100;  //2
 59       3:Hex1 <= 7'b0110000;  //3
 60       4:Hex1 <= 7'b0011001;  //4
 61       5:Hex1 <= 7'b0010010;  //5
 62       6:Hex1 <= 7'b0000010;  //6
 63       7:Hex1 <= 7'b1111000;  //7
 64       8:Hex1 <= 7'b0000000;  //8
 65       9:Hex1 <= 7'b0010000;  //9
 66         default:Hex1 <= 7'b1000000;  //0
 67      endcase
 68   end
 69   
 70 always@(*)    //
 71   begin
 72     case(sec_l)
 73        0:Hex2 <= 7'b1000000;  //0
 74       1:Hex2 <= 7'b1111001;  //1
 75       2:Hex2 <= 7'b0100100;  //2
 76       3:Hex2 <= 7'b0110000;  //3
 77       4:Hex2 <= 7'b0011001;  //4
 78       5:Hex2 <= 7'b0010010;  //5
 79       6:Hex2 <= 7'b0000010;  //6
 80       7:Hex2 <= 7'b1111000;  //7
 81       8:Hex2 <= 7'b0000000;  //8
 82       9:Hex2 <= 7'b0010000;  //9
 83         default:Hex2 <= 7'b1000000;  //0
 84     endcase
 85   end
 86 
 87 always@(*)    //
 88   begin
 89     case(sec_h)
 90        0:Hex3 <= 7'b1000000;  //0
 91       1:Hex3 <= 7'b1111001;  //1
 92       2:Hex3 <= 7'b0100100;  //2
 93       3:Hex3 <= 7'b0110000;  //3
 94       4:Hex3 <= 7'b0011001;  //4
 95       5:Hex3 <= 7'b0010010;  //5
 96         default:Hex3 <= 7'b1000000;  //0
 97     endcase
 98   end
 99 
100 always@(*)    //
101   begin
102     case(fen_l)
103        0:Hex4 <= 7'b1000000;  //0
104       1:Hex4 <= 7'b1111001;  //1
105       2:Hex4 <= 7'b0100100;  //2
106       3:Hex4 <= 7'b0110000;  //3
107       4:Hex4 <= 7'b0011001;  //4
108       5:Hex4 <= 7'b0010010;  //5
109       6:Hex4 <= 7'b0000010;  //6
110       7:Hex4 <= 7'b1111000;  //7
111       8:Hex4 <= 7'b0000000;  //8
112       9:Hex4 <= 7'b0010000;  //9
113         default:Hex4 <= 7'b1000000;  //0
114     endcase
115   end
116 
117 always@(*)    //
118   begin
119     case(fen_h)
120        0:Hex5 <= 7'b1000000;  //0
121       1:Hex5 <= 7'b1111001;  //1
122       2:Hex5 <= 7'b0100100;  //2
123       3:Hex5 <= 7'b0110000;  //3
124       4:Hex5 <= 7'b0011001;  //4
125       5:Hex5 <= 7'b0010010;  //5
126         default:Hex5 <= 7'b1000000;  //0
127     endcase
128   end
129   
130 endmodule
disp.v

仿真用的是Modelsim SE-64 10.4,只对计数模块进行了仿真,不是很直观,代码如下:

 1 `timescale 1ns/1ns
 2 `define clk_period 20
 3 module count_tb;
 4   reg clk;
 5   reg rst_n;
 6   reg pause;
 7   wire[3:0] h_sec_h;
 8   wire[3:0] h_sec_l;
 9   wire[3:0] sec_l;
10   wire[3:0] sec_h;
11   wire[3:0] fen_h;
12   wire[3:0] fen_l;
13 count u0(
14   .clk(clk),
15   .rst_n(rst_n),
16   .pause(pause),
17   .h_sec_h(h_sec_h),
18   .h_sec_l(h_sec_l),
19   .sec_h(sec_h),
20   .sec_l(sec_l),
21   .fen_h(fen_h),
22   .fen_l(fen_l)
23 );
24 
25 initial
26   clk = 0;
27   always#(`clk_period/2) clk = ~clk;
28   
29 initial
30   begin
31     rst_n = 1'b0;
32      #(`clk_period);
33      rst_n = 1'b1;
34      pause = 1'b1;
35      #(`clk_period*5);
36      pause = 1'b0;
37      #(`clk_period*1000000);
38      $stop;
39   end
40 endmodule
count_tb.v

由于分频为100hz进行百分秒计数,Modelsim跑的比较慢,所以我将百分秒计数模块,秒计数模块,分计数模块一个个单独来进行仿真,这样速度较快,容易找到问题,功能上是可以完全实现的。

 

 

 

 

 

=========================================================================

版本更新:2020.12.07 15:22

=========================================================================

硬件平台:米联客 MA703FA

软件环境:Vivado 2019.2

功能设计:

        三个按键,按键 1 控制清零,按键 2 控制 开始,按键 3 控制暂停,测时精度:0.01 S,测时范围:0 ~ 99.99 S。开发板上的按键悬空时都是高电平,按下之后为低电平,使用了 4 个七段数码管,理论上,至少需要 4 + 8 个 pin 与FPGA芯片相连,使用了 2 片74HC595芯片来节约引脚资源。

RTL 视图:

 

 

源码设计:

    1、模块一

 1 // *********************************************************************************
 2 // Project Name : data_generrate
 3 // Email        : 
 4 // Create Time  : 2020/12/6 15:52
 5 // Module Name  : data_generrate
 6 // editor        : Qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module data_generrate(
11     input                            sclk        ,
12     input                            s_rst_n        ,
13 
14     input                            start        ,
15     input                            stop        ,
16 
17     output        reg[15:0]            data_out    
18     );
19 
20 //========================================================================\
21 // =========== Define Parameter and Internal signals =========== 
22 //========================================================================/
23 
24 parameter                           TIME_1MS =   499999  ; //99999
25 
26 reg                   [23:0]          cnt_ms    =    24'd0    ;
27 reg                                   flag_add    =    1'b0    ;
28 
29 //=============================================================================
30 //****************************     Main Code    *******************************
31 //=============================================================================
32 
33 always @(posedge sclk) begin
34     if(!s_rst_n)
35         flag_add <= 1'b0;
36     else if(start == 1'b0)
37         flag_add <= 1'b1;
38     else if(stop == 1'b0)
39         flag_add <= 1'b0;
40     else
41         flag_add <= flag_add;
42 end
43 
44 always @(posedge sclk) begin
45     if(!s_rst_n)
46         cnt_ms <= 24'd0;
47     else if(flag_add == 1'b1) begin
48         if(cnt_ms == TIME_1MS)
49             cnt_ms <= 24'd0;
50         else
51             cnt_ms <= cnt_ms + 1'b1;
52     end
53     else
54         cnt_ms <= cnt_ms;
55 end
56 
57 always @(posedge sclk) begin
58     if(!s_rst_n)
59         data_out <= 16'd0;
60     else if(flag_add == 1'b1) begin
61         if(data_out == 16'd9999)
62             data_out <= 16'd0;
63         else if(cnt_ms == TIME_1MS)
64             data_out <= data_out + 1'b1;
65         else
66             data_out <= data_out;
67     end
68     else
69         data_out <= data_out;
70 end
71 
72 endmodule
View Code

    2、模块二

 1 // *********************************************************************************
 2 // Project Name : bcd_8421
 3 // Email        : 
 4 // Create Time  : 2020/12/05 22:14
 5 // Module Name  : bcd_8421
 6 // editor        : Qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module bcd_8421(
11     input                        sclk            ,
12     input                        s_rst_n            ,
13 
14     input        [15:0]            data_in            ,
15 
16     output     reg[ 3:0]            unit            ,
17     output   reg[ 3:0]          ten                ,
18     output     reg[ 3:0]            hun                ,
19     output     reg[ 3:0]          tho                
20     );
21 
22 //========================================================================\
23 // =========== Define Parameter and Internal signals =========== 
24 //========================================================================/
25 
26 reg            [ 4:0]                cnt_shift        ;
27 reg          [31:0]                data_shift        ;
28 reg                                shift_flag        ;
29 
30 //=============================================================================
31 //****************************     Main Code    *******************************
32 //=============================================================================
33 
34 always @(posedge sclk or negedge s_rst_n) begin
35     if(!s_rst_n)
36         cnt_shift <= 5'd0;
37     else if((cnt_shift == 5'd17) && (shift_flag == 1'b1))
38         cnt_shift <= 5'd0;
39     else if(shift_flag == 1'b1)
40         cnt_shift <= cnt_shift + 1'b1;
41     else
42         cnt_shift <= cnt_shift;
43 end
44 
45 always @(posedge sclk or negedge s_rst_n) begin
46     if(!s_rst_n)
47         data_shift <= 32'd0;
48     else if(cnt_shift == 5'd0)
49         data_shift <= {16'b0,data_in};
50     else if((cnt_shift <= 16) && (shift_flag == 1'b0)) begin
51         data_shift[19:16] <= (data_shift[19:16] > 4) ? (data_shift[19:16] + 2'd3) : (data_shift[19:16]);
52         data_shift[23:20] <= (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
53         data_shift[27:24] <= (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
54         data_shift[31:28] <= (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
55     end
56     else if((cnt_shift <= 16) && (shift_flag == 1'b1))
57         data_shift <= data_shift << 1;
58     else
59         data_shift <= data_shift;    
60 end
61 
62 always @ (posedge sclk or negedge s_rst_n) begin
63     if(s_rst_n == 1'b0) 
64         shift_flag <= 1'b0;
65     else    
66         shift_flag <= ~shift_flag;
67 end
68 
69 always @(posedge sclk or negedge s_rst_n) begin
70     if(!s_rst_n) begin
71         unit <= 4'b0;
72         ten <= 4'b0;
73         hun <= 4'b0;
74         tho <= 4'b0;
75     end    
76     else if(cnt_shift == 5'd17) begin
77         unit <= data_shift[19:16];
78         ten <= data_shift[23:20];
79         hun <= data_shift[27:24];
80         tho <= data_shift[31:28];
81     end
82 end
83 
84 endmodule
View Code

   3、模块三

  1 // *********************************************************************************
  2 // Project Name : disp
  3 // Email        : 
  4 // Create Time  : 2020/12/06 16:59
  5 // Module Name  : disp
  6 // editor        : Qing
  7 // Version        : Rev1.0.0
  8 // *********************************************************************************
  9 
 10 module disp(
 11     input                        sclk        ,
 12     input                        s_rst_n        ,
 13 
 14     input        [3:0]            unit        ,
 15     input        [3:0]            ten            ,
 16     input        [3:0]            hun            ,
 17     input        [3:0]            tho            ,
 18 
 19     output    reg    [3:0]            sel            ,
 20     output  reg [7:0]            seg
 21     );
 22 
 23 //========================================================================\
 24 // =========== Define Parameter and Internal signals =========== 
 25 //========================================================================/
 26 
 27 parameter            TIME_1MS    =    49999    ;
 28 parameter            point        =    4'b0100 ;
 29 
 30 reg        [15:0]        cnt_ms        =    16'd0    ;
 31 reg        [15:0]        disp_reg    =    16'd0    ;
 32 reg        [ 2:0]      lsm_cnt        =   3'd0    ;
 33 reg        [ 3:0]      data_reg    =    4'd0    ;
 34 reg                 dot_point   =   1'b0    ; 
 35 
 36 //=============================================================================
 37 //****************************     Main Code    *******************************
 38 //=============================================================================
 39 
 40 always @(posedge sclk) begin
 41     if(!s_rst_n)
 42         cnt_ms <= 16'd0;
 43     else if(cnt_ms == TIME_1MS)
 44         cnt_ms <= 16'd0;
 45     else
 46         cnt_ms <= cnt_ms + 1'b1;
 47 end
 48 
 49 always @(posedge sclk) begin
 50     if(!s_rst_n)
 51         disp_reg <= 16'd0;
 52     else if(tho != 4'd0)
 53         disp_reg <= {tho,hun,ten,unit};
 54     else if((hun != 4'd0))
 55         disp_reg <= {4'd10,hun,ten,unit};
 56     else if((ten != 4'd0))
 57         disp_reg <= {4'd10,4'd10,ten,unit};
 58     else if(unit != 4'd0)
 59         disp_reg <= {4'd10,4'd10,4'd10,unit};
 60     else
 61         disp_reg <= {4'd10,4'd10,4'd10,4'd10};
 62 end
 63 
 64 always @(posedge sclk) begin
 65     if(!s_rst_n)
 66         lsm_cnt <= 3'd0;
 67     else if((lsm_cnt == 3'd3) && (cnt_ms == TIME_1MS))
 68         lsm_cnt <= 3'd0;
 69     else if(cnt_ms == TIME_1MS)
 70         lsm_cnt <= lsm_cnt + 1'b1;
 71     else
 72         lsm_cnt <= lsm_cnt;
 73 end
 74 
 75 always @(posedge sclk) begin
 76     if(!s_rst_n)
 77         sel <= 4'b1111;  // 0000
 78     else if((cnt_ms == TIME_1MS) && (lsm_cnt == 3'd0))
 79         sel <= 4'b0001;
 80     else if(cnt_ms == TIME_1MS)
 81         sel <= sel << 1;
 82     else
 83         sel <= sel;
 84 end
 85 
 86 always @(posedge sclk) begin
 87     if(!s_rst_n)
 88         dot_point <= 1'b0;
 89     else if(cnt_ms == TIME_1MS) 
 90         dot_point <= ~point[lsm_cnt];
 91     else
 92         dot_point <= dot_point;
 93 end
 94 
 95 always @(posedge sclk) begin
 96     if(!s_rst_n)
 97         data_reg <= 4'd0;
 98     else if(cnt_ms == TIME_1MS) begin
 99         case(lsm_cnt)
100             3'd0:data_reg <= disp_reg[3:0];
101             3'd1:data_reg <= disp_reg[7:4];
102             3'd2:data_reg <= disp_reg[11:8];
103             3'd3:data_reg <= disp_reg[15:12];
104             default:data_reg <= 4'd0;
105         endcase
106     end
107     else
108         data_reg <= data_reg;
109 end
110 
111 always @(posedge sclk) begin
112     if(!s_rst_n)
113         seg <= 8'hc0;
114     else begin
115         case(data_reg)
116             4'd0: seg <= {dot_point,7'b100_0000};  //  8'hc0
117             4'd1: seg <= {dot_point,7'b111_1001};  //  8'hf9
118             4'd2: seg <= {dot_point,7'b010_0100};  //  8'ha4
119             4'd3: seg <= {dot_point,7'b011_0000};  //  8'hb0
120             4'd4: seg <= {dot_point,7'b001_1001};  //  8'h99
121             4'd5: seg <= {dot_point,7'b001_0010};  //  8'h92
122             4'd6: seg <= {dot_point,7'b000_0010};  //  8'h82
123             4'd7: seg <= {dot_point,7'b111_1000};  //  8'hf8
124             4'd8: seg <= {dot_point,7'b000_0000};  //  8'h80
125             4'd9: seg <= {dot_point,7'b001_0000};  //  8'h90
126             default:seg <= 8'hc0;
127         endcase
128     end
129 end
130 
131 endmodule
View Code

  4、模块四

 1 // *********************************************************************************
 2 // Project Name : HC595_driver
 3 // Email        : 
 4 // Create Time  : 2020/12/04 21:20
 5 // Module Name  : 74HC595_driver
 6 // editor        : Qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module HC595_driver(
11     input                    sclk            ,
12     input                    s_rst_n            ,
13 
14     input        [7:0]        seg                ,
15     input        [3:0]        sel                ,
16 
17     output reg                sh_cp            ,
18     output reg                st_cp           ,
19     output reg                ds                ,
20     output                    oe        
21     );
22 
23 //========================================================================\
24 // =========== Define Parameter and Internal signals =========== 
25 //========================================================================/
26 
27 reg                [2:0]        cnt0       =  3'd0    ;
28 reg                [3:0]        lsm_cnt    =  4'd0  ;
29 
30 wire            [11:0]        data                ;
31 
32 
33 //=============================================================================
34 //****************************     Main Code    *******************************
35 //=============================================================================
36 
37 always @(posedge sclk) begin
38     if(!s_rst_n)
39         cnt0 <= 3'd0;
40     else if(cnt0 == 3)
41         cnt0 <= 3'd0;
42     else
43         cnt0 <= cnt0 + 1'b1;
44 end
45 
46 always @(posedge sclk) begin
47     if(!s_rst_n)
48         lsm_cnt <= 4'd0;
49     else if((lsm_cnt == 11) && (cnt0 == 3))
50         lsm_cnt <= 4'd0;
51     else if(cnt0 == 3)
52         lsm_cnt <= lsm_cnt + 1'b1;
53     else
54         lsm_cnt <= lsm_cnt;
55 end
56 
57 always @(posedge sclk) begin  // 移位时钟
58     if(!s_rst_n)
59         sh_cp <= 1'b0;
60     else if(cnt0 >= 4'd2)
61         sh_cp <= 1'b1;
62     else
63         sh_cp <= 1'b0;
64 end
65 
66 always @(posedge sclk) begin
67     if(!s_rst_n)
68         st_cp <= 1'b0;
69     else if((lsm_cnt == 4'd11) && (cnt0 == 3))
70         st_cp <= 1'b1;
71     else
72         st_cp <= 1'b0;
73 end
74 
75 assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel};
76 
77 always @ (posedge sclk) begin
78     if(s_rst_n == 1'b0) 
79         ds <= 1'b0;
80     else if(cnt0 == 3'd0)
81         ds <= data[lsm_cnt];
82     else
83         ds <= ds;    
84         
85 end
86 
87 assign oe = 1'b1;
88 
89 endmodule
View Code

  5、模块五(顶层模块)

 1 // *********************************************************************************
 2 // Project Name : stop_watch
 3 // Email        : 
 4 // Create Time  : 2020/12/06 20:00
 5 // Module Name  : stop_watch
 6 // editor        : Qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module stop_watch(
11     input                        sclk            ,
12     input                        s_rst_n            ,
13 
14     input                        start            ,
15     input                        stop            ,
16 
17     output                      sh_cp            ,
18     output                      st_cp           ,
19     output                      ds                ,
20     output                        oe                    
21     );
22 
23 wire            [15:0]            data_in            ;
24 wire            [ 3:0]          unit            ;
25 wire            [ 3:0]          ten                ;
26 wire            [ 3:0]          hun                ;
27 wire            [ 3:0]          tho                ;
28 wire            [ 3:0]          sel             ;
29 wire            [ 7:0]          seg             ;
30 
31 data_generrate u0(
32     .sclk        ( sclk          ),
33     .s_rst_n    ( s_rst_n      ),
34     .start        ( start          ),
35     .stop        ( stop          ),
36     .data_out    ( data_in      )
37     );
38 
39 bcd_8421 u1(
40     .sclk        ( sclk        ),
41     .s_rst_n    ( s_rst_n    ),
42     .data_in    ( data_in    ),
43     .unit        ( unit        ),
44     .ten        ( ten        ),
45     .hun        ( hun        ),
46     .tho        ( tho        )
47     );
48 
49 disp u2(
50     .sclk        ( sclk        ),
51     .s_rst_n    ( s_rst_n    ),
52     .unit        ( unit        ),
53     .ten        ( ten        ),
54     .hun        ( hun        ),
55     .tho        ( tho        ),
56     .sel        ( sel        ),
57     .seg        ( seg       )
58     );
59 
60 HC595_driver u3(
61     .sclk       ( sclk        ),
62     .s_rst_n   ( s_rst_n    ),
63     .seg       ( seg        ),
64     .sel       ( sel        ),
65     .sh_cp       ( sh_cp        ),
66     .st_cp     ( st_cp      ),
67     .ds           ( ds            ),
68     .oe           ( oe            )
69     );
70 
71 endmodule
View Code

仿真代码:

数据生成模块的 testbench:

 1 `timescale 1ns/1ps
 2 module data_generrate_tb;
 3    reg                    sclk        ;
 4    reg                    s_rst_n        ;
 5    reg                    start        ;
 6    reg                    stop        ;
 7    wire        [15:0]        data_out    ;
 8 
 9 data_generrate data_generrate_inst(
10     .sclk        ( sclk        ),
11     .s_rst_n    ( s_rst_n    ),
12     .start        ( start        ),
13     .stop        ( stop        ),
14     .data_out    ( data_out    )
15     );
16 
17 initial
18    sclk = 1'b0;
19    always #10 sclk = ~sclk;
20 
21 initial
22     begin
23         #1;
24         s_rst_n = 1'b0;
25         start = 1'b1;
26         stop = 1'b1;
27         #21;
28 
29         s_rst_n = 1'b1;
30         #31;
31         start = 1'b0;
32         #31;
33         start = 1'b1;
34 
35         #100000;
36 
37         stop = 1'b0;
38         #31;
39         stop = 1'b1;
40     end
41 
42 endmodule
View Code

bcd_8421 模块的 testbench:

 1 `timescale 1ns/1ps
 2 module bcd_8421_tb;
 3     reg                        sclk        ;
 4     reg                        s_rst_n        ;
 5     reg            [15:0]        data_in        ;
 6 
 7     wire        [ 3:0]        unit        ;
 8     wire        [ 3:0]      ten            ;
 9     wire        [ 3:0]        hun            ;
10     wire        [ 3:0]      tho            ;
11 
12 bcd_8421 bcd_8421_inst(
13     .sclk            ( sclk        ),
14     .s_rst_n        ( s_rst_n    ),
15     .data_in        ( data_in    ),
16     .unit            ( unit        ),
17     .ten            ( ten        ),
18     .hun            ( hun        ),
19     .tho            ( tho        )
20     );
21 
22 initial
23    sclk = 1'b0;
24    always #10 sclk = ~sclk;
25 
26 initial
27     begin
28         #1;
29         data_in = 16'b0;
30         s_rst_n = 1'b0;
31         #21;
32         s_rst_n = 1'b1;
33 
34         #31;
35         data_in = 16'd1234;
36         #30000;
37         data_in = 16'd4321;
38         #30000;
39         data_in = 16'd0;
40     end
41 endmodule
View Code

disp 显示模块的 testbench:

 1 `timescale 1ns/1ps
 2 module disp_tb;
 3     reg                   sclk        ;
 4     reg                   s_rst_n        ;
 5 
 6     reg   [3:0]            unit        ;
 7     reg   [3:0]            ten            ;
 8     reg   [3:0]            hun            ;
 9     reg   [3:0]            tho            ;
10 
11     wire  [3:0]            sel            ;
12     wire  [7:0]            seg         ;
13 
14 disp disp_inst(
15     .sclk            ( sclk        ),
16     .s_rst_n        ( s_rst_n    ),
17     .unit            ( unit        ),
18     .ten            ( ten        ),
19     .hun            ( hun        ),
20     .tho            ( tho        ),
21     .sel            ( sel        ),
22     .seg             ( seg       )
23     );
24 
25 initial
26     sclk = 1'b0;
27     always #10 sclk = ~sclk;
28 
29 initial
30     begin
31         #1;
32         s_rst_n = 1'b0;
33         unit = 4'd0;
34         ten     = 4'd0;
35         hun     = 4'd0;
36         tho     = 4'd0;
37 
38         #21;
39         s_rst_n = 1'b1;
40         #51;
41 
42         unit = 4'd1;
43         ten     = 4'd2;
44         hun     = 4'd3;
45         tho     = 4'd4;
46     end
47 
48 endmodule
View Code

HC595驱动模块的testbench:

 1 `timescale 1ns/1ps
 2 module HC595_driver_tb;
 3     reg                    sclk            ;
 4     reg                    s_rst_n            ;
 5 
 6     reg        [7:0]        seg                ;
 7     reg        [3:0]        sel                ;
 8 
 9     wire                sh_cp            ;
10     wire                st_cp           ;
11     wire                ds                ;
12 
13  HC595_driver HC595_driver_inst(
14     .sclk              ( sclk        ),
15     .s_rst_n          ( s_rst_n        ),
16     .seg              ( seg            ),
17     .sel              ( sel            ),
18     .sh_cp              ( sh_cp        ),
19     .st_cp            ( st_cp       ),
20     .ds                  ( ds            )
21      ); 
22 
23  initial
24      sclk = 1'b0;
25      always #10 sclk = ~sclk;
26 
27  initial
28      begin
29          #1;
30          s_rst_n = 1'b0;
31          seg = 8'd0;
32          sel = 4'd0;
33          #21;
34 
35          s_rst_n = 1'b1;
36          #20;
37          seg = 8'b1010_1010;
38          sel = 4'b1111;
39      end
40 
41 endmodule
View Code

 

=========================================================================

版本更新:2021.05.01  20 : 10

=========================================================================

硬件平台:友晶DE1-SOC

软件环境:Quartus II 15.1   Modelsim 10.4 SE

功能描述:利用开发板实现了一个类似于数字秒表的设计,一个复位按键(KEY0),一个启动按键(KEY1),一个暂停按键(KEY2),测时精度1秒,通过4个七段数码管表示时间,左边两个数码管表示分钟的计时,右边两个数码管表示秒钟的计时,板卡代码烧录成功之后,数码管显示为4个0,最大计数值为2021,即最大计数时间为20分21秒,代码比较简单。其RTL视图如下:

 

1. 分频模块:div_clk的源码如下:

Verilog HDL 源码:

 1 module div_clk(
 2     input                clk            ,
 3     input                rst_n                ,
 4 
 5     output        reg        clk_1Hz        
 6     );
 7 
 8 reg        [27:0]            cnt         ;
 9 
10 always @(posedge clk or negedge rst_n) begin
11     if(!rst_n)
12         cnt <= 28'd0;
13     else if(cnt == 49_999999)  // 49_999999
14         cnt <= 28'd0;
15     else
16         cnt <= cnt + 1'b1;
17 end
18 
19 always @(posedge clk or negedge rst_n) begin
20     if(!rst_n)
21         clk_1Hz <= 1'b0;
22     else if(cnt == 49_999999)  // 49_999999
23         clk_1Hz <= ~clk_1Hz;
24     else
25         clk_1Hz <= clk_1Hz;
26 end
27 
28 endmodule
View Code

仿真代码testbench:

 1 `timescale 1ns/1ps
 2 module div_clk_tb;
 3 
 4     reg                        clk                ;
 5     reg                        rst_n            ;
 6 
 7     wire                    clk_1Hz            ;
 8 
 9 div_clk div_clk_inst(
10     .clk     ( clk       ),
11     .rst_n   ( rst_n     ),
12     .clk_1Hz ( clk_1Hz   )
13     );
14 
15 initial
16     clk = 1'b0;
17     always #10 clk = ~clk;
18 
19 initial
20     begin
21         #1;
22         rst_n = 1'b0;
23         #21;
24         rst_n = 1'b1;
25     end
26 
27 endmodule
View Code

 

2. 计数模块:count的源码如下:

 1 module count(
 2     input                        clk        ,
 3     input                        rst_n    ,
 4     input                        start    ,
 5     input                        stop    ,
 6 
 7     output    wire[3:0]            s_l        ,
 8     output  wire[3:0]           s_h        ,
 9     output  wire[3:0]           f_l        ,
10     output  wire[3:0]           f_h     ,
11 
12  output  reg                 LED     
13 
14     );
15 
16 reg                                flag    ;
17 reg              [15:0]            count   ;    
18 
19 always @(posedge clk or negedge rst_n) begin
20     if(!rst_n)
21         flag <= 1'b0;
22     else if(!start)
23         flag <= 1'b1;
24     else if(!stop)
25         flag <= 1'b0;
26     else
27         flag <= flag;
28 end
29 
30 always @(posedge clk or negedge rst_n) begin
31     if(!rst_n)
32         count <= 16'd0;
33     else if(flag == 1'b1) begin
34         if(count == 2021)
35             count <= count;
36         else
37             count <= count + 1'b1;
38     end
39     else
40         count <= count;
41 end
42 
43 always @(posedge clk or negedge rst_n) begin
44     if(!rst_n)
45          LED <= 1'b0;
46      else if(count == 2021)
47          LED <= 1'b1;
48      else
49          LED <= LED;
50 
51 end
52 
53 assign  s_l = count % 10;             // 个位
54 assign  s_h = count / 10 % 10;        // 十位
55 assign  f_l = count / 100 % 10;       // 百位
56 assign  f_h = count / 1000 % 10;      // 千位
57 
58 
59 endmodule
View Code

仿真代码testbench:

 1 `timescale 1ns/1ps
 2 
 3 module count_tb;
 4     reg                        clk        ;
 5     reg                        rst_n    ;
 6     reg                        start    ;
 7     reg                        stop    ;
 8 
 9        wire   [3:0]           s_l        ;
10     wire   [3:0]           s_h        ;
11     wire   [3:0]           f_l        ;
12     wire   [3:0]           f_h      ;
13 
14 count count_inst(
15   .clk        ( clk         ),
16   .rst_n    ( rst_n         ),
17   .start    ( start         ),
18   .stop     ( stop       ),
19   .s_l      ( s_l        ),
20   .s_h      ( s_h        ),
21   .f_l      ( f_l        ),
22   .f_h      ( f_h        )
23     );
24 
25 initial
26     clk = 1'b0;
27     always #10 clk = ~clk;
28 
29 initial
30     begin
31         #1;
32         rst_n = 1'b0;
33         start = 1'b1;
34         stop = 1'b1;
35         #21;
36         rst_n = 1'b1;
37         #50;
38         start = 1'b0;
39         #30;
40         start = 1'b1;
41         #1000;
42         stop = 1'b0;
43         #30;
44         stop = 1'b1;
45     end
46 
47 endmodule
View Code

 

3. 显示模块:disp 的源码如下:

 1 module disp(
 2     input                        clk        ,
 3     input                        rst_n    ,
 4 
 5     input     [3:0]                s_l        ,
 6     input     [3:0]             s_h        ,
 7     input     [3:0]             f_l        ,
 8     input     [3:0]             f_h     ,
 9 
10     output    reg[6:0]             HEX0    ,
11     output    reg[6:0]             HEX1    ,
12     output    reg[6:0]             HEX2    ,
13     output    reg[6:0]             HEX3    
14 
15     );
16 
17 
18 always@(s_l) begin
19     case(s_l)
20         4'b0000:HEX0[6:0]=7'b100_0000;
21         4'b0001:HEX0[6:0]=7'b111_1001;
22         4'b0010:HEX0[6:0]=7'b010_0100;
23         4'b0011:HEX0[6:0]=7'b011_0000;
24         4'b0100:HEX0[6:0]=7'b001_1001;
25         4'b0101:HEX0[6:0]=7'b001_0010;
26         4'b0110:HEX0[6:0]=7'b000_0010;
27         4'b0111:HEX0[6:0]=7'b111_1000;
28         4'b1000:HEX0[6:0]=7'b000_0000;
29         4'b1001:HEX0[6:0]=7'b001_1000;
30         default:HEX0[6:0]=7'b000_1110;
31     endcase
32 end
33 
34 always@(s_h) begin
35     case(s_h)
36         4'b0000:HEX1[6:0]=7'b100_0000;
37         4'b0001:HEX1[6:0]=7'b111_1001;
38         4'b0010:HEX1[6:0]=7'b010_0100;
39         4'b0011:HEX1[6:0]=7'b011_0000;
40         4'b0100:HEX1[6:0]=7'b001_1001;
41         4'b0101:HEX1[6:0]=7'b001_0010;
42         4'b0110:HEX1[6:0]=7'b000_0010;
43         4'b0111:HEX1[6:0]=7'b111_1000;
44         4'b1000:HEX1[6:0]=7'b000_0000;
45         4'b1001:HEX1[6:0]=7'b001_1000;
46         default:HEX1[6:0]=7'b000_1110;
47     endcase
48 end
49 
50 always@(f_l) begin
51     case(f_l)
52         4'b0000:HEX2[6:0]=7'b100_0000;
53         4'b0001:HEX2[6:0]=7'b111_1001;
54         4'b0010:HEX2[6:0]=7'b010_0100;
55         4'b0011:HEX2[6:0]=7'b011_0000;
56         4'b0100:HEX2[6:0]=7'b001_1001;
57         4'b0101:HEX2[6:0]=7'b001_0010;
58         4'b0110:HEX2[6:0]=7'b000_0010;
59         4'b0111:HEX2[6:0]=7'b111_1000;
60         4'b1000:HEX2[6:0]=7'b000_0000;
61         4'b1001:HEX2[6:0]=7'b001_1000;
62         default:HEX2[6:0]=7'b000_1110;
63     endcase
64 end
65 
66 always@(f_h) begin
67     case(f_h)
68         4'b0000:HEX3[6:0]=7'b100_0000;
69         4'b0001:HEX3[6:0]=7'b111_1001;
70         4'b0010:HEX3[6:0]=7'b010_0100;
71         4'b0011:HEX3[6:0]=7'b011_0000;
72         4'b0100:HEX3[6:0]=7'b001_1001;
73         4'b0101:HEX3[6:0]=7'b001_0010;
74         4'b0110:HEX3[6:0]=7'b000_0010;
75         4'b0111:HEX3[6:0]=7'b111_1000;
76         4'b1000:HEX3[6:0]=7'b000_0000;
77         4'b1001:HEX3[6:0]=7'b001_1000;
78         default:HEX3[6:0]=7'b000_1110;
79     endcase
80 end
81 
82 
83 endmodule
View Code

仿真代码testbench:

 1 `timescale 1ns/1ps
 2 module disp_tb;
 3     reg                          clk        ;
 4     reg                          rst_n        ;
 5     reg     [3:0]              s_l        ;
 6     reg     [3:0]             s_h        ;
 7     reg     [3:0]             f_l        ;
 8     reg     [3:0]             f_h       ;
 9     wire    [6:0]             HEX0      ;
10     wire    [6:0]             HEX1      ;
11     wire    [6:0]             HEX2      ;
12     wire    [6:0]             HEX3      ;
13 
14 disp disp_inst(
15  .clk        ( clk     ),
16  .rst_n        ( rst_n     ),
17  .s_l        ( s_l     ),
18  .s_h        ( s_h     ),
19  .f_l        ( f_l     ),
20  .f_h       ( f_h    ),
21  .HEX0      ( HEX0   ),
22  .HEX1      ( HEX1   ),
23  .HEX2      ( HEX2   ),
24  .HEX3      ( HEX3   )
25     );
26 
27 initial
28     clk = 1'b0;
29     always #10 clk = ~clk;
30 
31 initial
32     begin
33         #1;
34         rst_n = 1'b0;
35         s_l      = 4'd0;
36         s_h      = 4'd0;
37         f_l      = 4'd0;
38         f_h   = 4'd0;
39         #31;
40         rst_n = 1'b1;
41         #50;
42         s_l      = 4'd4;
43         s_h      = 4'd5;
44         f_l      = 4'd6;
45         f_h   = 4'd7;
46         #100;
47         s_l      = 4'd1;
48         s_h      = 4'd2;
49         f_l      = 4'd3;
50         f_h   = 4'd4;
51         #1005;
52     end
53 
54  endmodule
55  
View Code

 

4. 顶层模块:shuzizhong 的源码如下:

 1 module shuzizhong(
 2     input                clk                    ,
 3     input                rst_n                ,
 4 
 5     input                start                ,
 6     input                stop                ,
 7      
 8      output              LED                 ,
 9 
10     output    [6:0]     HEX0                ,
11     output    [6:0]     HEX1                ,
12     output    [6:0]     HEX2                ,
13     output    [6:0]     HEX3  
14     );
15 
16 wire                clk_1Hz                  ;
17 
18 wire[3:0]            s_l                        ;
19 wire[3:0]           s_h                        ;
20 wire[3:0]           f_l                        ;
21 wire[3:0]           f_h                     ;
22 
23 
24 div_clk u0(
25     .clk            ( clk        ),
26     .rst_n            ( rst_n        ),
27     .clk_1Hz         ( clk_1Hz    )
28     );
29 
30 count u1(
31     .clk            ( clk_1Hz    ),
32     .rst_n            ( rst_n        ),
33     .start            ( start        ),
34     .stop            ( stop        ),
35     .s_l            ( s_l        ),
36     .s_h            ( s_h        ),
37     .f_l            ( f_l        ),
38     .f_h            ( f_h       ),
39      .LED         ( LED         )
40     );
41 
42 disp u2(
43     .clk           ( clk_1Hz    ),
44     .rst_n           ( rst_n        ),
45     .s_l           ( s_l        ),
46     .s_h           ( s_h        ),
47     .f_l           ( f_l        ),
48     .f_h           ( f_h        ),
49     .HEX0          ( HEX0       ),
50     .HEX1          ( HEX1       ),
51     .HEX2          ( HEX2       ),
52     .HEX3          ( HEX3       ) 
53     );
54 endmodule
View Code

仿真代码testbench:

 1 `timescale 1ns/1ps
 2 module shuzizhong_tb;
 3     reg                clk                    ;
 4     reg                rst_n                ;
 5 
 6     reg                start                ;
 7     reg                stop                ;
 8      
 9     wire              LED               ;
10 
11     wire    [6:0]     HEX0              ;
12     wire    [6:0]     HEX1              ;
13     wire    [6:0]     HEX2              ;
14     wire    [6:0]     HEX3              ;
15 
16 shuzizhong shuzizhong_inst(
17     .clk                ( clk      ),
18     .rst_n                ( rst_n      ),
19     .start                ( start      ),
20     .stop                ( stop      ),
21     .LED                ( LED     ),
22     .HEX0               ( HEX0    ),
23     .HEX1               ( HEX1    ),
24     .HEX2               ( HEX2    ),
25     .HEX3               ( HEX3    )
26     );
27 
28 initial
29    clk = 1'b0;
30    always #10 clk = ~clk;
31 
32 initial
33     begin
34         #1;
35         rst_n = 1'b0;
36         start = 1'b1;
37         stop = 1'b1;
38         #21;
39         rst_n = 1'b1;
40         #50;
41         start = 1'b0;
42         #300;
43         start = 1'b1;
44         #1000000000;
45         stop = 1'b0;
46         #300;
47         stop = 1'b1;
48     end
49 
50 endmodule
View Code

 

 

注:

        (1)将代码移植到其他平台也是可以的;

        (2)按键控制部分没有添加消抖;

 

posted @ 2019-10-05 23:02  青河  阅读(3437)  评论(4编辑  收藏  举报