摘自:http://www.cnblogs.com/kongtiao/archive/2011/07/23/2114618.html
原理:
一般来说,多个数码管的连接并不是把每个数码管都独立的与可编程逻辑器件连接,而是把所有的LED管的输入连在一起。如图1.1所示。
图1.1 扫描数码管的原理图
这样做的好处有两点:一是节约了器件的IO口;其二是降低了功耗。每次向LED写数据时,通过片选选通其中一个LED,然后把数据写入该LED管,因此每个时刻只有一个LED管是亮的。为了能持续看见LED上面的显示内容,必须对LED管进行扫描,即依次并循环地点亮各个LED管。利用人眼的视觉暂停效应,在一定的扫描频率下,人眼就会看见好几个LED一起点亮。每个LED的功耗较大,如果所有的LED一起点亮,其功耗较大。利用扫描的方式,每个时刻只有LED管是亮的,可以大大的减少功耗。
扫描频率大小不许合适才能有很好的效果。如果太小,而每个LED开启的时间大于人眼的视觉暂停时间,那么会产生闪烁现象。而扫描频率太大,则会造成LED的频繁开启和关断,大大增加LED功耗(开启和关断的时刻功耗很大)。一般来说,稍描频率选在50Hz比较合适。
实验实现:
实现步骤请参照 【连载】 FPGA Verilog HDL 系列实例--------8-3编码器。这里就不再赘述。
设计文件输入Verilog HDL代码。


1 //------------------------------------------------------------------------------------------------- 2 // 3 // File : scan_seg.v 4 // Generated : 2011-07-23 5 // Author : wangliang 6 // 7 //------------------------------------------------------------------------------------------------- 8 9 `timescale 1 ns / 1 ps 10 11 module scan_seg ( rst ,clk ,DIG ,Y ); 12 13 input rst ; 14 wire rst ; 15 input clk ; 16 wire clk ; 17 18 output [7:0] DIG ; 19 wire [7:0] DIG ; 20 output [7:0] Y ; 21 wire [7:0] Y ; 22 23 reg clkout ; 24 reg [31:0]cnt; 25 reg [2:0]scan_cnt ; 26 27 parameter period= 100000; 28 29 assign Y = {1'b1,(~Y_r[6:0])}; 30 assign DIG =~DIG_r; 31 reg [6:0] Y_r; 32 reg [7:0] DIG_r ; 33 34 always @( posedge clk or negedge rst) //分频50Hz 35 begin 36 if (!rst) 37 cnt <= 0 ; 38 else begin 39 cnt<= cnt+1; 40 if (cnt == (period >> 1) - 1) 41 clkout <= #1 1'b1; 42 else if (cnt == period - 1) 43 begin 44 clkout <= #1 1'b0; 45 cnt <= #1 'b0; 46 end 47 48 end 49 end 50 51 always @(posedge clkout or negedge rst) 52 begin 53 if (!rst) 54 scan_cnt <= 0 ; 55 else begin 56 scan_cnt <= scan_cnt + 1; 57 if(scan_cnt==3'd7) scan_cnt <= 0; 58 end 59 end 60 61 always @( scan_cnt) //数码管选择 62 begin 63 case ( scan_cnt ) 64 3'b000 : DIG_r <= 8'b0000_0001; 65 3'b001 : DIG_r <= 8'b0000_0010; 66 3'b010 : DIG_r <= 8'b0000_0100; 67 3'b011 : DIG_r <= 8'b0000_1000; 68 3'b100 : DIG_r <= 8'b0001_0000; 69 3'b101 : DIG_r <= 8'b0010_0000; 70 3'b110 : DIG_r <= 8'b0100_0000; 71 3'b111 : DIG_r <= 8'b1000_0000; 72 default :DIG_r <= 8'b0000_0000; 73 endcase 74 end 75 76 always @ (scan_cnt ) //译码 77 begin 78 case (scan_cnt) 79 0: Y_r = 7'b0111111; // 0 80 1: Y_r = 7'b0000110; // 1 81 2: Y_r = 7'b1011011; // 2 82 3: Y_r = 7'b1001111; // 3 83 4: Y_r = 7'b1100110; // 4 84 5: Y_r = 7'b1101101; // 5 85 6: Y_r = 7'b1111101; // 6 86 7: Y_r = 7'b0100111; // 7 87 8: Y_r = 7'b1111111; // 8 88 9: Y_r = 7'b1100111; // 9 89 10: Y_r = 7'b1110111; // A 90 11: Y_r = 7'b1111100; // b 91 12: Y_r = 7'b0111001; // c 92 13: Y_r = 7'b1011110; // d 93 14: Y_r = 7'b1111001; // E 94 15: Y_r = 7'b1110001; // F 95 default: Y_r = 7'b0000000; 96 endcase 97 end 98 99 endmodule
代码分析:
可以看出这部分代码由4部分组成,第一部分是分频,因为我们扫描数码管不需要很快的频率,第二部分是选择控制数码管的位置,第三部分是对第二部分的译码,第四部分是显示数据。
引脚分配:
由Verilog HDL设计文件生成的.bsf文件如图1.2所示
图1.2 七段数码管的外部接口图
clk接系统时钟,rst接复位信号,DIG[7..0]接选择的的数码管(控制显示在哪一个数码管上),Y[7..0]接数码管的显示位(控制显示什么数字)。
实验结果:
在上面的数码管上从前到后一次显示76543210.