关于动态数码管显示以及24小时时钟的学习笔记

1.动态数码管显示

                输入变量:时钟,复位,以及对应数码管的输入数据

               输出变量:数码管显示数据,以及位选。

  对于数码管动态显示胡整体思路如下:此模块作为可以调用的模块,外部输入数据对应着相应位置数码管的输出(也就是对应的位选),设定一个函数根据输入数据用来选择数码管显示的数字,其次设定一个计数器,将输入的数据通过状态机传输出去,并且根据计数器一些位数的变化对位选输出进行移位操作,保证对应位选与段选对应,显示正确的数据。

module nixie_tube(
input clk,
input rst,
input 		[4:0] 	in7,
input 		[4:0]		in6,
input 		[4:0]		in5,
input 		[4:0]		in4,
input 		[4:0]		in3,
input 		[4:0]		in2,
input 		[4:0]		in1,
input 		[4:0]		in0,
output reg [7:0]sel_out,
output reg [7:0]sel_data
);
function [7:0]seg;
input[4:0] data;
begin
case(data)
 0: seg = 8'b1100_0000;
 1: seg = 8'b1111_1001;
 2: seg = 8'b1010_0100;
 3: seg = 8'b1011_0000;
 4: seg = 8'b1001_1001;
 5: seg = 8'b1001_0010;
 6: seg = 8'b1000_0010;
 7: seg = 8'b1111_1000;
 8: seg = 8'b1000_0000;
 9: seg = 8'b1001_0000;
 10: seg = 8'b1000_1000;//A
 11: seg = 8'b1000_0011;//B
 12: seg = 8'b1010_0111;//C
 13: seg = 8'b1010_0001;//D
 14: seg = 8'b1000_0110;//E
 15: seg = 8'b1000_1110;//F
 16: seg = 8'b0111_1111;//.
 17: seg = 8'b1011_1111;//-
 default seg=0;
 endcase
 end
 endfunction
 reg [31:0] sel_cnt;
 always@(posedge clk) sel_cnt<=sel_cnt+1;

wire [2:0]sel;
assign sel=sel_cnt[17:15];
always@(posedge clk)
 case(sel)
  0:sel_data<=seg(in0);
  1:sel_data<=seg(in1);
  2:sel_data<=seg(in2);
  3:sel_data<=seg(in3);
  4:sel_data<=seg(in4);
  5:sel_data<=seg(in5);
  6:sel_data<=seg(in6);
  7:sel_data<=seg(in7);
  endcase
  
  always@(posedge clk)
   sel_out<=~(1<<sel);
endmodule

              此模块收获:可通过计数器来同时确定数据和位选的,对于位选信号是一个8位数据输出,哪一位输出1,表示哪个对应的数码管点亮。一般来说人视力所观察到数码管正常亮起的,数码管的刷新时间20ms即可。

2.24小时时钟

本模块输入变量:时钟,复位。

           输出变量:数码管输出数据,数码管位选。

本模块思路:本模块用的开发板时钟为50MHz,将秒,分,时的个位和十位分开计算,这样节省资源,每次进位都需要求计数器计够,才能进位。

module clock24(
input clk,rst,
output [7:0]sel_data,
output[7:0]sel_out
 );
reg [3:0]secend_time_c;
reg [3:0]secend_time_ten;
reg [3:0]minute_time_c;
reg [3:0]minute_time_ten;
reg [3:0]clock_time_c;
reg [1:0]clock_time_ten;
reg [25:0]secend_time_cnt;
wire  secend_time_cnt_of=secend_time_cnt==50*1000*1000-1; 
wire  secend_time_of={secend_time_ten,secend_time_c}==8'b0101_1001;

wire minute_time_c_of=(secend_time_of && minute_time_c==4'd9);
wire  minute_time_ten_of={minute_time_ten,minute_time_c}==8'b0101_1001; 

wire clock_start=(minute_time_ten_of && secend_time_of);
wire clock_ten_start=(clock_start && clock_time_c==4'd9);
wire  clock_time_of={clock_time_ten,clock_time_c}==5'b1_0100; 

always@(posedge clk)
if(rst | (secend_time_cnt_of)) secend_time_cnt<=0;else secend_time_cnt<=secend_time_cnt+1;

always@(posedge clk)
if(rst|(secend_time_c==4'd9 && secend_time_cnt_of ))secend_time_c<=0;
else if(secend_time_cnt_of) secend_time_c<=secend_time_c+1;
always@(posedge clk) if(rst|(secend_time_cnt_of && secend_time_of)) secend_time_ten<=0; 
else if(secend_time_c==4'd9 && secend_time_cnt_of && secend_time_cnt_of) secend_time_ten<=secend_time_ten+1;

always@(posedge clk ) if(rst | (minute_time_c_of && secend_time_cnt_of && secend_time_of)) minute_time_c<=0; 
else if(secend_time_of && secend_time_cnt_of) minute_time_c<=minute_time_c+1;
always@(posedge clk) if(rst|(secend_time_cnt_of && clock_start )) minute_time_ten<=0; 
else if(minute_time_c_of && secend_time_of && secend_time_cnt_of) minute_time_ten<=minute_time_ten+1;
 
always@(posedge clk ) if(rst | (clock_ten_start && minute_time_ten_of && secend_time_cnt_of)) clock_time_c<=0; else if(clock_start &&secend_time_cnt_of) clock_time_c<=clock_time_c+1;
always@(posedge clk) if(rst|(clock_time_of && clock_start && secend_time_cnt_of)) clock_time_ten<=0;
 else if((clock_ten_start && minute_time_ten_of && secend_time_cnt_of)) clock_time_ten<=clock_time_ten+1;
 
 
 
 nixie_tube nixie_tube(
. clk(clk),
. rst(rst),
.in7({3'd0,clock_time_ten}),
.in6({1'd0,clock_time_c}),
.in5(17),
.in4({1'd0,minute_time_ten}),
.in3({1'd0,minute_time_c}),
.in2(17),
.in1({1'd0,secend_time_ten}),
.in0({1'd0,secend_time_c}),
.sel_out(sel_out),
.sel_data(sel_data)
);
 endmodule

2.1 24小时时钟第二种办法

此方法是直接计算秒,分,时。对于个位,用除法留余数(%),对于十位用除法(/)。但这种方法比较占用资源。

module nixie_tube(
input rst,clk,
output [7:0] seg7_sel,seg7_data
);

reg [31:0] cnt;
reg second_pulse;

wire cnt_of = cnt == 50*1000*10 - 1 ;
always@(posedge clk) if(rst) cnt <= 0; else cnt <= (cnt_of) ? 0 : cnt + 1;
always@(clk) if(cnt_of) second_pulse <= 1; else second_pulse <= 0;
reg [5:0] sec_c,min_c,hur_c;

//    R  T  L 
always@(posedge clk)if (rst) sec_c<=0; else if (second_pulse) sec_c <= (sec_c==59) ? 0 : (sec_c + 1 ) ; 

always@(posedge clk)if (rst) min_c<=0; else if (second_pulse && sec_c==59) min_c<= (min_c==59) ? 0 : (min_c + 1 ) ;

always@(posedge clk)if (rst) hur_c<=0; else if (second_pulse && sec_c==59 && min_c==59 ) hur_c<= (hur_c==23) ? 0 : (hur_c + 1 ) ;




display_number_4 display_number(
	.clk			(clk)	,
	.in7			(hur_c / 10),
	.in6			(hur_c % 10),
	.in5			(17)	,
	.in4			(min_c / 10),
	.in3			(min_c % 10),
	.in2			(17)	,
	.in1			(sec_c / 10),
	.in0			(sec_c % 10),
	.seg7_sel	(seg7_sel)	,
	.seg7_data	(seg7_data)	
);

endmodule

本模块收获:对于时钟显示,将数据传输给数码显示模块,对应位置显示对应数据。对于分,秒,时的进位要注意秒的计数器一定要计满50*1000*1000-1。对于代码编写,尽量避免乘除运算,因为单周期运算,占用资源太大。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一个简单的Verilog代码示例,用于在数码管上动态显示时间。以下是代码示例: ``` module time_display( input clk, input reset, output reg [6:0] seg, output reg [3:0] an ); reg [25:0] count = 0; reg [3:0] digit = 0; always @(posedge clk) begin if (reset) begin count <= 0; digit <= 0; end else begin count <= count + 1; if (count == 50000000) begin // 每秒钟更新一次时间 count <= 0; digit <= digit + 1; if (digit == 4) begin // 当前时间为4位数,重置为0 digit <= 0; end end end end always @(posedge clk) begin case (digit) // 根据不同的位数,设置不同的数码管输出 0: begin seg <= 7'b1000000; // 数码管显示时钟小时位 an <= 4'b1110; // 数码管选择第1位 end 1: begin seg <= 7'b0100000; // 数码管显示时钟小时位 an <= 4'b1101; // 数码管选择第2位 end 2: begin seg <= 7'b0010000; // 数码管显示时钟的分钟位 an <= 4'b1011; // 数码管选择第3位 end 3: begin seg <= 7'b0001000; // 数码管显示时钟的分钟位 an <= 4'b0111; // 数码管选择第4位 end default: begin seg <= 7'b1111111; // 数码管不显示任何数字 an <= 4'b1111; // 数码管不选择任何位 end endcase end endmodule ``` 该代码使用一个时钟信号(`clk`)和一个重置信号(`reset`)来更新数码管上的时间显示。每当时钟信号上升沿到来时,计数器(`count`)会递增。当计数器达到50000000时(即1秒钟),位数计数器(`digit`)会递增,从而更新数码管上的显示。 在数码管上显示时间的方法是,在第一位数码管上显示小时数的十位(`seg = 7'b1000000`),在第二位数码管上显示小时数的个位(`seg = 7'b0100000`),在第三位数码管上显示分钟数的十位(`seg = 7'b0010000`),在第四位数码管上显示分钟数的个位(`seg = 7'b0001000`)。同时,位数计数器(`digit`)用于选择要显示的数码管位数(`an`)。例如,当`digit`为0时,选择第一位数码管(`an = 4'b1110`),以此类推。 请注意,此代码仅用于演示目的,并不完整或可用于实际应用,您需要根据实际需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值