【数码管】— 静态显示

基础:

一、数码管类型:

共阴、共阳

以共阳极为例:

 二、段选、位选

段选:显示什么内容

位选:哪几位亮

 

 三、74hc595芯片

是什么:8位串行输入、并行输出的位移缓存器

使用目的:减少IO口的使用

由于需要控制6个8段的数码管,于是一共需要6+8=14个IO口连接到FPGA上,但是使用74hc595芯片只需要使用4个IO口连接到FPGA上,这样就减少了10 个IO口

分别是下面4个IO口连接到FPGA上:

DS:与FPGA相连,获取数据
SHCP:移位寄存器时钟,将DS上的数据串行移入8位寄存器
STCP:存储寄存器时钟,将8位寄存器中的数据写入存储器

OE:将存储器的数据通过8个端口输出,8个端口与数码管相连

 

 四、顶层框图

 

 

 实践:

一、设计文件

底层模块1:位选、段选驱动模块

复制代码
module seg_01
(

input sys_clk,
input sys_rst_n,

output reg [5:0]wei,
output reg[7:0]duan


);
reg     [25:0]  cnt_wait    ;   //时钟分频计数器
reg     [3:0]   num         ;   //数码管显示的十六进制数
parameter   CNT_WAIT_MAX  =  26'd49_999_999;   //计数器最大值(1s)

parameter   SEG_0 = 8'b1100_0000,   SEG_1 = 8'b1111_1001,
            SEG_2 = 8'b1010_0100,   SEG_3 = 8'b1011_0000,
            SEG_4 = 8'b1001_1001,   SEG_5 = 8'b1001_0010,
            SEG_6 = 8'b1000_0010,   SEG_7 = 8'b1111_1000,
            SEG_8 = 8'b1000_0000,   SEG_9 = 8'b1001_0000,
            SEG_A = 8'b1000_1000,   SEG_B = 8'b1000_0011,
            SEG_C = 8'b1100_0110,   SEG_D = 8'b1010_0001,
            SEG_E = 8'b1000_0110,   SEG_F = 8'b1000_1110;
parameter   IDLE  = 8'b1111_1111;   //不显示状态

// 共阳极数码管,位选需要让6位拉高,段选低电平有效

//wei:选中六个数码管
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        wei <=  6'b000000;
    else
        wei <=  6'b111111;

//显示什么
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        duan    <=  IDLE;
    else    case(num)
        4'd0:   duan    <=  SEG_0;
        4'd1:   duan    <=  SEG_1;
        4'd2:   duan    <=  SEG_2;
        4'd3:   duan    <=  SEG_3;
        4'd4:   duan    <=  SEG_4;
        4'd5:   duan    <=  SEG_5;
        4'd6:   duan    <=  SEG_6;
        4'd7:   duan    <=  SEG_7;
        4'd8:   duan    <=  SEG_8;
        4'd9:   duan    <=  SEG_9;
        4'd10:  duan    <=  SEG_A;
        4'd11:  duan    <=  SEG_B;
        4'd12:  duan    <=  SEG_C;
        4'd13:  duan    <=  SEG_D;
        4'd14:  duan    <=  SEG_E;
        4'd15:  duan    <=  SEG_F;
        default:duan    <=  IDLE ;  //闲置状态,不显示
    endcase

//cnt_wait:0.5秒计数 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_wait <= 26'd0; else if(cnt_wait == CNT_WAIT_MAX) cnt_wait <= 26'd0; else cnt_wait <= cnt_wait + 1'b1; //num:从 4'h0 加到 4'hf 循环 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) num <= 4'd0; else if(cnt_wait == CNT_WAIT_MAX - 1'b1) num <= num + 1'b1; else num <= num; endmodule
复制代码

底层模块2:控制74HC595芯片

复制代码
module seg_595
(
input                     clk        ,
input                     rst_n        ,
input         [5:0]        wei        ,
input           [7:0]        duan        ,

output        reg        ds            ,
output        reg        shcp        ,
output        reg        stcp        ,
output                    oe

);

wire   [13:0]        data            ;
reg    [1:0]            cnt_4            ;
reg    [3:0]            cnt_bit_14    ;

assign    data    =    {duan[0],duan[1],duan[2],duan[3],duan[4],duan[5],duan[6],duan[7],wei};
assign     oe = 1'b0;


// 4分频计数器

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    cnt_4 <= 2'b0    ;
else if(cnt_4 == 2'd3)
    cnt_4 <= 2'b0    ;
else
    cnt_4 <= cnt_4 + 2'b1    ;     
end


// 传输14位计数器

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    cnt_bit_14 <= 4'b0;
else if(cnt_bit_14 == 4'd13 && cnt_4 == 2'd3)
    cnt_bit_14 <= 4'b0;
else if(cnt_4 == 2'd3)
    cnt_bit_14 <= cnt_bit_14 + 4'b1;
else 
    cnt_bit_14 <= cnt_bit_14;    
end

// -------------------- 输出信号  ----------------------------------

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    shcp <= 1'b0;
else if(cnt_4>=2'd2)
    shcp <= 1'b1;
//else if(cnt_4 == 2'b0)
//    shcp <= 1'b0;
//else 
//    shcp <= shcp;
else
    shcp <= 1'b0;    

end

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    stcp <= 1'b0;
else if(cnt_bit_14 == 4'd0 && cnt_4 == 2'd0)
    stcp <= 1'b1;
else 
    stcp <= 1'b0;
end


always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    ds <= 1'b0;
else if(cnt_4 == 1'b0)
    ds <= data[cnt_bit_14];
else
    ds <= ds;
end


endmodule 
复制代码

顶层模块

复制代码
module seg
(
input clk                            ,
input rst_n                            ,

output                ds            ,
output                shcp        ,
output                stcp        ,
output                oe

);

wire[5:0]wei;
wire[7:0]duan;

seg_01 

#
(
    .CNT_WAIT_MAX(24'd24) // 减小仿真时间
)

a1
(

.sys_clk(clk),
.sys_rst_n(rst_n),

.wei(wei),
.duan(duan)


);


seg_595 a2
(
.clk(clk)        ,
.rst_n(rst_n)        ,
.wei(wei)        ,
.duan(duan)        ,

.ds(ds)            ,
.shcp(shcp)        ,
.stcp(stcp)        ,
.oe(oe)

);
endmodule 
复制代码

 

二、测试文件

复制代码
`timescale 1ns/1ns

module tb_seg;

reg clk;
reg rst_n;

wire ds;
wire shcp;
wire stcp;
wire oe;

initial begin 
clk = 1'b0;
rst_n = 1'b0;
#30;
rst_n = 1'b1;

end

always #10 clk = ~ clk;

seg b1
(
.clk(clk)                            ,
.rst_n(rst_n)                            ,

.ds(ds)            ,
.shcp(shcp)        ,
.stcp(stcp)        ,
.oe(oe)

);

endmodule 
复制代码

 

三、波形图

注意此时有两个模块之间的信号传输

怎么看这个波形图:

1.看a1模块的段选和位选变化,此处在cnt_wait技术到24后就清零,下一个时钟上升沿段选信号改变,与此同时a2模块的段选信号也发生改变

2.将a1模块传到a2模块的段选、位选信号拼接得到data: {duan[0],duan[1],duan[2],duan[3],duan[4],duan[5],duan[6],duan[7],wei}

3.看a2模块的ds输出信号,当cnt_4计到3后,下一个时钟周期就将data[cnt_bit_14] 检索到的值给ds

 

四、RTL图

posted @   刘小颜  阅读(757)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示