当前位置:   article > 正文

FPGA巩固基础:秒表的设计_fpga秒表设计显示模块

fpga秒表设计显示模块

设计要求:

6位8段数码管,低三位显示毫秒计数,最高位显示分钟,其余两位显示秒计数。

开始案件与暂停按键,复位按键直接全部归零。

扩展部分:每计满一次,led移位一次。

框图设计:

 

思路讲解:

首先按键信号经过消抖再用,然后把产生的标志信号传给控制模块,由于控制逻辑很简单就把这部分控制逻辑放进“数据产生模块中了”;

然后把数码管与led接口模块interface放进去。

按理来讲,应该重新定义个接口模块再把led与nixie放进去,比较规范。

模块讲解:

值得一提就是数据产生模块与数码管接口模块:

数据产生模块:

 其实输出端口是几个级联得计数器。

代码奉上:

  1. `include "para.v"
  2. module data_gen (
  3. input wire sys_clk ,
  4. input wire sys_rst_n ,
  5. input wire start_flag ,
  6. input wire stop_flag ,
  7. output reg [3:0] po_data_one ,
  8. output reg [3:0] po_data_two ,
  9. output reg [3:0] po_data_thr ,
  10. output reg [3:0] po_data_fou ,
  11. output reg [3:0] po_data_fiv ,
  12. output reg [3:0] po_data_six ,
  13. output reg minute_flag
  14. );
  15. // localparam
  16. localparam IDLE = 3'b001 ,
  17. WORKING = 3'b010 ,
  18. STOP = 3'b100 ;
  19. // reg signal
  20. reg [15:0] cnt_1ms ;
  21. reg [2:0] state_c ;
  22. reg [2:0] state_n ;
  23. // wire signal
  24. wire add_cnt_1ms ;
  25. wire end_cnt_1ms ;
  26. wire IDLEtoWORKING ;
  27. wire WORKINGtoSTOP ;
  28. wire STOPtoWORKING ;
  29. /******************************************************************************************
  30. ********************************************main code**************************************
  31. *******************************************************************************************/
  32. // // reg signal
  33. // reg [2:0] state_c ;
  34. always @(posedge sys_clk or negedge sys_rst_n) begin
  35. if(~sys_rst_n)
  36. state_c <= IDLE ;
  37. else
  38. state_c <= state_n ;
  39. end
  40. // reg [2:0] state_n ;
  41. always @(*) begin
  42. if(~sys_rst_n)
  43. state_n = IDLE ;
  44. else
  45. case(state_c)
  46. IDLE : if(IDLEtoWORKING)
  47. state_n = WORKING ;
  48. else
  49. state_n = IDLE ;
  50. WORKING: if(WORKINGtoSTOP)
  51. state_n = STOP ;
  52. else
  53. state_n = WORKING ;
  54. STOP : if(STOPtoWORKING)
  55. state_n = WORKING ;
  56. else
  57. state_n = STOP ;
  58. default: state_n = IDLE ;
  59. endcase
  60. end
  61. assign IDLEtoWORKING = (state_c == IDLE ) && (start_flag) ;
  62. assign WORKINGtoSTOP = (state_c == WORKING ) && (stop_flag ) ;
  63. assign STOPtoWORKING = (state_c == STOP ) && (start_flag) ;
  64. // reg [15:0] cnt_1ms ;
  65. always @(posedge sys_clk or negedge sys_rst_n) begin
  66. if(~sys_rst_n)
  67. cnt_1ms <= 16'd0 ;
  68. else if(add_cnt_1ms) begin
  69. if(end_cnt_1ms)
  70. cnt_1ms <= 16'd0 ;
  71. else
  72. cnt_1ms <= cnt_1ms + 1'b1 ;
  73. end
  74. else if(state_c == IDLE)
  75. cnt_1ms <= 16'd0 ;
  76. else
  77. cnt_1ms <= cnt_1ms ;// 注意这里,是保持还是归零。
  78. end
  79. // wire add_cnt_1ms ;
  80. assign add_cnt_1ms = (state_c == WORKING ) ;
  81. // wire end_cnt_1ms ;
  82. assign end_cnt_1ms = add_cnt_1ms && (cnt_1ms == `MAX_CNT_1MS - 1) ;
  83. // output signal description
  84. // output reg [3:0] po_data_one ,
  85. always @(posedge sys_clk or negedge sys_rst_n) begin
  86. if(~sys_rst_n)
  87. po_data_one <= 4'd0 ;
  88. else if(end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1)
  89. po_data_one <= 4'd0 ;
  90. else if(end_cnt_1ms)
  91. po_data_one <= po_data_one + 1'b1 ;
  92. else
  93. po_data_one <= po_data_one ;
  94. end
  95. // output reg [3:0] po_data_two ,
  96. always @(posedge sys_clk or negedge sys_rst_n) begin
  97. if(~sys_rst_n)
  98. po_data_two <= 4'd0 ;
  99. else if((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)
  100. po_data_two <= 4'd0 ;
  101. else if(end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1)
  102. po_data_two <= po_data_two + 1'b1 ;
  103. else
  104. po_data_two <= po_data_two ;
  105. end
  106. // output reg [3:0] po_data_thr ,
  107. always @(posedge sys_clk or negedge sys_rst_n) begin
  108. if(~sys_rst_n)
  109. po_data_thr <= 4'd0 ;
  110. else if((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1))
  111. po_data_thr <= 4'd0 ;
  112. else if(((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1))
  113. po_data_thr <= po_data_thr + 1'b1 ;
  114. else
  115. po_data_thr <= po_data_thr ;
  116. end
  117. // output reg [3:0] po_data_fou , 显示秒的个位 0 ~ 9
  118. always @(posedge sys_clk or negedge sys_rst_n) begin
  119. if(~sys_rst_n)
  120. po_data_fou <= 4'd0 ;
  121. else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1))
  122. po_data_fou <= 4'd0 ;
  123. else if((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1))
  124. po_data_fou <= po_data_fou + 1'b1 ;
  125. else
  126. po_data_fou <= po_data_fou ;
  127. end
  128. // output reg [3:0] po_data_fiv , 显示秒的十位 0 ~ 5
  129. always @(posedge sys_clk or negedge sys_rst_n) begin
  130. if(~sys_rst_n)
  131. po_data_fiv <= 4'd0 ;
  132. else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5))
  133. po_data_fiv <= 4'd0 ;
  134. else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1))
  135. po_data_fiv <= po_data_fiv + 1'b1 ;
  136. else
  137. po_data_fiv <= po_data_fiv ;
  138. end
  139. // output reg [3:0] po_data_six ,
  140. always @(posedge sys_clk or negedge sys_rst_n) begin
  141. if(~sys_rst_n)
  142. po_data_six <= 4'd0 ;
  143. else if((((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5)) && (po_data_six == `MAX_CNT_NUM - 1))
  144. po_data_six <= 4'd0 ;
  145. else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5))
  146. po_data_six <= po_data_six + 1'b1 ;
  147. else
  148. po_data_six <= po_data_six ;
  149. end
  150. // reg minute_flag
  151. always @(posedge sys_clk or negedge sys_rst_n) begin
  152. if(~sys_rst_n)
  153. minute_flag <= 1'b0 ;
  154. else if((((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5)) && (po_data_six == `MAX_CNT_NUM - 1))
  155. minute_flag <= 1'b1 ;
  156. else
  157. minute_flag <= 1'b0 ;
  158. end
  159. endmodule

状态机设计:

当复位按键按下,现态与次态都需要回到IDLE状态。
在代码层面,给state_n设置一个复位情况。

数码管模块: 

创新点,与以往不同的代码设计,这次用了“函数”,function。

代码奉上:

  1. `include "para.v"
  2. module nixie (
  3. input wire sys_clk ,
  4. input wire sys_rst_n ,
  5. input wire [3:0] pi_data_one ,
  6. input wire [3:0] pi_data_two ,
  7. input wire [3:0] pi_data_thr ,
  8. input wire [3:0] pi_data_fou ,
  9. input wire [3:0] pi_data_fiv ,
  10. input wire [3:0] pi_data_six ,
  11. output reg [5:0] sel ,
  12. output reg [7:0] dig
  13. );
  14. // reg
  15. reg dot ; // 数码管上的小数点。
  16. reg [31:0] cnt_time ; // 移位寄存器的移位时间,计数器。
  17. // wire
  18. wire add_cnt_time ;
  19. wire end_cnt_time ;
  20. /******************************************************************************************
  21. ********************************************main code**************************************
  22. *******************************************************************************************/
  23. // reg signal description
  24. // reg [31:0] cnt_time ; // 移位寄存器的移位时间。
  25. always @(posedge sys_clk or negedge sys_rst_n) begin
  26. if(~sys_rst_n)
  27. cnt_time <= 32'd0 ;
  28. else if(add_cnt_time) begin
  29. if(end_cnt_time)
  30. cnt_time <= 32'd0 ;
  31. else
  32. cnt_time <= cnt_time + 1'b1 ;
  33. end
  34. else
  35. cnt_time <= 32'd0 ; // 注意这里,是保持还是归零。
  36. end
  37. // reg dot ;
  38. always @(posedge sys_clk or negedge sys_rst_n) begin
  39. if(~sys_rst_n)
  40. dot <= 1'b1 ;
  41. else
  42. dot <= 1'b1 ;
  43. end
  44. // wire signal description
  45. assign add_cnt_time = 1'b1 ;
  46. assign end_cnt_time = add_cnt_time && (cnt_time == `MAX_CNT_TIES - 1) ;
  47. // task
  48. // task nixie_dig ;
  49. // input [3:0] data_num ;
  50. // output [7:0] po_dig ;
  51. // case (data_num)
  52. // 0 : po_dig = {dot, `ZERO } ;
  53. // 1 : po_dig = {dot, `ONE } ;
  54. // 2 : po_dig = {dot, `TWO } ;
  55. // 3 : po_dig = {dot, `THREE } ;
  56. // 4 : po_dig = {dot, `FOUR } ;
  57. // 5 : po_dig = {dot, `FIVE } ;
  58. // 6 : po_dig = {dot, `SIX } ;
  59. // 7 : po_dig = {dot, `SEVEN } ;
  60. // 8 : po_dig = {dot, `EIGHT } ;
  61. // 9 : po_dig = {dot, `NINE } ;
  62. // default: po_dig = 8'd0 ;
  63. // endcase
  64. // endtask
  65. // function
  66. function [6:0] dig_num;
  67. input [3:0] data_in ;
  68. case (data_in)
  69. 0 : dig_num = `ZERO ;
  70. 1 : dig_num = `ONE ;
  71. 2 : dig_num = `TWO ;
  72. 3 : dig_num = `THREE ;
  73. 4 : dig_num = `FOUR ;
  74. 5 : dig_num = `FIVE ;
  75. 6 : dig_num = `SIX ;
  76. 7 : dig_num = `SEVEN ;
  77. 8 : dig_num = `EIGHT ;
  78. 9 : dig_num = `NINE ;
  79. default: dig_num = 7'd0 ;
  80. endcase
  81. endfunction
  82. // Output signal description
  83. // output reg [5:0] sel ,
  84. always @(posedge sys_clk or negedge sys_rst_n) begin
  85. if(~sys_rst_n)
  86. sel <= 6'b111_110 ;
  87. else if(end_cnt_time)
  88. sel <= {sel[4:0],sel[5]} ;
  89. else
  90. sel <= sel ;
  91. end
  92. // output reg [7:0] dig
  93. always @(posedge sys_clk or negedge sys_rst_n) begin
  94. if(~sys_rst_n)
  95. dig <= 8'd0 ;
  96. else
  97. case (sel)
  98. 6'b111_110: dig <= {dot, dig_num(pi_data_one)} ;
  99. 6'b111_101: dig <= {dot, dig_num(pi_data_two)} ;
  100. 6'b111_011: dig <= {dot, dig_num(pi_data_thr)} ;
  101. 6'b110_111: dig <= {1'b0, dig_num(pi_data_fou)} ;
  102. 6'b101_111: dig <= {dot, dig_num(pi_data_fiv)} ;
  103. 6'b011_111: dig <= {1'b0, dig_num(pi_data_six)} ;
  104. default : dig <= {dot, `SIX } ;
  105. endcase
  106. end
  107. endmodule

函数或者任务的使用,是使得代码写起来更方便,设计起来更节省时间。

减少重复劳动。

要灵活使用。多观察,多分析,多获取信息。找到相关性,相似性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/796586
推荐阅读
相关标签
  

闽ICP备14008679号