赞
踩
本次实验是本人全部用状态机实现的,所以导致我的状态机空间有很多状态,有一部分状态可以进行修改,不过我认为全部写成状态机更有利于本人的理解,可能有人会觉得很绕,不过根据本人自身所画的状态图,就能较为清晰明了,本文结尾会附上所有代码,如有需要自取即可,但我希望不要一味的复制粘贴,理解之后手敲一遍更能提升自己,如需要工程文件私信我或者评论区找我,现写下此博客以便日后复习。
该开发板为EP4CE6F17C8
1、完成基本24时计数显示2、显示时间可调整
3、设置可调闹钟-闹钟触发时蜂鸣器响起
蜂鸣器原理输入一定频率的方波或者PWM信号,蜂鸣器就可以发出声音。输入不同频率的信号,蜂鸣器可以发出不同音色的声音
电子时钟原理是在数码管中由于有位选信号和段选信号的存在,我们无法做到将数码管同时进行变换,所以我们通过快速的切换和刷新,使得我们看到的是连续的多个数码管显示结果。通过控制位选信号和段选信号,可以实现不同的数字、字母或符号的动态显示。
将按键进行按键消抖获得稳定信号。
使用按键通过状态机切换状态控制位选信号,在相应的位选信号下,控制时位,分位,秒位的数值加一或减一。
利用相同原理使用状态机切换状态——闹钟设置状态和常规电子时钟状态,闹钟设置状态下对时分秒位的操作与电子时钟状态一致
闹钟状态中将设定的值与电子时钟的值比对,如果相等则传给蜂鸣器一个信号,并将该信号持续5s,是蜂鸣器发声五秒
我所用的板子自带的蜂鸣器是无源蜂鸣器——内部无振荡源,需要通以方波、PWM信号才能发出声音,以及是低电平有效
开发板上的数码管数码管位选和段选信号都是低电平有效。
位选信号根据需要的显示位数进行生成(该实验所用的开发板可用6个位选信号),它们用于选择要显示的数码管。
段选信号根据需要的显示内容进行生成,它们用于控制数码管的七段LED灯以及小数点LED灯的亮灭状态(该实验所用的开发板可用8个段选信号)。
本次实验有按键消抖模块、计数器模块、蜂鸣器模块、音符模块、数码管驱动模块
按键消抖模块将按键信号转化为稳定的有效信号
计数器模块通过输入的有效按键信号,key3切换闹钟和电子时钟状态,以及key1加,key2减,时位、分位、秒位的加减,比对闹钟空间和电子时钟的时间数值,若相等则传出一个蜂鸣器信号给音符模块,再将hour、min、sec数值输入进数码管驱动模块进行显示。
数码管驱动模块,将计数器模块产生的时分秒显示出来,以及key0切换时位、分位、秒位、空闲状态的切换。
音符模块,接收到闹钟信号时将pwm波发给蜂鸣器发声模块,持续5s
蜂鸣器模块,接收到音符模块的pwm波,发声
顶层模块,统合所有模块。
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | key_in | 按键信号 |
output | reg | key_flag | 稳定按键信号 |
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | key_flag | 稳定按键信号 |
output | wire | hour | 小时数 |
output | wire | min | 分钟数 |
output | wire | sec | 秒钟数 |
output | wire | music_flag | 闹钟信号 |
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | music_flag | 闹钟到时信号 |
output | reg | flag | 蜂鸣器发声信号 |
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | flag | 控制蜂鸣器发声信号 |
output | reg | beep | 蜂鸣器发声信号 |
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | hour | 小时数 |
input | wire | min | 分钟数 |
input | wire | sec | 秒钟数 |
input | wire | key_flag | 稳定按键信号 |
output | reg | seg | 数码管段选信号 |
output | reg | sel | 数码管位选信号 |
端口信号 | 信号类型 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
input | wire | key_in | 按键信号 |
output | wire | sel | 数码管位选信号 |
output | wire | beep | 蜂鸣器发声信号 |
output | wire | seg | 数码管段选信号 |
闹钟空间时分秒位也有相同的加一减一,这里本人偷懒了没有画全。
无仿真波形
# Copyright (C) 2018 Intel Corporation. All rights reserved. # Your use of Intel Corporation's design tools, logic functions # and other software and tools, and its AMPP partner logic # functions, and any output files from any of the foregoing # (including device programming or simulation files), and any # associated documentation or information are expressly subject # to the terms and conditions of the Intel Program License # Subscription Agreement, the Intel Quartus Prime License Agreement, # the Intel FPGA IP License Agreement, or other applicable license # agreement, including, without limitation, that your use is for # the sole purpose of programming logic devices manufactured by # Intel and sold by Intel or its authorized distributors. Please # refer to the applicable agreement for further details. # Quartus Prime Version 18.1.0 Build 625 09/12/2018 SJ Standard Edition # File: D:\intelFPGA\code\dig_clock\tcl\dig_clock.tcl # Generated on: Mon Aug 07 16:06:21 2023 package require ::quartus::project set_location_assignment PIN_A5 -to seg[7] set_location_assignment PIN_B8 -to seg[6] set_location_assignment PIN_A7 -to seg[5] set_location_assignment PIN_B6 -to seg[4] set_location_assignment PIN_B5 -to seg[3] set_location_assignment PIN_A6 -to seg[2] set_location_assignment PIN_A8 -to seg[1] set_location_assignment PIN_B7 -to seg[0] set_location_assignment PIN_E1 -to clk set_location_assignment PIN_A4 -to sel[0] set_location_assignment PIN_B4 -to sel[1] set_location_assignment PIN_A3 -to sel[2] set_location_assignment PIN_B3 -to sel[3] set_location_assignment PIN_A2 -to sel[4] set_location_assignment PIN_B1 -to sel[5] set_location_assignment PIN_E15 -to key_in[0] set_location_assignment PIN_E16 -to key_in[1] set_location_assignment PIN_M16 -to key_in[2] set_location_assignment PIN_M15 -to key_in[3] set_location_assignment PIN_J1 -to beep
module key ( input wire clk, input wire rst_n, input wire key_in, output reg key_out, output reg key_flag ); parameter CNT_MAX =20'd999_999; //20ms计数 reg [19:0] cnt_20ms; //reg key_flag; //20ms消抖 always@(posedge clk or negedge rst_n) if(!rst_n) cnt_20ms<=20'b0; else if(key_in==1'b1) cnt_20ms<=20'd0; else if(cnt_20ms==CNT_MAX) cnt_20ms<=CNT_MAX; else cnt_20ms<=cnt_20ms+20'd1; //取单个脉冲信号 always@(posedge clk or negedge rst_n) if(!rst_n) key_flag<=1'b0; else if(cnt_20ms==(CNT_MAX-20'd1)) key_flag<=1'b1; else key_flag<=1'b0; //有效长信号 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin key_out <= 1'b0; end else if(key_flag == 1'b1) key_out <= ~key_out; else key_out <= key_out; end endmodule
module counter ( input wire clk , input wire rst_n , input wire [3:0] key_flag, output wire [4:0] hour , output wire [5:0] min , output wire [5:0] sec , output wire music_flag ); reg [8:0] cnt_min ;//存放分钟加减 reg [8:0] cnt_sec ;//存放秒钟加减 parameter MAXDAY = 17'd86400;//24小时 24*60*60 parameter SEC = 26'd50_000_000;//1s reg [5:0] c_state;//现态,数码管选位加减 reg [5:0] n_state;//次态,数码管选位加减 parameter IDLE = 6'd0, //空闲状态 S1 = 6'd1, //数码管时位 S2 = 6'd2, //数码管分位 S3 = 6'd3, //数码管秒位 A1 = 6'd4, //时位加 M1 = 6'd5, //时位减 A2 = 6'd6, //分位加 M2 = 6'd7, //分位减 A3 = 6'd8, //秒位减 M3 = 6'd9, //秒位减 R1 = 6'd10, //闹钟功能空间 P1 = 6'd11, //数码管时位 P2 = 6'd12, //数码管分位 P3 = 6'd13, //数码管秒位 A4 = 6'd14, //时位加 M4 = 6'd15, //时位减 A5 = 6'd16, //分位加 M5 = 6'd17, //分位减 A6 = 6'd18, //秒位减 M6 = 6'd19; //秒位减 reg [25:0] cnt_1s ; reg [25:0] cnt_1s_r ; reg [16:0] cnt_day ; reg [16:0] cnt_day_r ; reg [31:0] cnt_10ms ; wire [4:0] hour_r ;//存放时钟加减 wire [5:0] min_r ; wire [5:0] sec_r ; parameter MAX_10ms = 32'd499_999; //10ms计数器 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_10ms <= 26'd0; end else if (cnt_10ms == MAX_10ms) begin cnt_10ms <= 26'd0; end else begin cnt_10ms <= cnt_10ms + 1'd1; end end //1秒计数器 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_1s <= 26'd0; end else if (cnt_1s == SEC - 1'd1) begin cnt_1s <= 26'd0; end else begin cnt_1s <= cnt_1s + 1'd1; end end //1天计时器_电子时钟 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_day <= 17'd0; end else if(cnt_day >= MAXDAY - 1'd1)begin cnt_day <= 17'd0; end else if( cnt_1s == SEC -1'd1)begin cnt_day <= cnt_day + 1'd1; end else if(n_state == A1) begin cnt_day <= cnt_day + 17'd3600; end else if(n_state == M1) begin cnt_day <= cnt_day - 17'd3600; end else if (c_state== S1 &&key_flag[2] && (cnt_day / 3600)== 0) begin cnt_day <= cnt_day + 17'd82800; end else if(n_state == A2) begin cnt_day <= cnt_day + 17'd60; end else if(n_state == M2) begin cnt_day <= cnt_day - 17'd60; end else if(n_state == A3) begin cnt_day <= cnt_day + 17'd1; end else if(n_state == M3) begin cnt_day <= cnt_day - 17'd1; end else begin cnt_day <= cnt_day; end end //1天计时器_r_闹钟空间 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_day_r <= 17'd0; end else if(cnt_day_r >= MAXDAY - 1'd1)begin cnt_day_r <= 17'd0; end else if(n_state == A4) begin cnt_day_r <= cnt_day_r + 17'd3600; end else if(n_state == M4) begin cnt_day_r <= cnt_day_r - 17'd3600; end else if (key_flag[2] && (cnt_day_r / 3600)== 0) begin cnt_day_r <= cnt_day_r + 17'd82800; end else if(n_state == A5) begin cnt_day_r <= cnt_day_r + 17'd60; end else if(n_state == M5) begin cnt_day_r <= cnt_day_r - 17'd60; end else if(n_state == A6) begin cnt_day_r <= cnt_day_r + 17'd10; end else if(n_state == M6) begin cnt_day_r <= cnt_day_r - 17'd10; end else begin cnt_day_r <= cnt_day_r; end end //如果处于闹钟空间则输出闹钟空间的值,否则输出电子时钟的值 assign hour = (c_state == R1||c_state == P1||c_state == P2||c_state == P3)?hour_r:cnt_day / 3600; assign min = (c_state == R1||c_state == P1||c_state == P2||c_state == P3)?min_r:cnt_day % 3600 / 60; assign sec = (c_state == R1||c_state == P1||c_state == P2||c_state == P3)?sec_r:cnt_day % 3600 % 60; assign hour_r = cnt_day_r /3600; assign min_r = cnt_day_r % 3600 / 60; assign sec_r = cnt_day_r % 3600 % 60; //如果闹钟空间的值除了零以外的时候和电子时钟的值相等,则输出音乐信号给乐谱模块 assign music_flag = (cnt_day == cnt_day_r&&cnt_day_r != 0)?1:0; //数码管选位状态机,第一段 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin c_state <= IDLE; end else begin c_state <= n_state; end end //数码管选位状态机,第二段 always @(*) begin case (c_state) //空闲状态 IDLE :begin if (key_flag[0]) begin n_state = S1; end else if (key_flag[3]) begin n_state = R1; end else begin n_state = IDLE; end end //闹钟状态 R1 :begin if (key_flag[0]) begin n_state = P1; end else if (key_flag[3]) begin n_state = IDLE; end else begin n_state = R1; end end //换位状态:时位 S1 :begin if (key_flag[0]) begin n_state = S2; end else if (key_flag[1]) begin n_state = A1; end else if (key_flag[2]) begin n_state = M1; end else begin n_state = S1; end end //换位状态:分位 S2 :begin if (key_flag[0]) begin n_state = S3; end else if (key_flag[1]) begin n_state = A2; end else if (key_flag[2]) begin n_state = M2; end else begin n_state = S2; end end //换位状态:秒位 S3 :begin if (key_flag[0]) begin n_state = IDLE; end else if (key_flag[1]) begin n_state = A3; end else if (key_flag[2]) begin n_state = M3; end else begin n_state = S3; end end //时位加一 A1 :begin if (c_state == A1) begin n_state = S1; end else begin n_state = A1; end end //时位减一 M1 :begin if (c_state == M1) begin n_state = S1; end else begin n_state = M1; end end //分位加一 A2 :begin if (c_state == A2) begin n_state = S2; end else begin n_state = A2; end end //分位减一 M2 :begin if (c_state == M2) begin n_state = S2; end else begin n_state = M2; end end //秒位加一 A3 :begin if (c_state == A3) begin n_state = S3; end else begin n_state = A3; end end //秒位减一 M3 :begin if (c_state == M3) begin n_state = S3; end else begin n_state = M3; end end //闹钟空间:时位 P1 :begin if (key_flag[0]) begin n_state = P2; end else if (key_flag[1]) begin n_state = A4; end else if (key_flag[2]) begin n_state = M4; end else begin n_state = P1; end end //闹钟空间:分位 P2 :begin if (key_flag[0]) begin n_state = P3; end else if (key_flag[1]) begin n_state = A5; end else if (key_flag[2]) begin n_state = M5; end else begin n_state = P2; end end //闹钟空间:秒位 P3 :begin if (key_flag[0]) begin n_state = R1; end else if (key_flag[1]) begin n_state = A6; end else if (key_flag[2]) begin n_state = M6; end else begin n_state = P3; end end //闹钟空间:时位加一 A4 :begin if (c_state == A4) begin n_state = P1; end else begin n_state = A4; end end //闹钟空间:时位减一 M4 :begin if (c_state == M4) begin n_state = P1; end else begin n_state = M4; end end //闹钟空间:分位加一 A5 :begin if (c_state == A5) begin n_state = P2; end else begin n_state = A5; end end //闹钟空间:分位减一 M5 :begin if (c_state == M5) begin n_state = P2; end else begin n_state = M5; end end //闹钟空间:秒位加一 A6 :begin if (c_state == A6) begin n_state = P3; end else begin n_state = A6; end end //闹钟空间:秒位减一 M6 :begin if (c_state == M6) begin n_state = P3; end else begin n_state = M6; end end default:n_state = IDLE; endcase end endmodule
module music ( input clk, input rst_n, input [3:0] key_out, input music_flag, output reg flag ); parameter MAX_0_3s = 25'd14_999_999; reg [31:0] cnt_0_3s; parameter MAX_1s = 32'd49_999_999; reg [31:0] cnt_1s ;//1秒计数器 parameter MAX_5s = 32'd5; reg [31:0] cnt_5s ;//1秒计数器 parameter MAX_7 = 6'd33;//乐谱 reg [15:0] cnt_7; //乐谱1寄存器 //parameter MAX_two_tiger = 6'd33; //reg [15:0] two_tiger;//乐谱2寄存器 //parameter MAX_300ms = 25'd14_999_999; //reg [31:0] cnt_300ms; reg [15:0] music_cnt;//音符音频计数器 wire[15:0] duty;//占空比 reg [15:0] music;//音符数据寄存器 reg music_delay; parameter DO = 16'd47750 ;//1 parameter RE = 16'd42250 ;//2 parameter MI = 16'd37900 ;//3 parameter FA = 16'd37550 ;//4 parameter SO = 16'd31850 ;//5 parameter LA = 16'd28400 ;//6 parameter XI = 16'd25400 ;//7 //1s计数器 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_1s <= 1'd0; end else if (cnt_1s == MAX_1s) begin cnt_1s <= 1'd0; end else begin cnt_1s <= cnt_1s + 1; end end //5s计数器 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_5s <= 1'd0; end else if (cnt_5s == MAX_5s) begin cnt_5s <= 1'd0; end else if (cnt_1s == MAX_1s)begin cnt_5s <= cnt_5s + 1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin music_delay <= 1'd0; end else if (cnt_5s == MAX_5s) begin music_delay <= 1'd0; end else if (music_flag)begin music_delay <= 1'd1; end end //0.3s计数器 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_0_3s <= 1'd0; end else if (cnt_0_3s == MAX_0_3s) begin cnt_0_3s <= 1'd0; end else begin cnt_0_3s <= cnt_0_3s + 1; end end //300ms计数器 //always @(posedge clk or negedge rst_n) begin // if (!rst_n) begin // cnt_300ms <= 1'd0; // end // else if (cnt_300ms == MAX_300ms) begin // cnt_300ms <= 1'd0; // end // else begin // cnt_300ms <= cnt_300ms + 1; // end //end //音符频率计数器 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin music_cnt <= 16'd0; end else if(music_cnt == music)begin music_cnt <= 16'd0; end else begin music_cnt <= music_cnt + 1'd1; end end //乐谱1每隔0.5s音符切换 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt_7 <= 1'd0; end else if (cnt_7 == MAX_7 && cnt_0_3s == MAX_0_3s) begin cnt_7 <= 1'd0; end else if (cnt_0_3s == MAX_0_3s) begin cnt_7 <= cnt_7 + 1'd1; end else begin cnt_7 <= cnt_7; end end //乐谱2的切换间隔为300ms //always @(posedge clk or negedge rst_n) begin // if (!rst_n) begin // two_tiger <= 1'd0; // end // else if (two_tiger == MAX_two_tiger && cnt_300ms == MAX_300ms) begin // two_tiger <= 1'd0; // end // else if (cnt_300ms == MAX_0_5s) begin // two_tiger <= two_tiger + 1'd1; // end // else begin // two_tiger <= two_tiger; // end //end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin music <= 1'd0; end //else if(key_out[1])begin case (cnt_7) 6'd0: music <= DO; 6'd1: music <= RE; 6'd2: music <= MI; 6'd3: music <= DO; 6'd4: music <= DO; 6'd5: music <= RE; 6'd6: music <= MI; 6'd7: music <= DO; 6'd8: music <= MI; 6'd9: music <= FA; 6'd10: music <= SO; 6'd11: music <= MI; 6'd12: music <= FA; 6'd13: music <= SO; 6'd14: music <= SO; 6'd15: music <= LA; 6'd16: music <= SO; 6'd17: music <= FA; 6'd18: music <= MI; 6'd19: music <= DO; 6'd20: music <= SO; 6'd21: music <= LA; 6'd22: music <= SO; 6'd23: music <= FA; 6'd24: music <= MI; 6'd25: music <= DO; 6'd26: music <= RE; 6'd27: music <= SO; 6'd28: music <= DO; 6'd29: music <= DO; 6'd30: music <= RE; 6'd31: music <= SO; 6'd32: music <= DO; 6'd33: music <= DO; default:music <= DO; endcase //end //else if(!key_out[1])begin // case(cnt_7) // 10'd0: music <= DO ; // 10'd1: music <= RE ; // 10'd2: music <= MI ; // 10'd3: music <= FA ; // 10'd4: music <= SO ; // 10'd5: music <= LA ; // 10'd6: music <= XI ; // 10'd7: music <= DO ; // 10'd8: music <= RE ; // 10'd9: music <= MI ; // 10'd10: music <= FA ; // 10'd11: music <= SO ; // 10'd12: music <= LA ; // 10'd13: music <= XI ; // 10'd14: music <= DO ; // 10'd15: music <= RE ; // 10'd16: music <= MI ; // 10'd17: music <= FA ; // 10'd18: music <= SO ; // 10'd19: music <= LA ; // 10'd20: music <= XI ; // default: music <= DO; // endcase //end end assign duty = music >> 1;//占空比50% always@(posedge clk or negedge rst_n)begin if(!rst_n)begin flag <= 1'b0; end else if (music_delay)begin flag <= (music_cnt >= duty) ? 1'b1 : 1'b0; end else begin flag <= 1'b0; end end endmodule
module beep ( input clk, input rst_n, input flag, output reg beep ); always @(posedge clk or negedge rst_n) begin if (!rst_n) begin beep <= 1'b1; end else if (flag) begin beep <= 1'b0; end else begin beep <= 1'b1; end end endmodule
module seg_driver ( input wire clk , input wire rst_n , input wire [4:0] hour , input wire [5:0] min , input wire [5:0] sec , input wire [3:0] key_flag, output reg [7:0] seg , //段选信号 output reg [5:0] sel //位选信号 ); reg [8:0] cnt_num ; reg [19:0] cnt_delay ; reg [7:0] point ;//小数点 reg [5:0] c_state;//现态,数码管选位加减 reg [5:0] n_state;//次态,数码管选位加减 parameter IDLE = 6'd0, //空闲状态 S1 = 6'd1, //数码管时位 S2 = 6'd2, //数码管分位 S3 = 6'd3; //数码管秒位 parameter MAX_1s = 32'd24_999_999; reg [31:0] cnt_1s ;//1秒计数器 parameter CNT_DELAY_MAX= 10'd1000 ; parameter ZERO = 8'b1100_0000 , ONE = 8'b1111_1001 , TWO = 8'b1010_0100 , THREE = 8'b1011_0000 , FOUR = 8'b1001_1001 , FIVE = 8'b1001_0010 , SIX = 8'b1000_0010 , SEVEN = 8'b1111_1000 , EIGHT = 8'b1000_0000 , NINE = 8'b1001_0000 ; //1s计数器 always @(posedge clk or negedge rst_n) begin if(!rst_n)begin cnt_1s <= 10'd0; end else if(cnt_1s == MAX_1s)begin cnt_1s <= 10'd0; end else begin cnt_1s <= cnt_1s + 1'd1; end end //20us计数器 always @(posedge clk or negedge rst_n) begin if(!rst_n)begin cnt_delay <= 10'd0; end else if(cnt_delay == CNT_DELAY_MAX - 1'd1)begin cnt_delay <= 10'd0; end else begin cnt_delay <= cnt_delay + 1'd1; end end //该板块无法同时变化,只能依次闪烁,该方法为依次闪烁的间隔,人肉眼无法判断 20us always @(posedge clk or negedge rst_n) begin if (!rst_n) begin sel <= 6'b111_110; end else if (cnt_delay == CNT_DELAY_MAX - 1'd1) begin sel <= {sel[4:0],sel[5]}; end else begin sel <= sel ; end end always @(*) begin //若处于时位,则相应的位选信号闪烁 if (c_state == S1) begin case (sel) 6'b111110:begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = hour / 10; end 6'b111101: begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = hour % 10 + 10; end 6'b111011: cnt_num = min / 10; 6'b110111: cnt_num = min % 10 + 10; 6'b101111: cnt_num = sec / 10; 6'b011111: cnt_num = sec % 10; default: cnt_num = 4'd0; endcase end //若处于分位,则相应的位选信号闪烁 else if (c_state == S2) begin case (sel) 6'b111110: cnt_num = hour / 10; 6'b111101: cnt_num = hour % 10 + 10; 6'b111011: begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = min / 10; end 6'b110111: begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = min % 10 + 10; end 6'b101111: cnt_num = sec / 10; 6'b011111: cnt_num = sec % 10; default: cnt_num = 4'd0; endcase end //若处于秒位,则相应的位选信号闪烁 else if (c_state == S3) begin case (sel) 6'b111110: cnt_num = hour / 10; 6'b111101: cnt_num = hour % 10 + 10; 6'b111011: cnt_num = min / 10; 6'b110111: cnt_num = min % 10 + 10; 6'b101111: begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = sec / 10; end 6'b011111: begin if (cnt_1s <= MAX_1s/2) begin cnt_num = 9'd20; end else cnt_num = sec % 10; end default: cnt_num = 4'd0; endcase end else begin //其他情况数码管正常显示 case (sel) 6'b111110: cnt_num = hour / 10; 6'b111101: cnt_num = hour % 10 + 10; 6'b111011: cnt_num = min / 10; 6'b110111: cnt_num = min % 10 + 10; 6'b101111: cnt_num = sec / 10; 6'b011111: cnt_num = sec % 10; default: cnt_num = 4'd0; endcase end end //通过数字num解析出seg值 always @(*) begin case (cnt_num) 9'd0:begin seg <= ZERO ; end 9'd1:begin seg <= ONE ; end 9'd2:begin seg <= TWO ; end 9'd3:begin seg <= THREE ; end 9'd4:begin seg <= FOUR ; end 9'd5:begin seg <= FIVE ; end 9'd6:begin seg <= SIX ; end 9'd7:begin seg <= SEVEN ; end 9'd8:begin seg <= EIGHT ; end 9'd9:begin seg <= NINE ; end 9'd10:begin seg <= {point[7],ZERO[6:0]} ; end 9'd11:begin seg <= {point[7],ONE[6:0]} ; end 9'd12:begin seg <= {point[7],TWO[6:0]} ; end 9'd13:begin seg <= {point[7],THREE[6:0]} ; end 9'd14:begin seg <= {point[7],FOUR[6:0]} ; end 9'd15:begin seg <= {point[7],FIVE[6:0]} ; end 9'd16:begin seg <= {point[7],SIX[6:0]} ; end 9'd17:begin seg <= {point[7],SEVEN[6:0]} ; end 9'd18:begin seg <= {point[7],EIGHT[6:0]} ; end 9'd19:begin seg <= {point[7],NINE[6:0]} ; end 9'd20:begin seg <= 8'b11111111 ; end default: seg <= ZERO; endcase end //数码管选位状态机,第一段 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin c_state <= IDLE; end else begin c_state <= n_state; end end //数码管选位状态机,第二段 always @(*) begin case (c_state) //空闲状态 IDLE :begin if (key_flag[0]) begin n_state = S1; end else begin n_state = IDLE; end end //数码管时位 S1 :begin if (key_flag[0]) begin n_state = S2; end else begin n_state = S1; end end //数码管分位 S2 :begin if (key_flag[0]) begin n_state = S3; end else begin n_state = S2; end end //数码管秒位 S3 :begin if (key_flag[0]) begin n_state = IDLE; end else begin n_state = S3; end end default:n_state = IDLE; endcase end endmodule
module top( input wire clk, input wire rst_n, input wire [3:0] key_in, output wire [7:0] seg, output wire [5:0] sel, output wire beep ); wire [3:0] key_flag; wire [4:0] hour; wire [5:0] min; wire [5:0] sec; wire music_flag; wire flag; key u_key//key_fsm ( /* input wire */ .clk (clk ) , /* input wire */ .rst_n (rst_n ) , /* input wire */ .key_in (key_in[0]) , /* output reg */ .key_flag (key_flag[0]) ); key u_key1 ( /* input wire */ .clk (clk ) , /* input wire */ .rst_n (rst_n ) , /* input wire */ .key_in (key_in[1]) , /* output reg */ .key_flag (key_flag[1]) ); key u_key2 ( /* input wire */ .clk (clk ) , /* input wire */ .rst_n (rst_n ) , /* input wire */ .key_in (key_in[2]) , /* output reg */ .key_flag (key_flag[2]) ); key u_key3 ( /* input wire */ .clk (clk ) , /* input wire */ .rst_n (rst_n ) , /* input wire */ .key_in (key_in[3]) , /* output reg */ .key_flag (key_flag[3]) ); beep u_beep ( /* input */.clk (clk ), /* input */.rst_n(rst_n), /* input */.flag (flag ), /* output */.beep (beep ) ); music u_music( /* input */.clk (clk ) , /* input */.rst_n (rst_n ) , /* input */.key_out (key_out ) , /* input */.music_flag(music_flag) , /* output */.flag(flag) ); counter u_counter( .clk (clk) , .rst_n (rst_n) , .hour (hour) , .key_flag (key_flag), .music_flag (music_flag), .min (min) , .sec (sec) ); seg_driver u_seg_driver( .clk (clk) , .rst_n (rst_n) , .hour (hour) , .key_flag (key_flag), .min (min) , .sec (sec) , .seg (seg) , .sel (sel) ); endmodule
虽然该代码仍有许多不足,但如果对各位有所帮助,还请各位不要吝啬手中的点赞和关注。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。