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动态显示。

相关推荐
cliffordl1 小时前
vscode 环境搭建
ide·vscode·编辑器
JANGHIGH1 小时前
VSCode引用Eigen库无法识别问题解决
ide·vscode·编辑器
千穹凌帝1 小时前
SpinalHDL之结构(二)
开发语言·前端·fpga开发
我就是全世界2 小时前
开源集成开发环境搭建之VSCode启动Jupyter Notebook
ide·vscode·jupyter
一口一口吃成大V7 小时前
FPGA随记——FPGA时序优化小经验
fpga开发
贾saisai8 小时前
Xilinx系FPGA学习笔记(九)DDR3学习
笔记·学习·fpga开发
redcocal13 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
科研小白_d.s13 小时前
vscode配置c/c++环境
c语言·c++·vscode
程序猿进阶20 小时前
如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?
java·ide·vscode·算法·面试·职场和发展·架构
猿饵块20 小时前
vscode
ide·vscode·编辑器