FPGA极易入门教程----数码管篇(1)静态显示_数码管静态显示(2)

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

+ dis\_sel[5:0]:数码管位宽,共6个数码管所以共需要6bit,低电平有效
+ dp:小数点二极管控制信号,低电平有效

3.2、Verilog代码

驱动代码很好写,我们只需要使用两个always块和1个assign语句即可完成。

第1个 always块来对位选信号赋值,这里复位熄灭所有数码管;复位完成后给所有数码管供电(选中所有数码管)

//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        dis_sel <= 6’b111111;                    //复位熄灭所有数码管
    else
        dis_sel <= 6’b000000;                    //复位完成后给所有数码管供电
end

第2个 always块来段选信号赋值,根据输入的数据(要显示的数)来对段选信号赋取对应的码值。

//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        dis_seg <= 7’b111_1111;                    //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
    else begin
        case (num)
            4’h0 : dis_seg <= 7’b000_0001;        //显示数字“0”,则数码管的段选编码为7’b000_0001
            4’h1 : dis_seg <= 7’b100_1111;
            4’h2 : dis_seg <= 7’b001_0010;
            4’h3 : dis_seg <= 7’b000_0110;
            4’h4 : dis_seg <= 7’b100_1100;
            4’h5 : dis_seg <= 7’b010_0100;
            4’h6 : dis_seg <= 7’b010_0000;
            4’h7 : dis_seg <= 7’b000_1111;
            4’h8 : dis_seg <= 7’b000_0000;
            4’h9 : dis_seg <= 7’b000_0100;        //显示数字“9”,则数码管的段选编码为7’b000_0100
            default : dis_seg <= 7’b111_1111;    //其他数字(16进制的数字相对10进制无效)则熄灭数码管
        endcase
    end
end

小数点显示我们暂时不用,直接将其赋值1,使其失效。

assign dis_dp = 1’b1;                            //小数点,我们暂时不同,使其无效即可

完整代码如下:

//6位8段式数码管静态显示驱动

//端口定义
module dis_sta_dri (
	input 				sys_clk ,				//时钟信号
	input 				sys_rst_n ,				//复位信号(低有效)
			
	input		[3:0]	num,					//数码管显示的十进制数
	output reg 	[5:0] 	dis_sel,				//数码管位选
	output reg 	[6:0] 	dis_seg, 				//数码管段选
	output				dis_dp					//数码管小数点
);

assign dis_dp = 1'b1;							//小数点,我们暂时不同,使其无效即可

//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
	if (!sys_rst_n)
		dis_sel <= 6'b111111;					//复位熄灭所有数码管
	else
		dis_sel <= 6'b000000;					//复位完成后给所有数码管供电
end

//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
	if (!sys_rst_n)
		dis_seg <= 7'b111_1111;					//复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
	else begin
		case (num)
			4'h0 : dis_seg <= 7'b000_0001;		//显示数字“0”,则数码管的段选编码为7'b000_0001
			4'h1 : dis_seg <= 7'b100_1111;
			4'h2 : dis_seg <= 7'b001_0010;
			4'h3 : dis_seg <= 7'b000_0110;
			4'h4 : dis_seg <= 7'b100_1100;
			4'h5 : dis_seg <= 7'b010_0100;
			4'h6 : dis_seg <= 7'b010_0000;
			4'h7 : dis_seg <= 7'b000_1111;
			4'h8 : dis_seg <= 7'b000_0000;
			4'h9 : dis_seg <= 7'b000_0100;		//显示数字“9”,则数码管的段选编码为7'b000_0100
			default : dis_seg <= 7'b111_1111;	//其他数字(16进制的数字相对10进制无效)则熄灭数码管
		endcase
	end
end

endmodule

那么现在静态显示的驱动写好了,我们还需要写个数据生成模块,也就是我们要想办法写入数据到这个驱动来进行显示。

这个模块只有两个always块,第1个 always块做一个1s的计时器,该计时器循环计时1s。该模块可以顺序生成0-9这10个数,每隔1s,数据累加1。

//1s计时模块,该模块循环计数到1s
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        cnt_1s <= 0;                            //复位计数器为0
    else if(cnt_1s == (50_000_000 - 1))            //计数器计数到了1s,每个时钟周期20ns,则从0开始需要计数(1_000_000_000/20 - 1)
        cnt_1s <= 0;                            //计数器清零重新开始计数
    else    
        cnt_1s <= cnt_1s + 1;                    //没有计数到1s则每个周期计数1次
end

第2个 always块每隔1s生成1个数据,数据范围0-9循环。

//数据生成模块,从0开始累加(每1s累加一次),到9结束。然后循环
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        data <= 0;                                //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
    else if(cnt_1s == (50_000_000 - 1))begin    //每次计数到1s
        if(data == 9)                            //数据生成到了9则重新开始从0生成
            data <= 0;
        else                                    //数据没有生成到9则累加1
            data <= data + 1;        
    end
end

有了驱动模块和数据生成模块,我们再写一个顶层模块,顶层模块调用这两个模块并完成连接,实现模块化设计。顶层模块的代码如下:

//6位8段式数码管静态顶层文件
//例化静态显示驱动模块和数据生成模块,将数据生成模块生成的数字,通过静态驱动,用数码管显示出来

//端口定义
module dis_sta_top (
	input 				sys_clk ,			//时钟信号
	input 				sys_rst_n ,			//复位信号(低有效)
			
	output  	[5:0] 	dis_sel,			//数码管位选
	output  	[6:0] 	dis_seg, 			//数码管段选
	output				dis_dp				//数码管小数点
);

wire	[3:0]	data;						//需要显示的数字

//例化静态显示驱动模块
dis_sta_dri	dis_sta_dri_inst(
	.sys_clk 	(sys_clk	),				//时钟信号
	.sys_rst_n 	(sys_rst_n	),				//复位信号(低有效)
	
	.num		(data		),				//数码管显示的十进制数
	.dis_sel	(dis_sel	),				//数码管位选
	.dis_seg 	(dis_seg	),				//数码管段选
	.dis_dp		(dis_dp		)
);	
	
//例化数据生成模块	
data_generate	data_generate_inst (	
	.sys_clk 	(sys_clk	),				//时钟信号,50M
	.sys_rst_n 	(sys_rst_n	),				//复位信号(低有效)
	
	.data 		(data		)				//4位二进制数字
);	

endmodule

3.3、Testbench及仿真结果

可能看到这里,很多朋友就已经想要直接上板验证了。**这里我说个忠告:做FPGA设计,一定要做仿真测试,一定要分析波形。**做FPGA的设计不能拿着做单片机的思维来做,不能上来就是看上板结果。设计完成后,先做仿真,90%的问题(有点夸张了)都可以通过仿真规避掉。当然我知道,作为初学者,看到实验现象在板卡上显示的时候是很有趣和很有成就感的,但是相信我,如果你想在这条路上走得更远,就一定要做仿真分析波形,随着时间的流逝、经验的增加,日后一定会大幅提高你的能力,并帮你节约大量时间。

由于我们的工程中,我已经设计了激励,所以在TB文件中,我们仅仅需要提供时钟、复位即可。完整的TB文件如下:

//静态显示仿真激励TESTBENCH

`timescale 1ns/1ns	//时间单位/精度

//------------<模块及端口声明>----------------------------------------
module tb_dis_sta_top();

reg 			sys_clk;			//时钟信号
reg 			sys_rst_n;          //复位信号(低有效)
                                    
wire	[5:0] 	dis_sel;            //数码管位选
wire	[6:0] 	dis_seg;            //数码管段选
wire			dis_dp;             //数码管小数点

//------------<例化被测试模块>----------------------------------------
dis_sta_top		dis_sta_top_inst(
	.sys_clk	(sys_clk	),
	.sys_rst_n	(sys_rst_n	),
	
	.dis_sel	(dis_sel	),
	.dis_seg	(dis_seg	),
	.dis_dp		(dis_dp		)
);

//------------<设置初始测试条件>----------------------------------------
initial begin
	sys_clk = 1'b0;					//初始时钟为0
	sys_rst_n <= 1'b0;				//初始复位
	#25								//25个时钟周期后
	sys_rst_n <= 1'b1;				//拉高复位,系统进入工作状态
	
end
//------------<设置时钟>----------------------------------------------
always #10 sys_clk = ~sys_clk;		//系统时钟周期20ns


![img](https://img-blog.csdnimg.cn/img_convert/1014891a2b31e7fc336383916c750872.png)
![img](https://img-blog.csdnimg.cn/img_convert/e3e6a881b7f15fe1f2062a5b752d54b5.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

5873296318)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值