【FPGA】实战之数码管静态显示

一、数码管静态显示的原理

数码管其实就是由8个led集成在一起的,我们这里是FPGA,是共阳极数码管,给低电平就是点亮,
在这里插入图片描述
数码管显示有静态和动态显示。
那啥叫静态显示,我们这里补充一个知识点,就是数码管的驱动方式有两种,一种是静态驱动,就是一个数码管的片选(哪个)和段选(显示哪个段)各自都接一个接口,所需的接口就是片选×段选的个数,所以需要的接口特别特别的多,这种就是数码管的静态显示,第二种就是动态驱动,动态驱动就是动态显示。
在这里插入图片描述

二、设计思路

单纯的显示一个数字也太简单了,只要给高电平就行了
这里我们老师给我们1个小时的时间去完成一个数码管静态显示和其他模块的结合的任务,可以一起去思考下设计思路
在这里插入图片描述
这里有三个模块,数码管模块,按键消抖模块,蜂鸣器模块,后两者就不用多说了,你可以去看我的其他博客
数码管的显示没有问题,主要思考的是数码管后面靠什么去变化
通过思考不难发现就是按键按下给一个寄存器值,按下自增,然后根据寄存器值去改变数码管的显示,蜂鸣器也不必多说,加个判断就行了。
这只是新手入门小练习

三、代码部分

数码管静态显示模块
seg.v

module seg( 
    input				    clk		,
    input				    rst_n	,
    input	      [1:0] 	key_down,
    output  reg   [3:0]     num     ,
    output  reg   [7:0]     seg_dig ,
    output  reg   [5:0]     seg_sel
);


localparam  D0 = 8'b11000000,
            D1 = 8'b11001111,
            D2 = 8'b10100100,
            D3 = 8'b10110000,
            D4 = 8'b10011001,
            D5 = 8'b10010010,
            D6 = 8'b10000010,
            D7 = 8'b11111000,
            D8 = 8'b10000000,
            D9 = 8'b10011000;
//参数定义			 
reg     [3:0]    num;                       	 

//按键控制数码管计数
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        num <= 6;
    end 
    else if(key_down[0])begin 
        num <= num + 1;
    end 
    else if(key_down[1])begin 
        num <= num - 1;
    end
    else if(num > 9)begin
        num <= 6;
    end
    else if(num < 6)begin
        num <= 6;
    end
    else begin
        num <= num;
    end
end

//通过num值来段选计算
always @(*)begin 
    if(!rst_n)begin
        seg_sel = 6'b000_000;
        seg_dig = D6;
    end 
    else begin    
        case (num)
            6   :   seg_dig = D6;
            7   :   seg_dig = D7;
            8   :   seg_dig = D8;
            9   :   seg_dig = D9;
            default: seg_dig = D6;
        endcase
    end
end

按键消抖模块
key_filter.v

module key_filter #(parameter KEY_W = 2,DELAY_TIME = 1_000_000)( 
    input				                clk		,
    input				                rst_n	,
    input	            [KEY_W-1:0]	    key_in	,
    output	    reg 	[KEY_W-1:0]	    key_down
);	

//计数器
reg     [19:0]      cnt;
wire                add_cnt;
wire                end_cnt;

// 标志信号
reg                 filter_flag; 

reg      [KEY_W-1:0]  key_r0;      
reg      [KEY_W-1:0]  key_r1; 
reg      [KEY_W-1:0]  key_r2;    

wire                  n_edge;
wire                  p_edge;


// 对输入按键进行打拍,异步信号同步并检测边沿
// 打几拍就是延时几个周期
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        key_r0 <= -1;//负数以补码的方式存放,对原码取反加1
        key_r1 <= -1;
        key_r2 <= -1;
    end 
    else begin 
        key_r0 <= key_in;
        key_r1 <= key_r0;
        key_r2 <= key_r1;
    end 
end

// assign  n_edge = {!key_r1[1] && key_r2[1],!key_r1[0] && key_r2[0]};//第一种检测边沿
//三目运算符
assign  n_edge = ~key_r1 & key_r2?1'b1:1'b0;//第二种检测边沿
// assign  p_edge = {key_r1[1] && !key_r2[1],key_r1[0] && !key_r2[1]};
assign  p_edge = key_r1 & ~key_r2?1'b1:1'b0;


//当检测到下降沿,filter_flag为1
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        filter_flag <= 1'b0;
    end 
    //检测到下降沿
    else if(n_edge)begin 
        filter_flag <= 1'b1;
    end 
    else if(end_cnt)begin
        filter_flag <= 1'b0;
    end
    else begin 
        filter_flag <= filter_flag;
    end 
end

//当检测到filter_flga为1的时候开始计数
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt <= 0;
    end 
    else if(add_cnt)begin 
            if(end_cnt || p_edge)begin 
                cnt <= 0;
            end
            else begin 
                cnt <= cnt + 1;
            end 
    end
   else  begin
       cnt <= cnt;
    end
end 

assign add_cnt = filter_flag;
assign end_cnt = add_cnt && cnt == DELAY_TIME-1;

//key_down取的值是最后当前周期的key_r2值,是个稳定的值
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        key_down <= 0;
    end 
    else if(end_cnt)begin 
        key_down <= ~key_r2;
    end 
    else begin 
        key_down <= 0;
    end 
end
endmodule

蜂鸣器模块
beep.v

module beep(
input				    clk		,
input				    rst_n	,
input     [3:0]         num ,
output    reg           beep 
);

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        beep <= 0;
    end 
    else if(num == 9)begin 
        beep <= ~beep;
    end 
    else begin 
        beep <= beep;
    end 
end

endmodule

顶层模块
top.v

module top(
    input				        clk		,
    input				        rst_n	,
    input	        [1:0]	    key_in	,
    output          [7:0]       seg_dig ,
    output          [5:0]       seg_sel 
    output                      beep 	
);

parameter KEY_W = 2;
//中间信号
wire    [KEY_W-1:0]     key_down;
// wire    [3:0]           num;

//按键消抖模块
key_filter #(.KEY_W(KEY_W),.DELAY_TIME(1_000_000)) u_key_filter(			      
.clk			(clk			),			      
.rst_n		    (rst_n		    ),			      
.key_in		    (key_in		    ),			      
.key_down		(key_down		)			      
);

//数码管模块
clock_top u_clock_top( 
/*input				        */.clk		(clk),
/*input				        */.rst_n	(rst_n),
/*input	      [1:0] 	    */.key_down (key_down),
/*output  reg   [7:0]       */.seg_dig  (seg_dig),
/*output  reg   [3:0]       */.num      (num),
/*output  reg   [5:0]       */.seg_sel  (seg_sel)
);	

//蜂鸣器模块
beep u_beep(
/*input				      */.clk		(clk),
/*input				      */.rst_n	    (rst_n),
/*input                   */.num        (num),
/*output                  */.beep       (beep)
);

endmodule

四、总结

静态显示有手就行,毕竟我也行。

猜你喜欢

转载自blog.csdn.net/weixin_45888898/article/details/121566841