【 FPGA 】四位16进制的数码管动态显示设计

举报
李锐博恩 发表于 2021/07/15 04:57:57 2021/07/15
6.3k+ 0 0
【摘要】 数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。 分时复用的扫描显示利用了人眼的视觉暂留特性,如果公共端的控制信号刷新速度足够快,人眼就不会区分出LED的闪烁,认为4个数码管是同时点亮。 如下图: D1、D2、D3、D4就是公共控制端口,也就是片选端,控制哪一个数码管被选中。 而abcdefg是段选,用来控制数码管...

数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。

分时复用的扫描显示利用了人眼的视觉暂留特性,如果公共端的控制信号刷新速度足够快,人眼就不会区分出LED的闪烁,认为4个数码管是同时点亮。

如下图:

D1、D2、D3、D4就是公共控制端口,也就是片选端,控制哪一个数码管被选中。

而abcdefg是段选,用来控制数码管的显示内容。

下面代码中的an就是片选端,以及控制信号一致的输出段码信号sseg。片选控制信号的刷新速度必须足够快才能避免闪烁感,但也不能太快,以免影响数码管的开关切换,最佳的工作频率为1000Hz左右。如果FPGA的时钟为50MHz,那么至少跑5*10^4个周期,也即50000个周期刷新一次才行,我们知道2^16=65536,2^15=32768。

所以,用16位2进制数来控制技术吧,技术满了刷新一次。

代码中采用的是18位2进制数,高2位控制片选,低16位计数满一次,进位一次,高两位的变化时00——01——10——11——00——...,分别选中数码管的其中之一,使用case语句即可完成这个功能。

下面代码中的hex0、hex1、hex2、hex3是输入信号,用来控制数码管显示的数字,dp_in用来控制小数点的亮灭。

Verilog HDL描述如下:


      `timescale 1ns / 1ps
      //
      // Company: 
      // Engineer: 
      // 
      // Create Date: 21:03:02 01/05/2019 
      // Design Name: 
      // Module Name: scan_led_hex_disp 
      // Project Name: 
      // Target Devices: 
      // Tool versions: 
      // Description: 
      //
      // Dependencies: 
      //
      // Revision: 
      // Revision 0.01 - File Created
      // Additional Comments: 
      //
      //
      module scan_led_hex_disp(
       input clk,
       input reset,
       input [3:0] hex0, //第一个数码管显示的数字
       input [3:0] hex1,
       input [3:0] hex2,
       input [3:0] hex3,
       input [3:0] dp_in, //小数点控制
       output reg [3:0] an,   //片选
       output reg [7:0] sseg  //段选
       );
      	localparam N = 18; //使用低16位对50Mhz的时钟进行分频(50MHZ/2^16)
      	reg [N-1:0] regN; //高两位作为控制信号,低16位为计数器,对时钟进行分频
      	reg [3:0] hex_in; //段选控制信号
      	reg dp;
      	always@(posedge clk, posedge reset)
      	begin
     		if(reset)
      			regN <= 0;
     		else
      			regN <= regN + 1;
      	end
      	always@ *
      	begin
     		case(regN[N-1:N-2])
     		2'b00:begin
      			an = 4'b1110; //选中第1个数码管
      			hex_in = hex0; //数码管显示的数字由hex_in控制,显示hex0输入的数字;
      			dp = dp_in[0]; //控制该数码管的小数点的亮灭
      		end
     		2'b01:begin
      			an = 4'b1101; //选中第二个数码管
      			hex_in = hex1;
      			dp = dp_in[1];
      		end
     		2'b10:begin
      			an = 4'b1011;
      			hex_in = hex2;
      			dp = dp_in[2];
      		end
     		default:begin
      			an = 4'b0111;
      			hex_in = hex3;
      			dp = dp_in[3];
      		end
      		endcase
      	end
      	always@ *
      	begin
     		case(hex_in)
     			4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
     			4'h1: sseg[6:0] = 7'b1001111;
     			4'h2: sseg[6:0] = 7'b0010010;
     			4'h3: sseg[6:0] = 7'b0000110;
     			4'h4: sseg[6:0] = 7'b1001100;
     			4'h5: sseg[6:0] = 7'b0100100;
     			4'h6: sseg[6:0] = 7'b0100000;
     			4'h7: sseg[6:0] = 7'b0001111;
     			4'h8: sseg[6:0] = 7'b0000010;
     			4'h9: sseg[6:0] = 7'b0000100;
     			4'ha: sseg[6:0] = 7'b0001000;
     			4'hb: sseg[6:0] = 7'b1100000;
     			4'hc: sseg[6:0] = 7'b0110001;
     			4'hd: sseg[6:0] = 7'b1000010;
     			4'he: sseg[6:0] = 7'b0110000;
     			default: sseg[6:0] = 7'b0111000;
      		endcase
      		sseg[7] = dp;
      	end
      endmodule
  
 

共阳极数码管码表:

            4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
            4'h1: sseg[6:0] = 7'b1001111;
            4'h2: sseg[6:0] = 7'b0010010;
            4'h3: sseg[6:0] = 7'b0000110;
            4'h4: sseg[6:0] = 7'b1001100;
            4'h5: sseg[6:0] = 7'b0100100;
            4'h6: sseg[6:0] = 7'b0100000;
            4'h7: sseg[6:0] = 7'b0001111;
            4'h8: sseg[6:0] = 7'b0000010;
            4'h9: sseg[6:0] = 7'b0000100;
            4'ha: sseg[6:0] = 7'b0001000;
            4'hb: sseg[6:0] = 7'b1100000;
            4'hc: sseg[6:0] = 7'b0110001;    
            4'hd: sseg[6:0] = 7'b1000010;
            4'he: sseg[6:0] = 7'b0110000;

为了验证上述代码的实际效果,用下列代码调用上述代码来测试:


      `timescale 1ns / 1ps
      //
      // Company: 
      // Engineer: 
      // 
      // Create Date: 14:05:56 01/06/2019 
      // Design Name: 
      // Module Name: scan_led_hex_disp_test 
      // Project Name: 
      // Target Devices: 
      // Tool versions: 
      // Description: 
      //
      // Dependencies: 
      //
      // Revision: 
      // Revision 0.01 - File Created
      // Additional Comments: 
      //
      //
      module scan_led_hex_disp_test(
       input clk,
      	input [3:0] sw,
       output [3:0] an,
       output [7:0] sseg
       );
      	wire [3:0] a,b;
      	wire [7:0] sum;
      	assign a = {2'b00,sw[1:0]};
      	assign b = {2'b00,sw[3:2]};
      	assign sum = {4'b0,a}+{4'b0,b};
      	scan_led_hex_disp uu1(
      	.clk(clk),.reset(1'b0),
      	.hex3(sum[7:4]),.hex2(sum[3:0]),
      	.hex1(b),.hex0(a),
      	.dp_in(4'b1011),.an(an),.sseg(sseg)
      	);
      endmodule
  
 

功能是两个数码管用来显示数字a和b,而其他两个数码管显示a和b之和。

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/85881999

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。