FPGA实战-----数码管(2)动态显示

上一章己经讲过了数码管的静态显示
传送门: FPGA实战------数码管(1)静态显示

接下来就是讲解一下动态显示。



前言

上一章已经对数码管的基础讲解了一遍,虽然不全且不完美,但基本上知道这些写代码就没问题。这里就不过多讲解了,有什么不会打在评论区或私信。
这里直接上动态显示的代码。


一、代码

/**************************************功能介绍***********************************
Date	: 2023年9月30日20:58:00
Author	: Yang.
Project : 数码管动态显示
Require : 数码管单显,从1-F六个数码管轮流显示
*********************************************************************************/
//---------<模块及端口声名>------------------------------------------------------
module seg_dynamics( 
    input            clk      ,
    input            rst_n    ,
    output reg [5:0] sel      ,
    output reg [7:0] dig     
);

parameter       ZERO   = 8'b1100_0000 ,
                ONE    = 8'b1111_1001 ,
                TWO    = 8'b1010_0100 ,
                THREE  = 8'b1011_0000 ,
                FOUR   = 8'b1001_1001 ,
                FIVE   = 8'b1001_0010 ,
                SIX    = 8'b1000_0010 ,
                SEVEN  = 8'b1111_1000 ,
                EIGHT  = 8'b1000_0000 ,
                NINE   = 8'b1001_0000 ,
                NUM_A  = 8'b1000_1000 ,
                NUM_B  = 8'b1000_0011 ,
                NUM_C  = 8'b1100_0110 ,
                NUM_D  = 8'b1010_0001 ,
                NUM_E  = 8'b1000_0110 ,
                NUM_F  = 8'b1000_1110 ;

parameter       MAX_1S = 26'd50_000_000 ;

reg  [25:0] cnt_1s      ;
wire        add_cnt_1s  ;
wire        end_cnt_1s  ;

reg  [4:0] cnt_num     ;//数码管显示的数字
reg  [2:0] cnt_seg     ;//控制位选信号 


//------------------------<1s计时器>---------------------------
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt_1s <= 0 ;
    end
    else if(add_cnt_1s)begin
        if(end_cnt_1s)begin
            cnt_1s <= 0 ;
        end
        else begin
            cnt_1s <= cnt_1s + 1 ;
        end
    end
end

assign add_cnt_1s = 1'b1 ;
assign end_cnt_1s = add_cnt_1s && cnt_1s == MAX_1S - 1 ;

//------------------------<cnt_seg>---------------------------
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt_seg <= 0 ;
    end
    else if((end_cnt_1s)&&(cnt_seg== 3'd5))begin
        cnt_seg <= 0 ;
    end
    else if(end_cnt_1s)begin
        cnt_seg <= cnt_seg + 1 ;
    end
    else begin
        cnt_seg <= cnt_seg ;
    end
end
//------------------------<位选>---------------------------
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        sel <= 6'b111_111 ;
    end
    else begin
        case (cnt_seg)
            3'd0 : sel <= 6'b111_110 ;
            3'd1 : sel <= 6'b111_101 ; 
            3'd2 : sel <= 6'b111_011 ; 
            3'd3 : sel <= 6'b110_111 ; 
            3'd4 : sel <= 6'b101_111 ; 
            3'd5 : sel <= 6'b011_111 ;  
            default: sel <= sel ;
        endcase
    end
end
//------------------------<cnt_num>---------------------------
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_num <= 'd0;
    end
    else if ((cnt_num == 5'd15)&&(end_cnt_1s)) begin
        cnt_num <= 'd0;
    end 
    else if(end_cnt_1s)begin 
        cnt_num <= cnt_num + 1 ;
        end 
    else begin 
        cnt_num <= cnt_num;
    end 
end
//------------------------<段选>---------------------------
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        dig <= ZERO ;
    end
    else begin
        case (cnt_num)
            5'd0  : dig <= ZERO   ;
            5'd1  : dig <= ONE    ;
            5'd2  : dig <= TWO    ;
            5'd3  : dig <= THREE  ;
            5'd4  : dig <= FOUR   ;
            5'd5  : dig <= FIVE   ;
            5'd6  : dig <= SIX    ;
            5'd7  : dig <= SEVEN  ;
            5'd8  : dig <= EIGHT  ;
            5'd9  : dig <= NINE   ;
            5'd10 : dig <= NUM_A  ;
            5'd11 : dig <= NUM_B  ;
            5'd12 : dig <= NUM_C  ;
            5'd13 : dig <= NUM_D  ;
            5'd14 : dig <= NUM_E  ;
            5'd15 : dig <= NUM_F  ; 
            default: dig <= dig  ;
        endcase
    end
end



endmodule

二、细节

为什么直接上代码,因为大致和静态显示差不多,就是多了一个和cnt_num一样作用的cnt_seg
因为它的加入,直接导致六个数码管的“协同合作”终止,变成了“孤军奋战”。六个数码管从右到左按顺序亮,并且改变数值。
case语句的作用,在上一章和led中都说到了,但我就是不厌其烦,为了让看博客的同学们记住(快夸夸我)。最简单的说法: sel知道自己在cnt_seg是什么值的时候应该让哪个数码管亮


三、仿真

`timescale 1ns/1ns
    
module tb_seg_dynamics();

//激励信号定义 
    reg				tb_clk  	;
    reg				tb_rst_n	;

//输出信号定义	 
    wire	[5:0]		seg_sel	;
    wire	[7:0]		seg_dig ;

//时钟周期参数定义	
    parameter		CLOCK_CYCLE = 20;   

//参数重新定义
    defparam u_seg_dynamics.MAX_1S = 100;

//模块例化
    seg_dynamics  u_seg_dynamics( 
    /*input            */.clk   (tb_clk )   ,
    /*input            */.rst_n (tb_rst_n )   ,
    /*output reg [5:0] */.sel   (seg_sel )   ,
    /*output reg [7:0] */.dig   (seg_dig )  
);	

//产生时钟
    initial 		tb_clk = 1'b0;
    always #(CLOCK_CYCLE/2) tb_clk = ~tb_clk;

//产生激励
    initial  begin 
        tb_rst_n = 1'b1;

        #(CLOCK_CYCLE*2);
        tb_rst_n = 1'b0;
        #(CLOCK_CYCLE*20);
        tb_rst_n = 1'b1;

        #(CLOCK_CYCLE*10000);
        $stop;

    end

endmodule 

总结

上板效果

FPGA数码管动态显示

仿真结果
仿真结果
总体来说,一切符合代码,合理且正确。

博客上传的工程都在百度网盘,有压缩包也有整个文件,可以自行下载。
链接:https://pan.baidu.com/s/1lQqqWZXfb3i6XHwkKf52zg
提取码:yang

数码管基础的操作就学完了,接下来还有深层的操作,期待吧!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值