FPGA之静态数码管显示实验

1、背景介绍

  •       数码管是一种现代经常使用的数码显示器件,具备发光显示清晰,响应速度快,功耗低 、体积小、寿命长、易于控制等诸多优势,在数显仪器仪表、数字控制设备等方面获得普遍应用。
  •       按发光二极管单元链接方式可分为共阳极数码管共阴极数码管。共阳数码管是指将全部发光二极管的阳极接到一块儿造成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将全部发光二极管的阴极接到一块儿造成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。一般咱们用的数码管都是段选公用的,位选独立的,例如四位一体数码管。

   

 

  • 数码管的内部原理图以下图所示:

2、实验过程

  • 实验任务:
    • 本节实验任务是使用FPGA开发板上的6位数码管以静态方式依次显示000000、1111十一、222222至FFFFFF,结束后继续从000000开始计数,每0.5s变化一次。
  • 硬件原理图
  • 硬件接口定义

  • 程序框图
  •  seg_led_static_top 

  • 主要分为两个模块
    • 计时模块 (time_count):实现0.5s的计时效果
    • 数码管静态显示模块(seg_led_static):经过状态机实现不一样状态下的显示配置,数码管静态显示模块在数码管上以静态方式显示数值。
  • 代码以下:
module seg_led_static_top(
    input      sys_clk,
    input      sys_rst_n,

    output   [5:0] seg_wei,
    output   [7:0] seg_duan
);
wire time_flag;
//wire clk;


time_count u_time_count(
      .sys_clk    (sys_clk),
      .sys_rst_n  (sys_rst_n),
      .time_flag  (time_flag)
);

seg_led_static u_seg_led_static(
          .sys_clk  (sys_clk),
          .sys_rst_n (sys_rst_n),
          .time_flag (time_flag),
          .seg_wei   (seg_wei),
          .seg_duan  (seg_duan)
);

endmodule

 

 

module time_count(
    input      sys_clk,
    input      sys_rst_n,
    output reg time_flag
);
 
reg [24:0]  time_num;

always @(posedge sys_clk or negedge sys_rst_n)begin
       if(!sys_rst_n)
       begin
           time_num<=25'd0;
           time_flag<=1'b0;  
       end

       else begin
                if(time_num<25'd25_000_000)begin
                                time_num<=time_num+1'b1;
                        time_flag<=1'b0; 
                end
            

                else
                begin
                    time_num<=25'd1;
                    time_flag<=1'b1;   
                end
            end  


end
endmodule

 

 

module seg_led_static(
    input      sys_clk,
    input      sys_rst_n,
    input      time_flag,
    output reg [5:0] seg_wei,
    output reg [7:0] seg_duan
);

reg [3:0] seg_fsm;

always  @(posedge sys_clk or negedge sys_rst_n)begin
  if(!sys_rst_n)
  seg_fsm<=4'd0;
  else if(time_flag)
  begin
    seg_fsm<=seg_fsm+1'b1;  
  end
  else
  seg_fsm<=seg_fsm;
end

always  @(posedge sys_clk or negedge sys_rst_n)begin
  if(!sys_rst_n)
  begin
   seg_wei  <=6'b000000;      //低电平点亮数码管
  seg_duan <=8'b00000000;   
  end
  else 
   case(seg_fsm)  //共阳数码管
 /*   4'b0000:  seg_duan <=8'b1100_0000;  //0
    4'b0001:  seg_duan <=8'b1111_1001;   //1
    4'b0010:  seg_duan <=8'b0100_1111;
    4'b0011:  seg_duan <=8'b0000_0000;
    4'b0100:  seg_duan <=8'b0000_0000;
    4'b0101:  seg_duan <=8'b0000_0000;
    4'b0110:  seg_duan <=8'b0000_0000;
    4'b0111:  seg_duan <=8'b0000_0000;
    4'b1000:  seg_duan <=8'b0000_0000;
    4'b1001:  seg_duan <=8'b0000_0000;
    4'b1010:  seg_duan <=8'b0000_0000;
    4'b1011:  seg_duan <=8'b0000_0000;
    4'b1100:  seg_duan <=8'b0000_0000;
    4'b1101:  seg_duan <=8'b0000_0000;
    4'b1110:  seg_duan <=8'b0000_0000;
    4'b1111:  seg_duan <=8'b0000)0000; 
    */ 
             4'h0 :    seg_duan  <= 8'b1100_0000; 
             4'h1 :    seg_duan  <= 8'b1111_1001; 
             4'h2 :    seg_duan  <= 8'b1010_0100; 
             4'h3 :    seg_duan  <= 8'b1011_0000; 
             4'h4 :    seg_duan  <= 8'b1001_1001; 
             4'h5 :    seg_duan  <= 8'b1001_0010; 
             4'h6 :    seg_duan  <= 8'b1000_0010; 
             4'h7 :    seg_duan  <= 8'b1111_1000; 
             4'h8 :    seg_duan  <= 8'b1000_0000; 
             4'h9 :    seg_duan  <= 8'b1001_0000; 
             4'ha :    seg_duan  <= 8'b1000_1000; 
             4'hb :    seg_duan  <= 8'b1000_0011; 
             4'hc :    seg_duan  <= 8'b1100_0110; 
             4'hd :    seg_duan  <= 8'b1010_0001; 
             4'he :    seg_duan  <= 8'b1000_0110; 
             4'hf :    seg_duan  <= 8'b1000_1110; 
             default : seg_duan  <= 8'b1100_0000;       
   endcase
end

endmodule

仿真结果以下图:3d

 

最终实现实验任务!调试

(PS:调试中 顶层时钟不要链接同一个模块的两个端口  sys_clk  形成实验问题)code