FPGA之旅设计99例之第六例-----动态数码管

简介: 笔记

一. 简介


这是FPGA之旅的第六个实例设计啦,驱动动态数码管,也是非常重要且基础的硬件电路。在数码管上,可以显示的字符有0-9和A-F,通过数码管,就可以将内部的相关信息直接显示出来,在学习初期使用的比较多,在课设中,一般利用数码管做数字时钟的比较多。其他例如可以显示DS18B20的温度数值和MPU6050传感器的ID值等等。


二. 硬件电路


每个数码管共有八个LED灯,分别标号为a-f和dp(dp通常用作小数点),点亮原理和普通的一样。从图中可以看到,八个数码管的八个LED灯连在了一起,进行了复用。这时候,通过上面的LED1-LED8片选来控制当前的数码管是否使能。使能了的数码管正常亮灭,没有使能的,始终处于灭的状态。


数码管共有两种接法,一种是共阴,即复用端给高电平,对应的LED亮,另外一种为共阳,即复用端给低电平,对应的LED亮

1.png


本实例使用的是共阳数码管。


三. Verilog代码实现—译码


当需要显示的字符为2的时候,很显然,并不能直接给这八个LED灯赋值为2,而是需要经过一个译码,将2转成数码管上显示2所对应的量。译码的过程也很容易,是个体力活,将2对应到数码管上,可以看到需要点亮的LED灯有:a,b,g,c,d,其余的LED灯均灭。如果按照{dp,g,f,e,d,c,b,a}排列组成一个byte的话,那么显示2对应的byte值为8’b1010_0100也就是0xA4,其余字符的译码也是如此。对应成代码如下(只译码了0-9)


module Decode(
  input[2:0]     in_data,  //输入的数据
    output reg[7:0]      out_data  //解码输出 
);
always@(*)
begin
  case(in_data)
  'd0:  out_data <= 8'b1100_0000;
  'd1:    out_data <= 8'b1111_1001;
  'd2:    out_data <= 8'b1010_0100;
  'd3:  out_data <= 8'b1011_0000;
  'd4:  out_data <= 8'b1001_1001;
  'd5:  out_data <= 8'b1001_0010;
  'd6:  out_data <= 8'b1000_0010;
  'd7:  out_data <= 8'b1111_1000;
  'd8:  out_data <= 8'b1000_0000;
  'd9:  out_data <= 8'b1001_0000;
  default:  out_data <= 8'hff;
  endcase
end


这样就完成了一个译码的模块,将需要显示的数据输入这个模块即可。


四. Verilog代码显示–数码管显示


一个数码管显示的话,就将译码过后的数据,输出即可。动态数码管,什么是动态呢?当数码管的个数达到两个以上的时候,要想显示两个不同的字符的话,这个时候,就需要在数码管的片选端来回切换,利用视觉残留效应,可以在多个数码管上显示不同的信息,来回切换的过程记为动态。


假如我们需要显示四个数据在数码管上,


module Seg_scan(
  input     clk,
  input    rst,
    output reg[3:0]  sel,  //数码管片选,低电平选中
    output reg[7:0]  dig,  //数码管LED
    //经译码过后的数据
    input[7:0]  seg_data_0,   
  input[7:0]  seg_data_1,  
  input[7:0]  seg_data_2,  
  input[7:0]  seg_data_3  
);
parameter SCAN_FREQ = 100000;     //扫描频率
reg[30:0] scan_cnt;
reg[3:0]  scan_sel;     //扫描选择
always@(posedge clk or negedge rst)
begin
  if(rst == 1'b0)
  scan_cnt <= 'd0;
  else  if(scan_cnt >= SCAN_FREQ)
  scan_cnt <= 'd0;
  else
  scan_cnt <= scan_cnt + 1'b1;
end
//选择数码管
always@(posedge clk or negedge rst)
begin
  if(rst == 1'b0)
  scan_sel <= 'd0;
  else if(scan_cnt >= SCAN_FREQ)
  if(scan_sel >= 3'b100)
    scan_sel <= 3'b000;
  else
    scan_sel <= scan_sel + 1'b1;
end
always@(posedge clk or negedge rst)
begin
  if(rst == 1'b0)
  begin
    sel <= 4'b1111;
    dig <= 8'hff;
  end
  else
  case(scan_sel)
  3'b000:
    begin
    sel <= 4'b1101;
    dig <= seg_data_0;
    end
  3'b001:
    begin
    sel <= 4'b1110;
    dig <= seg_data_1;
    end
  3'b010:
    begin
    sel <= 4'b1011;
    dig <= seg_data_2;
    end
  3'b011:
    begin
    sel <= 4'b0111;
    dig <= seg_data_3;
    end
  3'b100:
    begin
    sel <= 4'b0000;
    dig <= 8'hff;
    end 
  default
  begin
    sel <= 4'b1111;
    dig <= 8'hff;
  end
  endcase
end
endmodule


五. testbeach编写


接下来就是编写测试模块了,这个模块也很容易,主要是看译码后的数据是否正确,二是数码管的片选端是否正常切换。

`timescale 1ns/1ps
module testbeach();
    reg     clk;
    reg     rst;
    reg[2:0]    in_data0;
    reg[2:0]    in_data1;
    reg[2:0]    in_data2;
    reg[2:0]    in_data3;
    wire[7:0]   dedata0;
    wire[7:0]   dedata1;
    wire[7:0]   dedata2;
    wire[7:0]   dedata3;
    wire[3:0]   sel;   //数码管片选
    wire[7:0]   dig;   //数码管数据
    always #50 clk <= ~clk;
    initial begin
        clk = 1'b0;
        rst = 1'b1;
        in_data0 <= 'd1;
        in_data1 <= 'd3;
        in_data2 <= 'd5;
        in_data3 <= 'd8;
        #100
        rst = 1'b0;
        #100
        rst = 1'b1;
    end
Decode DecodeHP1(
  .in_data        (in_data0),  //输入的数据
  .out_data       (dedata0)  //解码输出 
);
Decode DecodeHP2(
  .in_data        (in_data1),  //输入的数据
  .out_data       (dedata1)  //解码输出 
);
Decode DecodeHP3(
  .in_data        (in_data2),  //输入的数据
  .out_data       (dedata2)  //解码输出 
);
Decode DecodeHP4(
  .in_data        (in_data3),  //输入的数据
  .out_data       (dedata3)  //解码输出 
);
Seg_scan Seg_scanHP(
  .clk                (clk),
  .rst                (rst),
  .sel                (sel),
  .dig                (dig),
  .seg_data_0         (dedata0),  
  .seg_data_1         (dedata1),  
  .seg_data_2         (dedata2),  
  .seg_data_3         (dedata3)  
);
endmodule

2.png

仿真波形如上图所示。可以看到片选和所译码给出的数据是一致的,也就是说我们的数码管可以正常显示啦。


欢迎关注微信公众号 回复 FPGA之旅设计99例之第六例 获取完整工程。


公众号:FPGA之旅

目录
相关文章
|
7月前
|
芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(一)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
213 2
|
7月前
|
芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(三)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
164 4
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(二)
FPGA入门(6):数码管静态/动态显示(二)
71 10
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(一)
FPGA入门(6):数码管静态/动态显示
54 0
|
7月前
|
存储 芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(二)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
180 4
|
异构计算
FPGA项目五:数码管动态扫描(下)
FPGA项目五:数码管动态扫描
219 0
FPGA项目五:数码管动态扫描(下)
|
程序员 异构计算
FPGA项目五:数码管动态扫描(中)
FPGA项目五:数码管动态扫描
263 0
FPGA项目五:数码管动态扫描(中)
|
异构计算
FPGA项目五:数码管动态扫描(上)
FPGA项目五:数码管动态扫描
324 0
FPGA项目五:数码管动态扫描(上)
|
13天前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的16QAM调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本项目基于FPGA实现了16QAM基带通信系统,包括调制、信道仿真、解调及误码率统计模块。通过Vivado2019.2仿真,设置不同SNR(如8dB、12dB),验证了软解调相较于传统16QAM系统的优越性,误码率显著降低。系统采用Verilog语言编写,详细介绍了16QAM软解调的原理及实现步骤,适用于高性能数据传输场景。
113 69