当前位置:   article > 正文

verilog 多功能数字钟_闹钟代码verilog

闹钟代码verilog

目录

SWJTU《数字电子技术》课程设计

一、设计任务

二、方案与电路设计

1. 总体方案设计

2. 主要电路设计

三、仿真结果与分析

四、硬件测试结果

五、Verilog HDL源代码


SWJTU《数字电子技术》课程设计

一、设计任务

功能:1.时钟 2.秒表 3.闹钟 4.调时 5.音乐系统

二、方案与电路设计

1. 总体方案设计

输入:1.50MHZ时钟信号 2.按键

输出:1.数码管位选 2.数码管段选 3.扬声器 4.模式灯

按键包括:1.初始化 2.模式选择 3.调时位选 4.时间加 5.时间减

6.调时确认 7.秒表开始/暂停 8.秒表清零 9.闹钟开关

把电路分成以下几个模块设计:

1.顶层模块 2.按键消抖模块 3.模式选择模块 4.消抖例化输出模块

5.分频器模块 6.计数器模块(时钟) 7.调时模块 8.音乐系统模块

9.秒表模块 10.数码管显示模块

2. 主要电路设计

消抖模块:(输入:clk、rst_n、key_in;输出:key_state、key_flag)消抖模块未采用状态机,而是采用两个计数器1,2。计数器1在按键为高电平时计数,低电平为零。计数器2在按键为低电平时计数,高电平为零。当计数满1_000_000(20ms)时立即对key_state进行状态转换,并判断出下降沿。

模式选择模块:(输入:clk、rst_n、key_in;输出:[1:0]model(模式))实质上是一个手动计数器。00、01、10、11循环。

消抖例化输出模块:(输入:clk、rst_n、key_in;输出:adjust_shif(调时位选)、key_up(时间加)、key_down(时间减)、pause(秒表信号)、clear(秒表清零信号))运用generate对各个按键进行例化。当按键按下pause进行0、1切换。

分频器模块:(输入:clk、rst_n;输出:clk_out)实质上是一个计数器。parameter CNT_MAX = 25_000_000;定义CNT_MAX方便例化。

计数器模块(时钟):(输入:clk、rst_n、[1:0]model(模式)、key_input(调时确认) 、[23:0]adjust_time_num(时钟调时值);输出:[23:0]time_num(时钟值)、time_led(整点报时信号))例化分频器产生1s上升沿,进行计时。并且判断调时确认信号为高电平时,时钟值等于时钟调时值。当分、秒为零时产生2s整点报时高电平信号(len_flag)。

调时模块:(输入:clk、rst_n、[1:0]model(模式)、adjust_shif(调时位选)、key_up(时间加)、key_down(时间减)、[23:0]time_num(时钟值);输出:[23:0]adjust_time_num、[15:0]adjust_clock_num)调时模块包括时钟调时和闹钟调时。每次切换到调试功能显示当前时间。

音乐系统模块:(输入:clk、rst_n、[15:0] adjust_clock_num、[23:0] time_num、key_alarm、time_led;输出:beep)想要实现《小星星》歌曲的播放首先需要找到对应简谱,并根据曲调找到相应的振动频率。定义一个count_end,我们可在不同音调下对count_end赋值,以此我们利用计数器(计数上限为count_end),每当到达上限beep便翻转一次就可实现不同频率声音的输出。在电路测试过程中我们发现,声音如果连续不断且遇到两个连续的相同短音调时,会连在一起,仿佛就是一个长音调。在两个音调之间插入一个短暂的无声状态可以很好解决这个问题。整点报时就是四个短音和一个长音之间插入一个短暂的无声状态。

秒表模块:(输入:clk、rst_n、[1:0]model、pause、clear(同步清零);输出:[23:0]stop_watch_num)例化分频器产生10ms上升沿,当秒表信号pause为1时计数器计数。到达显示上限自动清零,也可手动清零。

数码管显示模块:(输入:clk、rst_n、[1:0]model、[23:0]time_num、[23:0]adjust_time_num、[15:0]adjust_clock_num、[23:0]stop_watch_num;输出:[5:0]sel、[6:0]seg)定义一个[23:0]show_num,选择赋值,最终输出show_num的值。

三、仿真结果与分析

对时钟功能进行仿真,我们看到数码管秒的个位变化一次经历了1.00206ms(仿真时参数缩小了1/1000)并且时钟在235959之后变为000000符合要求。

切换模式功能正常

秒表模式按键功能正常

上面这张图是对秒表计时的仿真图,秒表十位变化一次经历了0.1ms,因为参数设为1/1000,实际应该经过100ms,而理论也应经过100ms.  

这部分是对调试模式下加减按钮的仿真,从仿真图可以看到减计数功能正常

这一部分是对调时功能的仿真图。依图我们可以知道,在调试完成并按下调时确认键后。我们迅速调至时钟模式便可以看到时钟模式下显示的数值就是我们设置的数值,并且时钟能够正常计数。这证明调时功能正常。

四、硬件测试结果

A. 计时功能:包括时、分、秒的计时,对数字钟来说,可以实现 1 天以内精确至1秒的计时,将小时和分钟显示在数码管上。

B. 闹钟功能:使用按键来开启或关闭闹钟功能,可设定闹钟定时的小时和分钟值,并用 LED 灯指示是否设置了闹钟功能。在闹钟定时到的时刻,启动闹铃响,响声持续一段时间后自动停止,也可以按键关闭闹铃响声。

C. 校时功能:通过按键对小时、分钟能手动调整以校准时间。

D. 设置整点报时功能:每逢整点产生持续 1s 的“嘀嘀嘀嘀——嘟”四短一长的报时音。

扩展功能:

E.秒表功能:只对秒计时,可以随时暂停与启动,包括重置,将秒的计时显示在数码管上。

F.音乐功能:在闹钟功能部分加了音乐,闹铃响声为音乐《小星星》。

五、Verilog HDL源代码

  1. module CourseDesign_513(
  2. input clk, //50MHz
  3. input rst_n, //初始化
  4. input [6:1] key_in, //按键输入
  5. input key_input, //设置时间的确认按键
  6. input key_alarm, //闹钟开关
  7. output [5:0] sel, //数码管位选
  8. output [7:6] sel_0, //数码管不显示
  9. output [6:0] seg, //数码管段选
  10. output beep, //闹钟音乐
  11. output reg [3:0] model_led //模式led
  12. );
  13. /*=============================定义变量==================================*/
  14. wire [1:0] model; //模式
  15. wire time_led; //整点报时(闪烁)
  16. wire [1:0] adjust_shif; //换位设置
  17. wire key_up; //加
  18. wire key_down; //减
  19. wire pause; //秒表暂停
  20. wire clear; //秒表清空
  21. wire [23:0] adjust_time_num; //时钟校准数值
  22. wire [23:0] time_num; //时钟数值
  23. wire [15:0] adjust_clock_num; //闹钟数值
  24. wire[23:0] stop_watch_num; //秒表数值
  25. assign sel_0=2'b00;
  26. /*=============================功能模块==================================*/
  27. key_module h1(
  28. clk,
  29. rst_n, //初始化
  30. key_in, //按键输入
  31. model, //模式
  32. adjust_shif, //调整时间
  33. key_up, //调整时间+
  34. key_down, //调整时间-
  35. pause, //秒表暂停/开始
  36. clear //秒表清除
  37. );
  38. /*=============================时钟==================================*/
  39. time_counter h2(
  40. clk, //分频clk_1s,
  41. rst_n, //初始化
  42. model, //模式
  43. adjust_time_num, //时间调整倠
  44. key_input, //设置时间的确认按键
  45. time_num, //时钟数值
  46. time_led //整点报时
  47. );
  48. /*==============================声音模块=================================*/
  49. alarm_music h3(
  50. clk,
  51. rst_n, //初始化
  52. adjust_clock_num, //闹钟调整值,只有小时和分钟
  53. time_num, //时钟数值
  54. key_alarm, //闹钟开关
  55. time_led, //整点报时
  56. beep
  57. );
  58. /*=============================秒表==================================*/
  59. stop_watch h4(
  60. clk,
  61. rst_n, //初始化
  62. model, //模式
  63. pause, //秒表暂停/开始
  64. clear, //秒表清除
  65. stop_watch_num //秒表数值
  66. );
  67. /*=============================调时==================================*/
  68. adjust_module h5(
  69. clk,
  70. rst_n, //初始化
  71. model, //模式
  72. adjust_shif, //调整时间时
  73. key_up, //调整时间+
  74. key_down, //调整时间-
  75. time_num, //时钟数值
  76. adjust_time_num, //时钟校准数值
  77. adjust_clock_num //闹钟数值
  78. );
  79. /*=============================数码管显示==================================*/
  80. led_seg7_display h6(
  81. clk,
  82. rst_n, //初始化
  83. model, //模式
  84. time_num, // 时钟数据
  85. adjust_time_num, // 调整时钟数据
  86. adjust_clock_num, // 调整闹钟数据
  87. stop_watch_num, // 秒表
  88. sel, // 数码管位选
  89. seg // 数码管段选
  90. );
  91. //================================模式显示LED===============================
  92. always@(model)
  93. case (model)
  94. 2'b00:model_led=4'b0001;
  95. 2'b01:model_led=4'b0010;
  96. 2'b10:model_led=4'b0100;
  97. 2'b11:model_led=4'b1000;
  98. endcase
  99. endmodule
  1. module key_filter( //消抖模块
  2. input clk,
  3. input rst_n,
  4. input key_in,
  5. output reg key_state, //状态说明
  6. output key_flag //下降沿
  7. );
  8. parameter CNT_MAX = 1_000_000; //20ms计数值 1_000_000
  9. //为方便仿真1_000
  10. reg [19:0] key_H, key_L; //计数变量
  11. //------------------按键为低 计数--------------------------
  12. always@(posedge clk, negedge rst_n) begin
  13. if(!rst_n)
  14. key_H <= 20'd0;
  15. else begin
  16. if(key_in)
  17. key_H <= key_H + 1;
  18. else
  19. key_H <= 20'd0;
  20. end
  21. end
  22. //-------------------按键为高 计数-------------------------
  23. always@(posedge clk, negedge rst_n) begin
  24. if(!rst_n)
  25. key_L <= 20'd0;
  26. else begin
  27. if(!key_in)
  28. key_L <= key_L + 1;
  29. else
  30. key_L <= 20'd0;
  31. end
  32. end
  33. //-------------------key_state输出判断--------------------
  34. always@(posedge clk, negedge rst_n) begin
  35. if(!rst_n)
  36. key_state <= 1'b0;
  37. else begin
  38. if(key_H > CNT_MAX)
  39. key_state <= 1'b1;
  40. else if(key_L > CNT_MAX)
  41. key_state <= 1'b0;
  42. end
  43. end
  44. //---------------------按键按下 下降沿判断----------------
  45. reg state1, state2;
  46. always@(posedge clk, negedge rst_n) begin
  47. if(!rst_n) begin
  48. state1 <= 1'b0;
  49. state2 <= 1'b0;
  50. end
  51. else begin
  52. state1 <= key_state;
  53. state2 <= state1;
  54. end
  55. end
  56. assign key_flag = (!state1) & state2; //按键按下,flag为高
  57. endmodule
  1. module model_change( //改变功能模块
  2. input clk,
  3. input rst_n,
  4. input key_in,
  5. output [1:0] model
  6. );
  7. //----------------- 模式:00:时钟,01:闹钟,10:秒表,11:调时 ------------
  8. reg [1:0] cnt;
  9. always@(posedge clk, negedge rst_n) begin
  10. if(!rst_n) begin
  11. cnt <= 2'd0;
  12. end
  13. else if(key_in) //按键按下
  14. cnt <= cnt + 1'b1; // 00 01 10 11循环
  15. else
  16. cnt <= cnt;
  17. end
  18. assign model = cnt;
  19. endmodule
  1. module key_module(
  2. input clk,
  3. input rst_n,
  4. input [6:1] key_in,
  5. output [1:0] model, //模式
  6. output reg [1:0] adjust_shif, //调整时间
  7. output key_up, //调整时间+
  8. output key_down, //调整时间-
  9. output reg pause, //秒表暂停/开始
  10. output clear //秒表清除
  11. );
  12. //-------- 例化key_filter,产生按键对应的高电平脉冲 -----------
  13. wire [6:1] key_out;
  14. genvar i;
  15. generate
  16. for(i = 1; i < 7; i = i + 1) begin: specify7_key_filter //块名
  17. key_filter fliter1(
  18. .clk (clk),
  19. .rst_n (rst_n),
  20. .key_in (key_in[i]),
  21. .key_state (),
  22. .key_flag (key_out[i])
  23. );
  24. end
  25. endgenerate
  26. assign key_up = key_out[3];
  27. assign key_down = key_out[4];
  28. assign clear = key_out[6];
  29. //----------- 例化 model_change ----------------
  30. model_change model1(
  31. .clk (clk),
  32. .rst_n (rst_n),
  33. .key_in (key_out[1]),
  34. .model (model)
  35. );
  36. //------------------- adjust_shif 调整时间位置 ---------------
  37. always@(posedge clk, negedge rst_n) begin
  38. if(!rst_n) begin
  39. adjust_shif <= 2'b00;
  40. end
  41. else begin
  42. if(key_out[2]) begin
  43. adjust_shif <= adjust_shif + 1'b1;
  44. if(adjust_shif == 2'b10)
  45. adjust_shif <= 2'b00;
  46. end
  47. if(key_out[1]) // model模式改变时,回到初始位
  48. adjust_shif <= 2'b00;
  49. end
  50. end
  51. //---------------- pause 秒表暂停/开始 --------------------
  52. always@(posedge clk, negedge rst_n) begin
  53. if(!rst_n)
  54. pause <= 1'b0;
  55. else if(key_out[5])
  56. pause <= ~pause;
  57. else if(model != 2'b10) //退出秒表模式暂停
  58. pause <= 1'b0;
  59. else
  60. pause <= pause;
  61. end
  62. endmodule
  1. module clk_div(
  2. input clk_in,
  3. input rst_n,
  4. output clk_out
  5. );
  6. //------------------------------------------------
  7. parameter CNT_MAX = 25_000_000; //任意值
  8. reg clk_reg;
  9. reg [24:0] cnt;
  10. //-------------------------------------------------
  11. assign clk_out = clk_reg;
  12. always@(posedge clk_in, negedge rst_n) begin
  13. if(!rst_n) begin
  14. clk_reg <= 1'b0;
  15. cnt <= 28'd0;
  16. end
  17. else begin
  18. if(cnt == CNT_MAX - 1) begin
  19. cnt <= 28'd0;
  20. clk_reg <= ~clk_reg;
  21. end
  22. else begin
  23. cnt <= cnt + 1'b1;
  24. clk_reg <= clk_reg;
  25. end
  26. end
  27. end
  28. endmodule
  1. module time_counter(
  2. input clk, //clk_1s,
  3. input rst_n,
  4. input [1:0] model,
  5. input [23:0] adjust_time_num,
  6. input key_input,
  7. output [23:0] time_num,
  8. output time_led
  9. );
  10. //------------------------- 1s时钟上升沿-----------------
  11. wire clk_1s;
  12. clk_div #(.CNT_MAX(25000000)) clk_div_1s(
  13. .clk_in (clk),
  14. .rst_n (rst_n),
  15. .clk_out (clk_1s)
  16. );//25000000 仿真改为25000
  17. reg clk_reg1, clk_reg2;
  18. wire pos_1s;
  19. always@(posedge clk, negedge rst_n) begin
  20. if(!rst_n) begin
  21. clk_reg1 <= 1'b0;
  22. clk_reg2 <= 1'b0;
  23. end
  24. else begin
  25. clk_reg1 <= clk_1s;
  26. clk_reg2 <= clk_reg1;
  27. end
  28. end
  29. assign pos_1s = clk_reg1 & (!clk_reg2);//上升沿
  30. //---------------------正常时间计数(时、分、秒)----------
  31. reg [3:0] sec0;
  32. reg [3:0] sec1;
  33. reg [3:0] min0;
  34. reg [3:0] min1;
  35. reg [3:0] hour0;
  36. reg [3:0] hour1;
  37. always@(posedge clk, negedge rst_n) begin
  38. if(!rst_n) begin
  39. sec0 <= 4'd5; //默认时间23:59:55
  40. sec1 <= 4'd5;
  41. min0 <= 4'd9;
  42. min1 <= 4'd5;
  43. hour0 <= 4'd3;
  44. hour1 <= 4'd2;
  45. end
  46. else begin
  47. if(pos_1s) begin
  48. sec0 <= sec0 + 1'b1;
  49. if(sec0 == 4'd9) begin
  50. sec0 <= 4'd0;
  51. sec1 <= sec1 + 1'b1;
  52. if(sec1 == 4'd5) begin
  53. sec1 <= 4'd0;
  54. min0 <= min0 + 1'b1;
  55. if(min0 == 4'd9) begin
  56. min0 <= 4'd0;
  57. min1 <= min1 + 1'b1;
  58. if(min1 == 4'd5) begin
  59. min1 <= 4'd0;
  60. hour0 <= hour0 + 1'b1;
  61. if(hour0 == 4'd9) begin
  62. hour0 <= 4'd0;
  63. hour1 <= hour1 + 1'b1;
  64. end
  65. end
  66. end
  67. end
  68. end
  69. end
  70. if(hour1 ==4'd2 && hour0 == 4'd4) begin
  71. hour1 <= 4'd0;
  72. hour0 <= 4'd0;
  73. end
  74. if((model == 2'b11)&&key_input) begin //时间校准
  75. {hour1, hour0, min1, min0, sec1, sec0} <= adjust_time_num[23:0];
  76. end
  77. end
  78. end
  79. //---------------- 整点报时 --------------------------------------
  80. reg len_flag;
  81. always@(posedge clk, negedge rst_n) begin
  82. if(!rst_n)
  83. len_flag <= 1'b0;
  84. else if(time_num[15:0] == 16'b0) //分钟和秒都归零
  85. len_flag <= 1'b1;
  86. else if(sec0 == 4'd2) //2s
  87. len_flag <= 1'b0;
  88. else
  89. len_flag <= len_flag;
  90. end
  91. assign time_led = len_flag;
  92. //------------------- 输出赋值---------------------
  93. assign time_num = {hour1, hour0, min1, min0, sec1, sec0};
  94. endmodule
  1. module adjust_module(
  2. input clk,
  3. input rst_n,
  4. input [1:0] model, //模式P:时钟,01:闹钟,10:秒表,11:调无
  5. input [1:0] adjust_shif, //调整时间时,调整位置P:秒个位Q:分个位P:时个位
  6. input key_up, //调整时间+
  7. input key_down, //调整时间-
  8. input [23:0] time_num,
  9. output [23:0] adjust_time_num,
  10. output [15:0] adjust_clock_num
  11. );
  12. //---------------------------- 闹钟变量 ---------------------------
  13. reg [3:0] clock_min0;
  14. reg [3:0] clock_min1;
  15. reg [3:0] clock_hour0;
  16. reg [3:0] clock_hour1;
  17. //----------------------------- 闹钟设置 -------------------------
  18. always@(posedge clk, negedge rst_n) begin
  19. if(!rst_n) begin
  20. clock_min0 <= 4'd0;
  21. clock_min1 <= 4'd0;
  22. clock_hour0 <= 4'd0;
  23. clock_hour1 <= 4'd0;
  24. end
  25. else if(model == 2'b01) begin //闹钟模式,只有小时、分钟
  26. if(adjust_shif == 2'b00) begin //调分钟个位
  27. if(key_up) begin
  28. clock_min0 <= clock_min0 + 1'b1;
  29. if(clock_min0 == 4'd9)
  30. clock_min0 <= 4'd0;
  31. end
  32. else if(key_down) begin
  33. clock_min0 <= clock_min0 - 1'b1;
  34. if(clock_min0 == 4'd0)
  35. clock_min0 <= 4'd9;
  36. end
  37. end
  38. else if(adjust_shif == 2'b01) begin //调分钟十位
  39. if(key_up) begin
  40. clock_min1 <= clock_min1 + 1'b1;
  41. if(clock_min1 == 4'd5)
  42. clock_min1 <= 4'd0;
  43. end
  44. else if(key_down) begin
  45. clock_min1 <= clock_min1 - 1'b1;
  46. if(clock_min1 == 4'd0)
  47. clock_min1 <= 4'd5;
  48. end
  49. end
  50. else begin //小时个位
  51. if(key_up) begin
  52. clock_hour0 <= clock_hour0 + 1'b1;
  53. if(clock_hour0 == 4'd9) begin
  54. clock_hour0 <= 4'd0;
  55. clock_hour1 <= clock_hour1 + 1'b1;
  56. end
  57. if(clock_hour1 ==4'd2 && clock_hour0 == 4'd3) begin
  58. clock_hour1 <= 4'd0;
  59. clock_hour0 <= 4'd0;
  60. end
  61. end
  62. else if(key_down) begin
  63. clock_hour0 <= clock_hour0 - 1'b1;
  64. if(clock_hour0 == 4'd0) begin
  65. clock_hour0 <= 4'd9;
  66. clock_hour1 <= clock_hour1 - 1'b1;
  67. end
  68. if(clock_hour1 ==4'd0 && clock_hour0 == 4'd0) begin
  69. clock_hour1 <= 4'd2;
  70. clock_hour0 <= 4'd3;
  71. end
  72. end
  73. end
  74. end
  75. end
  76. //-------------------------- 校准时间变量 --------------
  77. reg [3:0] adj_sec0;
  78. reg [3:0] adj_sec1;
  79. reg [3:0] adj_min0;
  80. reg [3:0] adj_min1;
  81. reg [3:0] adj_hour0;
  82. reg [3:0] adj_hour1;
  83. //----------------------------- 校准时间-----------------
  84. always@(posedge clk, negedge rst_n) begin
  85. if(!rst_n) begin
  86. adj_sec0 <= 4'd5;
  87. adj_sec1 <= 4'd3;
  88. adj_min0 <= 4'd9;
  89. adj_min1 <= 4'd5;
  90. adj_hour0 <= 4'd3;
  91. adj_hour1 <= 4'd2;
  92. end
  93. else if(model == 2'b11)begin
  94. case(adjust_shif) //调时 位置
  95. 2'b00: begin //秒个位
  96. if(key_up) begin
  97. adj_sec0 <= adj_sec0 + 1'b1;
  98. if(adj_sec0 == 4'd9) begin
  99. adj_sec0 <= 4'd0;
  100. adj_sec1 <= adj_sec1 + 1'b1;
  101. if(adj_sec1 == 4'd5) begin
  102. adj_sec1 <= 4'd0;
  103. end
  104. end
  105. end
  106. else if(key_down) begin
  107. adj_sec0 <= adj_sec0 - 1'b1;
  108. if(adj_sec0 == 4'd0) begin
  109. adj_sec0 <= 4'd9;
  110. adj_sec1 <= adj_sec1- 1'b1;
  111. if(adj_sec1 == 4'd0) begin
  112. adj_sec1 <= 4'd5;
  113. end
  114. end
  115. end
  116. end
  117. 2'b01: begin //分个位
  118. if(key_up) begin
  119. adj_min0 <= adj_min0 + 1'b1;
  120. if(adj_min0 == 4'd9) begin
  121. adj_min0 <= 4'd0;
  122. adj_min1 <= adj_min1 + 1'b1;
  123. if(adj_min1 == 4'd5) begin
  124. adj_min1 <= 4'd0;
  125. end
  126. end
  127. end
  128. else if(key_down) begin
  129. adj_min0 <= adj_min0 - 1'b1;
  130. if(adj_min0 == 4'd0) begin
  131. adj_min0 <= 4'd9;
  132. adj_min1 <= adj_min1- 1'b1;
  133. if(adj_min1 == 4'd0) begin
  134. adj_min1 <= 4'd5;
  135. end
  136. end
  137. end
  138. end
  139. 2'b10: begin //时个位
  140. if(key_up) begin
  141. adj_hour0 <= adj_hour0 + 1'b1;
  142. if(adj_hour0 == 4'd9) begin
  143. adj_hour0 <= 4'd0;
  144. adj_hour1 <= adj_hour1 + 1'b1;
  145. end
  146. if(adj_hour1 ==4'd2 && adj_hour0 == 4'd3) begin
  147. adj_hour1 <= 4'd0;
  148. adj_hour0 <= 4'd0;
  149. end
  150. end
  151. if(key_down) begin
  152. adj_hour0 <= adj_hour0 - 1'b1;
  153. if(adj_hour0 == 4'd0) begin
  154. adj_hour0 <= 4'd9;
  155. adj_hour1 <= adj_hour1 - 1;
  156. end
  157. if(adj_hour1 ==4'd0 && adj_hour0 == 4'd0) begin
  158. adj_hour1 <= 4'd2;
  159. adj_hour0 <= 4'd3;
  160. end
  161. end
  162. end
  163. default: begin
  164. adj_sec0 <= 4'dx;
  165. adj_sec1 <= 4'dx;
  166. adj_min0 <= 4'dx;
  167. adj_min1 <= 4'dx;
  168. adj_hour0 <= 4'dx;
  169. adj_hour1 <= 4'dx;
  170. end
  171. endcase
  172. end
  173. else begin
  174. {adj_hour1, adj_hour0, adj_min1, adj_min0, adj_sec1, adj_sec0} <= time_num; //将当前时间赋给调节变量
  175. end
  176. end
  177. //-------------------- 输出 ---------------
  178. assign adjust_time_num = {adj_hour1, adj_hour0, adj_min1, adj_min0, adj_sec1, adj_sec0};
  179. assign adjust_clock_num = {clock_hour1, clock_hour0, clock_min1, clock_min0};
  180. endmodule
  1. module alarm_music(
  2. input clk,
  3. input rst_n,
  4. input [15:0] adjust_clock_num, //闹钟调整值,只有小时和分钟
  5. input [23:0] time_num,
  6. input key_alarm,
  7. input time_led,
  8. output beep
  9. );
  10. //-------- 闹钟使能逻辑 --------------------------
  11. reg flag_en;
  12. reg [7:0] state;
  13. always@(posedge clk, negedge rst_n) begin
  14. if(!rst_n)
  15. flag_en <= 1'b0;
  16. else if(({adjust_clock_num,8'd0} == time_num)&&key_alarm) //闹钟时间到
  17. flag_en <= 1'b1;
  18. else if(state == 8'd191||!key_alarm) //一首音乐结束或关闭闹钟开关
  19. flag_en <= 1'b0;
  20. else
  21. flag_en <= flag_en;
  22. end
  23. //--------- 整点报时使能逻辑 ---------------
  24. wire flag_en1;
  25. assign flag_en1=(time_led&&!flag_en);//闹钟响起时不再整点报时
  26. //--------------- 音乐 -------------------------
  27. reg beep_r;
  28. reg [16:0] count, count_end;
  29. reg [23:0] count1;
  30. localparam C_1 = 17'd95_565,
  31. C_2 = 17'd85_149,
  32. C_3 = 17'd75_849,
  33. C_4 = 17'd71_592,
  34. C_5 = 17'd63_775,
  35. C_6 = 17'd56_818,
  36. C_7 = 17'd50_627,
  37. C_0 = 17'd55_555;
  38. localparam TIME = 6_250_000; //6_250_000每个音的长短(125ms)
  39. assign beep = beep_r;
  40. always@(posedge clk, negedge rst_n) begin
  41. if(!rst_n) begin
  42. count <= 17'h0;
  43. beep_r <= 1'b1;
  44. end
  45. else if(flag_en||flag_en1) begin //========
  46. count <= count + 1'b1;
  47. if(count == count_end) begin
  48. count <= 17'h0;
  49. if(count_end!=17'd55_555) beep_r <= !beep_r;
  50. end
  51. end
  52. else begin
  53. count <= 17'h0;
  54. beep_r <= 1'b1;
  55. end
  56. end
  57. always@(posedge clk, negedge rst_n) begin
  58. if(!rst_n) begin
  59. count1 <= 24'd0;
  60. state <= 8'd0;
  61. end
  62. else if(flag_en) begin
  63. if(count1 < TIME)
  64. count1 <= count1 + 1'b1;
  65. else begin
  66. count1 <= 24'd0;
  67. if(state >= 8'd191)
  68. state <= 8'd0;
  69. else
  70. state <= state + 1'b1;
  71. end
  72. end
  73. else if(flag_en1) begin //==================
  74. if(count1 < TIME)
  75. count1 <= count1 + 1'b1;
  76. else begin
  77. count1 <= 24'd0;
  78. if(state >= 8'd207||state < 8'd192)
  79. state <= 8'd192;
  80. else
  81. state <= state + 1'b1;
  82. end
  83. end
  84. else begin
  85. count1 <= 24'd0;
  86. state <= 8'd0;
  87. end
  88. end
  89. always@(state) begin
  90. case(state)
  91. 8'd0,8'd1,8'd2: count_end = C_1;
  92. 8'd3:count_end = C_0;
  93. 8'd4,8'd5,8'd6: count_end = C_1;
  94. 8'd7:count_end = C_0;
  95. 8'd8,8'd9,8'd10: count_end = C_5;
  96. 8'd11:count_end = C_0;
  97. 8'd12,8'd13,8'd14: count_end = C_5;
  98. 8'd15:count_end = C_0;
  99. 8'd16,8'd17,8'd18: count_end = C_6;
  100. 8'd19:count_end = C_0;
  101. 8'd20,8'd21,8'd22: count_end = C_6;
  102. 8'd23:count_end = C_0;
  103. 8'd24,8'd25,8'd26,8'd27: count_end = C_5;
  104. 8'd28,8'd29,8'd30: count_end = C_5;
  105. 8'd31:count_end = C_0;
  106. 8'd32,8'd33,8'd34: count_end = C_4;
  107. 8'd35:count_end = C_0;
  108. 8'd36,8'd37,8'd38: count_end = C_4;
  109. 8'd39:count_end = C_0;
  110. 8'd40,8'd41,8'd42: count_end = C_3;
  111. 8'd43:count_end = C_0;
  112. 8'd44,8'd45,8'd46: count_end = C_3;
  113. 8'd47:count_end = C_0;
  114. 8'd48,8'd49,8'd50: count_end = C_2;
  115. 8'd51:count_end = C_0;
  116. 8'd52,8'd53,8'd54: count_end = C_2;
  117. 8'd55:count_end = C_0;
  118. 8'd56,8'd57,8'd58,8'd59: count_end = C_1;
  119. 8'd60,8'd61,8'd62: count_end = C_1;
  120. 8'd63:count_end = C_0;
  121. 8'd64,8'd65,8'd66: count_end = C_5;
  122. 8'd67:count_end = C_0;
  123. 8'd68,8'd69,8'd70: count_end = C_5;
  124. 8'd71:count_end = C_0;
  125. 8'd72,8'd73,8'd74: count_end = C_4;
  126. 8'd75:count_end = C_0;
  127. 8'd76,8'd77,8'd78: count_end = C_4;
  128. 8'd79:count_end = C_0;
  129. 8'd80,8'd81,8'd82: count_end = C_3;
  130. 8'd83:count_end = C_0;
  131. 8'd84,8'd85,8'd86: count_end = C_3;
  132. 8'd87:count_end = C_0;
  133. 8'd88,8'd89,8'd90,8'd91: count_end = C_2;
  134. 8'd92,8'd93,8'd94: count_end = C_2;
  135. 8'd95:count_end = C_0;
  136. 8'd96,8'd97,8'd98: count_end = C_5;
  137. 8'd99:count_end = C_0;
  138. 8'd100,8'd101,8'd102: count_end = C_5;
  139. 8'd103:count_end = C_0;
  140. 8'd104,8'd105,8'd106: count_end = C_4;
  141. 8'd107:count_end = C_0;
  142. 8'd108,8'd109,8'd110: count_end = C_4;
  143. 8'd111:count_end = C_0;
  144. 8'd112,8'd113,8'd114: count_end = C_3;
  145. 8'd115:count_end = C_0;
  146. 8'd116,8'd117,8'd118: count_end = C_3;
  147. 8'd119:count_end = C_0;
  148. 8'd120,8'd121,8'd122,8'd123: count_end = C_2;
  149. 8'd124,8'd125,8'd126: count_end = C_2;
  150. 8'd127:count_end = C_0;
  151. 8'd128,8'd129,8'd130: count_end = C_1;
  152. 8'd131:count_end = C_0;
  153. 8'd132,8'd133,8'd134: count_end = C_1;
  154. 8'd135:count_end = C_0;
  155. 8'd136,8'd137,8'd138: count_end = C_5;
  156. 8'd139:count_end = C_0;
  157. 8'd140,8'd141,8'd142: count_end = C_5;
  158. 8'd143:count_end = C_0;
  159. 8'd144,8'd145,8'd146: count_end = C_6;
  160. 8'd147:count_end = C_0;
  161. 8'd148,8'd149,8'd150: count_end = C_6;
  162. 8'd151:count_end = C_0;
  163. 8'd152,8'd153,8'd154,8'd155: count_end = C_5;
  164. 8'd156,8'd157,8'd158: count_end = C_5;
  165. 8'd159:count_end = C_0;
  166. 8'd160,8'd161,8'd162: count_end = C_4;
  167. 8'd163:count_end = C_0;
  168. 8'd164,8'd165,8'd166: count_end = C_4;
  169. 8'd167:count_end = C_0;
  170. 8'd168,8'd169,8'd170: count_end = C_3;
  171. 8'd171:count_end = C_0;
  172. 8'd172,8'd173,8'd174: count_end = C_3;
  173. 8'd175:count_end = C_0;
  174. 8'd176,8'd177,8'd178: count_end = C_2;
  175. 8'd179:count_end = C_0;
  176. 8'd180,8'd181,8'd182: count_end = C_2;
  177. 8'd183:count_end = C_0;
  178. 8'd184,8'd185,8'd186,8'd187: count_end = C_1;
  179. 8'd188,8'd189,8'd190: count_end = C_1;
  180. 8'd191:count_end = C_0;
  181. //===================整点报时音乐=====================
  182. 8'd192: count_end = C_7;
  183. 8'd193:count_end = C_0;
  184. 8'd194: count_end = C_7;
  185. 8'd195:count_end = C_0;
  186. 8'd196: count_end = C_7;
  187. 8'd197:count_end = C_0;
  188. 8'd198: count_end = C_7;
  189. 8'd199:count_end = C_0;
  190. 8'd200,8'd201,8'd202,8'd203,
  191. 8'd204,8'd205,8'd206,8'd207: count_end = C_1;
  192. default: count_end = 17'hxxxxx;
  193. endcase
  194. end
  195. endmodule
  1. module stop_watch(
  2. input clk,
  3. input rst_n,
  4. input [1:0] model,
  5. input pause, //秒表暂停/开始
  6. input clear, //秒表清除
  7. output [23:0] stop_watch_num //输出显示
  8. );
  9. //---------------------- 10ms上升沿 ----------------------
  10. wire clk_10ms;
  11. reg clk_10ms_reg1, clk_10ms_reg2;
  12. wire pos_10ms;
  13. clk_div #(.CNT_MAX(250000)) clk_div_10ms( //250000仿真参数250
  14. .clk_in (clk),
  15. .rst_n (rst_n),
  16. .clk_out (clk_10ms)
  17. );
  18. always@(posedge clk, negedge rst_n) begin
  19. if(!rst_n) begin
  20. clk_10ms_reg1 <= 1'b0;
  21. clk_10ms_reg2 <= 1'b0;
  22. end
  23. else begin
  24. clk_10ms_reg1 <= clk_10ms;
  25. clk_10ms_reg2 <= clk_10ms_reg1;
  26. end
  27. end
  28. assign pos_10ms = clk_10ms_reg1 & (~clk_10ms_reg2);
  29. //----------------------- 10ms_计数 ------------------------
  30. reg [3:0] cnt_ms0;
  31. reg [3:0] cnt_ms1;
  32. reg [3:0] cnt_s0;
  33. reg [3:0] cnt_s1;
  34. reg [3:0] cnt_m0;
  35. reg [3:0] cnt_m1;
  36. always@(posedge clk, negedge rst_n) begin
  37. if(!rst_n) begin //异步复位
  38. cnt_ms0 <= 4'd0;
  39. cnt_ms1 <= 4'd0;
  40. cnt_s0 <= 4'd0;
  41. cnt_s1 <= 4'd0;
  42. cnt_m0 <= 4'd0;
  43. cnt_m1 <= 4'd0;
  44. end
  45. else if(clear) begin //同步清零
  46. cnt_ms0 <= 4'd0;
  47. cnt_ms1 <= 4'd0;
  48. cnt_s0 <= 4'd0;
  49. cnt_s1 <= 4'd0;
  50. cnt_m0 <= 4'd0;
  51. cnt_m1 <= 4'd0;
  52. end
  53. else if(pos_10ms) begin
  54. if(model == 2'b10) begin //秒表模式
  55. if(pause) begin //开始
  56. cnt_ms0 <= cnt_ms0 + 1'b1;
  57. if(cnt_ms0 == 4'd9) begin
  58. cnt_ms0 <= 4'd0;
  59. cnt_ms1 <= cnt_ms1 + 1'b1;
  60. if(cnt_ms1 == 4'd9) begin //99, 1s时间到
  61. cnt_ms1 <= 4'd0;
  62. cnt_s0 <= cnt_s0 + 1'b1;
  63. if(cnt_s0 == 4'd9) begin
  64. cnt_s0 <= 4'd0;
  65. cnt_s1 <= cnt_s1 + 1'b1;
  66. if(cnt_s1 == 4'd5) begin //59s
  67. cnt_s1 <= 4'd0;
  68. cnt_m0 <= cnt_m0 + 1'b1;
  69. if(cnt_m0 == 4'd9) begin
  70. cnt_m0 <= 4'd0;
  71. cnt_m1 <= cnt_m1 + 1'b1;
  72. end
  73. end
  74. end
  75. end
  76. end
  77. end
  78. end
  79. end
  80. else if(cnt_m1==4'd10) begin //上限
  81. cnt_ms0 <= 4'd0;
  82. cnt_ms1 <= 4'd0;
  83. cnt_s0 <= 4'd0;
  84. cnt_s1 <= 4'd0;
  85. cnt_m0 <= 4'd0;
  86. cnt_m1 <= 4'd0;
  87. end
  88. else begin
  89. cnt_ms0 <= cnt_ms0;
  90. cnt_ms1 <= cnt_ms1;
  91. cnt_s0 <= cnt_s0;
  92. cnt_s1 <= cnt_s1;
  93. cnt_m0 <= cnt_m0;
  94. cnt_m1 <= cnt_m1;
  95. end
  96. end
  97. //--------------------------- 输出 ------------------
  98. assign stop_watch_num = {cnt_m1, cnt_m0, cnt_s1, cnt_s0, cnt_ms1, cnt_ms0};
  99. endmodule
  1. //---------------------数码管显示-------------------------------------------------
  2. module led_seg7_display(
  3. input clk,
  4. input rst_n,
  5. input [1:0] model,
  6. input [23:0] time_num, // 时钟数据
  7. input [23:0] adjust_time_num, // 调整时钟数据
  8. input [15:0] adjust_clock_num,// 调整闹钟数据
  9. input [23:0] stop_watch_num, // 秒表
  10. output [5:0] sel, // 数码管位选(选择当前要显示的数码管)
  11. output reg [6:0] seg // 数码管段选(当前要显示的内容)
  12. );
  13. //---------------- 显示数据选择 ----------------------
  14. reg [23:0] show_num;
  15. always@(posedge clk, negedge rst_n) begin
  16. if(!rst_n)
  17. show_num <= 24'h0;
  18. else begin
  19. if(model == 2'b00) begin //常规显示
  20. show_num <= time_num;
  21. end
  22. else if(model == 2'b01) //闹钟显示
  23. show_num <= {adjust_clock_num, 8'b00000000}; //闹钟只有小时和分钟
  24. else if(model == 2'b10) //秒表显示
  25. show_num <= stop_watch_num;
  26. else begin //调整时间
  27. show_num <= adjust_time_num;
  28. end
  29. end
  30. end
  31. //--------------------- 数码管显示逻辑 ------------------------
  32. wire clk_1ms; //数码管扫描周期1ms
  33. clk_div #(.CNT_MAX(100000)) clk_div_1ms( //100000为了缩短仿真时间,参数设100
  34. .clk_in (clk),
  35. .rst_n (rst_n),
  36. .clk_out (clk_1ms)
  37. );
  38. reg [5:0]sel_r; //位选缓存
  39. reg [3:0]data_tmp; //数据缓存
  40. always@(posedge clk_1ms or negedge rst_n)
  41. if(!rst_n)
  42. sel_r <= 6'b0000_01;
  43. else if(sel_r == 6'b1000_00)
  44. sel_r <= 6'b0000_01;
  45. else
  46. sel_r <= sel_r << 1;
  47. always@(*)
  48. case(sel_r)
  49. 8'b0000_01:data_tmp = show_num[3:0];
  50. 8'b0000_10:data_tmp = show_num[7:4];
  51. 8'b0001_00:data_tmp = show_num[11:8];
  52. 8'b0010_00:data_tmp = show_num[15:12];
  53. 8'b0100_00:data_tmp = show_num[19:16];
  54. 8'b1000_00:data_tmp = show_num[23:20];
  55. default: data_tmp = 4'b0000;
  56. endcase
  57. always@(*)
  58. case(data_tmp)
  59. 4'd0:seg = 7'b1111110;
  60. 4'd1:seg = 7'b0110000;
  61. 4'd2:seg = 7'b1101101;
  62. 4'd3:seg = 7'b1111001;
  63. 4'd4:seg = 7'b0110011;
  64. 4'd5:seg = 7'b1011011;
  65. 4'd6:seg = 7'b1011111;
  66. 4'd7:seg = 7'b1110000;
  67. 4'd8:seg = 7'b1111111;
  68. 4'd9:seg = 7'b1111011;
  69. default: seg = 7'b1111111;
  70. endcase
  71. assign sel = sel_r;
  72. endmodule
  1. //modelsim仿真
  2. `timescale 10ns/ 10ns
  3. module text_CourseDesign_513();
  4. reg clk;
  5. reg rst_n;
  6. reg [6:1] key_in;
  7. reg key_input;
  8. reg key_alarm;
  9. wire [5:0] sel;
  10. wire [7:6] sel_0;
  11. wire [6:0] seg;
  12. wire beep;
  13. wire [3:0] model_led;
  14. CourseDesign_513 h(
  15. .clk(clk), //50MHz
  16. .rst_n(rst_n), //初始化
  17. .key_in(key_in), //按键输入
  18. .key_input(key_input), //设置时间的确认按键
  19. .key_alarm(key_alarm), //闹钟开关
  20. .sel(sel), //数码管位选
  21. .sel_0(sel_0), //数码管不显示
  22. .seg(seg), //数码管段选
  23. .beep(beep), //闹钟音乐
  24. .model_led(model_led) //模式led
  25. );
  26. initial
  27. begin
  28. clk = 1'b0;
  29. rst_n=1'b0;
  30. key_in=6'b000000;
  31. key_input=1'b0;
  32. key_alarm=1'b0;
  33. #50_000 rst_n=1'b1;//初始化结束
  34. #1_000_000 key_in=6'b000001;//切换闹钟模式
  35. #10_000 key_in=6'b000000;
  36. #10_000 key_in=6'b000001;//切换秒表模式
  37. #10_000 key_in=6'b000000;
  38. #50_000 key_in=6'b010000;//开始计时
  39. #10_000 key_in=6'b000000;
  40. #500_000 key_in=6'b010000;//暂停
  41. #10_000 key_in=6'b000000;
  42. #50_000 key_in=6'b100000;//清零
  43. #10_000 key_in=6'b000000;
  44. #50_000 key_in=6'b000001;//切换调时模式
  45. #10_000 key_in=6'b000000;
  46. #10_000 key_in=6'b000010;//调位置
  47. #10_000 key_in=6'b000000;
  48. #10_000 key_in=6'b001000;//加1
  49. #10_000 key_in=6'b000000;
  50. #10_000 key_in=6'b001000;//加2
  51. #10_000 key_in=6'b000000;
  52. #10_000 key_in=6'b001000;//加3
  53. #10_000 key_in=6'b000000;
  54. #10_000 key_in=6'b001000;//加4
  55. #10_000 key_in=6'b000000;
  56. #10_000 key_in=6'b001000;//加5
  57. #10_000 key_in=6'b000000;
  58. #10_000 key_input=1'b1;key_in=6'b000001;//调时确认
  59. #10000 key_input=1'b0;key_in=6'b000000;
  60. end
  61. always #1 clk = ~clk;
  62. endmodule

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

闽ICP备14008679号