zynq学习之fpga篇(四)数码管动态显示

一、设计要求

用拨码开关的开闭充当1与0,总的使用4个拨码开关,将其所组成二进制,使用六位数码管最高位进行十进制显示,后四位显示拨码开关所对应的BCD码。

解析

(1)十进制对应BCD码
8421码 十进制数
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
 (2)数码管显示原理

数码管显示分为静态显示和动态显示,静态显示所有数码管显示相同的数值,动态显示不同数码管显示不同数值。

静态显示:控制数码管需要控制两个信号,位选信号和段选信号。位选信号是独立控制的,用来控制单个数码管的亮灭。段选信号控制数码管显示数值,在电路中六个数码管的段选信号连接在一起,所以在同一时间,位选信号控制点亮的数码管显示的值是相同的。

动态显示:由“人眼视觉暂留”和“数码管余晖效应”,当我们让每个数码管快速轮流显示,当速度快到人眼无法分辨时,我们所看到的数码管就是同时显示了不同的数值。

二、模块设计

数码管动态显示系统框图

分析

整个系统分为三个模块:

Top_seg 顶层模块,连接各模块对应信号
data_change 数据转化模块,将拨码开关对应二进制转化为数字信号
Seg_dynamic 动态数码管扫描模块

三、波形设计

data_change模块波形设计

分析

Data_BCD信号将四个输入转为二进制编码,seg_en信号为控制数码管动态扫描信号,在此次项目中可一直拉高。

Seg_dynamic模块波形设计

分析 

在编写过程中,想到时序逻辑,数据会延迟一拍,为了保证数据同步需要编写寄存器,用来寄存数据。

四、代码编写

顶层模块 

module top_seg(
		input	wire 	sys_clk		,
		input	wire 	sys_rst_n	,
		input	wire	key_in_0	,
		input	wire	key_in_1	,
		input	wire	key_in_2	,
		input	wire	key_in_3	,
		
		output	wire	[5:0]	sel	,
		output	wire	[7:0]	seg	
    );
	
wire		[3:0]	data_bcd	;
wire				seg_en		;	
	

data_change		data_change_inst(
		.sys_clk	(sys_clk	)	,
		.sys_rst_n	(sys_rst_n	),
		.key_in_0	(key_in_0	),
		.key_in_1	(key_in_1	),
		.key_in_2	(key_in_2	),
		.key_in_3	(key_in_3	),
		
		.data_bcd	(data_bcd	),
		.seg_en	    (seg_en	    )
    );

seg_dynamic		seg_dynamic_inst(
		.sys_clk	(sys_clk	),
		.sys_rst_n	(sys_rst_n	),
		.data_bcd	(data_bcd	),
		.seg_en		(seg_en		),

		.sel		(sel		),
		.seg	    (seg	    )
    );
		
endmodule

 数据转化模块:

module data_change(
		input	wire 			sys_clk		,
		input	wire 			sys_rst_n	,
		input	wire			key_in_0	,
		input	wire			key_in_1	,
		input	wire			key_in_2	,
		input	wire			key_in_3	,
		
		output	reg	[3:0]	data_bcd	,
		output	reg			seg_en	
    );
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)begin
		data_bcd <= 4'd0;
		seg_en <= 1'b0;
		end
	else begin
		data_bcd <= {key_in_0,key_in_1,key_in_2,key_in_3};	
		seg_en <= 1'b1;
		end	
endmodule

数码管动态扫描模块:

module seg_dynamic(
		input	wire 	sys_clk			,
		input	wire 	sys_rst_n		,
		input	wire	[3:0]	data_bcd,
		input	wire			seg_en	,

		output	reg	[5:0]	sel		,
		output	reg	[7:0]	seg	
    );
parameter	CNT_MAX = 16'd49_999;
	
reg		[24:0]	cnt_1ms		;
reg				cnt_flag	;	
reg		[2:0]	cnt_sel		;
reg		[5:0]	sel_reg		;
reg		[3:0]	data_reg	;
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		cnt_1ms <= 16'd0;
	else if(cnt_1ms==CNT_MAX)
		cnt_1ms <= 16'd0;
	else
		cnt_1ms <= cnt_1ms + 1'b1;
			
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		cnt_flag <= 1'b0;
	else if(cnt_1ms==CNT_MAX-1)
		cnt_flag <= 1'b1;
	else
		cnt_flag <= 1'b0;		
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		cnt_sel <= 3'd0;
	else if(cnt_flag==1'b1)
		cnt_sel <= cnt_sel + 1'b1;
	else if((cnt_sel==3'd5)&&(cnt_flag==1'b1))
		cnt_sel <= 3'd0;		
	else
		cnt_sel <= cnt_sel;	
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		sel_reg <= 6'd0 ;
	else  case(cnt_sel)
		3'b000	:	sel_reg <= 6'b111_110	;
		//3'b001	:	sel_reg <= 6'b111_101   ;
		3'b010	:	sel_reg <= 6'b111_011   ;
		3'b011	:	sel_reg <= 6'b110_111   ;
		3'b100	:	sel_reg <= 6'b101_111   ;
		3'b101	:	sel_reg <= 6'b011_111	;
		default		sel_reg <= 6'b111_111 	;
	endcase	
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		data_reg <= 3'd0 ;
	else  case(cnt_sel)
		3'b000	:	data_reg <= data_bcd	 ;
		//3'b001	:	data_reg <= 6'b000_010   ;
		3'b010	:	data_reg <= {4'b00,data_bcd[3]}   ;
		3'b011	:	data_reg <= {4'b00,data_bcd[2]}   ;
		3'b100	:	data_reg <= {4'b00,data_bcd[1]}   ;
		3'b101	:	data_reg <= {4'b00,data_bcd[0]}	 ;
		default		data_reg <= 4'b0000 	 ;
	endcase		
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		seg <= 8'h79 ;
	else  case(data_reg)
		4'd0	:	seg <= 8'h3f;	
		4'd1	:	seg <= 8'h06;   
		4'd2	:	seg <= 8'h5b;   
		4'd3	:	seg <= 8'h4f;   
		4'd4	:	seg <= 8'h66;   
		4'd5	:	seg <= 8'h6d;	
		4'd6	:	seg <= 8'h7d;	
		4'd7	:	seg <= 8'h07;   
		4'd8	:	seg <= 8'h7f;   
		4'd9	:	seg <= 8'h6f;   	
		default		seg <= 8'h79 	;
		
	endcase		
	
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		sel <= 6'd0;
	else
		sel <= sel_reg;		
	
endmodule

五、RTL视图

由RTL视图发现该代码有待改进,多路选择部分没有写完整。 

六、Testbench编写

module tb_seg();

reg 	sys_clk	  ;
reg 	sys_rst_n	;
reg	key_in_0	  ;
reg	key_in_1	  ;
reg	key_in_2	  ;
reg	key_in_3	  ;

wire	[5:0]	sel	;
wire	[7:0]	seg	;

initial
	begin
		sys_clk	<=	1'b1;
		sys_rst_n	<=	1'b0;
		key_in_0 <=   1'b0;
		key_in_1 <=   1'b0;
		key_in_2 <=   1'b0;
		key_in_3 <=   1'b0;		
		#20
		sys_rst_n		<=	1'b1;
	end 	
always#10 sys_clk <= ~sys_clk;
always#100_0007 key_in_1 <= {$random} % 2;
always#100_0007 key_in_2 <= {$random} % 2;
always#100_0007 key_in_3 <= {$random} % 2;

top_seg top_seg_inst(
		.sys_clk   (sys_clk	)		,
		.sys_rst_n	(sys_rst_n),
		.key_in_0	(key_in_0),
		.key_in_1	(key_in_1),
		.key_in_2	(key_in_2),
		.key_in_3	(key_in_3),

		.sel	   (sel)  ,
		.seg	   (seg)
    );
endmodule

七、仿真结果

仿真波形图

仿真波形主要查看动态数码管扫描模块部分是否正确。 

八、上板实测

上板实测

 如图所示,用左下方四个拨码开关进行输入,数码管进行输出。

九、下期内容

没有系统的跟谁学习,每次做完一个项目不知道下个项目学什么,每次都提前想好吧!

下个项目FPGA部分最后一个项目——摄像头驱动,可以学到:IIC通信协议、SPI通信协议、UART通信、FIFO、SDRAM 等等。

行而不辍,未来可期。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-01-29 21:16:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-29 21:16:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-29 21:16:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-29 21:16:01       18 阅读

热门阅读

  1. 计算机网络之三次握手,四次挥手

    2024-01-29 21:16:01       36 阅读
  2. Mongodb查询投射中的$elemMatch

    2024-01-29 21:16:01       35 阅读
  3. VLM 系列——Monkey——论文解读

    2024-01-29 21:16:01       40 阅读
  4. Web 上升的圆心

    2024-01-29 21:16:01       27 阅读
  5. 用二分法在有序数列中查找元素位置

    2024-01-29 21:16:01       26 阅读
  6. MySQL表的增删改查(进阶)

    2024-01-29 21:16:01       27 阅读
  7. Anaconda 镜像清华大学开源软件镜像站

    2024-01-29 21:16:01       40 阅读