文章目录
- 一.数码管
- 二.数码管静态显示
- ①数码管全部显示,以0.5s为间隔依次显示0~F
- ②修改上述代码,数码管轮流亮,并以0.5s为间隔依次显示1~6
- ③继续修改上述代码,以0.5s为间隔依次显示1~6,显示几就亮几个数码管
- 三.总结
一.数码管
数码管就是由8个LED灯组成的,通过让部分LED灯亮显示相应数字
我的开发板是共阳极类型,给低电平发光
数字真值表:
段选信号,位选信号:
二.数码管静态显示
①数码管全部显示,以0.5s为间隔依次显示0~F
新建计时模块
time_count.v
module time_count(
input wire clk, //时钟,50MHZ
input wire rst_n, //复位信号,下降沿有效,negative
output wire sec_05//0.5s输出一个脉冲信号
);
parameter MAX_NUM = 24_999_999;//记最大数0.5s,25_000_000次
reg [24:0] cnt_05;//计数寄存器
reg sec_05_r;
//0.5s计时器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_05 <= 25'd0;
end
else if(cnt_05 == MAX_NUM)begin
cnt_05 <= 25'd0;
end
else begin
cnt_05 <= cnt_05 + 1'd1;
end
end
//0.5s脉冲信号
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sec_05_r <= 1'b0;
end
else if(cnt_05 == MAX_NUM)begin
sec_05_r <= 1'b1;
end
else begin
sec_05_r <= 1'b0;
end
end
assign sec_05 = sec_05_r;//当右边改变,立马赋值给左边 assign和always并行
endmodule
新建数码管显示模块
seg_led_static.v
module seg_led_static(
input wire clk,//时钟
input wire rst_n,//复位
input wire sec_05,//0.5s脉冲信号
output wire [7:0] seg,//8位数码管段选信号
output wire [5:0] sel//6位数码管位选信号
);
reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;
//位选信号全亮
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sel_r <= 6'b111_111;//复位全灭
end
else begin
sel_r <= 6'b000_000;
end
end
assign sel = sel_r;
//0~f计数功能
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
value <= 4'h0;
end
else if(sec_05)begin
if(value < 4'hf)begin
value <= value + 1'h1;
end
else begin
value <= 4'h0;
end
end
else begin
value <= value;
end
end
//数码管译码功能,组合逻辑
always@(*)begin
case(value)
4'h0 : seg_r = 8'b1100_0000;
4'h1 : seg_r = 8'b1111_1001;
4'h2 : seg_r = 8'b1010_0100;
4'h3 : seg_r = 8'b1011_0000;
4'h4 : seg_r = 8'b1001_1001;
4'h5 : seg_r = 8'b1001_0010;
4'h6 : seg_r = 8'b1000_0010;
4'h7 : seg_r = 8'b1111_1000;
4'h8 : seg_r = 8'b1000_0000;
4'h9 : seg_r = 8'b1001_0000;
4'ha : seg_r = 8'b1000_1000;
4'hb : seg_r = 8'b1000_0011;
4'hc : seg_r = 8'b1100_0110;
4'hd : seg_r = 8'b1010_0001;
4'he : seg_r = 8'b1000_0110;
4'hf : seg_r = 8'b1000_1110;
default: seg_r = 8'b1100_0000;
endcase
end
assign seg = seg_r;
endmodule
设计顶层文件
top_seg_led.v
module top_seg_led(
input wire clk,
input wire rst_n,
output wire [7:0] seg,
output wire [5:0] sel
);
wire sec_05;//将两个模块的信号连接起来
//推荐变量名传值,还有位置传值
time_count inst_time_count(
.clk (clk ),//时钟,50MHZ
.rst_n (rst_n ),//复位信号,下降沿有效,negative
.sec_05 (sec_05) //0.5s输出一个脉冲信号
);
seg_led_static inst_seg_led_static(
.clk (clk ),//时钟
.rst_n (rst_n ),//复位
.sec_05 (sec_05),//0.5s脉冲信号
.seg (seg ),//8位数码管段选信号
.sel (sel ) //6位数码管位选信号
);
endmodule
编译:
查看RTL门级电路:
绑定引脚:
硬件测试:
②修改上述代码,数码管轮流亮,并以0.5s为间隔依次显示1~6
修改seg_led_static.v
①修改计数从1~6
②修改位选信号和计数器同步变化
module seg_led_static(
input wire clk,//时钟
input wire rst_n,//复位
input wire sec_05,//0.5s脉冲信号
output wire [7:0] seg,//8位数码管段选信号
output wire [5:0] sel//6位数码管位选信号
);
reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;
//位选信号轮流亮
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sel_r <= 6'b111_110;//复位
end
else if(sec_05)begin
sel_r <= {sel_r[4:0],sel_r[5]};
end
else begin
sel_r <= sel_r;
end
end
//1~6计数功能
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
value <= 4'h1;
end
else if(sec_05)begin
if(value < 4'h6)begin
value <= value + 1'h1;
end
else begin
value <= 4'h1;
end
end
else begin
value <= value;
end
end
assign sel = sel_r;
//数码管译码功能,组合逻辑
always@(*)begin
case(value)
4'h0 : seg_r = 8'b1100_0000;
4'h1 : seg_r = 8'b1111_1001;
4'h2 : seg_r = 8'b1010_0100;
4'h3 : seg_r = 8'b1011_0000;
4'h4 : seg_r = 8'b1001_1001;
4'h5 : seg_r = 8'b1001_0010;
4'h6 : seg_r = 8'b1000_0010;
4'h7 : seg_r = 8'b1111_1000;
4'h8 : seg_r = 8'b1000_0000;
4'h9 : seg_r = 8'b1001_0000;
4'ha : seg_r = 8'b1000_1000;
4'hb : seg_r = 8'b1000_0011;
4'hc : seg_r = 8'b1100_0110;
4'hd : seg_r = 8'b1010_0001;
4'he : seg_r = 8'b1000_0110;
4'hf : seg_r = 8'b1000_1110;
default: seg_r = 8'b1100_0000;
endcase
end
assign seg = seg_r;
endmodule
硬件测试:
③继续修改上述代码,以0.5s为间隔依次显示1~6,显示几就亮几个数码管
module seg_led_static(
input wire clk,//时钟
input wire rst_n,//复位
input wire sec_05,//0.5s脉冲信号
output wire [7:0] seg,//8位数码管段选信号
output wire [5:0] sel//6位数码管位选信号
);
reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;
reg [16:0] cnt;
parameter MAX_NUM = 99_999;
//0.2s计时器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 1'b0;
end
else if(cnt == MAX_NUM)begin
cnt <= 1'b0;
end
else begin
cnt <= cnt + 1'b1;
end
end
//1~6计数功能
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
value <= 4'h1;
end
else if(sec_05)begin
if(value < 4'h6)begin
value <= value + 1'h1;
end
else begin
value <= 4'h1;
end
end
else begin
value <= value;
end
end
//位选信号显示数字几就亮几个
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sel_r <= 6'b111_110;
end
else if(cnt == MAX_NUM)begin
case(value)
3'h1 : sel_r <= 6'b111_110;
3'h2 : sel_r <= 6'b111_100;
3'h3 : sel_r <= 6'b111_000;
3'h4 : sel_r <= 6'b110_000;
3'h5 : sel_r <= 6'b100_000;
3'h6 : sel_r <= 6'b000_000;
default: sel_r <= 6'b111_110;
endcase
end
else begin
sel_r <= sel_r;
end
end
assign sel = sel_r;
//数码管译码功能,组合逻辑
always@(*)begin
case(value)
4'h0 : seg_r = 8'b1100_0000;
4'h1 : seg_r = 8'b1111_1001;
4'h2 : seg_r = 8'b1010_0100;
4'h3 : seg_r = 8'b1011_0000;
4'h4 : seg_r = 8'b1001_1001;
4'h5 : seg_r = 8'b1001_0010;
4'h6 : seg_r = 8'b1000_0010;
4'h7 : seg_r = 8'b1111_1000;
4'h8 : seg_r = 8'b1000_0000;
4'h9 : seg_r = 8'b1001_0000;
4'ha : seg_r = 8'b1000_1000;
4'hb : seg_r = 8'b1000_0011;
4'hc : seg_r = 8'b1100_0110;
4'hd : seg_r = 8'b1010_0001;
4'he : seg_r = 8'b1000_0110;
4'hf : seg_r = 8'b1000_1110;
default: seg_r = 8'b1100_0000;
endcase
end
assign seg = seg_r;
endmodule
硬件测试效果:
思考?
在②中怎么使得数字看起来全部显示?
修改变化周期,当周期足够小时,由于余晖效应看起来就像是一直亮着一样。
余晖效应:
余晖效应即视觉暂留现象,人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”。
视觉暂留现象是光对视网膜所产生的视觉在光停止作用后,仍保留一段时间的现象,其具体应用是电影的拍摄和放映。原因是由视神经的反应速度造成的。是动画、电影等视觉媒体形成和传播的根据。视觉实际上是靠眼睛的晶状体成像,感光细胞感光,并且将光信号转换为神经电流,传回大脑引起人体视觉。感光细胞的感光是靠一些感光色素,感光色素的形成是需要一定时间的,这就形成了视觉暂停的机理。
三.总结
利用case语句设计类似于查找表的结构,对相应状态有不同的操作,数码管就是使多个LED灯按照所需显示,当数码管亮灭的时间周期足够短,肉眼不能发现,利用这个特性可以完成更为复杂的设计。