赞
踩
本次实验我们需要实现生活中常见的电子手表的所有功能。
我们知道:
电子手表有五个功能,包括:时间显示功能,夜光模式功能,计时功能,闹钟功能,调时功能,
各功能实际效果介绍:
- 时间显示功能:正常状态下,时间正常显示时分秒
- 调光功能:按下1键也就是light键表灯亮度会逐渐改变
- 记时功能:按下2键也就是mooe键一次进入计时功能,这时按下3键也就是start键开始计时,再次按下时间停止,再次则继续,按下4键也就是reset键即记时归零。
- 闹钟调整及实现功能:按下2键两次进入闹钟功能,这时按下3键调整当前闪烁区域,按下4键更换区域。
- 时间调整功能:按下2键三次进入时间调整功能,这时按下三键调整当前闪烁区域,按下4键更换区域。
本次实验为了代码优美易于修正,整体上使用模块化设计实现多功能数字钟。
其中使用一个按钮开关调节模式mode:
- 0.时间显示功能
- 1.记时功能
- 2.闹钟调整功能
- 3.时间调整功能
详细使用FPGA资源如下:
- 拨动开关SW[0] —用于系统复位即顶层模块中的sys_rst_n,低电平有效
- 4个按钮开关KEY3—KEY0,其中
KEY3-light实现调光功能,
KEY2-mooe调整当前模式
KEY1-start调整数据/计时启动
KEY0-rst调整数据位置/计时复位- LED[17]-[14]用于显示当前mode,17亮则为mode0,16亮-mode1…
- LED[0]闪烁用于模拟闹钟报警
- 数码管0-1显示秒,3-4显示分,6-7显示时,2和5显示’-'将时分秒间隔开来

下面我将详细介绍各个模块及原理:
统筹整个实验的整体,其中mode改变,led模式显示,闹钟报警功能在此模块实现,其余都是调用模块部分
/* mode (按下mooe按键+1) 0 显示 小时:0-23 分钟:0-59 秒:0-59 1 计时 分钟:秒:99 start-->开始计时(1)-->暂停计时(0)-->开始计时... reset-归零 2 闹钟设置 start--加1(默认分钟) reset--切换小时/分钟设置 默认分钟-->小时-->分钟 小时:0-23 分钟:0-59 3 时间设置 start-- 秒(默认)-->归0 分钟/小时-->+1 reset--> 秒-->分钟-->小时 */ module clock ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 input wire light_an , //控制亮度 input wire mooe_an , //功能按键 input wire start_an , //调整数值按键 input wire reset_an , //切换区域按键 output reg led , //做闹钟用 LEDR0 闪烁 output reg [3:0] led_mode , //显示当前模式 LEDR17-LEDR14 output wire [6:0] SG0,SG1,SG2,SG3,SG4,SG5,SG6,SG7 //数码管的值 7-6,4-3,1-0显示数字 5,2显示: ); reg [1:0] mode;//模式, mooe按键控制 wire light,mooe,start,reset; //按键脉冲,高电平有效 wire clk1s_flag,clk10ms_flag; //时钟标志位 wire [7:0] sec,min,hour; //时钟变量寄存 wire [7:0] min_keti,sec_keti,misec_keti;//计时变量寄存 wire [7:0] min_alarm,hour_alarm ; //闹钟变量寄存 //1s,10ms时钟产生模块 clk clk_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n ) , //复位 .clk1s_flag (clk1s_flag ) , //1s时钟脉冲标志位 .clk10ms_flag (clk10ms_flag ) //10ms时钟脉冲标志位 ); //mode改变 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) mode <= 2'd0; else if(mooe && (mode == 2'd3)) mode <= 2'd0; else if(mooe) mode <= mode + 1'd1; else mode <= mode; //led_mode-显示当前模式 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) led_mode <= 4'b0000; else case(mode) 0:led_mode <= 4'b1000; 1:led_mode <= 4'b0100; 2:led_mode <= 4'b0010; 3:led_mode <= 4'b0001; default: led_mode <= 4'b1000; endcase //0.显示功能+ 3.时间设置 clockdisplay clockdisplay_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n ) , //复位 .mode (mode ) , //模式-相当于使能 .clk1s_flag(clk1s_flag ) , //1s脉冲 .mooe (mooe ) , //调整功能按键 .start (start ) , //开始暂停计数 .reset (reset ) , //置0 .sec_out (sec ) , //显示-秒 .min_out (min ) , //显示-分钟 .hour_out (hour ) //显示-小时 ); //1.计数功能 keeptime keeptime_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n ) , //复位 .mode (mode ) , //模式-相当于使能 .clk10ms_flag (clk10ms_flag ) , //10ms脉冲 .mooe (mooe ) , //调整功能按键 .start (start ) , //开始暂停计数 .reset (reset ) , //置0 .min_keti (min_keti ) , //计时-分钟 .sec_keti (sec_keti ) , //计时-秒 .misec_keti (misec_keti ) //计时-10ms ); //2.闹钟调整 alarmclock alarmclock_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n ) , //复位 .mode (mode ) , //模式-相当于使能 .mooe (mooe ) , //调整功能按键 .start (start ) , //开始暂停计数 .reset (reset ) , //置0 .min_alarm (min_alarm ) , //闹钟-分钟 .hour_alarm(hour_alarm) //闹钟-小时 ); //闹钟报警-1分钟灯闪烁 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) led <= 1'b0; else if(min != min_alarm || hour != hour_alarm) led <= 1'b0; else if((hour == hour_alarm) && (min == min_alarm) && clk1s_flag) led <= ~led; //数码管显示模块 segdisplay segdisplay_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n ) , //复位 .mode (mode ) , //模式-相当于使能 .light (light ) , //控制显示亮度 //时钟变量 .sec (sec ) , .min (min ) , .hour (hour ) , //计时变量 .min_keti (min_keti ) , .sec_keti (sec_keti ) , .misec_keti(misec_keti) , //闹钟变量 .min_alarm (min_alarm ) , .hour_alarm(hour_alarm) , //数码管的值 7-6,4-3,1-0显示数字 5,2显示: .SG0 (SG0) , .SG1 (SG1) , .SG2 (SG2) , .SG3 (SG3) , .SG4 (SG4) , .SG5 (SG5) , .SG6 (SG6) , .SG7 (SG7) ); //按键滤波器,按下按键产生一个高脉冲 key_filiter key_filiter_inst0 ( .sys_clk (sys_clk ) , .sys_rst_n(sys_rst_n) , .key_in (light_an) , .key_flag (light) ); key_filiter key_filiter_inst1 ( .sys_clk (sys_clk ) , .sys_rst_n(sys_rst_n) , .key_in (mooe_an) , .key_flag (mooe) ); key_filiter key_filiter_inst2 ( .sys_clk (sys_clk ) , .sys_rst_n(sys_rst_n) , .key_in (start_an) , .key_flag (start) ); key_filiter key_filiter_inst3 ( .sys_clk (sys_clk ) , .sys_rst_n(sys_rst_n) , .key_in (reset_an) , .key_flag (reset) ); endmodule
按键滤波器,按下按钮后即低电平输入,经过该模块输出一个系统时钟周期的高脉冲。
本次实验使用的四个按键都是通过这个模块产生高脉冲起作用。
//按键滤波器,按下按钮后即低电平输入,经过该模块输出一个系统时钟周期的高脉冲 module key_filiter ( input sys_clk , input sys_rst_n , input key_in , output reg key_flag ); reg [19:0] cnt_20ms; parameter CNT_MAX=20'd999999; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) cnt_20ms<=20'd0; else if(key_in) cnt_20ms<=20'd0; else if(cnt_20ms==CNT_MAX) //最大值保持 cnt_20ms<=CNT_MAX; else cnt_20ms<=cnt_20ms+1'd1; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) key_flag<=1'b0; else if(cnt_20ms==CNT_MAX-20'd1) key_flag<=1'b1; else key_flag<=1'b0; endmodule
本模块输入系统时钟50MHZ与复位信号,输出1s/10ms时钟脉冲标志位,高电平有效
因为1个系统时钟20ns,所以实现1s需要计数50_000_000次,10ms即500_000次
//1s,10ms时钟产生模块 module clk ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 output reg clk1s_flag , //1s时钟脉冲标志位 output reg clk10ms_flag //10ms时钟脉冲标志位 ); parameter CNT_MAX_1S = 28'd49_999_999; parameter CNT_MAX_10MS = 20'd499_999; reg [27:0] clk_1s ; reg [19:0] clk_10ms ; //1s时钟脉冲产生 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk_1s <= 28'd0; else if(clk_1s == CNT_MAX_1S) clk_1s <= 28'd0; else clk_1s <= clk_1s + 1'd1; always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk1s_flag <= 1'b0; else if(clk_1s == CNT_MAX_1S-1) clk1s_flag <= 1'b1; else clk1s_flag <= 1'b0; //10ms时钟脉冲产生 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk_10ms <= 20'd0; else if(clk_10ms == CNT_MAX_10MS) clk_10ms <= 20'd0; else clk_10ms <= clk_10ms + 1'd1; always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk10ms_flag <= 1'b0; else if(clk_10ms == CNT_MAX_10MS-1) clk10ms_flag <= 1'b1; else clk10ms_flag <= 1'b0; endmodule
输入1s脉冲与3个按键,输出时分秒
通过秒溢出分溢出时溢出之间的关系每秒时分秒值
当进入调试时间模式即模式3时,时间停止,这时默认更改秒,按下start按键,秒归0,rst更改调整位置
/* 0 显示 小时:0-23 分钟:0-59 秒:0-59 3 时间设置 start-- 秒(默认)-->归0 分钟/小时-->+1 reset--> 秒-->分钟-->小时 mode-->返回时间显示(按过start,reset) */ module clockdisplay ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 input wire [1:0] mode , //模式-相当于使能 input wire clk1s_flag , //1s脉冲 input wire mooe , //调整功能按键 input wire start , //开始暂停计数 input wire reset , //调整位置 output reg [7:0] sec_out , //显示-秒 output reg [7:0] min_out , //显示-分钟 output reg [7:0] hour_out //显示-小时 ); reg [1:0] position;//调整数据位置 //position;调整数据位置 0-秒,1-分,2-时 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) position <= 2'd0; else if(mode != 2'd3) position <= 2'd0; else if((mode == 2'd3) && reset && (position == 2'd2)) position <= 2'd0; else if((mode == 2'd3) && reset) //每按下一次reset建位置更改一次 position <= position + 1'd1; //秒产生 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) sec_out <= 8'd57; else if((mode != 2'd3) && clk1s_flag && (sec_out == 8'd59)) sec_out <= 8'd0; else if((mode != 2'd3) && clk1s_flag) //秒产生 sec_out <= sec_out + 1'd1; //mode == 2'd3 else if((mode == 2'd3) && (position == 2'd0) && start) //mode==3即时间设置,按下start秒清0 sec_out <= 8'd0; //分产生 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) min_out <= 8'd59; else if((mode != 2'd3) && clk1s_flag && (min_out == 8'd59) && (sec_out == 8'd59)) min_out <= 8'd0; else if((mode != 2'd3) && clk1s_flag && (sec_out == 8'd59)) //分产生 min_out <= min_out + 1'd1; //mode == 2'd3 else if((mode == 2'd3) && (position == 2'd1) && start && (min_out == 8'd59)) //分钟==59,按下start秒分清0 min_out <= 8'd0; else if((mode == 2'd3) && (position == 2'd1) && start) //mode==3即时间设置,按下start分加一 min_out <= min_out + 1'd1; //时产生 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) hour_out <= 8'd23; else if((mode != 2'd3) && clk1s_flag && (hour_out == 8'd23) && (min_out == 8'd59) && (sec_out == 8'd59)) hour_out <= 8'd0; else if((mode != 2'd3) && clk1s_flag && (min_out == 8'd59) && (sec_out == 8'd59)) hour_out <= hour_out + 1'd1; //mode == 2'd3 else if((mode == 2'd3) && (position == 2'd1) && start && (hour_out == 8'd23) && (min_out == 8'd59)) //分钟溢出且小时==23,时清0 hour_out <= 8'd0; else if((mode == 2'd3) && (position == 2'd2) && start && (hour_out == 8'd23)) //小时==23,按下start秒时清0 hour_out <= 8'd0; else if((mode == 2'd3) && (position == 2'd2) && start) //mode==3即时间设置,按下start时加一 hour_out <= hour_out + 1'd1; endmodule
这儿我们使用10ms脉冲用于实现秒表计数.输出计时三个数值用于显示
原理跟时间显示差不多,都是溢出判断即可
进入模式1后,按下start开始计时,再次按下暂停,按下rst计时归0
注意:进入模式1后,数字钟时间正常运行,但是此时显示计时值
/* mooe 1 计时 分钟:秒:99 start-->开始计时(1)-->暂停计时(0)-->开始计时... reset-归零 //mode-->返回时间显示(按过start,reset) */ module keeptime ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 input wire [1:0] mode , //模式-相当于使能 input wire clk10ms_flag , //10ms脉冲 input wire mooe , //调整功能按键 input wire start , //开始暂停计数 input wire reset , //置0 output reg [7:0] min_keti , //计时-分钟 output reg [7:0] sec_keti , //计时-秒 output reg [7:0] misec_keti //计时-10ms ); reg keeptime_flag;//控制计数启动暂停变量 //keeptime_flag;//控制计数启动暂停变量 0-停止/暂停,1-启动 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) keeptime_flag <= 1'b0; else if(mode != 2'd1) keeptime_flag <= 1'b0; else if((mode == 2'd1) && start) keeptime_flag <= ~keeptime_flag; else if((mode == 2'd1) && reset) keeptime_flag <= 1'b0; //misec_keti 计时-10ms always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) misec_keti <= 8'd0; else if(mode != 2'd1) misec_keti <= 8'd0; else if(reset || (mode == 2'd1 && keeptime_flag && clk10ms_flag && misec_keti == 99)) //按下reset按键 或者 计满99 us清0 misec_keti <= 8'd0; else if(mode == 2'd1 && keeptime_flag && clk10ms_flag) //keeptime_flag==1,启动计时 misec_keti <= misec_keti + 1'd1; //sec_keti 计时-秒 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) sec_keti <= 8'd0; else if(mode != 2'd1) sec_keti <= 8'd0; else if(reset || (mode == 2'd1 && keeptime_flag && clk10ms_flag && sec_keti == 59)) //按下reset按键 或者 计满59 s清0 sec_keti <= 8'd0; else if(mode == 2'd1 && keeptime_flag && clk10ms_flag && misec_keti == 99) //keeptime_flag==1,misec_keti溢出sec_keti++ sec_keti <= sec_keti + 1'd1; //min_keti 计时-分钟 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) min_keti <= 8'd0; else if(mode != 2'd1) min_keti <= 8'd0; else if(reset || (mode == 2'd1 && keeptime_flag && clk10ms_flag && min_keti == 59)) //按下reset按键 或者 计满59 分清0 min_keti <= 8'd0; else if(mode == 2'd1 && keeptime_flag && clk10ms_flag && sec_keti == 59 && misec_keti == 99) //keeptime_flag==1,misec_keti溢出min_keti++ min_keti <= min_keti + 1'd1; endmodule
此模块用于对闹钟数值的调整,根据输入的按键,输出调整后的闹钟值
进入模式2后,按下start默认调整闹钟分+1,按下rst调节闹钟时
注意:进入模式2后,数字钟时间正常运行,但是此时显示闹钟设置时分值
/* 2 闹钟设置 start--加1(默认分钟) reset--切换小时/分钟设置 默认分钟-->小时-->分钟 小时:0-23 分钟:0-59 mode-->返回时间显示(按过start,reset) */ module alarmclock ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 input wire [1:0] mode , //模式-相当于使能 input wire mooe , //调整功能按键 input wire start , //开始暂停计数 input wire reset , //置0 output reg [7:0] min_alarm , //闹钟-分钟 output reg [7:0] hour_alarm //闹钟-小时 ); reg position;//调整数据位置 //position;调整数据位置 0-分钟设置,1-小时设置 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) position <= 1'b0; else if(mode != 2'd2) position <= 1'b0; else if(reset) position <= ~position; //min_alarm//闹钟-分钟 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) min_alarm <= 8'd0; else if((mode == 2'd2) && (!position) && (start) && (min_alarm == 8'd59))//溢出清0 min_alarm <= 8'd0; else if((mode == 2'd2) && (!position) && (start)) //mode == 2'd2,按下start键,闹钟-分钟+1 min_alarm <= min_alarm + 1'd1; //hour_alarm//闹钟-小时 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) hour_alarm <= 8'd0; else if((mode == 2'd2) && (!position) && (start) && (min_alarm == 8'd59) && (hour_alarm == 8'd23))//闹钟-分钟+1,且小时==23溢出清0 hour_alarm <= 8'd0; else if((mode == 2'd2) && (position) && (start) && (hour_alarm == 8'd23)) //闹钟-小时+1,且小时==23溢出清0 hour_alarm <= 8'd0; else if((mode == 2'd2) && (position) && (start)) //mode == 2'd2,按下start键,闹钟-小时+1 hour_alarm <= hour_alarm + 1'd1; endmodule
此模块输入之前各模块运算得出的数值,输出到数码管显示
还包括调光功能,使用PWM波实现,按下light调节,共分5档
//数码管显示模块 module segdisplay ( input wire sys_clk , //系统时钟50MHZ input wire sys_rst_n , //复位 input wire [1:0] mode , //模式-相当于使能 input wire light , //控制显示亮度 //时钟变量 input wire [7:0] sec , input wire [7:0] min , input wire [7:0] hour , //计时变量 input wire [7:0] min_keti , input wire [7:0] sec_keti , input wire [7:0] misec_keti , //闹钟变量 input wire [7:0] min_alarm , input wire [7:0] hour_alarm , output reg [6:0] SG0,SG1,SG2,SG3,SG4,SG5,SG6,SG7 //数码管的值 7-6,4-3,1-0显示数字 5,2显示: ); parameter CNT_1US_MAX=6'd49; //1个时钟20ns,50个即1us parameter CNT_1MS_MAX=10'd999; //计满1000个即1ms parameter unit = 4'd5; reg [9:0] tim; reg [5:0] cnt_1us; reg [9:0] cnt_1ms; wire [3:0] sec_ten,sec_unit,min_ten,min_unit,hour_ten,hour_unit;//时钟变量显示 wire [3:0] minketi_ten,minketi_unit,secketi_ten,secketi_unit,misecketi_ten,misecketi_unit;//计数变量显示变量 wire [3:0] minalarm_ten,minalarm_unit,houralarm_ten,houralarm_unit;//闹钟变量显示变量 assign sec_ten=sec/10;assign sec_unit=sec%10; assign min_ten=min/10;assign min_unit=min%10; assign hour_ten=hour/10;assign hour_unit=hour%10; assign minketi_ten=min_keti/10;assign minketi_unit=min_keti%10; assign secketi_ten=sec_keti/10;assign secketi_unit=sec_keti%10; assign misecketi_ten=misec_keti/10;assign misecketi_unit=misec_keti%10; assign minalarm_ten=min_alarm/10;assign minalarm_unit=min_alarm%10; assign houralarm_ten=hour_alarm/10;assign houralarm_unit=hour_alarm%10; //1us脉冲产生 always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) cnt_1us<=6'd0; else if(cnt_1us==CNT_1US_MAX) cnt_1us<=6'd0; else cnt_1us<=cnt_1us+6'd1; //1ms脉冲产生 always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) cnt_1ms<=10'd0; else if((cnt_1ms==CNT_1MS_MAX)&&(cnt_1us==CNT_1US_MAX)) cnt_1ms<=10'd0; else if(cnt_1us==CNT_1US_MAX) cnt_1ms<=cnt_1ms+10'd1; else cnt_1ms<=cnt_1ms; //亮度变量调整 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) tim <= 10'd0; else if(tim >= 10'd999) tim <= 10'd0; else if(light) tim <= tim + 10'd200; else tim <= tim; //数码管显示 always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) begin SG0 <= 7'b1111111; SG1 <= 7'b1111111; SG3 <= 7'b1111111; SG4 <= 7'b1111111; SG6 <= 7'b1111111; SG7 <= 7'b1111111; SG2 <= 7'b1111111; SG5 <= 7'b1111111; end else if(cnt_1ms<=tim) begin SG0 <= 7'b1111111; SG1 <= 7'b1111111; SG3 <= 7'b1111111; SG4 <= 7'b1111111; SG6 <= 7'b1111111; SG7 <= 7'b1111111; SG2 <= 7'b1111111; SG5 <= 7'b1111111; end else begin if(mode == 2'd0)//时钟显示 begin SG2 <= 7'b0111111; SG5 <= 7'b0111111; case(sec_unit) 0:SG0<=7'b1000000; 1:SG0<=7'b1111001; 2:SG0<=7'b0100100; 3:SG0<=7'b0110000; 4:SG0<=7'b0011001; 5:SG0<=7'b0010010; 6:SG0<=7'b0000010; 7:SG0<=7'b1111000; 8:SG0<=7'b0000000; 9:SG0<=7'b0010000; //7段译码值 default: SG0 <= 7'b1111111; endcase case(sec_ten) 0:SG1<=7'b1000000; 1:SG1<=7'b1111001; 2:SG1<=7'b0100100; 3:SG1<=7'b0110000; 4:SG1<=7'b0011001; 5:SG1<=7'b0010010; 6:SG1<=7'b0000010; 7:SG1<=7'b1111000; 8:SG1<=7'b0000000; 9:SG1<=7'b0010000; //7段译码值 default: SG1 <= 7'b1111111; endcase case(min_unit) 0:SG3<=7'b1000000; 1:SG3<=7'b1111001; 2:SG3<=7'b0100100; 3:SG3<=7'b0110000; 4:SG3<=7'b0011001; 5:SG3<=7'b0010010; 6:SG3<=7'b0000010; 7:SG3<=7'b1111000; 8:SG3<=7'b0000000; 9:SG3<=7'b0010000; //7段译码值 default: SG3 <= 7'b1111111; endcase case(min_ten) 0:SG4<=7'b1000000; 1:SG4<=7'b1111001; 2:SG4<=7'b0100100; 3:SG4<=7'b0110000; 4:SG4<=7'b0011001; 5:SG4<=7'b0010010; 6:SG4<=7'b0000010; 7:SG4<=7'b1111000; 8:SG4<=7'b0000000; 9:SG4<=7'b0010000; //7段译码值 default: SG4 <= 7'b1111111; endcase case(hour_unit) 0:SG6<=7'b1000000; 1:SG6<=7'b1111001; 2:SG6<=7'b0100100; 3:SG6<=7'b0110000; 4:SG6<=7'b0011001; 5:SG6<=7'b0010010; 6:SG6<=7'b0000010; 7:SG6<=7'b1111000; 8:SG6<=7'b0000000; 9:SG6<=7'b0010000; //7段译码值 default: SG6 <= 7'b1111111; endcase case(hour_ten) 0:SG7<=7'b1000000; 1:SG7<=7'b1111001; 2:SG7<=7'b0100100; 3:SG7<=7'b0110000; 4:SG7<=7'b0011001; 5:SG7<=7'b0010010; 6:SG7<=7'b0000010; 7:SG7<=7'b1111000; 8:SG7<=7'b0000000; 9:SG7<=7'b0010000; //7段译码值 default: SG7 <= 7'b1111111; endcase end else if(mode == 2'd1)//计时显示 begin SG2 <= 7'b0111111; SG5 <= 7'b0111111; case(misecketi_unit) 0:SG0<=7'b1000000; 1:SG0<=7'b1111001; 2:SG0<=7'b0100100; 3:SG0<=7'b0110000; 4:SG0<=7'b0011001; 5:SG0<=7'b0010010; 6:SG0<=7'b0000010; 7:SG0<=7'b1111000; 8:SG0<=7'b0000000; 9:SG0<=7'b0010000; //7段译码值 default: SG0 <= 7'b1111111; endcase case(misecketi_ten) 0:SG1<=7'b1000000; 1:SG1<=7'b1111001; 2:SG1<=7'b0100100; 3:SG1<=7'b0110000; 4:SG1<=7'b0011001; 5:SG1<=7'b0010010; 6:SG1<=7'b0000010; 7:SG1<=7'b1111000; 8:SG1<=7'b0000000; 9:SG1<=7'b0010000; //7段译码值 default: SG1 <= 7'b1111111; endcase case(secketi_unit) 0:SG3<=7'b1000000; 1:SG3<=7'b1111001; 2:SG3<=7'b0100100; 3:SG3<=7'b0110000; 4:SG3<=7'b0011001; 5:SG3<=7'b0010010; 6:SG3<=7'b0000010; 7:SG3<=7'b1111000; 8:SG3<=7'b0000000; 9:SG3<=7'b0010000; //7段译码值 default: SG3 <= 7'b1111111; endcase case(secketi_ten) 0:SG4<=7'b1000000; 1:SG4<=7'b1111001; 2:SG4<=7'b0100100; 3:SG4<=7'b0110000; 4:SG4<=7'b0011001; 5:SG4<=7'b0010010; 6:SG4<=7'b0000010; 7:SG4<=7'b1111000; 8:SG4<=7'b0000000; 9:SG4<=7'b0010000; //7段译码值 default: SG4 <= 7'b1111111; endcase case(minketi_unit) 0:SG6<=7'b1000000; 1:SG6<=7'b1111001; 2:SG6<=7'b0100100; 3:SG6<=7'b0110000; 4:SG6<=7'b0011001; 5:SG6<=7'b0010010; 6:SG6<=7'b0000010; 7:SG6<=7'b1111000; 8:SG6<=7'b0000000; 9:SG6<=7'b0010000; //7段译码值 default: SG6 <= 7'b1111111; endcase case(minketi_ten) 0:SG7<=7'b1000000; 1:SG7<=7'b1111001; 2:SG7<=7'b0100100; 3:SG7<=7'b0110000; 4:SG7<=7'b0011001; 5:SG7<=7'b0010010; 6:SG7<=7'b0000010; 7:SG7<=7'b1111000; 8:SG7<=7'b0000000; 9:SG7<=7'b0010000; //7段译码值 default: SG7 <= 7'b1111111; endcase end else if(mode == 2'd2)//闹钟设置显示 begin SG0 <= 7'b1111111; SG1 <= 7'b1111111; SG2 <= 7'b1111111; case(minalarm_unit) 0:SG3<=7'b1000000; 1:SG3<=7'b1111001; 2:SG3<=7'b0100100; 3:SG3<=7'b0110000; 4:SG3<=7'b0011001; 5:SG3<=7'b0010010; 6:SG3<=7'b0000010; 7:SG3<=7'b1111000; 8:SG3<=7'b0000000; 9:SG3<=7'b0010000; //7段译码值 default: SG3 <= 7'b1111111; endcase case(minalarm_ten) 0:SG4<=7'b1000000; 1:SG4<=7'b1111001; 2:SG4<=7'b0100100; 3:SG4<=7'b0110000; 4:SG4<=7'b0011001; 5:SG4<=7'b0010010; 6:SG4<=7'b0000010; 7:SG4<=7'b1111000; 8:SG4<=7'b0000000; 9:SG4<=7'b0010000; //7段译码值 default: SG4 <= 7'b1111111; endcase case(houralarm_unit) 0:SG6<=7'b1000000; 1:SG6<=7'b1111001; 2:SG6<=7'b0100100; 3:SG6<=7'b0110000; 4:SG6<=7'b0011001; 5:SG6<=7'b0010010; 6:SG6<=7'b0000010; 7:SG6<=7'b1111000; 8:SG6<=7'b0000000; 9:SG6<=7'b0010000; //7段译码值 default: SG6 <= 7'b1111111; endcase case(houralarm_ten) 0:SG7<=7'b1000000; 1:SG7<=7'b1111001; 2:SG7<=7'b0100100; 3:SG7<=7'b0110000; 4:SG7<=7'b0011001; 5:SG7<=7'b0010010; 6:SG7<=7'b0000010; 7:SG7<=7'b1111000; 8:SG7<=7'b0000000; 9:SG7<=7'b0010000; //7段译码值 default: SG7 <= 7'b1111111; endcase end else if(mode == 2'd3)//时钟设置显示 begin SG2 <= 7'b0111111; SG5 <= 7'b0111111; case(sec_unit) 0:SG0<=7'b1000000; 1:SG0<=7'b1111001; 2:SG0<=7'b0100100; 3:SG0<=7'b0110000; 4:SG0<=7'b0011001; 5:SG0<=7'b0010010; 6:SG0<=7'b0000010; 7:SG0<=7'b1111000; 8:SG0<=7'b0000000; 9:SG0<=7'b0010000; //7段译码值 default: SG0 <= 7'b1111111; endcase case(sec_ten) 0:SG1<=7'b1000000; 1:SG1<=7'b1111001; 2:SG1<=7'b0100100; 3:SG1<=7'b0110000; 4:SG1<=7'b0011001; 5:SG1<=7'b0010010; 6:SG1<=7'b0000010; 7:SG1<=7'b1111000; 8:SG1<=7'b0000000; 9:SG1<=7'b0010000; //7段译码值 default: SG1 <= 7'b1111111; endcase case(min_unit) 0:SG3<=7'b1000000; 1:SG3<=7'b1111001; 2:SG3<=7'b0100100; 3:SG3<=7'b0110000; 4:SG3<=7'b0011001; 5:SG3<=7'b0010010; 6:SG3<=7'b0000010; 7:SG3<=7'b1111000; 8:SG3<=7'b0000000; 9:SG3<=7'b0010000; //7段译码值 default: SG3 <= 7'b1111111; endcase case(min_ten) 0:SG4<=7'b1000000; 1:SG4<=7'b1111001; 2:SG4<=7'b0100100; 3:SG4<=7'b0110000; 4:SG4<=7'b0011001; 5:SG4<=7'b0010010; 6:SG4<=7'b0000010; 7:SG4<=7'b1111000; 8:SG4<=7'b0000000; 9:SG4<=7'b0010000; //7段译码值 default: SG4 <= 7'b1111111; endcase case(hour_unit) 0:SG6<=7'b1000000; 1:SG6<=7'b1111001; 2:SG6<=7'b0100100; 3:SG6<=7'b0110000; 4:SG6<=7'b0011001; 5:SG6<=7'b0010010; 6:SG6<=7'b0000010; 7:SG6<=7'b1111000; 8:SG6<=7'b0000000; 9:SG6<=7'b0010000; //7段译码值 default: SG6 <= 7'b1111111; endcase case(hour_ten) 0:SG7<=7'b1000000; 1:SG7<=7'b1111001; 2:SG7<=7'b0100100; 3:SG7<=7'b0110000; 4:SG7<=7'b0011001; 5:SG7<=7'b0010010; 6:SG7<=7'b0000010; 7:SG7<=7'b1111000; 8:SG7<=7'b0000000; 9:SG7<=7'b0010000; //7段译码值 default: SG7 <= 7'b1111111; endcase end end endmodule
以上就是本次实验的全部代码。
`timescale 1ns/1ns module tb_clock(); //模块相关数据定义 reg sys_clk ; //系统时钟50MHZ reg sys_rst_n ; //复位 reg light_an ; //控制亮度 reg mooe_an ; //功能按键 reg start_an ; //调整数值按键 reg reset_an ; //切换区域按键 wire led ; //做闹钟用 LEDR0 闪烁 wire [3:0] led_mode ; //显示当前模式 LEDR17-LEDR14 wire [6:0] SG0,SG1,SG2,SG3,SG4,SG5,SG6,SG7; //数码管的值 7-6,4-3,1-0显示数字 5,2显示: //sys_clk,sys_rst_n初始赋值,模拟触摸按键信号值 initial begin sys_clk <= 1'b1 ; sys_rst_n <= 1'b0 ; light_an <= 1'b1 ; start_an <= 1'b1 ; reset_an <= 1'b1 ; mooe_an <= 1'b1 ; #30 sys_rst_n <= 1'b1 ; #1000 mooe_an <= 1'b0 ; #100 mooe_an <= 1'b1 ; #100 mooe_an <= 1'b0 ; #100 mooe_an <= 1'b1 ; #100 mooe_an <= 1'b0 ; #100 mooe_an <= 1'b1 ; #100 start_an <= 1'b0; #100 start_an <= 1'b1; #100 reset_an <= 1'b0; #100 reset_an <= 1'b1; #100 start_an <= 1'b0; #100 start_an <= 1'b1; #100 reset_an <= 1'b0; #100 reset_an <= 1'b1; #100 start_an <= 1'b0; #100 start_an <= 1'b1; #100 mooe_an <= 1'b0 ; #100 mooe_an <= 1'b1 ; end //clk:产生时钟 always #10 sys_clk = ~sys_clk ; //重定义模块内部CNT溢出值 defparam clock_inst.clk_inst.CNT_MAX_1S = 100'd49; defparam clock_inst.clk_inst.CNT_MAX_10MS = 100'd19; defparam clock_inst.key_filiter_inst0.CNT_MAX = 100'd5; defparam clock_inst.key_filiter_inst1.CNT_MAX = 100'd5; defparam clock_inst.key_filiter_inst2.CNT_MAX = 100'd5; defparam clock_inst.key_filiter_inst3.CNT_MAX = 100'd5; //模块例化 clock clock_inst ( .sys_clk (sys_clk ) , //系统时钟50MHZ .sys_rst_n (sys_rst_n) , //复位 .light_an (light_an ) , //控制亮度 .mooe_an (mooe_an ) , //功能按键 .start_an (start_an ) , //调整数值按键 .reset_an (reset_an ) , //切换区域按键 .led (led ) , //做闹钟用 LEDR0 闪烁 .led_mode (led_mode ) , //显示当前模式 LEDR17-LEDR14 .SG0 (SG0) , .SG1 (SG1) , .SG2 (SG2) , .SG3 (SG3) , .SG4 (SG4) , .SG5 (SG5) , .SG6 (SG6) , .SG7 (SG7) ); endmodule
系统启动默认时间从23:59:57开始,左下角灯为模式显示灯

系统自动走了一段时间,可以看到正常进位

按下light调节亮度

按下mooe按键调节到模式1计时模式,启动

再次按下mooe按键调节到模式2,进行闹钟调整

再次按下mooe按键调节到模式3,进行时间调整

再次按下mooe按键回到模式1,正常显示时钟

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。