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

相关推荐
夜雨听萧瑟1 天前
VSCode的clangd插件简单介绍和使用
vscode
FPGA小c鸡1 天前
AXI-Full突发传输完全攻略:从INCR/WRAP/FIXED到4KB边界、地址计算、响应机制(附实战案例)
fpga开发
集芯微电科技有限公司1 天前
DC-DC|40V/10A大电流高效率升压恒压控制器
c语言·数据结构·单片机·嵌入式硬件·fpga开发
minglie11 天前
Vitis HLS c转verilog
c语言·开发语言·fpga开发
GDAL1 天前
vscode 使用正则查找替换
ide·vscode·正则表达式·编辑器
江蘇的蘇1 天前
基于FPGA实现NVMe硬盘的读写功能
fpga开发
forgeda1 天前
国产FPGA故障注入测试-用户使用指南
fpga开发·国产fpga·故障注入测试·大容量芯片·7vx690t·复旦jmf fpga·高可用系统
HERR_QQ1 天前
【cpp tool】GDB coredump vscode GUI 和多线程常用笔记
ide·笔记·vscode
扮作大侠1 天前
vitis板级支持包的.c文件位置
fpga开发
FPGA_小田老师1 天前
FPGA例程(2):LED流水灯--vivado FPGA程序固化下载
fpga开发·fpga程序固化·flash烧写·mcs文件生成