• FPGA之旅设计99例之第六例-----动态数码管


    一. 简介

    这是FPGA之旅的第六个实例设计啦,驱动动态数码管,也是非常重要且基础的硬件电路。在数码管上,可以显示的字符有0-9和A-F,通过数码管,就可以将内部的相关信息直接显示出来,在学习初期使用的比较多,在课设中,一般利用数码管做数字时钟的比较多。其他例如可以显示DS18B20的温度数值和MPU6050传感器的ID值等等。

    二. 硬件电路

    每个数码管共有八个LED灯,分别标号为a-f和dp(dp通常用作小数点),点亮原理和普通的一样。从图中可以看到,八个数码管的八个LED灯连在了一起,进行了复用。这时候,通过上面的LED1-LED8片选来控制当前的数码管是否使能。使能了的数码管正常亮灭,没有使能的,始终处于灭的状态。

    数码管共有两种接法,一种是共阴,即复用端给高电平,对应的LED亮,另外一种为共阳,即复用端给低电平,对应的LED亮
    在这里插入图片描述

    本实例使用的是共阳数码管。

    三. Verilog代码实现—译码

    当需要显示的字符为2的时候,很显然,并不能直接给这八个LED灯赋值为2,而是需要经过一个译码,将2转成数码管上显示2所对应的量。译码的过程也很容易,是个体力活,将2对应到数码管上,可以看到需要点亮的LED灯有:a,b,g,c,d,其余的LED灯均灭。如果按照{dp,g,f,e,d,c,b,a}排列组成一个byte的话,那么显示2对应的byte值为8’b1010_0100也就是0xA4,其余字符的译码也是如此。对应成代码如下(只译码了0-9)

    module Decode(
    	input[2:0]	 		 in_data,		//输入的数据
        output reg[7:0]	     out_data		//解码输出	
    );
    always@(*)
    begin
    	case(in_data)
    	'd0:	out_data <= 8'b1100_0000;
    	'd1:    out_data <= 8'b1111_1001;
    	'd2:    out_data <= 8'b1010_0100;
    	'd3:	out_data <= 8'b1011_0000;
    	'd4:	out_data <= 8'b1001_1001;
    	'd5:	out_data <= 8'b1001_0010;
    	'd6:	out_data <= 8'b1000_0010;
    	'd7:	out_data <= 8'b1111_1000;
    	'd8:	out_data <= 8'b1000_0000;
    	'd9:	out_data <= 8'b1001_0000;
    	default:	out_data <= 8'hff;
    	endcase
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这样就完成了一个译码的模块,将需要显示的数据输入这个模块即可。

    四. Verilog代码显示–数码管显示

    一个数码管显示的话,就将译码过后的数据,输出即可。动态数码管,什么是动态呢?当数码管的个数达到两个以上的时候,要想显示两个不同的字符的话,这个时候,就需要在数码管的片选端来回切换,利用视觉残留效应,可以在多个数码管上显示不同的信息,来回切换的过程记为动态。

    假如我们需要显示四个数据在数码管上,

    module Seg_scan(
    	input	 			clk,
    	input				rst,
    
        output reg[3:0]		sel,  //数码管片选,低电平选中
        output reg[7:0]		dig,  //数码管LED
    	
        //经译码过后的数据
        input[7:0]		seg_data_0,	 	
    	input[7:0]		seg_data_1,		
    	input[7:0]		seg_data_2,		
    	input[7:0]		seg_data_3		
    );
    parameter SCAN_FREQ = 100000;     //扫描频率
    reg[30:0]	scan_cnt;
    reg[3:0] 	scan_sel;     //扫描选择
    
    always@(posedge clk or negedge rst)
    begin
    	if(rst == 1'b0)
    		scan_cnt <= 'd0;
    	else	if(scan_cnt >= SCAN_FREQ)
    		scan_cnt <= 'd0;
    	else
    		scan_cnt <= scan_cnt + 1'b1;
    end
    //选择数码管
    always@(posedge clk or negedge rst)
    begin
    	if(rst == 1'b0)
    		scan_sel <= 'd0;
    	else if(scan_cnt >= SCAN_FREQ)
    		if(scan_sel >= 3'b100)
    			scan_sel <= 3'b000;
    		else
    			scan_sel <= scan_sel + 1'b1;
    end
    always@(posedge clk or negedge rst)
    begin
    	if(rst == 1'b0)
    		begin
    				sel <= 4'b1111;
    				dig <= 8'hff;
    		end
    	else
    		case(scan_sel)
    		3'b000:
    			begin
    				sel <= 4'b1101;
    				dig <= seg_data_0;
    			end
    		3'b001:
    			begin
    				sel <= 4'b1110;
    				dig <= seg_data_1;
    			end
    		3'b010:
    			begin
    				sel <= 4'b1011;
    				dig <= seg_data_2;
    			end
    		3'b011:
    			begin
    				sel <= 4'b0111;
    				dig <= seg_data_3;
    			end
    		3'b100:
    			begin
    				sel <= 4'b0000;
    				dig <= 8'hff;
    			end	
    		default
    		begin
    				sel <= 4'b1111;
    				dig <= 8'hff;
    		end
    		endcase
    end
    endmodule 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    五. testbeach编写

    接下来就是编写测试模块了,这个模块也很容易,主要是看译码后的数据是否正确,二是数码管的片选端是否正常切换。

    `timescale 1ns/1ps
    module testbeach();
        reg     clk;
        reg     rst;
        reg[2:0]    in_data0;
        reg[2:0]    in_data1;
        reg[2:0]    in_data2;
        reg[2:0]    in_data3;
    
        wire[7:0]   dedata0;
        wire[7:0]   dedata1;
        wire[7:0]   dedata2;
        wire[7:0]   dedata3;
    
        wire[3:0]   sel;   //数码管片选
        wire[7:0]   dig;   //数码管数据
    
    
        always #50 clk <= ~clk;
    
        initial begin
            clk = 1'b0;
            rst = 1'b1;
    
            in_data0 <= 'd1;
            in_data1 <= 'd3;
            in_data2 <= 'd5;
            in_data3 <= 'd8;
            #100
            rst = 1'b0;
            #100
            rst = 1'b1;
        end
    Decode DecodeHP1(
    	.in_data        (in_data0),		//输入的数据
    	.out_data       (dedata0)		//解码输出	
    );
    Decode DecodeHP2(
    	.in_data        (in_data1),		//输入的数据
    	.out_data       (dedata1)		//解码输出	
    );
    Decode DecodeHP3(
    	.in_data        (in_data2),		//输入的数据
    	.out_data       (dedata2)		//解码输出	
    );
    Decode DecodeHP4(
    	.in_data        (in_data3),		//输入的数据
    	.out_data       (dedata3)		//解码输出	
    );
    Seg_scan Seg_scanHP(
    	.clk                (clk),
    	.rst                (rst),
    	.sel                (sel),
    	.dig                (dig),
    	
    	.seg_data_0         (dedata0),		
    	.seg_data_1         (dedata1),		
    	.seg_data_2         (dedata2),		
    	.seg_data_3         (dedata3)		
    );
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    在这里插入图片描述

    仿真波形如上图所示。可以看到片选和所译码给出的数据是一致的,也就是说我们的数码管可以正常显示啦。

    欢迎关注微信公众号 回复 FPGA之旅设计99例之第六例 获取完整工程。

  • 相关阅读:
    Tomcat运行常见问题
    typescript17-函数可选参数
    Python编程实例-使用HTTP进行Web编程详解-(基于urllib库)
    I/O软件层次
    java毕业设计鸿鹄教育培训(附源码、数据库)
    RK3568-clock
    Mysql日志
    模板特化--类和函数
    CSS基础入门笔记(选择器)
    TextRCNN、TextCNN、RNN
  • 原文地址:https://blog.csdn.net/weixin_44678052/article/details/126630124