首页 > 其他分享 >基于EP4CE6F17C8的FPGA数码管动态显示实例

基于EP4CE6F17C8的FPGA数码管动态显示实例

时间:2024-03-16 11:47:59浏览次数:40  
标签:动态显示 FPGA clk EP4CE6F17C8 seg 数码管 data data0 时钟

一、电路模块

1、数码管

开发板板载了6个数码管,全部为共阳型,原理图如下图所示,段码端引脚为DIG[0]~DIG[7]共8位(包含小数点),位选端引脚为SEL[0]~SEL[5]共6位。端口均为低电平有效。

其实物图如下所示。

数码管引脚分配见下表。

2、时钟晶振

开发板板载了一个50MHz的有源晶振,为系统提供时钟。

其实物图如下所示。

时钟输出引脚分配见下表。

3、按键

开发板板载了4个独立按键,其中有3个用户按键(KEY1~KEY3),1个功能按键(RESET)。按键按下为低电平(0),释放为高电平(1),4个按键的原理图如下图所示。本例中只使用了RESET键。

其实物图如下所示。

按键的引脚分配见下表。

 

二、实验代码

本例实现6个数码管显示123456,代码使用Verilog编写,采用例化的形式,共有两个文件。

先编写数码管实现字形的程序,模块名称为seg,文件名称为seg.v,代码如下。

module seg(
    input clk,                       //板载50HMz系统时钟
    input[3:0]  data,                //显示的字形,可显示0~F十六个字形,所以需要4位
    output reg[7:0] seg              //字形编码,包含小数点,共8位
);

always@(posedge clk)                 //敏感信号为时钟上沿
begin
    case(data)
        4'd0:seg <= 8'b1100_0000;    //字形0的编码
        4'd1:seg <= 8'b1111_1001;    //字形1的编码
        4'd2:seg <= 8'b1010_0100;    //字形2的编码
        4'd3:seg <= 8'b1011_0000;    //字形3的编码
        4'd4:seg <= 8'b1001_1001;    //字形4的编码
        4'd5:seg <= 8'b1001_0010;    //字形5的编码
        4'd6:seg <= 8'b1000_0010;    //字形6的编码
        4'd7:seg <= 8'b1111_1000;    //字形7的编码
        4'd8:seg <= 8'b1000_0000;    //字形8的编码
        4'd9:seg <= 8'b1001_0000;    //字形9的编码
        4'ha:seg <= 8'b1000_1000;    //字形A的编码
        4'hb:seg <= 8'b1000_0011;    //字形B的编码
        4'hc:seg <= 8'b1100_0110;    //字形C的编码
        4'hd:seg <= 8'b1010_0001;    //字形D的编码
        4'he:seg <= 8'b1000_0110;    //字形E的编码
        4'hf:seg <= 8'b1000_1110;    //字形F的编码
        default:seg <= 7'b111_1111;  //默认不显示
    endcase
end
endmodule

接下来编写数码管显示的程序,模块名称为seg_show,文件名称为seg_show.v,代码如下。

module seg_show(
    input clk,                    //板载50HMz系统时钟
    input rst,                    //复位按键
    output reg[7:0] seg7,         //段码端口
    output reg[5:0] bit           //位选端口
);

reg[19:0]     cnt;                //定义20位时钟计数器//下面定义6个存放显示字形的变量
wire[7:0]     seg_data0,seg_data1,seg_data2,seg_data3,seg_data4,seg_data5;
//下面定义6个要显示的数字
wire[3:0]     data0 = 4'd1;    //data0赋值1
wire[3:0]     data1 = 4'd2;    //data1赋值2
wire[3:0]     data2 = 4'd3;    //data2赋值3
wire[3:0]     data3 = 4'd4;    //data3赋值4
wire[3:0]     data4 = 4'd5;    //data4赋值5
wire[3:0]     data5 = 4'd6;    //data5赋值6

//以下例化了6个数码管seg0~seg5,把各自的显示数字与字形编码联系起来
seg seg0(.clk(clk), .data(data0), .seg(seg_data0));
seg seg1(.clk(clk), .data(data1), .seg(seg_data1));
seg seg2(.clk(clk), .data(data2), .seg(seg_data2));
seg seg3(.clk(clk), .data(data3), .seg(seg_data3));
seg seg4(.clk(clk), .data(data4), .seg(seg_data4));
seg seg5(.clk(clk), .data(data5), .seg(seg_data5));

//20毫秒循环计数
always@(posedge clk or negedge rst)     //敏感信号为时钟上沿或复位下沿
begin
    if(!rst)                            //低电平复位
        cnt <= 20'd0;                   //复位时时钟计数器清零
    else if(cnt == 20'd999_999)         //时钟计数器到达20毫秒时
        cnt <= 20'd0;                   //时钟计数器清零
    else
        cnt <= cnt + 1;                 //否则时钟计数器加1,即来一次时钟脉冲加一次
end

//数码管扫描显示
always@(posedge clk or negedge rst)    //敏感信号为时钟上沿或复位下沿
begin
    if(!rst)                           //低电平复位时数码管全灭
    begin
        bit <= 6'b111111;
        seg7 <= 8'hff;
    end
    else if(cnt == 20'd166_666)        //时钟到3毫秒时,数码管0显示1
    begin
        bit <= 6'b111110;
        seg7 <= seg_data0;
    end
    else if(cnt == 20'd333_333)        //时钟到6毫秒时,数码管1显示2
    begin
        bit <= 6'b111101;
        seg7 <= seg_data1;
    end
    else if(cnt == 20'd499_999)        //时钟到10毫秒时,数码管2显示3
    begin
        bit <= 6'b111011;
        seg7 <= seg_data2;
    end
    else if(cnt == 20'd666_666)        //时钟到13毫秒时,数码管3显示4
    begin
        bit <= 6'b110111;
        seg7 <= seg_data3;
    end
    else if(cnt == 20'd833_333)        //时钟到16毫秒时,数码管4显示5
    begin
        bit <= 6'b101111;
        seg7 <= seg_data4;
    end
    else if(cnt == 20'd999_999)        //时钟到20毫秒时,数码管5显示6
    begin
        bit <= 6'b011111;
        seg7 <= seg_data5;
    end
end
endmodule

三、代码说明

1、本例中使用了计数器来分频时钟,总计约20ms的循环,并在此间分配了6个数码管进行显示,每个数码管大约分得3.3ms左右的显示时间。
2、时钟计数器选取了20位,对50MHz时钟进行分频,最大能达到20.9ms,刚好大于所需要的20ms,所以取20位进行计数比较合适,太多了浪费硬件资源。
3、时钟分频还可以采用PLL的方式,待频率降下来了之后,再使用少量的计数器来得到所需要的时间,可进一步节约资源,但会消耗一个PLL。
4、程序中使用了数码管例化的形式,共例化出了6个数码管。例化的数码管负责解码,即把要显示的数值解码成显示的字形编码,再输出给数码管的段码端口。
5、在定义的变量中,data0~data5分别给了固定值1~6,seg_data0~seg_data5分别接收解码后的字形编码,并在下面的过程语句中,分别送给相应数码管的段端口进行显示。以0号数码管为例,它要显示字符1,先把1赋值给变量data0,然后通过例化seg seg0(.clk(clk), .data(data0), .seg(seg_data0));把data0的值传给元件内部变量data(即文件seg.v中的data),而后得到字形编码,输出给变量seg_data0,然后当时钟计数cnt达到20'd166_666时,把seg_data0的数据送给seg7端口,同时打开0号数码管的位选通端口(bit <= 6'b111110;),此时该数码管显示出字形1。其他数码管的显示原理以此类推。
6、由上可以看出,元件例化有点类似于C语句中的函数调用及返回,但元件的每一个例化都是要产生出实际的电路的(要消耗逻辑器件),可查看生成的RTL电路图。

四、实验步骤

FPGA开发的详细步骤请参见“基于EP4CE6F17C8的FPGA开发流程(以半加器为例)”一文,本例只对一同之处进行说明。

本例工程放在D:\EDA_FPGA\Exam_3文件夹下,工程名称为Exam_3。有两个模块文件,一个名称为seg_show.v,设置为顶层实体,另一个名称为seg.v,用于提供例化。其余步骤与“基于EP4CE6F17C8的FPGA开发流程”中的一样。

接下来看管脚约束,本例中6个数码管一共有16个引脚,再加上时钟晶振和复位按钮,一共18个。具体的端口分配如下图所示。

对于未用到的引脚设置为三态输入方式,多用用途引脚全部做为普通I/O端口,电压设置为3.3-V LVTTL(与”基于EP4CE6F17C8的FPGA开发流程“中的一样)。需要注意,程序中的每个端口都必须为其分配管脚,如果系统中存在未分配的I/O,软件可能会进行随机分配,这将造成不可预料的后果,存在烧坏FPGA芯片的风险。

接下来对工程进行编译,编译完成后,可查看一下逻辑器件的消耗情况,如下图所示。

另外,还可以点击菜单Tools->Netlist Viewers->RTL Viewer,查看一下生成的RTL电路图。

最后进行程序下载,并查看结果。下图为6个数码我们管的动态显示效果。

当按下复位键后,所有数码管均熄灭,如下图所示。

标签:动态显示,FPGA,clk,EP4CE6F17C8,seg,数码管,data,data0,时钟
From: https://www.cnblogs.com/fxzq/p/18074784

相关文章

  • FPGA常用通信协议——I2C(二)
    一、时序 上一篇中我们已经了解了I2C的基本时序,这里我们只考虑I2C的写数据,具体时序见下图 二、信号列表sta_flag开始信号,拉高时开始一次读或写sda_en三态门控制信号,控制SDA是输出还是输入ready_flag结束标志,传入下一个模块,提醒下一模块可继续发送write总线正在工作信号,......
  • (笔记)FPGA多周期路径及set_multicycle_path详解
    默认情况下综合工具会把每条路径定义为单周期路径,即源触发器在时钟的任一边沿启动(launch)的数据都应该由目的触发器在时钟的下一上升沿捕获(capture)。有的设计可能存在时序例外(timingexceptions),如多周期路径、虚假路径等。数据从起点到终点的传输时间需要一个时钟周期以上才能稳定......
  • FPGA交通信号灯设计报告(VHDL语言)
    FPGA的大作业我选择了交通灯控制系统的设计,此课程只有2个学分,因此只需要在相应软件仿真出结果即可。以下是我的设计报告,当时写的匆忙,没有对代码进行优化改进,但仿真结果是正确的,可以给大家提供一下思路。一、任务分析1.输入和输出2.多进程3.特殊情况4.注意二、quartus......
  • m基于FPGA的Alamouti编码verilog实现,包含testbench测试文件
    1.算法仿真效果 本系统进行了Vivado2019.2平台的开发,结果如下:   2.算法涉及理论知识概要        在无线通信领域,多天线技术是提高系统容量和可靠性的关键手段之一。Alamouti编码是空时编码(STC)的一种,它为两发射天线的系统提供了一种全速率、全分集的简单编码方......
  • FPGA的FIFO部分的知识点
    看的小梅哥的新视频,FIFO这边讲的不太清楚,换正点原子的fifo听一下。后面的以太网和HDMI有空也看一下正点原子的,主要是想快速看zynq的知识,而且现在学的很多都是模仿抄代码,真正自己来还是得工程中实际应用的时候才会使用学习FIFO,先入先出,像队列。常用于数据的缓存,因为数据的读写带......
  • 从零开始利用MATLAB进行FPGA设计(一):建立脉冲检测模型的Simulink模型2
    目录1.模块的总体结构1.1从工作空间导入输入信号1.2FIR滤波器2.Subsystem3.MATLABFunction文章灵感来源于MATLAB官方免费教程:HDLCoderSelf-GuidedTutorial考虑到MATLAB官网的英文看着慢,再加上视频讲解老印浓浓的咖喱味,我决定记录利用MATLAB&Simulink&SystemGenerat......
  • FPGA的时钟IP核知识点
    IP核在我看来就跟stm32中的一些驱动的库函数一样,可以调用快速使用。不用一步一步的自己写底层原理。可以加速设计,快速设计代码。IP核的PLL还有一个MMCM。PLL是锁相环,对时钟进行管理。也是后面使用中很重要的IP核。不同器件需要不同的时钟。时钟管理单元CMT=PLL+MMCM混合时钟管......
  • 基于FPGA各种视频接口转换的国产化设计
    随着国产化进程推进,现在许多项目需要实现国产化设计,本博主通过器件选型/原理图设计,到视频接口输入,DDR3缓存,再到图像输出,使用者可在此基础实现二次开发,功能实现通过verilog,操作简单,添加功能方便。接口包含lvds/camelink/bt1120/hdmi/sdi等等常用视频接口,也可定制其他接口,带......
  • OMAP-L138 + FPGA开发板(Pin-To-Pin国产FPGA)
    XQ138F-EVM是广州星嵌电子科技有限公司基于TIOMAP-L138(定点/浮点DSPC674x+ARM9)+FPGA处理器研制的开发板;OMAP-L138选用TI德州仪器的TMS320C6748+ARM926EJ-S异构双核处理器,主频456MHz,高达3648MIPS和2746MFLOPS的运算能力;FPGA采用中科亿海微eHiChip6家族EQ6......
  • 提高性能、减小尺寸的1SG250HU3F50E3VG、1SG250HN3F43I3VG、1SG250HN3F43E2VG高性能 S
    概述英特尔®Stratix®10GXFPGA包含多达1020万个LE。它们在单独的收发器块上配备多达96个通用收发器,可提供2666MbpsDDR4外部内存接口性能。这些收发器可提供高达28.3Gbps的短距离和跨背板传输。这些设备针对需要最高收发器带宽和核心结构性能的FPGA应用而优化......