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

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

当有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
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog 数码管动态显示实现方法如下: 首先,需要定义数码管的引脚和位选引脚: ```verilog module digit_display( input clk, // 时钟信号 output reg [6:0] seg, // 数码管引脚 output reg [3:0] sel // 位选引脚 ); ``` 接着,定义一个计数器,用于控制数码管的扫描: ```verilog reg [23:0] counter; // 计数器,用于控制数码管的扫描 ``` 在时钟上升沿处,对计数器进行加一操作,并根据计数器的值来选择要显示的数码管和位选引脚。 ```verilog always @(posedge clk) begin counter <= counter + 1; // 计数器加一 case(counter[23:20]) 4'b0000: begin sel <= 4'b1110; seg <= 7'b1000000; end // 第一位显示0 4'b0001: begin sel <= 4'b1101; seg <= 7'b1111001; end // 第二位显示1 4'b0010: begin sel <= 4'b1011; seg <= 7'b0100100; end // 第三位显示2 4'b0011: begin sel <= 4'b0111; seg <= 7'b0110000; end // 第四位显示3 // ... 可以继续添加其他数字的显示 endcase end ``` 最后,将数码管和位选引脚连接到对应的硬件引脚上即可。 完整代码如下: ```verilog module digit_display( input clk, // 时钟信号 output reg [6:0] seg, // 数码管引脚 output reg [3:0] sel // 位选引脚 ); reg [23:0] counter; // 计数器,用于控制数码管的扫描 always @(posedge clk) begin counter <= counter + 1; // 计数器加一 case(counter[23:20]) 4'b0000: begin sel <= 4'b1110; seg <= 7'b1000000; end // 第一位显示0 4'b0001: begin sel <= 4'b1101; seg <= 7'b1111001; end // 第二位显示1 4'b0010: begin sel <= 4'b1011; seg <= 7'b0100100; end // 第三位显示2 4'b0011: begin sel <= 4'b0111; seg <= 7'b0110000; end // 第四位显示3 // ... 可以继续添加其他数字的显示 endcase end endmodule ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值