【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(一)

简介: 【FPGA】高云FPGA之数字钟实验->HC595驱动数码管

1、设计定义

通过74HC595芯片点亮8位数码管,通过计时器实现数码管计时显示

软件开发环境高云V1.99版本

硬件开发环境采用小梅哥ACG525(主芯片GW5A-LV25-UG324C2)

2、设计输入

本章节内容分为分两个子模块和一个主模块,一个子模块负责驱动74hc595一个子模块负责数码管显示,主模块负责计时和调用子模块进行数码管显示。

2.1 数码管译码显示

首先我们设计数码管显示子模块,数码管有两种结构:共阴极与共阳极。 这两者的区别在于,公共端是连接到地还是高电平,对于共阴数码管需要给对应段以高电平才会使其点亮, 而对于共阳极数码管则需要给低电平才会点亮。 本次实验环境上是使用的共阳数码管,同时为了显示数字或字符,必须对数字或字符进行编码译码。这里的表格dp点默认全部显示,当我们需要显示dp点的时候与上8’b01111111即可,相应的关闭显示就或上8’b10000000;

数码管的显示方式也分为两种静态显示和动态显示,静态显示的特点是每个数码管的段选必须接一个 8 位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。这种方法由于每一个数码管均需要独立的数据线因此硬件电路比较复杂,成本较高,很少使用为了节约 IO 以及成本一般采用如下图所示的电路结构,这样 3 个数码管接在一起就比静态的少了 7*2 个 I/O。

这样就实现了另一种显示模式,动态显示。动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示,板载设计的电路为动态显示电路,下面开始设计数码管显示代码;

位选控制也就是我们上面说到的轮流选择8位数码管的位信号线(sel);

/*********************位选扫描时钟**********************/
reg clk_1k; // 1k时钟
reg [14:0]clk_count; // 系统时钟计数
reg [7:0]sel_reg;//数码管位选寄存器,通过信号传送给seg_sel
// 系统clk采用50mhz进行计算
always@(posedge clk or posedge reset)
begin
    if(reset)
    clk_count <= 15'd0;
  else if(!en)
    clk_count <= 15'd0;
  else if(clk_count == 24999)
    clk_count <= 15'd0;
  else
    clk_count <= clk_count + 1'b1;
end
always@(posedge clk or posedge reset) 
begin
    if(reset)
        clk_1k <= 1'b0;
    else if(clk_count == 24999)
        clk_1k <= ~clk_1k;
    else
        clk_1k <= clk_1k;
end
always@(posedge clk_1k or posedge reset)
begin
    if(reset)
        sel_reg <= 8'b0000_0001;
    else if(sel_reg == 8'b1000_0000)
        sel_reg <= 8'b0000_0001;
    else 
        sel_reg <= sel_reg << 1;
end
assign sel = (en)?sel_reg:8'b0000_0000;

段选信号,通过上面的译码表实现查表传送给seg端口,这里的dp点显示我以位判断的方式进行显示,哪一位需要显示dp点给dp寄存器哪一位或1即可

/***********************段选数据***********************/
reg [3:0]data_tmp;//数据缓存
always@(*)
begin
    case(sel_reg)
        8'b0000_0001:data_tmp = disp_data[3:0];
        8'b0000_0010:data_tmp = disp_data[7:4];
        8'b0000_0100:data_tmp = disp_data[11:8];
        8'b0000_1000:data_tmp = disp_data[15:12];
        8'b0001_0000:data_tmp = disp_data[19:16];
        8'b0010_0000:data_tmp = disp_data[23:20];
        8'b0100_0000:data_tmp = disp_data[27:24];
        8'b1000_0000:data_tmp = disp_data[31:28];
        default:data_tmp = 4'b0000;
    endcase
end
always@(*)
begin
    case(data_tmp)
        4'h0:seg = 8'b11000000;
        4'h1:seg = 8'b11111001;
        4'h2:seg = 8'b10100100;
        4'h3:seg = 8'b10110000;
        4'h4:seg = 8'b10011001;
        4'h5:seg = 8'b10010010;
        4'h6:seg = 8'b10000010;
        4'h7:seg = 8'b11111000;
        4'h8:seg = 8'b10000000;
        4'h9:seg = 8'b10010000;
        4'ha:seg = 8'b10001000;
        4'hb:seg = 8'b10000011;
        4'hc:seg = 8'b11000110;
        4'hd:seg = 8'b10100001;
        4'he:seg = 8'b10000110;
        4'hf:seg = 8'b10001110;
    endcase
    if((sel_reg&dp) > 0)
        seg = seg & 8'b01111111;
end

完整代码

module hex8(
    input clk,
    input reset_n,
    input en,
    input [31:0]disp_data, //显示数据
    input [7:0]dp,
    output [7:0]sel,//数码管段选(当前要显示的内容)
    output reg [7:0]seg //数码管位选(选择当前要显示的数码管) 
);
assign reset=~reset_n;
/*********************位选扫描时钟**********************/
reg clk_1k; // 1k时钟
reg [14:0]clk_count; // 系统时钟计数
reg [7:0]sel_reg;//数码管位选寄存器,通过信号传送给seg_sel
always@(posedge clk or posedge reset)
begin
    if(reset)
    clk_count <= 15'd0;
  else if(!en)
    clk_count <= 15'd0;
  else if(clk_count == 24999)
    clk_count <= 15'd0;
  else
    clk_count <= clk_count + 1'b1;
end
always@(posedge clk or posedge reset) 
begin
    if(reset)
        clk_1k <= 1'b0;
    else if(clk_count == 24999)
        clk_1k <= ~clk_1k;
    else
        clk_1k <= clk_1k;
end
always@(posedge clk_1k or posedge reset)
begin
    if(reset)
        sel_reg <= 8'b0000_0001;
    else if(sel_reg == 8'b1000_0000)
        sel_reg <= 8'b0000_0001;
    else 
        sel_reg <= sel_reg << 1;
end
assign sel = (en)?sel_reg:8'b0000_0000;
/***********************段选数据***********************/
reg [3:0]data_tmp;//数据缓存
always@(*)
begin
    case(sel_reg)
        8'b0000_0001:data_tmp = disp_data[3:0];
        8'b0000_0010:data_tmp = disp_data[7:4];
        8'b0000_0100:data_tmp = disp_data[11:8];
        8'b0000_1000:data_tmp = disp_data[15:12];
        8'b0001_0000:data_tmp = disp_data[19:16];
        8'b0010_0000:data_tmp = disp_data[23:20];
        8'b0100_0000:data_tmp = disp_data[27:24];
        8'b1000_0000:data_tmp = disp_data[31:28];
        default:data_tmp = 4'b0000;
    endcase
end
always@(*)
begin
    case(data_tmp)
        4'h0:seg = 8'b11000000;
        4'h1:seg = 8'b11111001;
        4'h2:seg = 8'b10100100;
        4'h3:seg = 8'b10110000;
        4'h4:seg = 8'b10011001;
        4'h5:seg = 8'b10010010;
        4'h6:seg = 8'b10000010;
        4'h7:seg = 8'b11111000;
        4'h8:seg = 8'b10000000;
        4'h9:seg = 8'b10010000;
        4'ha:seg = 8'b10001000;
        4'hb:seg = 8'b10000011;
        4'hc:seg = 8'b11000110;
        4'hd:seg = 8'b10100001;
        4'he:seg = 8'b10000110;
        4'hf:seg = 8'b10001110;
    endcase
    if((sel_reg&dp) > 0)
        seg = seg & 8'b01111111;
end
endmodule

模块使用

wire [31:0]disp_data;
wire [7:0] sel;//数码管位选(选择当前要显示的数码管)
wire [7:0] seg;//数码管段选(当前要显示的内容)
wire [7:0]dp_data;//数码管小数点(某位点亮某位置1)
reg dp_flag;  // 小数点寄存器
reg [31:0]disp_data_reg = 32'h00000000; // 显示数据寄存器
hex8 hex8_mod(
    .clk(clk), // 50m时钟
    .reset_n(reset_n), // 复位信号
    .en(1'b1),  // 使能模块寄存器
    .disp_data(disp_data), // 32位数据显示,每一个数码管可以显示0-f占4位
    .sel(sel), // 位选信号
    .seg(seg), // 段选信号
    .dp(dp_data) // 8位dp信号
);


【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(二)https://developer.aliyun.com/article/1472643

相关文章
|
7月前
|
芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(三)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
157 4
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(二)
FPGA入门(6):数码管静态/动态显示(二)
61 10
|
5月前
|
数据采集 计算机视觉 异构计算
FPGA进阶(2):基于I2C协议的EEPROM驱动控制
FPGA进阶(2):基于I2C协议的EEPROM驱动控制
71 0
|
5月前
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(二)
FPGA进阶(1):基于SPI协议的Flash驱动控制
60 0
|
5月前
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
189 0
|
5月前
|
异构计算
FPGA强化(9):TFT_LCD液晶屏驱动
FPGA强化(9):TFT_LCD液晶屏驱动
60 0
|
5月前
|
异构计算
FPGA强化(8):HDMI显示器驱动
FPGA入门(8):VGA显示器驱动
39 0
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(一)
FPGA入门(6):数码管静态/动态显示
48 0
|
2天前
|
算法 异构计算
基于FPGA的4ASK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4-ASK调制解调系统的算法仿真效果、理论基础及Verilog核心程序。仿真在Vivado2019.2环境下进行,分别测试了SNR为20dB、15dB、10dB时的性能。理论部分概述了4-ASK的工作原理,包括调制、解调过程及其数学模型。Verilog代码实现了4-ASK调制器、加性高斯白噪声(AWGN)信道模拟、解调器及误码率计算模块。
19 8
|
18天前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的1024QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的1024QAM调制解调系统的仿真与实现。通过Vivado 2019.2进行仿真,分别在SNR=40dB和35dB下验证了算法效果,并将数据导入Matlab生成星座图。1024QAM调制将10比特映射到复数平面上的1024个星座点之一,适用于高数据传输速率的应用。系统包含数据接口、串并转换、星座映射、调制器、解调器等模块。Verilog核心程序实现了调制、加噪声信道和解调过程,并统计误码率。
36 1

热门文章

最新文章

下一篇
无影云桌面