進階項目(8)數碼管顯示設計講解


寫在前面的話

項目設計中我們通常需要一些顯示設備來顯示我們需要的信息,可以選擇的顯示設備更是種類繁多,玲琅滿目,數碼管無疑是最常用,最簡單的顯示設備之一。本節,夢翼師兄和大家一起學習數碼管的顯示原理和驅動方式,為我們以后項目的開發做好准備。

項目需求

設計一個數碼管的驅動電路,使數碼管能夠同時顯示出任意的六位數字(夢翼師兄使用的開發板集成的數碼管為六位連體數碼管)。

原理分析

數碼管作為一種外設,我們首先需要了解它的工作原理以及它的對應電路連接關系,七段數碼管結構示意圖如下:

顧名思義,七段數碼管就是使用七段點亮的線段來拼成常見的數字和某些字母,這種顯示方式我們在數字電路中非常容易見到。再加上右下角顯示的小數點,實際上一個顯示單元包括了8根信號線。根據電路設計的不同,這些信號線可能高有效也可能低有效。我們通過FPGA控制這些線段的亮滅,就可以達到相應的顯示效果。

對於多個數碼管的顯示模塊,將每一個都連接到FPGA的管腳會耗用大量FPGA的管腳資源。因此我們同樣引入一種類似矩陣鍵盤的掃描方式。任何時刻我們只使用8根信號點亮一個數碼管,但是8個數碼管是隨着時鍾步調交替點亮的,只要時鍾的速度夠快,我們觀察到數碼管就好像幾個同時點亮一樣。夢翼師兄使用的開發板原理圖如下:

如圖所示,我們的開發板使用的是六位共陽極數碼管,六個PNP型三極管分別作為六組數碼管電源的輸入開關,也就是我們常說的位選信號,PNP三極管為低電平導通,所以我們的位選信號低有效。在這里,為了節約FPGA的IO資源,我們把六個位選信號連接到了三八譯碼器74HC138D,該三八譯碼器的真值表如下:

 

由此,我們可以得出結論,當{SEL2, SEL1, SEL0}=3’b000時,Y0變為低電平,而由於Y0連接到了第一個數碼管,所以第一個數碼管點亮。當{SEL2, SEL1, SEL0}=3’b001時,對應第二個數碼管點亮,以此類推。SEG_0到SEG_7分別對應二極管a-g以及“小數點”,即我們所說的段選信號。由於是共陽極數碼管,所以二極管只要給低電平就可以點亮,根據點亮的二極管不同,就可以顯示出不同的字符。假如我們要點亮第一個數碼管,並且顯示出字符“A”,那么我們就只需要選中第一個數碼管{SEL2, SEL1, SEL0}=3’b000,而且SEG=8’b1000_1000。

如果要讓數碼管“全部亮起來”,並同時顯示相同字符,那我們只能通過比較快速的切換位選信號來實現這一目的。但是切換頻率如果過高,數碼管顯示也會出現不穩定的狀態,這和器件的工藝有關,我們可以選擇切換的經驗頻率1KHZ。那么這時,我們就需要用到分頻模塊,將50MHZ的晶振時鍾分頻成我們所需要的1KHZ。

單個數碼管顯示

單個數碼管顯示的系統架構

單個數碼管顯示最大的數字是十六進制中的F(15),15對應的二進制數是4’b1111,所以我們的輸入應該是四位。

 

單個數碼管顯示的模塊模塊功能介紹

模塊名

功能描述

SEG7

輸出控制線

單個數碼管顯示模塊的端口描述

端口名

端口說明

clk

系統時鍾輸入

Rst_n

系統復位

Data[3:0]

數據輸入

sel[2:0]

片選信號輸出

seg[7:0]

段選信號輸出

代碼解釋

SEG7模塊代碼

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 

 *   The module function:控制單個數碼管顯示任意的數字

*****************************************************/

00 module SEG7 (

01 clk, //系統時鍾

02 rst_n,//系統復位

03 data, //輸入數據

04 seg,//數碼管段選

05 sel//數碼管位選

06 );

07 //系統輸入

08 input clk;//系統時鍾

09 input rst_n;//系統復位

10 input [3:0] data;//輸入數據

11 //系統輸出

12 output reg [7:0] seg;//數碼管段選

13 output reg [2:0] sel;//數碼管位選

14

15 always @ (posedge clk or negedge rst_n)

16 begin

17 if (!rst_n)//復位的時候選擇第一個數碼管

18 begin

19 sel <= 0;

20 end

21 else

22 begin//選擇第一個數碼管

23 sel <= 0;

24 end

25 end

26

27 always @ (*)//用組合邏輯進行輸出段選信號

28 begin

29 if (!rst_n)//復位的時候數碼管熄滅

30 begin

31 seg = 8'b1111_1111;

32 end

33 else

34 begin

35 case(data)

36 0 : seg = 8'b1100_0000;//顯示“0”

37 1 : seg = 8'b1111_1001;//顯示“1”

38 2 : seg = 8'b1010_0100;//顯示“2”

39 3 : seg = 8'b1011_0000;//顯示“3”

40 4 : seg = 8'b1001_1001;//顯示“4”

41 5 : seg = 8'b1001_0010;//顯示“5”

42 6 : seg = 8'b1000_0010;//顯示“6”

43 7 : seg = 8'b1111_1000;//顯示“7”

44 8 : seg = 8'b1000_0000;//顯示“8”

45 9 : seg = 8'b1001_0000;//顯示“9”

46 10 : seg = 8'b1000_1000;//顯示“A”

47 11 : seg = 8'b1000_0011;//顯示“B”

48 12 : seg = 8'b1100_0110;//顯示“C”

49 13 : seg = 8'b1010_0001;//顯示“D”

50 14 : seg = 8'b1000_0110;//顯示“E”

51 15 : seg = 8'b1000_1110;//顯示“F”

52 default : seg = 8'b1111_1111;//全滅

53 endcase

54 end

55 end

56

57 endmodule

 

 

 

仿真代碼

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function:測試SEG7模塊,並顯示“A”

*****************************************************/

00 `timescale 1ns/1ps //定義時間單位和精度

01

02 module SEG7_tb;

03 //系統輸入

04 reg clk;//系統時鍾

05 reg rst_n;//系統復位

06 reg [3:0] data;//輸入數據

07 //系統輸出

08 wire [7:0] seg;//數碼管段選

09 wire [2:0] sel;//數碼管位選

10

11 initial begin

12 clk = 1;

13 rst_n = 0;

14 data = 10;//data = 4'hA; 這兩種方式都可以

15 # 200.1 //復位200ns

16 rst_n = 1;

17 end

18

19 always # 10 clk = ~clk;//50M的時鍾

20

21 SEG7 SEG7 (

22 .clk(clk), //系統時鍾

23 .rst_n(rst_n),//系統復位

24 .data(data), //輸入數據

25 .seg(seg),//數碼管段選

26 .sel(sel)//數碼管位選

27 );

28

29 endmodule

 在本模塊中,夢翼師兄只是測試了顯示”A”,有興趣的話,可以把0~9A~F,全部測試一下。

 單個數碼管顯示的仿真分析

 

 

在復位期間,seg信號全部為“1”,數碼管熄滅。當復位信號拉高以后,seg信號變成了“10001000”,正好是“A”的段選,而sel(位選)一直就是0(選擇第一個數碼管),證明我們的設計是正確的。

 六個數碼管顯示

六個數碼顯示的系統架構

應用六個數碼管去顯示任意數字,每個數碼管顯示的數字需要用4位二進制數去表示,那么六個數碼管一共需要24位二進制數

數碼管各模塊功能介紹

模塊名

功能描述

SEG7

輸出數碼管控制位選和段選信號

freq

時鍾分頻模塊,輸出1KHz時鍾

top

頂層模塊,負責模塊級聯

端口和內部連線描述

頂層端口

端口名

端口說明

clk

系統時鍾輸入

Rst_n

系統復位

Data[23:0]

數據輸入

sel[2:0]

片選信號輸出

seg[7:0]

段選信號輸出

模塊內部連線

連線名

連線說明

Clk_1K

數碼管的切換時鍾

代碼解釋

freq模塊代碼

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function: 產生慢時鍾

*****************************************************/

00 module freq (

01 clk, //系統時鍾

02 rst_n, //系統復位

03 clk_1K//切換時鍾

04 );

05 //系統輸入

06 input clk;//系統時鍾

07 input rst_n;//系統復位

08 //系統輸出

09 output reg clk_1K;//切換時鍾

10 //定義中間寄存器

11 reg [19:0] count;//定義一個計數的寄存器

12

13 always @ (posedge clk or negedge rst_n)

14 begin

15 if (!rst_n)

16 begin

17 clk_1K <= 1;

18 count <= 0;

19 end

20 else

21 begin

22 if (count < 24999)// 50000分頻,得出1K的時鍾

23 count <= count + 1;

24 else

25 begin

26 count <= 0;

27 clk_1K <= ~clk_1K;

28 end

29 end

30 end

31

32 endmodule

 

SEG7模塊代碼

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function: 產生段選信號和位選信號

*****************************************************/

000 module SEG7 (

001 clk, //模塊時鍾

002 rst_n,//系統復位

003 data, //輸入數據

004 seg,//數碼管段選

005 sel//數碼管位選

006 );

007 //系統輸入

008 input clk;//模塊時鍾

009 input rst_n;//系統復位

010 input [23:0] data;//輸入數據

011 //系統輸出

012 output reg [7:0] seg;//數碼管段選

013 output reg [2:0] sel;//數碼管位選

014 //定義中間寄存器

015 reg [3:0] data_temp;//數碼管顯示的數值

016 reg [2:0] state;//狀態寄存器

017

018 always @ (posedge clk or negedge rst_n)

019 begin

020 if (!rst_n)//復位的時候選擇第一個數碼管

021 begin

022 sel <= 0;

023 data_temp <= 0;

024 state <= 0;

025 end

026 else

027 begin

028 case (state)

029 0 : begin//將最高位的數顯示在第一個數碼管上

030 sel <= 0;

031 data_temp <= data[23:20];

032 state <= 1;

033 end

034

035 1 : begin//將第2位的數顯示在第二個數碼管上

036 sel <= 1;

037 data_temp <= data[19:16];

038 state <= 2;

039 end

040

041 2 : begin//將第3位的數顯示在第三個數碼管上

042 sel <= 2;

043 data_temp <= data[15:12];

044 state <= 3;

045 end

046

047 3 : begin//將第4位的數顯示在第四個數碼管上

048 sel <= 3;

049 data_temp <= data[11:8];

050 state <= 4;

051 end

052

053 4 : begin//將最5位的數顯示在第五個數碼管上

054 sel <= 4;

055 data_temp <= data[7:4];

056 state <= 5;

057 end

058

059 5 : begin//將最低位的數顯示在第六個數碼管上

060 sel <= 5;

061 data_temp <= data[3:0];

062 state <= 0;

063 end

064

065 default : state <= 0;

066 endcase

067 end

068 end

069

070 always @ (*)//根據data_temp的中的值,用組合邏輯進行輸出段選信號

071 begin

072 if (!rst_n)//復位的時候數碼管熄滅

073 begin

074 seg = 8'b1111_1111;

075 end

076 else

077 begin

078 case(data_temp)

079 0 : seg = 8'b1100_0000;//顯示“0”

080 1 : seg = 8'b1111_1001;//顯示“1”

081 2 : seg = 8'b1010_0100;//顯示“2”

082 3 : seg = 8'b1011_0000;//顯示“3”

083 4 : seg = 8'b1001_1001;//顯示“4”

084 5 : seg = 8'b1001_0010;//顯示“5”

085 6 : seg = 8'b1000_0010;//顯示“6”

086 7 : seg = 8'b1111_1000;//顯示“7”

087 8 : seg = 8'b1000_0000;//顯示“8”

088 9 : seg = 8'b1001_0000;//顯示“9”

089 10 : seg = 8'b1000_1000;//顯示“A”

090 11 : seg = 8'b1000_0011;//顯示“B”

091 12 : seg = 8'b1100_0110;//顯示“C”

092 13 : seg = 8'b1010_0001;//顯示“D”

093 14 : seg = 8'b1000_0110;//顯示“E”

094 15 : seg = 8'b1000_1110;//顯示“F”

095 default : seg = 8'b1000_1110;//顯示“F”

096 endcase

097 end

098 end

099

100 endmodule

 

top模塊代碼

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function: 頂層模塊

*****************************************************/

00 module top (

01 clk, //系統時鍾

02 rst_n, //系統復位

03 data, //輸入數據

04 seg, //數碼管段選

05 sel//數碼管位選

06 );

07 //系統輸入

08 input clk;//系統時鍾

09 input rst_n;//系統復位

10 input [23:0] data;//輸入數據

11 //系統輸出

12 output [7:0] seg;//數碼管段選

13 output [2:0] sel;//數碼管位選

14 //定義中間連線

15 wire clk_1K;//定義切換時鍾

16 //調用pll(鎖相環)

17 freq freq(

18 .clk( clk ),//外部時鍾

19 .rst_n(rst_n),//系統復位

20 .clk_1K( clk_1K ) //切換時鍾

21 );

22 //實例化SEG7

23 SEG7 SEG7 (

24 .clk(clk_1K), //切換時鍾

25 .rst_n(rst_n),//系統復位

26 .data(data), //輸入數據

27 .seg(seg),//數碼管段選

28 .sel(sel)//數碼管位選

29 );

30

31 endmodule

編寫完可綜合代碼之后查看RTL視圖如下:

RTL視圖可知代碼綜合以后得到的電路和我們設計的系統框圖一致,說明頂層連接關系正確,接下來編寫測試代碼如下:

 

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function: 測試數碼管模塊

*****************************************************/

00 `timescale 1ns/1ps //定義時間單位和精度

01

02 module top_tb;

03 //系統輸入

04 reg clk;//系統時鍾

05 reg rst_n;//系統復位

06 reg [23:0] data;//輸入數據

07 //系統輸出

08 wire [7:0] seg;//數碼管段選

09 wire [2:0] sel;//數碼管位選

10

11 initial begin

12 clk = 1;

13 rst_n = 0;

14 data = 24'h123456;

15 # 200.1 //復位200.1ns

16 rst_n = 1;

17 end

18

19 always # 10 clk = ~clk;//50M的時鍾

20

21 top top(

22 .clk(clk), //系統時鍾

23 .rst_n(rst_n),//系統復位

24 .data(data), //輸入數據

25 .seg(seg),//數碼管段選

26 .sel(sel)//數碼管位選

27 );

28

29 endmodule

 

 仿真分析

 

 

 

在對應的數碼管上,給出對應數值的段選信號,經過比對,我們的設計都是正確的。

 



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM