FPGA开发——数码管的使用

一、概述

在我们的日常开发中,数字显示的领域中用得最多的就是数码管,这篇文章也是围绕数码管的静态显示和动态显示进行一个讲解。

1、理论

(1)数码管原理图

在对数码管进行相关控制时,其实就是对于8段发光二极管和一个位选信号进行控制,也就是我们熟悉的段选和位选。段选就包括a,b,c,d,e,f,g,h这八个二极管,位选就是选择某个二极管工作的一个简单引脚。

2、共阴极和共阳极的判断

市场上我们常见的数码管有共阴极啊和共阳极两种信号,其外观上没有什么区别,都是通过原理图进行判断和区分,两种数码挂对应的驱动方式也不一样。共阴极是高电平驱动,共阳极是低电平驱动。所谓的共阴极和共阳极实际上就是看公共引脚接在正极还是负极上。

3、本次使用的数码管原理图

其实在原理图中并没有明确说明是共阴极还是共阳极,我们需要通过SEL位选信号进行判断。在最下面的三极管我们可以看到只有当SELx_T为低电平时三极管才会接通,所以这里通过判断是共阳极,通过低电平触发。

二、工程实现

1、单个数码管静态显示

(1)、设计文件

新建seg.v文件,如下:

这里不需要使用任何时序功能,只是简单显示一个数字,直接就用连续赋值进行实现。这里代码过于简单,就不去进行仿真和下板验证了。

cpp 复制代码
module top(
    output  seg_sel,
    output [7:0] seg_dual

);

assign seg_sel=1'b0;//选择第一个数码管
assign seg_dual=8'b11_000_000;//数码管显示0

2、单个数码管实现动态显示

(1)、设计文件

cpp 复制代码
//分频器
module seg0(
  input  clk,
  input  rst_n,
  
  input  seg_sel,//位选
  output reg [7:0] seg_dual0//段选
);
localparam  ZERO  = 8'b11100_0000, //共阳极段码
            ONE   = 8'b11111_1001,
            TWO   = 8'b11010_0100,
            THREE = 8'b11011_0000,
            FOUR  = 8'b11001_1001,
            FIVE  = 8'b11001_0010,
            SIX   = 8'b11000_0010,
            SEVEN = 8'b11111_1000,
            EIGHT = 8'b11000_0000,
            NINE  = 8'b11001_0000,
            A     = 8'b11000_1000,
            b     = 8'b11000_0011,
            c     = 8'b11100_0110,
            d     = 8'b11010_0001,
            E     = 8'b11000_0110,
            f     = 8'b11000_1110;
reg [26:0] cnt;
wire       add_cnt;
wire       end_cnt;  
reg [4:0]   flag;
wire        add_flag;
wire        end_flag;
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      cnt<=0;
    else if(add_cnt)begin
      if(end_cnt)
        cnt<=0;
      else
        cnt<=cnt+1'b1;
    end
end
assign add_cnt=1'b1;
assign end_cnt=add_cnt && (cnt==50_000_000-1);

always @(posedge clk or negedge rst_n)begin
  if(!rst_n)
    flag<=0;
  else if(add_flag)begin
    if(end_flag)
      flag<=0;
    else
      flag<=flag+1'b1;
  end
end
assign add_flag=end_cnt;
assign end_flag=add_flag && (flag==16-1);

always @(posedge clk or negedge rst_n)begin
  if(!rst_n)
    seg_dual0<=8'b1111_1111;
  else begin
    case (flag)
      4'd0:seg_dual0<=ZERO ;
      4'd1:seg_dual0<=ONE  ;
      4'd2:seg_dual0<=TWO  ; 
      4'd3:seg_dual0<=THREE;
      4'd4:seg_dual0<=FOUR ;
      4'd5:seg_dual0<=FIVE ;
      4'd6:seg_dual0<=SIX  ;
      4'd7:seg_dual0<=SEVEN;
      4'd8:seg_dual0<=EIGHT;
      4'd9:seg_dual0<=NINE ;
      4'd10:seg_dual0<=A ;
      4'd11:seg_dual0<=b  ;
      4'd12:seg_dual0<=c;
      4'd13:seg_dual0<=d;
      4'd14:seg_dual0<=E ;
      4'd15:seg_dual0<=f ;
      default: ;
    endcase
  end 
end
endmodule 

(2)、测试文件

cpp 复制代码
//定义时间尺度
`timescale 1ns/1ns
module seg_tb ;

//输入信号定义
reg  clk;
reg rst_n;

wire [7:0] seg_dual0;
wire  seg_sel;
defparam  seg0_inst.TIME_1s=500;
//模块例化
seg0 seg0_inst(
    /*input */.clk      (clk     ),
    /*input */.rst_n    (rst_n   ),
    /*output*/.seg_sel  (seg_sel ),
    /*output*/.seg_dual0 (seg_dual0)

);
//激励信号产生
parameter CLK_CLY = 20;
//时钟
initial clk=1;
always #(CLK_CLY/2)clk=~clk;

//复位
initial begin
    rst_n= 1'b0;
    #(CLK_CLY*3);
    #5;//复位结束避开时钟上升沿
    rst_n= 1'b1;
end
endmodule

(3)、波形图仿真

在波形图中我们可以看到段选从8'b11_000_000------8'b11_000_1110,也就是从0------F动态显示。

相关推荐
Mortal_hhh34 分钟前
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
ide·vscode·stm32·编辑器
DS小龙哥1 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
会发光的猪。10 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
上理考研周导师11 小时前
第二章 虚拟仪器及其构成原理
fpga开发
lucky九年11 小时前
vscode翻译插件
ide·vscode·编辑器
真·Wild·攻城狮12 小时前
【码农日常】Vscode Clangd初始化失败(Win10)
ide·vscode·编辑器
小堇不是码农12 小时前
在VScode中配置C_C++环境
c语言·c++·vscode
七灵微12 小时前
【测试】【Debug】vscode中同一个测试用例出现重复
ide·vscode·编辑器