FPGA 数码管的静态显示

目标:设计一个 6 位数码管静态显示:控制六位数码管让其以 000000、111111、222222 一直到 FFFFFF 循环显示。每个字符显示 0.5s 后变化。

一、理论知识:

1.八段数码管结构图

 八段数码管分为共阴极和共阳极数码管。这两者的区别在于,公共端是连接到地还是高电平,对
于共阳极数码管需要给对应段低电平才会使其点亮,而对于共阴极数码管则需要给其高电平才会点亮。此次使用的是共阳极数码管,给对应段低电平才会被点亮。

数码管编码译码表

 

 六位数码管等效电路图

 注:sel为位选信号,控制着数码管的亮灭。

 

74HC595简介

       

74HC595芯片内部结构图

1)SHCP 为移位寄存器时钟输入,上升沿时将输入的串行数据(DS 端输入)移入移位寄存器中。需要注要的是它是一个移位寄存器,也就是说当下一个脉冲(时钟上升沿)到来时,上一个脉冲移入的数据就会往下移动一位。

如果我们串行输入 8bit 数据,8bit 数据输入完之后,那么第一位输入的数据将会移动到最后面。

若我们一次输入的数据超过 8bit,那么后面的数据就会通过 Q7S 端口输出,此时我们可以将该接口接到另一片74HC595 芯片的串行输入端(级联),这样数据就会随着脉冲依次移位到另一片 74HC595芯片上。

 74HC595的使用步骤

1、 首先把要传输的数据通过引脚 DS 输入到 74HC595 中。
2、 产生 SHCP 时钟,将 DS 上的数据串行移入移位寄存器。
3、 产生 STCP 时钟,将移位寄存器里的数据送入存储寄存器。

4、 将OE引脚置为低电平,存储寄存器的数据会在 Q0—Q7 并行输出,同时并行输出
的数据会被锁存起来。

         

    

74HC595原理图

我们将两片 74HC595 进行级联,一片的 Q7S 输出端接到另一片的数据输入端 DS,这样我
们输入的 14 位串行输入数码管信号的前六位就会在第二片就行输出。

二、程序设计

1.模块框图

    

 系统框图 

 

      

    静态数码管驱动模块框图

输入信号为sys_clk和sys_rst_n,输出信号为6位位选信号和8位段选信号

数码管静态显示参考代码:

module  seg_static
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低电平有效

    output  reg     [5:0]   sel         ,   //数码管位选信号
    output  reg     [7:0]   seg             //数码管段选信号
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter   CNT_WAIT_MAX  =  25'd24_999_999;   //计数器最大值(0.5s)
//十六进制数显示编码
parameter   SEG_0 = 8'b1100_0000,   SEG_1 = 8'b1111_1001,
            SEG_2 = 8'b1010_0100,   SEG_3 = 8'b1011_0000,
            SEG_4 = 8'b1001_1001,   SEG_5 = 8'b1001_0010,
            SEG_6 = 8'b1000_0010,   SEG_7 = 8'b1111_1000,
            SEG_8 = 8'b1000_0000,   SEG_9 = 8'b1001_0000,
            SEG_A = 8'b1000_1000,   SEG_B = 8'b1000_0011,
            SEG_C = 8'b1100_0110,   SEG_D = 8'b1010_0001,
            SEG_E = 8'b1000_0110,   SEG_F = 8'b1000_1110;
parameter   IDLE  = 8'b1111_1111;   //不显示状态

//reg   define
reg             add_flag    ;   //数码管数值+1标志信号
reg     [24:0]  cnt_wait    ;   //时钟分频计数器
reg     [3:0]   num         ;   //数码管显示的十六进制数

//********************************************************************//
//*************************** Main Code ******************************//
//********************************************************************//
//cnt_wait:0.5秒计数
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_wait    <=  25'd0;
    else    if(cnt_wait == CNT_WAIT_MAX)
        cnt_wait    <=  25'd0;
    else
        cnt_wait    <=  cnt_wait + 1'b1;

//add_flag:0.5s拉高一个标志信号
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        add_flag    <=  1'b0;
    else    if(cnt_wait == CNT_WAIT_MAX)
        add_flag    <=  1'b1;
    else
        add_flag    <=  1'b0;

//num:从 4'h0 加到 4'hf 循环
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        num <=  4'd0;
    else    if(add_flag == 1'b1)
        num <=  num + 1'b1;
    else
        num <=  num;

//sel:选中六个数码管
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel <=  6'b000000;
    else
        sel <=  6'b111111;

//给要显示的值编码
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg    <=  IDLE;
    else    case(num)
        4'd0:   seg    <=  SEG_0;
        4'd1:   seg    <=  SEG_1;
        4'd2:   seg    <=  SEG_2;
        4'd3:   seg    <=  SEG_3;
        4'd4:   seg    <=  SEG_4;
        4'd5:   seg    <=  SEG_5;
        4'd6:   seg    <=  SEG_6;
        4'd7:   seg    <=  SEG_7;
        4'd8:   seg    <=  SEG_8;
        4'd9:   seg    <=  SEG_9;
        4'd10:  seg    <=  SEG_A;
        4'd11:  seg    <=  SEG_B;
        4'd12:  seg    <=  SEG_C;
        4'd13:  seg    <=  SEG_D;
        4'd14:  seg    <=  SEG_E;
        4'd15:  seg    <=  SEG_F;
        default:seg    <=  IDLE ;  //闲置状态,不显示
    endcase

endmodule

   

       74HC595控制模块框图

74HC595控制模块参考代码

module  hc595_ctrl
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低有效
    input   wire    [5:0]   sel         ,   //数码管位选信号
    input   wire    [7:0]   seg         ,   //数码管段选信号
    
    output  reg             stcp        ,   //数据存储器时钟
    output  reg             shcp        ,   //移位寄存器时钟
    output  reg             ds          ,   //串行数据输入
    output  wire            oe              //使能信号,低有效
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//reg   define
reg     [1:0]   cnt_4   ;   //分频计数器
reg     [3:0]   cnt_bit ;   //传输位数计数器

//wire  define
wire    [13:0]  data    ;   //数码管信号寄存

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//将数码管信号寄存
assign  data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel};

//将复位取反后赋值给其即可
assign oe = ~sys_rst_n;

//分频计数器:0~3循环计数
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_4 <=  2'd0;
    else    if(cnt_4 == 2'd3)
        cnt_4 <=  2'd0;
    else
        cnt_4 <=  cnt_4 +   1'b1;

//cnt_bit:每输入一位数据加一
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_bit   <=  4'd0;
    else    if(cnt_4 == 2'd3 && cnt_bit == 4'd13)
        cnt_bit   <=  4'd0;
    else    if(cnt_4  ==  2'd3)
        cnt_bit   <=  cnt_bit   +   1'b1;
    else
        cnt_bit   <=  cnt_bit;

//stcp:14个信号传输完成之后产生一个上升沿
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        stcp    <=  1'b0;
    else    if(cnt_bit == 4'd13 && cnt_4 == 2'd3)
        stcp    <=  1'b1;
    else
        stcp    <=  1'b0;

//shcp:产生四分频移位时钟
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shcp    <=  1'b0;
    else    if(cnt_4 >= 4'd2)
        shcp    <=  1'b1;
    else
        shcp    <=  1'b0;

//ds:将寄存器里存储的数码管信号输入即
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        ds  <=  1'b0;
    else    if(cnt_4 == 2'd0)
        ds  <=  data[cnt_bit];
    else
        ds  <=  ds;

endmodule

顶层模块

  顶层模块参考代码                     

module  seg_595_static
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低有效

    output  wire            stcp        ,   //输出数据存储寄时钟
    output  wire            shcp        ,   //移位寄存器的时钟输入
    output  wire            ds          ,   //串行数据输入
    output  wire            oe              //输出使能信号
);

//********************************************************************//
//******************** Parameter And Internal Signal *****************//
//********************************************************************//
//wire  define
wire    [5:0]   sel;
wire    [7:0]   seg;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//---------- seg_static_inst ----------
seg_static  seg_static_inst
(
    .sys_clk     (sys_clk   ),   //系统时钟,频率50MHz
    .sys_rst_n   (sys_rst_n ),   //复位信号,低电平有效

    .sel         (sel       ),   //数码管位选信号
    .seg         (seg       )    //数码管段选信号
);

//---------- hc595_ctrl_inst ----------
hc595_ctrl  hc595_ctrl_inst
(
    .sys_clk     (sys_clk  ),   //系统时钟,频率50MHz
    .sys_rst_n   (sys_rst_n),   //复位信号,低有效
    .sel         (sel      ),   //数码管位选信号
    .seg         (seg      ),   //数码管段选信号

    .stcp        (stcp     ),   //输出数据存储寄时钟
    .shcp        (shcp     ),   //移位寄存器的时钟输入
    .ds          (ds       ),   //串行数据输入
    .oe          (oe       )    //输出使能信号
);

endmodule

 

注:本文参考野火fpga教程

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值