数码管动态显示Verilog实现(参考小梅哥教程)(视觉暂留)

本文详细介绍了数码管动态显示的原理,通过利用人眼的视觉暂留效应,减少控制引脚数量,实现资源的有效利用。文章提供了一段Verilog设计代码,包括分频、循环、3-8译码器、八选一数据选择器和真值表转换模块,用于控制多个数码管的动态显示。此外,还给出了测试平台的设置和演示实例,展示了数码管如何显示不同数值。
摘要由CSDN通过智能技术生成

一个数码管有八个引脚,控制八段二极管的亮灭,用以显示需要的数字。

当有N个数码管时,一个一个控制的话需要N x 8 个引脚,消耗资源较多。

因此可以利用动态显示的方案通过人眼的视觉暂留特性达到静态显示的效果(动态显示周期<20ms),只需N+8个引脚。节省了大量资源。(动态静显)

数码管动态显示的逻辑电路如下:

Verilog设计代码如下:

module digital_tube(//八个数码管显示
    clk,
    reset,
    disp_num_all,
    dg_tube,
    tube_part
    );
    
    input clk ;
    input reset ;
    input [31:0]disp_num_all ;
    output [7:0]dg_tube ;
    output [7:0]tube_part ;
    
    parameter one_dis_t = 25'd1_000_000 ;//每个晶体管显示时间(计数)
    
    reg [16:0]counter1 ;
    reg [2:0] counter2 ;
    
    always @ ( posedge clk or negedge reset )//分频
    begin
        if (! reset )
        counter1 <= 17'd0 ;
        else if ( (one_dis_t-1) <= counter1 )
        counter1 <= 17'd0 ;
        else
        counter1 <= counter1 +1'b1 ;
    end
    
    always @ ( posedge clk or negedge reset )//循环
    begin
        if (! reset )
        counter2 <= 3'd0 ;
        else if ( (one_dis_t-1) <= counter1 ) 
        counter2 <= counter2 +1'b1 ;
    end
    
    wire [3:0]disp_num_one ;
    
    //3-8译码器 控制哪个数码管显示
    decoder_3_8 tube_select(//控制
               .a(counter2[2] ),
               .b(counter2[1]),
               .c(counter2[0]),
               .out(dg_tube)
        );
    
    //需要一个八选一选通器,对应哪个数码管显示什么内容
    mux8  tube_display(//选通
    .sel(counter2),
    .data(disp_num_all),
    .out(disp_num_one)
    );
    
    //真值表对应显示数字
    LUT_truth translator(//控制
    .num(disp_num_one),
    .out(tube_part)
    );
endmodule
module decoder_3_8(
               a,
               b,
               c,
               out
        );
      input a;
      input b;
      input c;
      output reg [7:0]out;
      
      always@(*)begin//等价于always({a,b,c})a是高位,c是低位
         case({a,b,c})
              3'b000:out=8'b0000_0001;             
              3'b001:out=8'b0000_0010; 
              3'b010:out=8'b0000_0100; 
              3'b011:out=8'b0000_1000; 
              3'b100:out=8'b0001_0000; 
              3'b101:out=8'b0010_0000; 
              3'b110:out=8'b0100_0000; 
              3'b111:out=8'b1000_0000; 
         endcase
      end
      
endmodule
module mux8(
    sel,
    data,
    out
    );
    
    input [2:0]sel ;
    input [31:0]data ;
    output reg [3:0]out ;
    
    always@(*)
    begin
    case(sel)

        3'b000 : out = data[3:0] ;
        3'b001 : out = data[7:4] ;
        3'b010 : out = data[11:8] ;
        3'b011 : out = data[15:12] ;
        3'b100 : out = data[19:16] ;
        3'b101 : out = data[23:20] ;
        3'b110 : out = data[27:24] ;
        3'b111 : out = data[31:28] ;

    endcase
    end
endmodule
module LUT_truth(
    num,
    out
    );
    
    input [3:0]num ;
    output reg [7:0]out ;
    
    always@(num)
    begin
        case(num)
        4'h0 : out = 8'hc0 ;
        4'h1 : out = 8'hf9 ;
        4'h2 : out = 8'ha4 ;
        4'h3 : out = 8'hb0 ;
        4'h4 : out = 8'h99 ;
        4'h5 : out = 8'h92 ;
        4'h6 : out = 8'h82 ;
        4'h7 : out = 8'hf8 ;
        4'h8 : out = 8'h80 ;
        4'h9 : out = 8'h90 ;
        4'ha : out = 8'h88 ;
        4'hb : out = 8'h83 ;
        4'hc : out = 8'hc6 ;
        4'hd : out = 8'ha1 ;
        4'he : out = 8'h86 ;
        4'hf : out = 8'h8e ;
        endcase
    end
endmodule
`timescale 1ns / 1ns
module digital_tube_tb();
    
    reg clk ;
    reg reset ;
    reg [31:0]disp_num_all;
    wire [7:0]dg_tube ;
    wire [7:0]tube_part ;
    
    digital_tube   
    #( 
    .one_dis_t( 100 )
    )
    digital_tube_im(//八个数码管显示
    clk,
    reset,
    disp_num_all,
    dg_tube,
    tube_part
    );
    
    initial clk = 1 ;
    always #10 clk = ! clk ;
    initial
    begin
        reset = 0 ;
        disp_num_all = 32'd0 ;
        #201 ;
        reset = 1 ;
        #200 ;
        disp_num_all = 32'habb02525 ;
        #20000;
        disp_num_all = 32'h52520bba ;
        #30000;        
        $stop;
    end
    


    
endmodule

  • 6
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的数码管动态显示Verilog 代码示例: ``` module seven_segment_display( input clk, input [3:0] data, output reg [6:0] seg ); reg [22:0] counter; reg [3:0] digit; always @(posedge clk) begin counter <= counter + 1; if (counter == 500000) begin // 修改此处的数值可以调整刷新频率 counter <= 0; digit <= digit + 1; if (digit > 3) begin digit <= 0; end end case (digit) 0: begin case (data) 0: seg <= 7'b1000000; 1: seg <= 7'b1111001; 2: seg <= 7'b0100100; 3: seg <= 7'b0110000; 4: seg <= 7'b0011001; 5: seg <= 7'b0010010; 6: seg <= 7'b0000010; 7: seg <= 7'b1111000; 8: seg <= 7'b0000000; 9: seg <= 7'b0010000; default: seg <= 7'b1111111; endcase end 1: begin case (data) 0: seg <= 7'b1000000; 1: seg <= 7'b1111001; 2: seg <= 7'b0100100; 3: seg <= 7'b0110000; 4: seg <= 7'b0011001; 5: seg <= 7'b0010010; 6: seg <= 7'b0000010; 7: seg <= 7'b1111000; 8: seg <= 7'b0000000; 9: seg <= 7'b0010000; default: seg <= 7'b1111111; endcase end 2: begin seg <= 7'b0000001; // 显示小数点 end 3: begin seg <= 7'b1111111; // 关闭数码管 end endcase end endmodule ``` 这个模块接收一个时钟信号 `clk` 和一个 4 位的数据信号 `data`,以及一个 7 位的数码管输出信号 `seg`。信号 `data` 代表要显示的数字,信号 `seg` 是根据 `data` 和当前的显示位置动态生成的,以实现数字在数码管上的动态显示。在这个例子中,我们使用了一个计数器来控制数字的显示位置和刷新频率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值