1. 程式人生 > >【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗六:數碼管模組

【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗六:數碼管模組

實驗六:數碼管模組

有關數碼管的驅動,想必讀者已經學爛了 ... 不過,作為學習的新儀式,再爛的東西也要溫故知新,不然學習就會不健全。黑金開發板上的數碼管資源,由始至終都沒有改變過,筆者因此由身懷念。為了點亮多位數碼管從而顯示數字,一般都會採用動態掃描,然而有關動態掃描的資訊請怒筆者不再重複。在此,同樣也是動態掃描,但我們卻用不同的思路去理解。

clip_image002

圖6.1 6位數碼管。

如圖6.1所示,哪裡有一排6位數碼管,其中包好8位DIG訊號還有6位SEL訊號。DIG為digit,即俗稱的數碼管碼,如果數碼管預要顯示“A”,那麼DIG必須輸入“A”的數碼管碼。SEL為select,即俗稱的位選,從左至右即SEL[0]~SEL[5],如果想要使能第一位最左邊的數碼管,SEL[0]必須設定有效位。不管DIG還是SEL,黑金開發板都是拉低有效,亦即0值表示有效位。

clip_image004

圖6.2 訊號DIG與數碼管碼。

DIG訊號位寬為8,亦即一個數碼管資源內藏8個LED,8位DIG訊號分別表示各個LED,結果如圖6.2所示。除了DIG[7]較為少用以外,DIG[0]~[6] 一般都用來顯示十六進位制的數字 0~F。筆者在此強調,黑金開發板所採用的數碼管是拉低有效,亦即點亮LED筆者設定為0。為此,十六進位制的數字0~F可以用Verilog這樣表示,如程式碼6.1所示:

1.         parameter     _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, 
2.                        _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'
b1001_0010,
3.                      _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,
4.                      _9 = 8'b1001_0000, _A = 8'b1000_1000, _B = 8'b1000_0011,
5.                      _C = 8'b1100_0110, _D = 8'b1010_0001, _E = 8'b1000_0110,
6.                      _F = 8'b1000_1110;

程式碼6.1

如程式碼6.1所示,筆者用常量宣告16個16進位制的數字。

clip_image006

圖6.3 16進位制數字的數碼管碼(拉低有效)。

為了方便讀者,筆者也順便繪製一張直觀的示意圖 ... 如圖6.3所示,哪裡有16個16進位制數字以及相關的數碼管碼。理解DIG訊號與數碼管碼的關係以後,接下來筆者會解釋SEL訊號與數碼管的關係。

clip_image008

圖6.4 訊號SEL與數碼管碼。

如圖6.4所示,我們可以看見SEL訊號與數碼管的關係,每當SEL為值不同,相關的數碼管就會顯示數字,例如SEL為值6’b111_110,最左邊的數碼管就會顯示數字;SEL為值6’b011_111,最右邊的數碼管就會顯示數字。如何實現自左向右輪流顯示數字,就是將 6’b111_110 其中的“0值”按間隔向左位移即可,這也是動態掃描最基本的理論。

clip_image010

圖6.5 流水燈的理想時序圖(腦補)。

例如實驗一的流水燈實驗,流水操作負責輪流點亮4位1組的LED資源。假設流水間隔是一個時鐘,如圖6.5所示,LED訊號分別在T0~T3之間輸出4’b0001,4’b0010,4’b0100,4’b10000,上述行為重複N次以後便產生流水效果。Verilog 則可以這樣描述,結果如程式碼6.2所示:

1.        case( i )
2.    
3.            0:
4.            begin LED <= 4’b0001; i <= i + 1’b1; end
5.            1:
6.            begin LED <= 4’b0010; i <= i + 1’b1; end
7.            2:
8.            begin LED <= 4’b0100; i <= i + 1’b1; end
9.            3:
10.            begin LED <= 4’b1000; i <= 4’d0; end
11.    
12.        endcase

程式碼6.2

如程式碼6.2所示, 相較實驗一的內容,步驟0~3也是實現流水效果,不過步驟0~3卻沒有考慮每個步驟所保持的時間,亦即流水間隔僅有一個時鐘而已。

clip_image012

圖6.6 數碼管顯示數字的例子。

相較實驗一的流水燈實驗,動態掃描就是功能稍微複雜一點的流水等而已,SEL訊號類似LED訊號,不過不是點亮LED而是負責位選工作,換之DIG訊號則是顯示內容。

如圖6.6所示,假設筆者想要顯示上述的結果,即自左向右輪流顯示數字0~5,其中DIG訊號負責數字0~5等資訊,至於數字的顯示次序則是SIG訊號負責。

clip_image013

圖6.7 自左向右顯示數字0~5的理想時序圖(腦補)。

假設流水間隔亦然是1個時鐘,為了自左向右輪流顯示數字“012345”,每個時鐘的SEL(位選)資訊,必須對應有效的DIG內容(數碼管碼),結果如圖6.6所示。時序發生過程如下:

T0的時候,DIG傳送未來值8’b1100_0000,SEL傳送未來值6’b111_110;

T1的時候,DIG傳送未來值8’b1111_1001,SEL傳送未來值6’b111_101;

T2的時候,DIG傳送未來值8’b1010_0100,SEL傳送未來值6’b111_011;

T3的時候,DIG傳送未來值8’b1011_0000,SEL傳送未來值6’b110_111;

T4的時候,DIG傳送未來值8’b1001_1001,SEL傳送未來值6’b101_111;

T5的時候,DIG傳送未來值8’b1001_0010,SEL傳送未來值6’b011_111;

Verilog則可以這樣表示,如程式碼6.3所示:

1.        case( i )
2.    
3.            0:
4.            begin DIG <= 8’b1100_0000; SEL <= 6’b111_110; i <= i + 1’b1; end
5.            1:
6.            begin DIG <= 8’b1111_1001; SEL <= 6’b111_101; i <= i + 1’b1; end
7.            2:
8.            begin DIG <= 8’b1010_0100; SEL <= 6’b111_011; i <= i + 1’b1; end
9.            3:
10.            begin DIG <= 8’b1011_0000; SEL <= 6’b110_111; i <= i + 1’b1; end
11.            4:
12.            begin DIG <= 8’b1001_1001; SEL <= 6’b101_111; i <= i + 1’b1; end
13.            5:
14.            begin DIG <= 8’b1001_0010; SEL <= 6’b011_111; i <= 4’d0; end
15.    
16.    endcase

程式碼6.3

如程式碼6.3所示,步驟0~5分別對應6位數碼管的顯示次序。如步驟0為DIG被賦予8’b1100_0000,即數字0的數碼管碼,期間SEL也被賦予6’b111_110,即點亮第一位數碼管(左邊第一個);步驟1為DIG被賦予8’b1111_1001,即數字1的數碼管碼,期間SEL也被賦予6’b111_101,即點亮第二位數碼管(左邊第二個);至於步驟2~5以此類推,完後便返回步驟0,重複一樣的操作。

流水間隔亦即動態掃描頻率,常規是10ms,不過喪心病狂的筆者卻設定為100us。100us經過50Mhz的時鐘量化以後是 5000,Verilog則可以這樣表示:

parameter T100US = 13'd5000;

如果步驟6.3的流水間隔不是一個時鐘而是100us,那麼程式碼6.3可以這樣修改,修改結果如程式碼6.4所示:

1.    case( i )
2.    
3.            0:
4.            if( C1 == T100US -1 ) begin C1 <= 13’d0; i <= i + 1’b1; end
5.            else DIG <= 8’b1100_0000; SEL <= 6’b111_110; end
6.            ...
7.            5:
8.            if( C1 == T100US -1 ) begin C1 <= 13’d0; i <= i + 1’b1; end
9.            else DIG <= 8’b1001_0010; SEL <= 6’b011_111; end
10.    
11.    endcase

程式碼6.4

理解這些內容以後,我們便可以開始建模了 ...

clip_image015

圖6.8 實驗六的建模圖。

如圖6.8所示,那是實驗六的建模圖,其中smg_basemod 是組合模組,它包含數碼管功能模組,還有數碼管加碼模組。接下來,讓我們來分析一下內部情況,數碼管功能模組它有一組24位的iData,然後又有10位oData。隨後oData[9:6]會經由加碼模組(即時模組)成為8位的數碼管資訊,並且驅動DIG頂層訊號。反之oData[5:0]則會直接驅動SEL頂層訊號。

smg_funcmod.v

clip_image017

圖6.9 數碼管功能模組。

接下來,讓我們獨自分析個體模組 ... 首先是數碼管功能模組,人如其名它是負責所有數碼管驅動工作的功能模組,24位的iData分別針對6位數碼管的顯示內容(數字),位分配如表6.1所示:

表 6.1 輸入資料位分配

位分配

[23..20]

[19..16]

[15..12]

[11..8]

[7..4]

[3..0]

數碼管分配

第一位

第二位

第三位

第四位

第五位

第六位

至於oData的作用如上所示,oData[9:6]必須經由數碼管加碼模組,oData[5:0]則直接驅動SEL頂層訊號。詳細內容就讓我們直接窺視程式碼吧:

1.    module smg_funcmod
2.    (
3.         input CLOCK, RESET,
4.         input [23:0]iData,
5.         output [9:0]oData
6.    );
7.         parameter T100US = 13'd5000;

以上內容為相關出入端宣告。第8行則是100us的常量宣告(流水間隔/停留時間)。

8.     
9.         reg [3:0]i;
10.         reg [12:0]C1;
11.         reg [3:0]D1;
12.         reg [5:0]D2;
13.         
14.         always @ ( posedge CLOCK or negedge RESET )
15.             if( !RESET )
16.                  begin
17.                          i <= 4'd0;
18.                         C1 <= 13'd0;
19.                             D1 <= 4'd0;
20.                         D2 <= 6'b111_110;
21.                    end
以上內容為相關的暫存器宣告以及復位操作。D1暫存iData的部分資料,D2則暫存位選資料。第17~21則是這些暫存器的復位操作。
22.              else 
23.                  case( i )
24.                    
25.                         0:
26.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= i + 1'b1; end
27.                         else begin C1 <= C1 + 1'b1; D1 <= iData[23:20]; D2 <= 6'b111_110; end
28.                         
29.                         1:
30.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= i + 1'b1; end
31.                         else begin C1 <= C1 + 1'b1; D1 <= iData[19:16]; D2 <= 6'b111_101; end
32.                         
33.                         2:
34.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= i + 1'b1; end
35.                         else begin C1 <= C1 + 1'b1; D1 <= iData[15:12]; D2 <= 6'b111_011; end
36.                         
37.                         3:
38.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= i + 1'b1; end
39.                         else begin C1 <= C1 + 1'b1; D1 <= iData[11:8]; D2 <= 6'b110_111; end
40.                         
41.                         4:
42.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= i + 1'b1; end
43.                         else begin C1 <= C1 + 1'b1; D1 <= iData[7:4]; D2 <= 6'b101_111; end
44.                         
45.                         5:
46.                         if( C1 == T100US -1 ) begin C1 <= 13'd0; i <= 4'd0; end
47.                         else begin C1 <= C1 + 1'b1; D1 <= iData[3:0]; D2 <= 6'b011_111; end
48.                         
49.                    endcase
50.         
51.         assign oData = { D1,D2 };
52.         
53.    endmodule

以上內容為核心操作以及輸出驅動宣告,步驟0~5用來輪流點亮數碼管,大概的思路之前已經解釋過 ... 舉例來說,步驟0為D1賦予iData[23:20]的內容,D2賦予 6’b111_110的內容,簡單說就是將iData[23:20]的數字顯示在第一位數碼管,至於步驟1~5也是以此類推,完後操作會返回步驟0。第51行則是輸出驅動宣告。

smg_encode_immdmod.v

clip_image019

圖6.10 數碼管加碼(即時)模組。

如圖6.10所示,數碼管加碼模組是一隻即時模組,它有一組4位的iData與一組8位的oData。該模組接收iData的內容,然後轉換為數碼管資訊,最後再經由oData輸出。具體內容,還是來瀏覽程式碼吧:

1.    module smg_encode_immdmod
2.    (
3.         input [3:0]iData,
4.         output [7:0]oData
5.    );
6.         parameter      _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, 
7.                       _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010, 
8.                      _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,
9.                      _9 = 8'b1001_0000, _A = 8'b1000_1000, _B = 8'b1000_0011,
10.                      _C = 8'b1100_0110, _D = 8'b1010_0001, _E = 8'b1000_0110,
11.                      _F = 8'b1000_1110;
12.         
13.         reg [7:0]D = 8'b1111_1111;
14.         
15.         always @ ( * )
16.              if( iData == 4'd0 ) D = _0;
17.              else if( iData == 4'd1 ) D = _1;
18.              else if( iData == 4'd2 ) D = _2;
19.              else if( iData == 4'd3 ) D = _3;
20.              else if( iData == 4'd4 ) D = _4;
21.              else if( iData == 4'd5 ) D = _5;
22.              else if( iData == 4'd6 ) D = _6;
23.              else if( iData == 4'd7 ) D = _7;
24.              else if( iData == 4'd8 ) D = _8;
25.              else if( iData == 4'd9 ) D = _9;
26.              else if( iData == 4'hA ) D = _A;
27.              else if( iData == 4'hB ) D = _B;
28.              else if( iData == 4'hC ) D = _C;
29.              else if( iData == 4'hD ) D = _D;
30.              else if( iData == 4'hE ) D = _E;
31.              else if( iData == 4'hF ) D = _F;
32.              else D = 8'dx;
33.         
34.         assign oData = D;
35.    
36.    endmodule

第3~4行是出入端宣告。第6~11行是數碼管碼0~F的常量宣告。第13行是相關的暫存器宣告。第15~32行則是加碼操作。第34行是輸出驅動宣告。

smg_basemod.v

至於組合模組smg_basemod筆者就不重複貼圖了,讀者請自行看回圖6.8。詳細的內容讓我們來瀏覽程式碼吧:

1.    module smg_basemod
2.    (
3.         input CLOCK, RESET,
4.         output [7:0]DIG,
5.         output [5:0]SEL
6.    );     
7.        wire [9:0]DataU1;
8.    
9.        smg_funcmod U1
10.        (
11.              .CLOCK( CLOCK ),
12.              .RESET( RESET ),
13.              .iData( 24'hABCDEF ), // < top
14.              .oData( DataU1 )  // > U2
15.        );
16.        
17.        assign SEL = DataU1[5:0];
18.    
19.         smg_encode_immdmod U2
20.         (
21.              .iData( DataU1[9:6] ),  // < U1
22.              .oData( DIG )       // > top
23.         );
24.         
25.    endmodule

該程式碼由於演示的作用,並沒有將U1的iData直接引出,而是直接在其輸入設定常量24’hABCDEF(第13行)。至於相關的連線部署就複習圖6.8吧。編譯完後下載程式,我們便會發現數字“ABCDEF”分別自左向右顯示在6位數碼管。

細節一:完整的個體模組

clip_image021

圖6.11 數碼管基礎模組的建模圖。

如圖6.11所示,那是完整的數碼管基礎模組,除了將smg_funcmod的iData向外引出,餘下都一樣。

smg_basemod.v
1.    module smg_basemod
2.    (
3.         input CLOCK, RESET,
4.         input [23:0]iData,
5.         output [7:0]DIG,
6.         output [5:0]SEL
7.    );     
8.        wire [3:0]DataU1;
9.    
10.        smg_funcmod U1
11.        (
12.              .CLOCK( CLOCK ),
13.              .RESET( RESET ),
14.              .iData( iData ), // < top
15.              .oData( DataU1 ),  // > U2
16.         );
17.        
18.        assign SEL = DataU1[5:0];
19.     
20.         smg_encode_immdmod U2
21.         (
22.              .iData( DataU1[9:6] ),  // < U1
23.              .oData( DIG )        // > top
24.         );
25.         
26.    endmodule

相關推薦

黑金原創教程FPGA那些事兒-驅動I 實驗流水燈模組

實驗一:流水燈模組 對於發展商而言,動土儀式無疑是最重要的任務。為此,流水燈實驗作為低階建模II的動土儀式再適合不過了。廢話少說,我們還是開始實驗吧。 圖1.1 實驗一建模圖。 如圖1.1 所示,實驗一有名為 led_funcmod的功能模組。如果無視環境訊號(時鐘訊號還有復位訊號),該功能模組只有

黑金原創教程FPGA那些事兒-驅動I 連載導讀

前言: 無數晝夜的來回輪替以後,這本《驅動篇I》終於編輯完畢了,筆者真的感動到連鼻涕也流下來。所謂驅動就是認識硬體,還有前期建模。雖然《驅動篇I》的硬體都是我們熟悉的老友記,例如UART,VGA等,但是《驅動篇I》貴就貴在建模技巧的昇華,亦即低階建模II。 話說低階建模II,讀過《建模篇》的朋友多少也會面

黑金原創教程FPGA那些事兒-驅動I 實驗按鍵模組② — 點選與長點選

實驗三:按鍵模組② — 點選與長點選 實驗二我們學過按鍵功能模組的基礎內容,其中我們知道按鍵功能模組有如下操作: l 電平變化檢測; l 過濾抖動; l 產生有效按鍵。 實驗三我們也會z執行同樣的事情,不過卻是產生不一樣的有效按鍵: l 按下有效(點選); l 長按下有效(長點選)。 圖3

黑金原創教程FPGA那些事兒-驅動I 實驗按鍵模組

實驗二:按鍵模組① - 消抖 按鍵消抖實驗可謂是經典中的經典,按鍵消抖實驗雖曾在《建模篇》出現過,而且還惹來一堆麻煩。事實上,筆者這是在刁難各位同學,好讓對方的慣性思維短路一下,但是慘遭口水攻擊 ... 面對它,筆者宛如被甩的男人,對它又愛又恨。不管怎麼樣,如今 I’ll be back,筆者再也不會重複一

黑金原創教程FPGA那些事兒-驅動I 實驗數碼模組

實驗六:數碼管模組 有關數碼管的驅動,想必讀者已經學爛了 ... 不過,作為學習的新儀式,再爛的東西也要溫故知新,不然學習就會不健全。黑金開發板上的數碼管資源,由始至終都沒有改變過,筆者因此由身懷念。為了點亮多位數碼管從而顯示數字,一般都會採用動態掃描,然而有關動態掃描的資訊請怒筆者不再重複。在此,同樣也是

黑金原創教程FPGA那些事兒-驅動I 實驗按鍵模組③ — 單擊與雙擊

實驗四:按鍵模組③ — 單擊與雙擊 實驗三我們建立了“點選”還有“長點選”等有效按鍵的多功能按鍵模組。在此,實驗四同樣也是建立多功能按鍵模組,不過卻有不同的有效按鍵。實驗四的按鍵功能模組有以下兩項有效按鍵: l 單擊(按下有效); l 雙擊(連續按下兩下有效)。 圖4.1 單擊有效按鍵,時序示意圖

黑金原創教程FPGA那些事兒-驅動I 實驗按鍵模組④ — 點選,長點選,雙擊

實驗五:按鍵模組④ — 點選,長點選,雙擊 實驗二至實驗四,我們一共完成如下有效按鍵: l 點選(按下有效) l 點選(釋放有效) l 長擊(長按下有效) l 雙擊(連續按下有效) 然而,不管哪個實驗都是隻有兩項“功能”的按鍵模組而已,如今我們要建立三項“功能”的按鍵模組,亦即點選(按下有效),長

黑金原創教程FPGA那些事兒-驅動I 原創教程連載導讀連載完成,共二十九章

前言: 無數晝夜的來回輪替以後,這本《驅動篇I》終於編輯完畢了,筆者真的感動到連鼻涕也流下來。所謂驅動就是認識硬體,還有前期建模。雖然《驅動篇I》的硬體都是我們熟悉的老友記,例如UART,VGA等,但是《驅動篇I》貴就貴在建模技巧的昇華,亦即低階建模II。 話說低階建模II,讀過《建模篇》的朋友多少也會面

黑金原創教程FPGA那些事兒-驅動I 實驗二十一SDRAM模組④ — 頁讀寫 β

實驗二十一:SDRAM模組④ — 頁讀寫 β 未進入主題之前,讓我們先來談談一些重要的體外話。《整合篇》之際,筆者曾經比擬Verilog如何模仿for迴圈,我們知道for迴圈是順序語言的產物,如果Verilog要實現屬於自己的for迴圈,那麼它要考慮的東西除了步驟以外,還有非常關鍵的時鐘。 for(

黑金原創教程FPGA那些事兒-驅動I 實驗PS/2模組④ — 普通滑鼠

實驗十:PS/2模組④ — 普通滑鼠 學習PS/2鍵盤以後,接下來就要學習 PS/2 滑鼠。PS/2滑鼠相較PS/2鍵盤,驅動難度稍微高了一點點,因為FPGA(從機)不僅僅是從PS/2滑鼠哪裡讀取資料,FPGA還要往滑鼠裡寫資料 ... 反之,FPGA只要對PS/2鍵盤讀取資料即可。然而,最傷腦筋的地方就在

黑金原創教程FPGA那些事兒-驅動I 實驗十八SDRAM模組① — 單字讀寫

實驗十八:SDRAM模組① — 單字讀寫 筆者與SDRAM有段不短的孽緣,它作為冤魂日夜不斷糾纏筆者。筆者嘗試過許多方法將其退散,不過屢試屢敗的筆者,最終心情像橘子一樣橙。《整合篇》之際,筆者曾經大戰幾回兒,不過內容都是點到即止。最近它破蠱而出,日夜不停:“好~痛苦!好~痛苦!”地呻吟著,嚇得筆者不敢半夜如

黑金原創教程FPGA那些事兒-驅動I 實驗二十七TFT模組

實驗二十七:TFT模組 - 顯示 所謂TFT(Thin Film Transistor)就是眾多LCD當中,其中一種支援顏色的LCD,相較古老的點陣LCD(12864笑),它可謂高階了。黑金的TFT LCD除了320×240大小以外,內建SSD1289控制器,同時也是獨立模組。事實上,無論是驅動點陣LCD還

黑金原創教程FPGA那些事兒-驅動I 實驗十三串列埠模組② — 接收

實驗十三:串列埠模組② — 接收 我們在實驗十二實現了串列埠傳送,然而這章實驗則要實現串列埠接收 ... 在此,筆者也會使用其它思路實現串列埠接收。 圖13.1 模組之間的資料傳輸。 假設我們不考慮波特率,而且一幀資料之間的傳輸也只是發生在FPGA之間,即兩隻模組之間互轉,並且兩塊模組都使用相同的時

黑金原創教程FPGA那些事兒-驅動I 實驗PS/2模組① — 鍵盤

實驗七:PS/2模組① — 鍵盤 實驗七依然也是熟爛的PS/2鍵盤。相較《建模篇》的PS/2鍵盤實驗,實驗七實除了實現基本的驅動以外,我們還要深入解PS/2時序,還有PS/2鍵盤的行為。不過,為了節省珍貴的頁數,怒筆者不再重複有關PS/2的基礎內容,那些不曉得的讀者請複習《建模篇》或者自行谷歌一下。 市場

黑金原創教程FPGA那些事兒-驅動I 實驗PS/2模組③ — 鍵盤與多組合鍵

實驗九:PS/2模組③ — 鍵盤與多組合鍵 筆者曾經說過,通碼除了單位元組以外,也有雙位元組通碼,而且雙位元組通碼都是 8’hE0開頭,別名又是 E0按鍵。常見的的E0按鍵有,<↑>,<↓>,<←>,<→>,<HOME>,<PRTSC>

黑金原創教程FPGA那些事兒-驅動I 實驗二十五SDHC模組

實驗二十五:SDHC模組 筆者曾經說過,SD卡發展至今已經衍生許多版本,實驗二十四就是針對版本SDV1.×的SD卡。實驗二十四也說過,CMD24還有CMD17會故意偏移地址29,讓原本範圍指向從原本的232 變成 223,原因是SD卡讀寫一次都有512個位元組。為此我們可以這樣計算: SDV1.x = 2

黑金原創教程FPGA那些事兒-驅動I 實驗二十SDRAM模組③ — 頁讀寫 α

實驗二十:SDRAM模組③ — 頁讀寫 α 完成單字讀寫與多字讀寫以後,接下來我們要實驗頁讀寫。醜話當前,實驗二十的頁讀寫只是實驗性質的東西,其中不存在任何實用價值,筆者希望讀者可以把它當成頁讀寫的熱身運動。 表示20.1 Mode Register的內容。 Mode Register

黑金原創教程FPGA那些事兒-驅動I 實驗二十八TFT模組

實驗二十八:TFT模組 - 觸屏 讀者在上一個實驗所玩弄過的 TFT LCD模組,除了顯示大小為 320 × 240,顏色為16位RGB的影象資訊以外,它還支援觸屏。所謂觸屏就是滑鼠還有鍵盤以外的輸入手段,例如現在流行平板還有智慧手機,觸屏輸入對我們來說,已經成為日常的一部分。描述語言一門偏向硬體的語言

黑金原創教程FPGA那些事兒-驅動I 實驗二十二SDRAM模組⑤ — FIFO讀寫

經過漫長的戰鬥以後,我們終於來到最後。對於普通人而言,頁讀寫就是一名戰士的墓碑(最終戰役) ... 然而,怕死的筆者想透過這個實驗告訴讀者,旅程的終點就是旅程的起點。一直以來,筆者都在煩惱“SDRAM是否應該成為儲存類?”SDRAM作為一介儲存資源(儲存器),它的好處就是大容量空間,壞處則就是麻煩的控制規

黑金原創教程FPGA那些事兒-驅動I 實驗十四儲存模組

實驗十四比起動手筆者更加註重原理,因為實驗十四要討論的東西,不是其它而是低階建模II之一的模組類,即儲存模組。接觸順序語言之際,“儲存”不禁讓人聯想到變數或者陣列,結果它們好比資料的暫存空間。 1. int main() 2. { 3. int VarA; 4.