FPGA基础项目训练(一)——————数字时钟(一)

该博客介绍了如何在FPGA中实现数码管动态显示时间(时、分、秒)的功能,包括时钟控制模块和数码管显示模块的Verilog代码实现。数码管动态显示通过轮询6个数码管进行刷新,而时钟控制模块则负责计时,更新数码管的显示数值。
摘要由CSDN通过智能技术生成

一、功能描述
1.数码管显示时间(时、分、秒)

二、代码部分

顶层代码

module top_clock_key(
		 input  		sys_clk, //50M时钟信号
		 input 			rst_n  ,
		 
		 //按键	
		 input  [3:0]  key	 ,
		 //数码管
		 output [5:0]  sel    ,
		 output [7:0]  seg_led
		 
);

parameter POINT   = 6'b010100;




//wire [23:0]  data		  ;	
wire 			 state_flag;
wire [7:0]   min;
wire [7:0]   sec;
wire [7:0]   hour;
//设置时间
clock u_clock(
		  .sys_clk    (sys_clk   )   ,
          .rst_n   	  (rst_n     )   ,
		  .state_flag (state_flag)   ,
		  
		  .sec  	  (sec       )   ,
		  .min  	  (min       )   ,
		  .hour  	  (hour      )	   	
			
		  //.data		  (data)
);

//数码管动态显示模块
seg_led u_seg_led(
    //input
   .clk          (sys_clk    ),    // 时钟信号
   .rst_n        (rst_n      ),    // 复位信号
   //.num        (data       ),    // 6个数码管要显示的数值
   .point        (POINT      ),    // 小数点具体显示的位置,从高到低,高有效
	
	.sec  	  	  (sec       ),
	.min  	  	  (min       ),
	.hour  	      (hour      ),	   	
   //output
   .sel          (sel        ),    // 数码管位选
   .seg_led      (seg_led    )     // 数码管段选
);


/*
//按键控制
key_control u_key_control(
		  .sys_clk    (sys_clk)  ,
          .rst_n   	  (rst_n)    ,
          
		
		  .key       (key)  	 ,
	      .flag		  (state_flag)
);
*/


endmodule 

数码管显示代码

module seg_led(
   //input
   input                       clk   ,        // 时钟信号
   input                      rst_n  ,        // 复位信号
   //input        [23:0]    num      ,        // 6个数码管要显示的数值 
	input   		 [7:0]	  sec    , 	 
	input   		 [7:0]	  min    , 	 
	input   		 [7:0]	  hour   , 	 
   input             [5:0]    point  ,        // 小数点具体显示的位置,从高到低,高有效

   //output
   output  reg  	[5:0]     sel    ,        // 数码管位选
   output  reg  	[7:0]     seg_led         // 数码管段选
);


//parameter define
parameter  WIDTH0 = 50_000;

//reg define
reg    [15:0]             cnt0;           // 1ms计数
reg    [2:0]              cnt;            // 切换显示数码管用
reg    [3:0]              num1;           // 送给要显示的数码管,要亮的灯
reg                       point1;         // 要显示的小数点

//wire define
wire   [3:0]              data0    ;        // 个位数
wire   [3:0]              data1    ;        // 十位数
wire   [3:0]              data2    ;        // 百位数
wire   [3:0]              data3    ;        // 千位数
wire   [3:0]              data4    ;        // 万位数
wire   [3:0]              data5    ;        // 十万位数


//提取显示数值所对应的十进制数的各个位
assign  data0 = sec  % 4'd10;               // 个位数
assign  data1 = sec  / 4'd10;    			  // 十位数
assign  data2 = min  % 4'd10;               // 百位数
assign  data3 = min  / 4'd10;    			  // 千位数
assign  data4 = hour % 4'd10;               // 万位数
assign  data5 = hour / 4'd10;               // 十万位数


//*****************************************************
//**                    main code
//*****************************************************

//计数1ms
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        cnt0 <= 15'b0;
    else if(cnt0 < WIDTH0)
        cnt0 <= cnt0 + 1'b1;
    else
        cnt0 <= 15'b0;
end

//计数器,用来计数6个状态(因为有6个灯)
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        cnt <= 3'b0;
    else if(cnt < 3'd6) begin
        if(cnt0 == WIDTH0)
            cnt <= cnt + 1'b1;
        else
            cnt <= cnt;
    end
    else
        cnt <= 3'b0;
end

//6个数码管轮流显示,完成刷新(从右到左)
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        sel     <= 6'b000001;
        num1 <= 4'b0;
    end
    else begin
        case (cnt)
            3'd0:begin
                 sel    <= 6'b111110;
                 num1   <= data0    ;
                 point1 <= point[0] ;
            end
            3'd1:begin
                 sel    <= 6'b111101;
                 num1   <= data1    ;
                 point1 <= point[1] ;
            end
            3'd2:begin
                 sel    <= 6'b111011;
                 num1   <= data2    ;
                 point1 <= point[2] ;
            end
            3'd3:begin
                 sel    <= 6'b110111 ;
                 num1   <= data3    ;
                 point1 <= point[3]  ;
            end
            3'd4:begin
                 sel    <= 6'b101111 ;
                 num1   <= data4     ;
                 point1 <= point[4]  ;
            end
            3'd5:begin
                 sel    <= 6'b011111 ;
                 num1   <= data5     ;
                 point1 <= point[5]  ;
            end
            default: begin
                 sel    <= 6'b000000;
                 num1   <= 4'b0;
                 point1 <= 1'b1;
            end
        endcase
    end
end

//数码管显示数据
always @ (posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        seg_led <= 7'b0;
    else begin
        case(num1)
            4'd0: seg_led <= {~point1,7'b1000000};
            4'd1: seg_led <= {~point1,7'b1111001};
            4'd2: seg_led <= {~point1,7'b0100100};
            4'd3: seg_led <= {~point1,7'b0110000};
            4'd4: seg_led <= {~point1,7'b0011001};
            4'd5: seg_led <= {~point1,7'b0010010};
            4'd6: seg_led <= {~point1,7'b0000010};
            4'd7: seg_led <= {~point1,7'b1111000};
            4'd8: seg_led <= {~point1,7'b0000000};
            4'd9: seg_led <= {~point1,7'b0010000};
            default: seg_led <= {point1,7'b1000000};
        endcase
    end
end
endmodule 

时钟控制代码

module clock
(
		 input       		 sys_clk      ,
		 input		 		 rst_n  		  ,
		 input				 state_flag   , //状态控制标志位 
		 
		 
		 //output     [23:0] data
		 output  reg	 [7:0] sec  	  ,
		 output  reg	 [7:0] min  	  ,
		 output  reg	 [7:0] hour  	  	   		 
		 

);


parameter CNT_1S_TIME = 28'd50_000_000;//1秒  计算方式1s/20ns求得计数值

reg [27:0] cnt_1s  ; 
reg 	   flag_1s ; //1秒计时标志位
/*
reg [7:0]  sec	;
reg [7:0]  min	;
reg [7:0]  hour;
*/
wire [23:0]rtc_rime; 

assign rtc_rime = {hour,min,sec};
assign data     = rtc_rime;

//1秒计数		
always@(posedge sys_clk or negedge rst_n)begin 
		if(!rst_n)begin    
			cnt_1s  <= 1'b0; 
			flag_1s <= 1'b0;
		end 
		else if(cnt_1s  < CNT_1S_TIME - 1'b1 )begin 
			cnt_1s  <= cnt_1s + 1'b1;	
		   flag_1s <= 1'b0;	
		end 
		else begin 
			cnt_1s  <=  1'b0;	 
			flag_1s <=  1'b1;
		end 
end 
		
always@(posedge sys_clk or negedge rst_n)begin 
		if(!rst_n)begin 
			sec  <= 8'd55;    //秒初始值       
			min  <= 8'd58;	  //分初始值    
			hour <= 8'd23;	  //时初始值    
		end 
		else if(flag_1s) 
			sec <= sec + 1'b1;		
		else if(sec >= 6'd60)begin  
				sec <= 1'b0;
				min <= min + 1'b1;				
		end	
		else 	if(min >= 6'd60)begin 
			   min  <= 1'b0;
				hour <= hour + 1'b1;
		end
		else if(hour >= 5'd24)
				hour <= 1'b0;
	
end 

endmodule 

三、拓展练习
后续补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Little.Boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值