数字时钟计数器
简单的数字时钟计数器,其实现方法也是通过计数器的级联,由两个模60计数器和一个模24计数器子模块共同构成,下面的这段代码采用结构性描述方法,U1,U2,U3为调用的两个模60计数器和一个模24计数器子模块,模60计数器实现分秒的计数,模24计数器实现小时的计数。
在进行设计数字时钟计数器之前,分别介绍模60计数器count60以及8421BCD计数器count24。
1、模60计数器的verilog设计代码如下:
1. module counter60(clk, rst_n, en, dout, co);
2. input clk, rst_n, en;
3. output co;
4. output [7:0] dout;
5. wire co10_1, co10, co6;
6. wire [3:0] dout10, dout6;
7. count10 U1(.clk(clk), .rst_n(rst_n), .en(en), .dout(dout10), .co(co10_1));
8. count6 U2(.clk(clk), .rst_n(rst_n), .en(co10), .dout(dout6), .co(co6));
9. and U3(co, co10, co6);
10. and U4(co10, en, co10_1);
11. assign dout = {dout6, dout10};
12. endmodule
13.
14. //模10计数器
15. module count10(clk, rst_n, en, dout, co);
16. input clk, rst_n, en;
17. output co;
18. output [3:0] dout;
19. reg [3:0] dout;
20.
21. always @ (posedge clk or negedge rst_n)
22. begin
23. if(!rst_n)
24. dout <= 4'b0000;
25. else if(en == 1'b1)
26. begin
27. if(dout == 4'b1001)
28. dout <= 4'b0000;
29. else
30. dout <= dout + 1'b1;
31. end
32. else
33. dout <= dout;
34. end
35.
36. assign co = dout[0] & dout[3];
37. endmodule
38.
39. //模6计数器
40. module count6(clk, rst_n, en, dout, co);
41. input clk, rst_n, en;
42. output co;
43. output [3:0] dout;
44. reg [3:0] dout;
45. always @(posedge clk or negedge rst_n)
46. begin
47. if(!rst_n)
48. dout <= 4'b0000;
49. else if(en == 1'b1)
50. begin
51. if(dout == 4'b0101)
52. dout <= 4'b0000;
53. else
54. dout <= dout + 1;
55. end
56. else
57. dout <= dout;
58. end
59. assign co = dout[0] & dout[2];
60. endmodule
综合工具综合而出的电路如下:
2、模24的8421BCD码计数器
计数器实现的模制为24,clr为异步清零信号,当时钟上升沿到来或clr下降沿到来,
clr = 0时,计数器清零为0000_0000。该计数器的计数过程为,当输出信号的低4位(即 dout[3:0])从0000计数到1001后(即十进制的0 ~ 9),高4位(即dout[3:4])计数加1,当计数计到23时(即0010_0011),计数器又清零为0000_0000,然后重新开始计数。
其verilog HDL代码如下:
1. module count24(clk, clr, en, dout);
2. input clk; //时钟信号
3. input clr; //异步清零信号
4. input en; //计数使能信号
5. output [7:0] dout; //计数输出信号
6. reg [7:0] dout;
7. always @(posedge clk or negedge clr) //敏感信号源
8. begin
9. if(clr == 1'b0) //异步清零信号有效时,计数输出为0
10. dout <= 8'b0000_0000;
11. else if(en == 1'b0) //计数使能信号无效时,计数停止
12. dout <= dout;
13. else if((dout[7:4] == 4'b0010)&&(dout[3:0] == 4'b0011)) //当计数到达23时,输出清零
14. dout <= 8'b0000_0000;
15. else if(dout[3:0] == 4'b1001) //当低4位为9时,低4位清零,高4位加1
16. begin
17. dout[3:0] <= 4'b0000;
18. dout[7:4] <= dout[7:4] + 1'b1;
19. end
20. else //排除以上所有情况,高4位
21. begin
22. dout[7:4] <= dout[7:4];
23. dout[3:0] <= dout[3:0] + 1'b1;
24. end
25. end
26. endmodule
其测试文件为:
1. `timescale 1ns/1ps
2. module count24_tb;
3. reg clk, clr, en;
4. wire [7:0] dout;
5. always
6. begin
7. #10 clk = ~clk;
8. end
9. initial
10. begin
11. clk = 1'b0;
12. clr = 1'b1;
13. en = 1'b0;
14. #20 clr = 1'b0;
15. #10 clr = 1'b1;
16. #30 en = 1'b1;
17. #100;
18. end
19.
20. count24 U1(.clk(clk), .clr(clr), .en(en), .dout(dout));
21. endmodule
在Modelsim中仿真得到的波形为:(为了能看清,截了一部分图片)
下面正式给出数字时钟计数器的verilog HDL代码:
1. module digital_clock(hour, min, sec, clk, rst_n, en);
2. input clk, rst_n, en;
3. output [7:0] hour, min, sec;
4. wire co_sec1, co_sec, co_min, co_min1;
5.
6. count60 U1(.clk(clk), .rst_n(rst_n), .en(en), .dout(sec), .co(co_sec1));
7. count60 U2(.clk(clk), .rst_n(rst_n), .en(co_sec), .dout(min), .co(co_min1));
8. count24 U3(.clk(clk), .clr(rst_n), .en(co_min), .dout(hour));
9.
10. and U4(co_min, co_sec, co_min1);
11. and U5(co_sec, en, co_sec1);
12.
13. endmodule
14.
15. module count60(clk, rst_n, en, dout, co);
16. input clk, rst_n, en;
17. output co;
18. output [7:0] dout;
19. wire co10_1, co10, co6;
20. wire [3:0] dout10, dout6;
21. count10 U1(.clk(clk), .rst_n(rst_n), .en(en), .dout(dout10), .co(co10_1));
22. count6 U2(.clk(clk), .rst_n(rst_n), .en(co10), .dout(dout6), .co(co6));
23. and U3(co, co10, co6);
24. and U4(co10, en, co10_1);
25. assign dout = {dout6, dout10};
26. endmodule
27.
28. //模10计数器
29. module count10(clk, rst_n, en, dout, co);
30. input clk, rst_n, en;
31. output co;
32. output [3:0] dout;
33. reg [3:0] dout;
34.
35. always @ (posedge clk or negedge rst_n)
36. begin
37. if(!rst_n)
38. dout <= 4'b0000;
39. else if(en == 1'b1)
40. begin
41. if(dout == 4'b1001)
42. dout <= 4'b0000;
43. else
44. dout <= dout + 1'b1;
45. end
46. else
47. dout <= dout;
48. end
49.
50. assign co = dout[0] & dout[3];
51. endmodule
52.
53. //模6计数器
54. module count6(clk, rst_n, en, dout, co);
55. input clk, rst_n, en;
56. output co;
57. output [3:0] dout;
58. reg [3:0] dout;
59. always @(posedge clk or negedge rst_n)
60. begin
61. if(!rst_n)
62. dout <= 4'b0000;
63. else if(en == 1'b1)
64. begin
65. if(dout == 4'b0101)
66. dout <= 4'b0000;
67. else
68. dout <= dout + 1;
69. end
70. else
71. dout <= dout;
72. end
73. assign co = dout[0] & dout[2];
74. endmodule
75.
76. //模24计数器
77. module count24(clk, clr, en, dout);
78. input clk; //时钟信号
79. input clr; //异步清零信号
80. input en; //计数使能信号
81. output [7:0] dout; //计数输出信号
82. reg [7:0] dout;
83. always @(posedge clk or negedge clr) //敏感信号源
84. begin
85. if(clr == 1'b0) //异步清零信号有效时,计数输出为0
86. dout <= 8'b0000_0000;
87. else if(en == 1'b0) //计数使能信号无效时,计数停止
88. dout <= dout;
89. else if((dout[7:4] == 4'b0010)&&(dout[3:0] == 4'b0011)) //当计数到达23时,输出清零
90. dout <= 8'b0000_0000;
91. else if(dout[3:0] == 4'b1001) //当低4位为9时,低4位清零,高4位加1
92. begin
93. dout[3:0] <= 4'b0000;
94. dout[7:4] <= dout[7:4] + 1'b1;
95. end
96. else //排除以上所有情况,高4位
97. begin
98. dout[7:4] <= dout[7:4];
99. dout[3:0] <= dout[3:0] + 1'b1;
100. end
101. end
102. endmodule
其测试代码为:
1. `timescale 1ns/1ps
2. module digital_clock_tb;
3. reg clk, rst_n, en;
4. wire [7:0] hour, min, sec;
5.
6. always
7. begin
8. #10 clk = ~clk;
9. end
10.
11. initial
12. begin
13. clk = 1'b0;
14. rst_n = 1'b1;
15. en = 1'b0;
16. #20 rst_n = 1'b0;
17. #20 rst_n = 1'b1;
18. en = 1'b1;
19. #100;
20. end
21.
22. digital_clock U1(.hour(hour), .min(min), .sec(sec), .clk(clk), .rst_n(rst_n), .en(en));
23. endmodule
在Modelsim中仿真得到如下波形图:
用综合工具综合后的数字时钟: