1. 程式人生 > >【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗二:按鍵模組①

【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗二:按鍵模組①

實驗二:按鍵模組① - 消抖

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

按鍵消抖說傻不傻說難不難。所謂傻,它因為原理不僅簡單(就是延遲幾下下而已),而且順序語言(C語言)也有無數不盡的例子。所謂難,那是因為人們很難從微控制器的思維跳出來 ... 此外,按鍵消抖也有許多細節未曾被人重視,真是讓人傷心。按鍵消抖一般有3段操作:

l 檢測電平變化;

l 過濾抖動(延遲);

l 產生有效按鍵。

假設C語言與微控制器的組合想要檢測電平變化,它們一般是利用if查詢或者外部中斷。事後,如果這對組合想要過濾抖動,那麼可以借用for延遲的力量,又或者依賴定時中斷產生精明的延遲效果。反觀有效案件的產生,這對組合視乎而外鍾情“按下有效”似的 ... 不管怎麼樣,C語言與微控制器這對組合在處理按鍵的時候,它們往往會錯過一些黃金。

“黃金?”,讀者震撼道。

所謂黃金時間就是電平發生變化那一瞬間,還有消抖(延遲)以後那一瞬間。按鍵按下期間,按鍵的輸入電平故會發生變化,如果使用if查詢去檢測,結果很容易浪費微控制器的處理資源,因為微控制器必須一直等待 ... 換之,如果反用外部中斷,中斷定址也會耽誤諾干時間。

假設C語言與微控制器這對組合捱過電平檢測這起難關,餘下的困難卻是消抖動作。如果利用for迴圈實現去消抖,例如 Delay_ms(10) 之類的函式。For迴圈不僅計數不緊密,而且還會白白浪費微控制器的處理資源。定時中斷雖然計數緊密,但是中斷觸發依然也會產生諾乾的定址延遲。補上,所謂定址延遲是處理器處理中斷觸發的時候,它要事先保護現場之餘,也要定址中斷處理入口,然後執行中斷函式,完後回覆現場,最後再返回當前的工作。

感覺上,筆者好似在欺負C語言以及微控制器,死勁說它們的不是。親愛的讀者,千萬別誤會,筆者只是在陳述事實而已。微控制器本來就是比較粗野的爺們,它很難做到緊湊又毫無空隙的操作,反觀FPGA卻異常在行。所以說,微控制器的思路很難沿用在FPGA身上,否則會出現許多笑話。如今,這是描述語言以及FPGA的新時代,所謂後浪推前浪正是新舊時代的替換。

FPGA不僅沒有隱性處理,而且描述語言也是自由自身。我們只要方法得當,手段有效,“黃金”要多少就有多少 ... 哇哈哈!在此,筆者說了那麼多廢話只是告知讀者,千萬別用微控制器的思維去猜摸FPGA如何處理按鍵校抖,不然問號會沒完沒了。好了,廢話差不多說完了,讓我們切回主題吧。

clip_image002

圖2.1 按鍵活動的時序示意圖。

如圖2.1 所示,那是按鍵活動的時序圖。高電為平按鍵預設狀態,按鍵一旦按下,“按下事件”就發生了,電平隨之發生抖動,抖動週期大約為10ms。事後,如果按鍵依然按著不放,那麼電平便會處於低電平。換之,如果按鍵此刻被釋放,那麼“釋放事件”發生了,電平隨之由低變高,然後發生抖動,抖動週期大約為10ms。筆者曾在前面說過,按鍵消抖組一般有3個工作要做,亦即檢測電平變化,過濾抖動,還有產生有效按鍵。

檢測電平變化:

clip_image004

圖2.2 按鍵電平變化,按下事件與釋放事件。

顧名思義,檢測電平變化就是用來察覺“按下事件”還有“釋放事件”,或者監控電平的狀態變化。如圖2.2所示,筆者建立一組暫存器F1~F2,F1暫存當前的電平狀態,F2則暫存上一個時鐘的電平狀態。Verilog語言可以這樣表示,如程式碼2.1所示:

reg F2,F1;
always @ ( posedge CLOCK )
    { F2,F1 } <= { F1,KEY };

程式碼2.1所示

根據圖2.2的顯示,按下事件是 F2 為1值,F1為0值;釋放事件則是 F2為0值,F1為1值。為了不要錯過電平變化的黃金時間,“按下事件”還有“釋放事件”必須作為“即時“,為此 Verilog語言可以這樣表示:

wire isH2L = ( F2 == 1 && F1 == 0 );
wire isL2H = ( F2 == 0 && F1 == 1 );

過濾抖動:

clip_image006

圖2.3 過濾抖動。

過濾抖動就是也可以稱為延遲抖動,常規又廉價的機械按鍵,抖動時間大約是10ms之內,如圖2.3.所示。抖動一般都發生在“按下事件”或者“釋放事件”以後,過濾抖動就是延遲諾干時間即可。Verilog語言則可以這樣表示,如程式碼2.2所示:

3: 
if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;

程式碼2.2

產生有效按鍵:

clip_image008

圖2.4 產生有效按鍵。

產生有效按鍵亦即立旗有效的按鍵事件,如圖2.4所示,按下有效isPress訊號,還有釋放有效isRelease訊號,兩個訊號分別都是拉高一個時鐘。除了常見的按下有效或者釋放有效以外,根據設計要求,有效按鍵按也有其它,例如:按鍵按下兩下有效(雙擊),按鍵按下一段時間有效(長擊)。至於Verilog語言則可以這樣表示,如程式碼2.3所示:

1: begin isPress <= 1'b1; i <= i + 1'b1; end               
2: begin isPress <= 1'b0; i <= i + 1'b1; end
...
1: begin isRelease <= 1'b1; i <= i + 1'b1; end               
2: begin isRelease <= 1'b0; i <= i + 1'b1; end

程式碼2.3

熱身完畢後,我們就可以進入實驗主題了。

clip_image010

圖2.5 實驗二建模圖。

如圖2.5所示,哪裡有一塊名為 key_funcmod 的功能模組,輸入端為 KEY訊號,輸出端卻為 LED訊號。KEY訊號連線按鍵資源,LED訊號分別驅動兩位LED資源。按鍵功能模組的工作主要是過濾 KEY訊號變化以後所發生的抖動,接著產生“按下有效”還有“釋放有效”兩個有效按鍵,然後點亮LED資源。

key_funcmod.v
1.    module key_funcmod
2.    (
3.         input CLOCK, RESET,
4.         input KEY,
5.         output [1:0]LED
6.    );

以上內容為出入端宣告。

7.         parameter T10MS = 19'd500_000;
8.         
9.         /***************************/ //sub
10.         
11.         reg F2,F1; 
12.             
13.         always @ ( posedge CLOCK or negedge RESET ) 
14.             if( !RESET ) 
15.                  { F2, F1 } <= 2'b11;
16.              else 
17.                  { F2, F1 } <= { F1, KEY };
18.                    
19.         /***************************/ //core            
20.        
21.        wire isH2L = ( F2 == 1 && F1 == 0 );
22.        wire isL2H = ( F2 == 0 && F1 == 1 );

以上內容為常量宣告以及電平檢測的周邊操作。第7行則是10ms的常量宣告,第11~17則是電平狀態檢測的周邊操作。至於第21~22行則是“按下事件”還有“釋放事件”的即時宣告。

23.         reg [3:0]i;         
24.         reg isPress, isRelease;
25.         reg [18:0]C1;
26.         
27.         always @ ( posedge CLOCK or negedge RESET )
28.             if( !RESET )
29.                   begin
30.                          i <= 4'd0;
31.                         { isPress,isRelease } <= 2'b00;
32.                         C1 <= 19'd0;
33.                     end
34.              else

以上內容為相關的暫存器宣告以及復位操作。i用來指向步驟,isPress與 isRelease則標示按下有效亦即釋放有效,C1則用來計數。

35. case(i)
36.
37.         0: // H2L check
38.         if( isH2L ) i <= i + 1'b1;
39.
40.         1: // H2L debounce
41.         if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
42.         else C1 <= C1 + 1'b1;
43.
44.         2: // Key trigger prees up
45.         begin isPress <= 1'b1; i <= i + 1'b1; end
46.
47.         3: // Key trigger prees down
48.         begin isPress <= 1'b0; i <= i + 1'b1; end
49.
50.         4: // L2H check
51.         if( isL2H ) i <= i + 1'b1;
52.
53.         5: // L2H debounce
54.         if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
55.         else C1 <= C1 + 1'b1;
56.
57.         6: // Key trigger prees up
58.        begin isRelease <= 1'b1; i <= i + 1'b1; end
59.
60.         7: // Key trigger prees down
61.        begin isRelease <= 1'b0; i <= 4’d0; end
62.       
63. endcase


以上內容為核心操作。具體的核心操作過程如下:
步驟 0 等待電平由高變低;
步驟 2 用來過濾由高變低所引發的抖動;
步驟 1~3 用來產生按下有效的高脈衝;
步驟 4 等待電平由低變高;
步驟 5 用來過濾由低變高所引發的抖動;
步驟 6~7 用來產生釋放有效的高脈衝,然後返回步驟 0。

64.        
65.        /***********************/ // sub-demo
66.        
67.        reg [1:0]D1;
68.        
69.        always @ ( posedge CLOCK or negedge RESET )
70.             if( !RESET )
71.                 D1 <= 2'b00;
72.             else if( isPress )
73.                 D1[1] <= ~D[1];
74.             else if( isRelease )
75.                 D1[0] <= ~D[0];
76.                    
77.        assign LED = D1;
78.    
79.    endmodule

以上內容為演示用的周邊操作,它根據 isPress 還有 isRelease 的高脈衝,分別翻轉 D1[1] 還有 D1[0]的內容。至於第77行則是輸出驅動的宣告,D1驅動LED輸出端。編譯完後便下載程式。

我們會發現第一次按下 <KEY2> 會點亮 LED[1],釋放<KEY2>會點亮 LED[0]。第二次按下 <KEY2> 會消滅 LED[1],釋放 <KEY2> 則會消滅 LED[0]。如此一來,實驗二已經成功。實驗二未結束之前,讓筆者分析一下實驗二的諾幹細節:

細節一:過分消抖

clip_image012

圖2.6 過分消抖(過分延遲)。

結果如圖2.6所示,假設筆者手癢將消抖時間拉長至1s,Verilog語言則可以這樣表示,如程式碼2.4所示:

    3: 
    if( C1 == T1S -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
    else C1 <= C1 + 1'b1;

程式碼2.4

一般消抖期間,按鍵功能模組的核心操作就會停留在消抖(延遲)步驟,如果消抖期間筆者釋放按鍵,那麼釋放事件會被無視,然後核心操作會被打亂,最後整個功能模組會跑飛。反之,如果筆者等待消抖完畢再釋放按鍵,那麼釋放事件會照常發生,整個功能模組也會照常運作。

細節二:精密控時

1: // H2L debounce
if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
2: // Key trigger prees up
begin isPress <= 1'b1; i <= i + 1'b1; end
3: // Key trigger prees down
begin isPress <= 1'b0; i <= i + 1'b1; end

程式碼2.5

根據按鍵功能模組,核心操作執行消抖之後都會產生有效按鍵,亦即為立旗暫存器
(isPress 或者 isRelease)拉高又拉低一個時鐘,如程式碼 2.5 所示。如果筆者是一位精
密控時的狂人,這段拉高又拉低的時鐘消耗,筆者也會將其考慮進去消抖時間。為此,
筆者可以這樣修改,如程式碼 2.6 所示:

1: // H2L debounce
if( C1 == T10MS -1 -2 ) begin C1 <= 19'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
2: // Key trigger prees up
begin isPress <= 1'b1; i <= i + 1'b1; end
3: // Key trigger prees down
begin isPress <= 1'b0; i <= i + 1'b1; end

程式碼2.6

程式碼2.6相較程式碼2.6,消抖步驟部分的if判斷內多了 -2,其中 -2表示產生按鍵有效所消耗的時鐘。

細節三:完整的個體模組

clip_image014

圖2.7 完整的按鍵功能模組。

圖2.6是演示用的建模圖,然而圖2.7則是完整的建模圖,其中按鍵功能模組有一個 KEY輸入端,主要連線按鍵資源。此外,按鍵功能模組也有一組兩位的溝通訊號Trig,亦即按下Trig[1]產生一個高脈衝,釋放Trig[0]產生一個高脈衝。

key_funcmod.v
1. module key_funcmod
2. (   
3.     input CLOCK, RESET,
4.     input KEY,
5.     output [1:0]oTrig
6. );
7.     parameter T10MS = 19'd500_000;
8.
9.     /***************************/ //sub
10.
11.     reg F2,F1;
12.
13.     always @ ( posedge CLOCK or negedge RESET )
14.         if( !RESET )
15.             { F2, F1 } <= 2'b11;
16.         else
17.             { F2, F1 } <= { F1, KEY };
18.
19.    /***************************/ //core
20.
21.    wire isH2L = ( F2 == 1 && F1 == 0 );
22.    wire isL2H = ( F2 == 0 && F1 == 1 );
23.    reg [3:0]i;
24.    reg isPress, isRelease;
25.    reg [18:0]C1;
26.
27.     always @ ( posedge CLOCK or negedge RESET )
28.         if( !RESET )
29.             begin
30.                 i <= 4'd0;
31.                 { isPress,isRelease } <= 2'b00;
32.                 C1 <= 19'd0;
33.             end
34.         else
35.             case(i)
36.
37.                 0: // H2L check
38.                 if( isH2L ) i <= i + 1'b1;
39.
40.                 1: // H2L debounce
41.                 if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
42.                 else C1 <= C1 + 1'b1;
43.
44.                 2: // Key trigger prees up
45.                 begin isPress <= 1'b1; i <= i + 1'b1; end
46.
47.                 3: // Key trigger prees down
48.                 begin isPress <= 1'b0; i <= i + 1'b1; end
49.
50.                 4: // L2H check
51.                 if( isL2H ) i <= i + 1'b1;
52.
53.                 5: // L2H debounce
54.                 if( C1 == T10MS -1 ) begin C1 <= 19'd0; i <= i + 1'b1; end
55.                 else C1 <= C1 + 1'b1;
56.
57.                 6: // Key trigger prees up
58.                 begin isRelease <= 1'b1; i <= i + 1'b1; end
59.
60.                 7: // Key trigger prees down
61.                 begin isRelease <= 1'b0; i <= 4’d0; end
62.
63.         endcase
64.
65.         /********************************/
66.
67. assign oTrig = { isPress, isRelease };
68.       
69. 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.