当前位置:   article > 正文

verilog数字钟实验总结_数字钟1s时钟产生模块clk

数字钟1s时钟产生模块clk

本文部分代码参考的b站教学,记录下来仅方便期末考试的时候复习。

要想实现数字时钟,我们首先要明确几个问题:1.怎么形成以秒为单位的“输入”(这里并非输入,其实是一秒钟产生一次响应);2.处理时分秒的进位问题;3.将其显示在数码管上。理清这三个需求其实verilog的编写也就很明确了,即三个问题各对应三个模块。

首先解决第一个问题。为了模拟现实中的1s我们可以采用对周期信号进行计数的方式来实现,很容易就想到clk信号,而时钟信号是周期激励,显然我们不可能手动对它完成输入,那这时候我们就需要接到FPGA开发板上自带的时钟信号激励源上。以我手上的BASYS 3为例,自带100MHz的clk激励,也就是1ns产生一次clk信号,那我们就可以通过对clk计数,当counter达到100_000_000次时,时长就达到了1s。输出就用0和1区分

代码如下:

  1. module clk_1s(
  2. input clk,
  3. input rstn,
  4. output flag_1s
  5. );
  6. parameter num_1s = 100_000_000;
  7. reg [26:0]cnt_1s;
  8. always@(posedge clk or negedge rstn)
  9. begin
  10. if(!rstn) begin
  11. cnt_1s <= 0;
  12. end
  13. else
  14. begin
  15. if(cnt_1s == num_1s) cnt_1s <= 0;
  16. else cnt_1s <= cnt_1s+1;
  17. end
  18. end
  19. assign flag_1s = (cnt_1s == num_1s) ? 1 : 0;
  20. endmodule

第二个问题,处理时分秒进位问题其实和C语言是一样的用if else语句一一处理不同的情况就行了

输出是6个三位位宽的二进制数分别对应时分秒的十位和个位

代码如下:

  1. module clock(
  2. input clk,
  3. input rstn,
  4. input flag_1s,
  5. output reg[3:0] data0,
  6. output reg[3:0] data1,
  7. output reg[3:0] data2,
  8. output reg[3:0] data3,
  9. output reg[3:0] data4,
  10. output reg[3:0] data5
  11. );
  12. reg [5:0] second;
  13. reg [5:0] minute;
  14. reg [4:0] hour;
  15. always@(posedge clk or negedge rstn)
  16. begin
  17. if(!rstn) begin
  18. second <= 0;
  19. end else begin
  20. if(second==59&&flag_1s)begin
  21. second <= 0;
  22. end else if(flag_1s)begin
  23. second = second + 1;
  24. end else begin
  25. second <= second;
  26. end
  27. end
  28. end
  29. always@(posedge clk or negedge rstn)
  30. begin
  31. if(!rstn) minute <= 0;
  32. else
  33. begin
  34. if(minute==59&&second==59&&flag_1s) minute <= 0;
  35. else if(second==59&&flag_1s) minute <= minute + 1;
  36. else minute <= minute;
  37. end
  38. end
  39. always@(posedge clk or negedge rstn)
  40. begin
  41. if(!rstn) hour <= 0;
  42. else
  43. begin
  44. if(hour==23&&minute==59&&second==59&&flag_1s) hour<=0;
  45. else if(minute==59&&second==59&&flag_1s) hour <= hour + 1;
  46. else hour <= hour;
  47. end
  48. end
  49. always@(posedge clk or negedge rstn)
  50. begin
  51. if(!rstn) begin
  52. data0 <= 0;
  53. data1 <= 0;
  54. data2 <= 0;
  55. data3 <= 0;
  56. data4 <= 0;
  57. data5 <= 0;
  58. end else begin
  59. data0 <= hour/10;
  60. data1 <= hour%10;
  61. data2 <= minute/10;
  62. data3 <= minute%10;
  63. data4 <= second/10;
  64. data5 <= second%10;
  65. end
  66. end
  67. endmodule

第三个问题:数码管的输出。要想解决这个问题首先要明确数码管点亮的逻辑是什么。

需要控制数码管的时间在人眼可滞留范围的同时保证数据不会更新,否则就会出现显示误差

直接贴图了

简而言之,就是一次性只能点亮一个数码管,而且是低电平点亮。想呈现出四个数码管同时亮的情况就得对clk信号进行分频,太快会让数码管扫描过快,出现显示上的出错,比如混亮,过亮,来不及变化等情况;太慢又会出现灯光过暗或者只有一个灯光在亮的情况。我把频率分到了1kHz

分频的代码如下:
reg[15:0]cnl;
reg clk1k;
always@(posedge clk or negedge rstn)
  begin
    if(!rstn)
    begin
      cnl<=0;
      clk1k<=0;
    end
    else if(cnl>=49999)
    begin
      clk1k<=!clk1k;
      cnl<=0;
    end
    else cnl<=cnl+1;
  end

接下来就是具体数码管的显示处理,因为我们前面提到了有六个数字需要显示,再结合同时只能点亮一个数码管(只有四个数码管,所以其中有两个数据显示在led上),就想到需要六个状态去一一对应,改变状态就改变了数码管的选择。同时一个中间变量去承接每个状态需要输出的数字,再将数字用译码器变化成对应的编码去数码管上显示就好了,注意区别这里的数码管选择和数码管显示

代码如下:

  1. module digital(
  2. input clk,
  3. input rstn,
  4. input [3:0]data0,
  5. input [3:0]data1,
  6. input [3:0]data2,
  7. input [3:0]data3,
  8. input [3:0]data4,
  9. input [3:0]data5,
  10. output reg[7:0]seg,
  11. output reg[3:0]sel,
  12. output reg[2:0]hours1,
  13. output reg[2:0]hours2
  14. );
  15. reg[15:0]cnl;
  16. reg clk1k;
  17. always@(posedge clk or negedge rstn)//分频
  18. begin
  19. if(!rstn)
  20. begin
  21. cnl<=0;
  22. clk1k<=0;
  23. end
  24. else if(cnl>=24999)
  25. begin
  26. clk1k<=!clk1k;
  27. cnl<=0;
  28. end
  29. else cnl<=cnl+1;
  30. end
  31. reg [3:0]tub;//中间变量
  32. reg [2:0]state;//状态变量
  33. always@(posedge clk1k or negedge rstn)
  34. begin
  35. if(!rstn)
  36. begin
  37. tub<=0;
  38. state<=0;
  39. sel<=0;
  40. hours1<=0;
  41. hours2<=0;
  42. end
  43. else
  44. begin
  45. case(state)//每种状态的数码管选择,0111即第四个数码管,hours12显示在led上,并且在状态转换的同时,数据也更新一次
  46. 0:begin hours1<=data0;sel<=4'b1111;state<=1;end
  47. 1:begin hours2<=data1;sel<=4'b1111;state<=2;end
  48. 2:begin tub<=data2;sel<=4'b0111;state<=3;end
  49. 3:begin tub<=data3;sel<=4'b1011;state<=4;end
  50. 4:begin tub<=data4;sel<=4'b1101;state<=5;end
  51. 5:begin tub<=data5;sel<=4'b1110;state<=0;end
  52. default:state<=0;
  53. endcase
  54. end
  55. end
  56. always@(*)//数码管数字显示
  57. if(!rstn)
  58. seg<=8'b1100_0000;
  59. else
  60. case(tub)
  61. 0:seg<=8'b1100_0000;
  62. 1:seg<=8'b1111_1001;
  63. 2:seg<=8'b1010_0100;
  64. 3:seg<=8'b1011_0000;
  65. 4:seg<=8'b1001_1001;
  66. 5:seg<=8'b1001_0010;
  67. 6:seg<=8'b1000_0010;
  68. 7:seg<=8'b1111_1000;
  69. 8:seg<=8'b1000_0000;
  70. 9:seg<=8'b1001_0000;
  71. default:seg<=8'b1100_0000;
  72. endcase
  73. endmodule

最后的流程就是用一个顶层模块把三个模块穿起来就行了:

  1. module top(
  2. input clk,
  3. input rstn,
  4. output [7:0]seg,//输出用于数码管数字的显示
  5. output [3:0]sel,//输出控制六个数码管的显示
  6. output [2:0]hours1,//输出时的
  7. output [2:0]hours2
  8. );
  9. wire flag_1s;
  10. wire [3:0]data0;
  11. wire [3:0]data1;
  12. wire [3:0]data2;
  13. wire [3:0]data3;
  14. wire [3:0]data4;
  15. wire [3:0]data5;
  16. clk_1s clk_1s_u(
  17. .clk(clk),
  18. .rstn(rstn),
  19. .flag_1s(flag_1s)
  20. );
  21. clock clock_u(
  22. .clk(clk),
  23. .rstn(rstn),
  24. .flag_1s(flag_1s),
  25. .data0(data0),
  26. .data1(data1),
  27. .data2(data2),
  28. .data3(data3),
  29. .data4(data4),
  30. .data5(data5)
  31. );
  32. digital digital_u(
  33. .clk(clk),
  34. .rstn(rstn),
  35. .data0(data0),
  36. .data1(data1),
  37. .data2(data2),
  38. .data3(data3),
  39. .data4(data4),
  40. .data5(data5),
  41. .seg(seg),
  42. .sel(sel),
  43. .hours1(hours1),
  44. .hours2(hours2)
  45. );
  46. endmodule

下面贴上具体的电路图

 约束文件的编写因为有数码管所以需要去查表进行约束,采用图像化约束会简单一些

这个是约束后的代码

  1. set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
  2. set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
  3. set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
  4. set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
  5. set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
  6. set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
  7. set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
  8. set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]
  9. set_property IOSTANDARD LVCMOS33 [get_ports {sel[5]}]
  10. set_property IOSTANDARD LVCMOS33 [get_ports {sel[4]}]
  11. set_property IOSTANDARD LVCMOS33 [get_ports {sel[3]}]
  12. set_property IOSTANDARD LVCMOS33 [get_ports {sel[2]}]
  13. set_property IOSTANDARD LVCMOS33 [get_ports {sel[1]}]
  14. set_property IOSTANDARD LVCMOS33 [get_ports {sel[0]}]
  15. set_property IOSTANDARD LVCMOS33 [get_ports clk]
  16. set_property IOSTANDARD LVCMOS33 [get_ports rstn]
  17. set_property PACKAGE_PIN W5 [get_ports clk]
  18. set_property PACKAGE_PIN R2 [get_ports rstn]
  19. set_property PACKAGE_PIN U2 [get_ports {sel[0]}]
  20. set_property PACKAGE_PIN U4 [get_ports {sel[1]}]
  21. set_property PACKAGE_PIN V4 [get_ports {sel[2]}]
  22. set_property PACKAGE_PIN W4 [get_ports {sel[3]}]
  23. set_property PACKAGE_PIN V7 [get_ports {seg[7]}]
  24. set_property PACKAGE_PIN W7 [get_ports {seg[0]}]
  25. set_property PACKAGE_PIN W6 [get_ports {seg[1]}]
  26. set_property PACKAGE_PIN U8 [get_ports {seg[2]}]
  27. set_property PACKAGE_PIN V8 [get_ports {seg[3]}]
  28. set_property PACKAGE_PIN U5 [get_ports {seg[4]}]
  29. set_property PACKAGE_PIN V5 [get_ports {seg[5]}]
  30. set_property PACKAGE_PIN U7 [get_ports {seg[6]}]
  31. set_property PACKAGE_PIN P3 [get_ports {hours1[2]}]
  32. set_property PACKAGE_PIN U3 [get_ports {hours1[1]}]
  33. set_property PACKAGE_PIN W3 [get_ports {hours1[0]}]
  34. set_property PACKAGE_PIN V3 [get_ports {hours2[2]}]
  35. set_property PACKAGE_PIN V13 [get_ports {hours2[1]}]
  36. set_property PACKAGE_PIN V14 [get_ports {hours2[0]}]
  37. set_property IOSTANDARD LVCMOS33 [get_ports {hours1[2]}]
  38. set_property IOSTANDARD LVCMOS33 [get_ports {hours1[1]}]
  39. set_property IOSTANDARD LVCMOS33 [get_ports {hours1[0]}]
  40. set_property IOSTANDARD LVCMOS33 [get_ports {hours2[0]}]
  41. set_property IOSTANDARD LVCMOS33 [get_ports {hours2[1]}]
  42. set_property IOSTANDARD LVCMOS33 [get_ports {hours2[2]}]

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

闽ICP备14008679号