在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 1159|回复: 0

[原创] 明德扬至简设计法完成数字时钟设计

[复制链接]
发表于 2020-3-3 11:50:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 chop147 于 2020-3-3 15:45 编辑

数字时钟是常见的毕业设计题目。我们做毕业设计时,一般使用数码管来显示数字。小时、分钟和秒钟各两位数字,所以需要用到6位的数码管。

如果平时不动手,要做这个毕业设计,很多人都会觉得挺难的。收集到的代码,其风格也是五花八门,第一感觉是貌似能看懂,但就是不知道怎么设计出来的。

其实如果有正确的设计思路和方法,其实现起来是非常简单的。下面我们就核心的数字模块为例,讲解如何使用至简设计法来实现。

数字模块的功能,是产生6个信号,分别表示时十位、时个位、分十位、分个位、秒十位和秒个位的值。例如上述信号值依次为2、1、4、3、5、9时,则表示时间为21点43分59秒。

仔细观察6个信号,每个单独来看,其数字都是递增的,增加到一定数后就清零。以秒个位为例,开始时值为0,然后是1、2、3依次增加,直到变成9后,然后变成0,再次循环。其他信号都是相同的规律。这些依次递增的信号,就是计数器。

我们认识到这些信号是计数器,那就好办了。计数器设计只需要考虑两点,什么时候加1和要数多少个,明确这两个问题后,剩下的就是套用计数器模板了。

以秒个位这个计数器为例,这个计数器加1的条件是什么呢?到了1秒就加1。那我们怎么知道1秒钟时间到了呢?FPGA是通过数时钟周期数来确定时间的。例如下图,假设时钟频率是50MHz,即时钟周期是20ns,cnt是每个时钟加1,则当cnt==99时,就说明数了100个时钟周期,也就是时间是100*20=2000ns了。

同样的道理,1秒钟时间,我们就是数1s/20ns= 50_000_000个时钟周期。我们也认识到这个cnt也是计数器,其加1条件是“1”,要数50_000_000个数。我们套用计数器模块,即有下面代码。





  1. always @(posedge clk or negedge rst_n)begin

  2. if(!rst_n)begin

  3. cnt 《= 0;

  4. end

  5. else if(add_cnt)begin

  6. if(end_cnt)

  7. cnt 《= 0;

  8. else

  9. cnt 《= cnt + 1;

  10. end

  11. end

  12. assign add_cnt = 1 ;

  13. assign end_cnt = add_cnt && cnt== 50_000_000-1;


复制代码

代码中,always语句除了名字后,完全套用模板,不用更改。加1条件体现在第13行,要数多少个体现在第14行。

确定了cnt后,那么秒个位的加1条件就非常明确了,就是cnt数到50_000_000个,也就是end_cnt有效的时候。所以秒个位的加1条件是end_cnt。

秒个位要数多少个数字呢?由0到9,因此有10个。

综上所述,我们得到秒个位的代码如下表。





  1. always@(posedge clk or negedge rst_n)begin

  2. if(rst_n==1‘b0)begin

  3. miao_g 《= 0;

  4. end

  5. else if(add_miao_g)begin

  6. if(end_miao_g)

  7. miao_g 《= 0;

  8. else

  9. miao_g 《= miao_g + 1;

  10. end

  11. end

  12. assign add_miao_g = end_cnt;

  13. assign end_miao_g = add_miao_g && miao_g == 10-1;


复制代码

用类似于秒个位的思考方法,我们可以得到秒十位、分个位、分十位、时个位和时十位的代码,完整的代码如下表。





  1. always @(posedge clk or negedge rst_n)begin

  2. if(!rst_n)begin

  3. cnt 《= 0;

  4. end

  5. else if(add_cnt)begin

  6. if(end_cnt)

  7. cnt 《= 0;

  8. else

  9. cnt 《= cnt + 1;

  10. end

  11. end

  12. assign add_cnt = 1 ;

  13. assign end_cnt = add_cnt && cnt== 50_000_000-1;

  14. always@(posedge clk or negedge rst_n)begin

  15. if(rst_n==1’b0)begin

  16. miao_g 《= 0;

  17. end

  18. else if(add_miao_g)begin

  19. if(end_miao_g)begin

  20. miao_g 《= 0;

  21. end

  22. else begin

  23. miao_g 《= miao_g + 1;

  24. end

  25. end

  26. end

  27. assign add_miao_g = end_cnt;

  28. assign end_miao_g = add_miao_g && miao_g == 10-1;

  29. always @(posedge clk or negedge rst_n)begin

  30. if(rst_n==1‘b0)begin

  31. miao_s 《= 0;

  32. end

  33. else if(add_miao_s)begin

  34. if(end_miao_s)begin

  35. miao_s 《= 0;

  36. end

  37. else begin

  38. miao_s 《= miao_s + 1;

  39. end

  40. end

  41. end

  42. assign add_miao_s = end_miao_g;

  43. assign end_miao_s = add_miao_s && miao_s == 6-1;

  44. always @(posedge clk or negedge rst_n)begin

  45. if(rst_n==1’b0)begin

  46. fen_g 《= 0;

  47. end

  48. else if(add_fen_g)begin

  49. if(end_fen_g)begin

  50. fen_g 《= 0;

  51. end

  52. else begin

  53. fen_g 《= fen_g + 1;

  54. end

  55. end

  56. end

  57. assign add_fen_g = end_miao_s;

  58. assign end_fen_g = add_fen_g && fen_g == 10-1;

  59. always @(posedge clk or negedge rst_n)begin

  60. if(rst_n==1‘b0)begin

  61. fen_s 《= 0;

  62. end

  63. else if(add_fen_s)begin

  64. if(end_fen_s)begin

  65. fen_s 《= 0;

  66. end

  67. else begin

  68. fen_s 《= fen_s + 1;

  69. end

  70. end

  71. end

  72. assign add_fen_s = end_fen_g;

  73. assign end_fen_s = add_fen_s && fen_s == 6-1;

  74. always @(posedge clk or negedge rst_n)begin

  75. if(rst_n==1’b0)begin

  76. shi_g 《= 0;

  77. end

  78. else if(add_shi_g)begin

  79. if(end_shi_g)begin

  80. shi_g 《= 0;

  81. end

  82. else begin

  83. shi_g 《= shi_g + 1;

  84. end

  85. end

  86. end

  87. assign add_shi_g = end_fen_s;

  88. assign end_shi_g = add_shi_g && shi_g ==x-1;

  89. always @(posedge clk or negedge rst_n)begin

  90. if(rst_n==1‘b0)begin

  91. shi_s 《= 0;

  92. end

  93. else if(add_shi_s)begin

  94. if(end_shi_s)begin

  95. shi_s 《= 0;

  96. end

  97. else begin

  98. shi_s 《= shi_s + 1;

  99. end

  100. end

  101. end

  102. assign add_shi_s = end_shi_g;

  103. assign end_shi_s = add_shi_s && shi_s == 3-1;

  104. always@(*)begin

  105. if(shi_s==2)

  106. x =4;

  107. else

  108. x =10;

  109. end


复制代码

细心的读者可以发现,上面每段计数器格式都非常相似。没错,这就是技巧。我们设计的这套模板,基本上可以应用于任何场合,任何时候读者只考虑两个因素就够了,不会出现丢三落四的情况,而且每次只需要考虑一个因素,保证能做出最优的设计。

对了,上面代码中,我们没有补充信号定义这些。其实我们认为这些信号定义纯属体力劳动,是根本就不需要学习的,所以我们就没列出来。读者有兴趣可必补充。另外加上数码管译码电路,那么一个完整的数字时钟代码就出来了。


您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-17 02:51 , Processed in 0.012634 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表