FPGA-DE2-115-实验二-模块化多功能数字钟

这篇具有很好参考价值的文章主要介绍了FPGA-DE2-115-实验二-模块化多功能数字钟。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言:
本文主要介绍了集成电路EDA这门课程的相关实验及代码。使用的软件是Quartus Ⅱ,该实验使用fpga芯片为cyclone IV EP4CE115F29C7。

1.实验要求

本次实验我们需要实现生活中常见的电子手表的所有功能。
我们知道:
电子手表有五个功能,包括:时间显示功能,夜光模式功能,计时功能,闹钟功能,调时功能,
各功能实际效果介绍:

  • 时间显示功能:正常状态下,时间正常显示时分秒
  • 调光功能:按下1键也就是light键表灯亮度会逐渐改变
  • 记时功能:按下2键也就是mooe键一次进入计时功能,这时按下3键也就是start键开始计时,再次按下时间停止,再次则继续,按下4键也就是reset键即记时归零。
  • 闹钟调整及实现功能:按下2键两次进入闹钟功能,这时按下3键调整当前闪烁区域,按下4键更换区域。
  • 时间调整功能:按下2键三次进入时间调整功能,这时按下三键调整当前闪烁区域,按下4键更换区域。

2.实现过程

本次实验为了代码优美易于修正,整体上使用模块化设计实现多功能数字钟。
其中使用一个按钮开关调节模式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显示’-'将时分秒间隔开来

多功能数字钟的整体RTL视图

quartus时钟代码,集成电路EDA,fpga开发,fpga
下面我将详细介绍各个模块及原理:

2.1 顶层模块clock

统筹整个实验的整体,其中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

2.2 按键消抖模块key_filiter

按键滤波器,按下按钮后即低电平输入,经过该模块输出一个系统时钟周期的高脉冲。
本次实验使用的四个按键都是通过这个模块产生高脉冲起作用。

//按键滤波器,按下按钮后即低电平输入,经过该模块输出一个系统时钟周期的高脉冲
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

2.3 数字钟1s/10ms时钟产生模块clk

本模块输入系统时钟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

2.4 时间显示(模式0)与调整模块(模式3)clockdisplay

输入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

2.5 计时(模式1)模块keeptime

这儿我们使用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.6 闹钟调整(模式2)模块alarmclock

此模块用于对闹钟数值的调整,根据输入的按键,输出调整后的闹钟值
进入模式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

2.7 数码管显示模块segdisplay

此模块输入之前各模块运算得出的数值,输出到数码管显示
还包括调光功能,使用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

以上就是本次实验的全部代码。

modelsim仿真的实验代码

`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

3.实物验证

系统启动默认时间从23:59:57开始,左下角灯为模式显示灯
quartus时钟代码,集成电路EDA,fpga开发,fpga
系统自动走了一段时间,可以看到正常进位
quartus时钟代码,集成电路EDA,fpga开发,fpga
按下light调节亮度
quartus时钟代码,集成电路EDA,fpga开发,fpga
按下mooe按键调节到模式1计时模式,启动
quartus时钟代码,集成电路EDA,fpga开发,fpga
再次按下mooe按键调节到模式2,进行闹钟调整
quartus时钟代码,集成电路EDA,fpga开发,fpga
再次按下mooe按键调节到模式3,进行时间调整
quartus时钟代码,集成电路EDA,fpga开发,fpga
再次按下mooe按键回到模式1,正常显示时钟
quartus时钟代码,集成电路EDA,fpga开发,fpga文章来源地址https://www.toymoban.com/news/detail-762987.html

到了这里,关于FPGA-DE2-115-实验二-模块化多功能数字钟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 多功能交通灯控制系统VHDL十字路口红绿灯倒计时DE2-115开发板代码

    名称:多功能交通灯控制系统VHDL十字路口红绿灯倒计时DE2-115开发板 软件:Quartus II 语言:VHDL 代码功能: 要求设计一个多功能交通灯控制系统。并进行软件仿真与硬件实现。要求做到  (1)主干道绿灯亮时,支干道红灯亮,反之亦然,两者交替允许通行,主干道每次放行60s,支干道每

    2024年02月04日
    浏览(69)
  • 【FPGA】VGA显示文字、彩条、图片——基于DE2-115

    **VGA(Video Graphics Array)**视频图形阵列是IBM于1987年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号

    2024年02月02日
    浏览(43)
  • 什么是模块化?为什么要进行模块化开发?

    模块化是一种软件开发的设计模式,它将一个大型的软件系统划分成多个独立的模块,每个模块都有自己的功能和接口,并且能够与其他模块独立地工作。  先来一段八股文 模块化开发可以带来以下好处: 提高代码的复用性:模块化可以将代码划分成可重用的部分,降低代

    2023年04月12日
    浏览(59)
  • 基于Quartus Prime平台FPGA关于VGA显示的模块化设计:VGA八种单色屏1s切换显示、横条纹、竖条纹、棋盘格显示、显示模式按键可调、数码管显示单色屏序号

    VGA(Video Graphics Array)是一种显示接口标准,它最初由IBM于1987年推出。VGA协议定义了计算机视频输出信号的格式和特性。它主要用于连接计算机和显示器之间的传输,实现图像和视频的显示。 VGA协议支持最高分辨率为640x480像素,色彩深度为16位色(即65,536种颜色)。它使用模

    2024年02月03日
    浏览(51)
  • 23年,我又学习了一次amd模块化,模块化思想

    src/view1/index.html src/view1/main.js plugins/module.js 源码链接: https://gitee.com/littleboyck/front/tree/master/front-module 联系方式:QQ: 1187253007

    2024年02月07日
    浏览(57)
  • 【前端模块化】JS模块化思想以及相关规范(CommonJS、ES module)

    1.模块化概念 随着前端应用日趋复杂,项目代码也大量膨胀,模块化就是一种最主流的代码组织方式, 一个模块就是一个实现特定功能的文件 ,它通过把我们的复杂代码按照功能的不同,划分为不同的模块单独维护的这种方式,去提高我们的开发效率,降低维护成本。要用

    2024年02月01日
    浏览(62)
  • JavaScript模块化

    JavaScript模块化,让我们通过一个实际的例子来更好地理解。 假设我们正在开发一个简单的购物车应用,需要实现计算商品总价和展示购物车列表的功能。我们可以将这个应用划分为两个模块:`cart.js`和`main.js`。 1. cart.js模块: ```javascript // cart.js // 定义一个私有变量,用于存

    2024年02月14日
    浏览(57)
  • js模块化开发

    ◼ 到底什么是模块化、模块化开发呢?  事实上模块化开发最终的目的是将程序划分成一个个小的结构;  这个结构中编写属于自己的逻辑代码,有自己的作用域,定义变量名词时不会影响到其他的结构;  这个结构可以将自己希望暴露的变量、函数、对象等导出给其结

    2024年02月13日
    浏览(61)
  • 前端模块化

      随着前端应用的日益复杂,我们的项目代码已经逐渐膨胀到了不得不花大量时间去管理的程度了。而模块化就是一种最主流的代码组织方式,它通过把复杂的代码按照功能的不同划分为不同的模块单独维护,从而提高开发效率、降低维护成本。模块化可以使你能够更容易地

    2024年02月08日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包