1. 程式人生 > >【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗八:PS/2模組② — 鍵盤與組合鍵

【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗八:PS/2模組② — 鍵盤與組合鍵

實驗八:PS/2模組② — 鍵盤與組合鍵

實驗七之際,我們學習如何讀取PS/2鍵盤傳送過來的通碼與斷碼,不過實驗內容也是一鍵按下然後釋放,簡單按鍵行為而已。然而,實驗八的實驗內容卻是學習組合鍵的按鍵行為。

不知讀者是否有類似的經歷?當我們使用鍵盤的時候,如果5~6按鍵同時按下,電腦隨之便會發出“嗶嗶”的警報聲,鍵盤立即失效。這是鍵盤限制設計,不同產品也有不同限制的按鍵數量。預設下,最大按鍵數量是5~7個。所謂組合鍵就是兩個以上的按鍵所產生的有效按鍵。舉例而言,按下按鍵 <A> 輸出“字元a”,按下 <Shift> + <A>便輸出“字元A”。不過要實現組合鍵,我們必須深入瞭解鍵盤的按鍵行為不可。

clip_image002

圖8.1 按下又立即釋放。

PS/2鍵盤最常見的按鍵行為是按下以後又立即釋放,假設筆者按下<A>鍵又立即釋放<A>鍵,那麼PS/2鍵盤便會產生類似圖8.1的時序。如圖8.1所示,當筆者按下 <A> 的時候,PS/2鍵盤便會發送8’h1C的通碼;反之,如果 <A> 被釋放,PS2鍵盤也會立即傳送8’hF0 8’h1C的斷碼。

clip_image004

圖8.2 長按又立即釋放。

如果筆者手癢長按 <A> 不放,那麼PS/2鍵盤便會按照100ms的間隔時間,不斷髮送通碼 8’h1C。期間,如果筆者釋放 <A>,那麼PS/2鍵盤便會發送 8’hF0 8’h1C的斷碼,時序結果如圖8.2所示。不管是圖8.1還是圖8.2的情況,都是PS/2鍵盤最常見的按鍵行為,亦即單鍵行為。話雖如此,單鍵行為既是最基礎的按鍵行為,多鍵行為也必須基於它。

clip_image006

圖8.3 多鍵行為,先按後放①。

多鍵行為不同單鍵行為,因為多鍵行為同時存在兩個以上的按鍵被按下,因此多鍵行為便有先按後放,先按先放等次序。假設筆者先按下<A>,然後又按下<LShift>,隨之PS/2鍵盤便會接續傳送通碼 8’h1C與 8’h12。如果筆者想要撒手, <LShift> 必須事先釋放,再者是 <A>,結果PS/2鍵盤便會連續傳送 8’hF0 8’h12 與 8’hF0 8’h1C的斷碼。

clip_image008

圖8.3 多鍵行為,先按後放②。

再假設筆者先按下 <A> 後按下 <LShift> 以後並沒有立即釋放任何按鍵,作為最後按下的按鍵,它可以得到執行權。如圖8.3所示,筆者先是按下 <A> 然後又按下 <Shift>,那麼PS/2鍵盤便會接續傳送 8’h1C 與 8’h12等通碼。假設筆者手指麻痺沒有立即釋放任何按鍵,那麼 <LShift> 就會得到執行權,結果保持長按狀態。此刻,PS/2鍵盤便會不停傳送 <LShift> 的通碼。

一旦手指回復知覺,然後按照先按後放的次序,先行釋放 <LShift> 然後釋放 <A>

,結果PS/2鍵盤便會接續傳送 8’hF0 8’h12 與 8’hF0 8’h1C 等斷碼。

clip_image010

圖8.5 多鍵行為,先按先放。

如果讀者不是按照先按後放,而是先按先放的次序,先按下 <A>,後按下 <LShift> 的話 ... 如圖8.5所示,假設筆者先按下 <A>,然後又按下 <LShift>,此刻PS/2鍵盤便會接續傳送 8’h1C與 8’h12等通碼。期間,筆者忽然手癢,覺得先按先放比較好玩,於是筆者故意鬆開 <A>,此刻PS/2鍵盤便會發送 8’hF0 8’h1C的斷碼。

同一時刻,<LShift> 亦然保持按下的姿勢,PS/2鍵盤傳送完畢 <A> 的斷碼以後,PS/2鍵盤也會不停傳送 <LShift> 的通碼 ... 直至筆者釋放 <LShift>,PS/2鍵盤傳送 8’hF0 8’h12的斷碼為止。

多鍵行為的終點就在於“先按後放”還是“先按先放”。不管是哪一種次序,下一刻按鍵都會搶奪上一刻按鍵的執行權與長按狀態。不過根據習慣,先按後放固然已經成為主流,唯有意外或者那個神經不協調的傻子才會選擇先按先放的次序。當我們理解PS/2鍵盤的多鍵行為以後,我們便可以開始實現組合鍵。

根據筆者的認識,PS/2鍵盤也有按鍵分類,如: <Shift>,<Ctrl> 還有 <Alt> 等按鍵,它們都是常見的組合(補助)按鍵。除此之外,筆記本或者一些特殊鍵盤也有不同的組合鍵,如:<FN> 與 <WIN> 按鍵。一般而言,我們都認為組合鍵是軟體的工作,雖然這是不擇不扣的事實,不過我們只要換個思路,Verilog也可以實現組合鍵。對此,我們只要將一隻組合鍵視為一個立旗狀態,所有難題都能迎刃而解。

clip_image012

圖8.6 組合鍵與立旗狀態。

假設筆者先按下 <LCtrl> 又按下 <LShift>,PS/2鍵盤傳送完畢 <LCtrl> 的通碼以後,isCtrl便會立旗。緊接著PS/2鍵盤又會發送 <L Shift> 的通碼,隨後 isShift也會立旗。

事後,筆者先釋放 <LShift> 再釋放 <LCtrl>,那麼PS/2鍵盤便會接續傳送 <LShift> 與 <LCtrl> 的斷碼。<LShift> 斷碼傳送完畢以後,isShift便會消除立旗。同樣 <LCtrl>斷碼傳送完畢以後 isCtrl也會消除立旗。

clip_image014

圖8.7 有效的組合鍵①。

為了表示有效的組合鍵,我們依然需要isDone這個高脈衝,我們雖然知道isDone產生高脈衝都是一般通碼輸出以後。不過在此,組合鍵不被認為是一般通碼。如圖8.7所示,假設筆者先按下 <LShift> 又按下 <A>,<LShift> 通碼傳送完畢以後便立旗 isShift;<A> 通碼 傳送完畢以後便拉高一會 isDone。如果此刻 isShift為拉高狀態,而且通碼<A> 又有效,那麼有效的組合鍵 <Shift> + <A> 便產生。

完後,筆者先釋放 <A> 在釋放 <LShift>,PS/2鍵盤便會接續傳送 <A> 與 <LShift>的斷碼。<A> 的斷碼沒有產生任何效果,反之 <LShift> 的斷碼則消除 isShift的立旗狀態。

clip_image016

圖8.8 有效的組合鍵②。

為了產生各種各樣的有效組合鍵,我們不可能不斷按下又釋放組合鍵 ... 換言之,不斷切換的傢伙只有非組合鍵而已,組合鍵則一直保持有效的狀態,直至傳送斷碼為止。如圖8.8所示,假設筆者先按下 <LShift> 又按下 <A>, <LShift> 通碼使 isShift 立旗,<A> 通碼使 isDone產生高脈衝,對此組成鍵 <Shift> + <A> 完成。

隨後,筆者釋放 <A>,PS/2鍵盤便傳送 <A> 斷碼。不一會,筆者又按下 <B>,<B>通碼使 isDone產生高脈衝,結果完成組合鍵 <Shift> + <B>。事後,筆者釋放 <B> 又釋放 <LShift>,PS/2鍵盤便會接續傳送斷碼 <B> 與 <LShift>,<B> 斷碼沒有異樣,<LShift> 斷碼則消除 isShift 的立旗狀態。

clip_image018

圖8.9 多狀態有效組合鍵。

除了當個組合鍵(一個立即狀態)以外,同樣的道理也能實現多個組合鍵(多個立旗狀態)。如圖8.9所示,筆者先是按下 <LCtrl> 又按下 <LShift>,<LCtrl>通碼立旗 isCtrl狀態,<LShift> 通碼則立旗 isShift 狀態。緊接著筆者又按下 <A>,<A>通碼導致 isDone產生一個高脈衝,此刻組合鍵 <Ctrl> + <Shift> + <A> 已經完成。然後筆者釋放 <A> 使其產生 <A>斷碼。

不一會,筆者又按下 <B>,結果 <B> 通碼驅使 isDone又產生另一個高脈衝,此刻組合鍵 <Ctrl> + <Shift> + <B> 已經完成。心滿意足的筆者接續釋放 <B>,<LShift> 還有 <LCtrl>。<B> 斷碼沒有任何異樣,<LShift> 斷碼消除 isShift立旗狀態,<LCtrl> 斷碼則消除 isCtrl立旗狀態。

一般而言,組合鍵最多可以達到3級,亦即 <Ctrl> + <Shift> + <Alt> + ?。話雖如此,除非對方的手指比猴子更靈活,不然要同時按照次序按下4個按鍵是一件容易傷害手指的蠢事。換之,一級與兩級的組合鍵已經足夠應用。理論上,Verilog要實現多少級組合鍵也沒有問題,但是過多的功能只是浪費而已。

好了,上述這些內容理解完畢以後,我們便可以開始建模了!

clip_image020

圖8.10 實驗八建模圖。

圖8.10是實驗八的建模圖,一個名為ps2_demo的組合模組,內含PS/2功能模組,還有數碼管基礎模組。PS/2功能模組的左方是 PS2_CLK 與 PS2_DAT 等頂層訊號的輸入,右方則是oData與oTag聯合驅動數碼管基礎模組。對此,數碼管除了輸出通碼以外,數碼管也會表示組合鍵的有效狀態。

ps2_funcmod.v

clip_image022

圖8.11 PS/2功能模組的建模圖。

相較圖8.10與圖8.11,圖8.11的PS/2功能模組還有oTrig,用來發送isDone的高脈衝。至於具體內容如何,讓我們來瞧瞧程式碼吧:

1.    module ps2_funcmod
2.    (
3.         input CLOCK, RESET,
4.         input PS2_CLK, PS2_DAT,
5.         output oTrig,
6.         output [7:0]oData,
7.         output [2:0]oTag
8.    );

以上內容為出入端宣告。

9.    
10.         parameter LSHIFT = 8'h12, LCTRL = 8'h14, LALT = 8'h11, BREAK = 8'hF0;
11.         parameter FF_Read= 5'd5;
12.    
13.         /*******************************/ // sub1
14.         
15.        reg F2,F1; 
16.         
17.        always @ ( posedge CLOCK or negedge RESET )
18.             if( !RESET )
19.                  { F2,F1 } <= 2'b11;
20.              else
21.                  { F2, F1 } <= { F1, PS2_CLK };
22.    
23.         /*******************************/ // core
24.         
25.         wire isH2L = ( F2 == 1'b1 && F1 == 1'b0 );

以上內容為常量宣告,周邊操作以及即時宣告。第10行是 LSHIFT,LCTRl 還有 LALT 等通碼的常量宣告。此外也有 BREAK 斷碼第一幀資料,還有偽函式的入口(第11行)。第15~21行是用來檢測電平變化的周邊操作,第25行則是下降沿的即時宣告。

26.         reg [7:0]D1;
27.         reg [2:0]isTag;  // [2] isShift, [1] isCtrl, [0] isAlt
28.         reg [4:0]i,Go;
29.         reg isDone;
30.         
31.         always @ ( posedge CLOCK or negedge RESET )
32.             if( !RESET )
33.                  begin
34.                         D1 <= 8'd0;
35.                         isTag <= 3'd0;
36.                         i <= 5'd0;
37.                         Go <= 5'd0;
38.                         isDone <= 1'b0;
39.                    end
40.               else

以上內容是相關的暫存器宣告以及復位操作。期間 isTag是狀態暫存器,isTag[2] 標示 isShift,isTag[1] 標示 isCtrl,isTag[0] 標示 isAlt。第33~38行則是這番暫存器的復位操作。

65.                          /****************/ // PS2 Read Function
66.                          
67.                          5:  // Start bit
68.                          if( isH2L ) i <= i + 1'b1; 
69.                          
70.                          6,7,8,9,10,11,12,13:  // Data byte
71.                          if( isH2L ) begin i <= i + 1'b1; D1[ i-6 ] <= PS2_DAT; end
72.                          
73.                          14: // Parity bit
74.                          if( isH2L ) i <= i + 1'b1;
75.                          
76.                          15: // Stop bit
77.                          if( isH2L ) i <= Go;
78.                            
79.                     endcase

以上內容為部分核心操作的偽函式。該偽函式讀取PS/2的1幀資料。

41.                    case( i )
42.                          
43.                          0: // Read Make
44.                          begin i <= FF_Read; Go <= i + 1'b1; end
45.                          
46.                          1: // Set Flag
47.                          if( D1 == LSHIFT ) begin isTag[2] <= 1'b1; D1 <= 8'd0; i <= 5'd0;end
48.                          else if( D1 == LCTRL ) begin isTag[1] <= 1'b1; D1 <= 8'd0; i <= 5'd0; end
49.                          else if( D1 == LALT ) begin isTag[0] <= 1'b1; D1 <= 8'd0; i <= 5'd0; end
50.                          else if( D1 == BREAK ) begin i <= FF_Read; Go <= i + 5'd3; end
51.                          else begin i <= i + 1'b1; end
52.                          
53.                          2:
54.                          begin isDone <= 1'b1; i <= i + 1'b1; end
55.                          
56.                          3:
57.                          begin isDone <= 1'b0; i <= 5'd0; end
58.                          
59.                          4: // Clear Flag
60.                          if( D1 == LSHIFT  ) begin isTag[2] <= 1'b0; D1 <= 8'd0; i <= 5'd0;  end
61.                          else if( D1 == LCTRL ) begin isTag[1] <= 1'b0; D1 <= 8'd0; i <= 5'd0; end
62.                          else if( D1 == LALT ) begin isTag[0] <= 1'b0; D1 <= 8'd0; i <= 5'd0;  end
63.                          else begin D1 <= 8'd0; i <= 5'd0; end

以上內容是核心操作,操作的過程如下:

步驟0,進入偽函式等待讀取通碼,並且Go指向下一個步驟。

步驟1,檢測組合鍵與斷碼,如果是LShift 那麼isTag[2]立旗,然後返回步驟0;如果是 LCTRL 那麼 isTag[1] 立旗,然後返回步驟0;如果是 LALT 那麼 isTag[0] 立旗,然後返回步驟0。如果是 BREAK便進入偽函式,然後Go指向步驟4。如果什麼都不是便進入步驟2~3。

步驟2~3,產生完成訊號,然後返回步驟0。

步驟4,用來消除立旗狀態。步驟1為 BREAK便會進入這裡,如果斷碼為 LSHIFT便會消除 isTag[2],LCTRL消除 isTag[1],LALT 消除 isTag[0],無視其它斷碼。最後返回步驟0。

80.         
81.         assign oTrig = isDone;
82.         assign oData = D1;
83.         assign oTag = isTag;
84.        
85.    endmodule

第81~83行是輸出驅動宣告。

ps2_demo.v

筆者在此就不再重複貼上建模圖了,請自行復習圖8.10。

1.    module ps2_demo
2.    (
3.         input CLOCK, RESET,
4.         input PS2_CLK, PS2_DAT,
5.         output [7:0]DIG,
6.         output [5:0]SEL
7.    );
8.         wire [7:0]DataU1;
9.         wire [2:0]TagU1;
10.    
11.         ps2_funcmod U1
12.         (
13.              .CLOCK( CLOCK ),
14.              .RESET( RESET ),
15.              .PS2_CLK( PS2_CLK ), // < top
16.              .PS2_DAT( PS2_DAT ), // < top
17.              .oTrig(),
18.              .oData( DataU1 ),  // > U2
19.              .oTag( TagU1 ) // > U2
20.         );
21.         
22.       smg_basemod U2
23.        (
24.            .CLOCK( CLOCK ),
25.            .RESET( RESET ),
26.            .DIG( DIG ),  // > top
27.            .SEL( SEL ),  // > top
28.            .iData( { 12'h000 , 1'b0, TagU1, DataU1 } ) // < U1
29.        );
30.                 
31.    endmodule

基本上,ps2_demo 的內容並沒有什麼難度,所有連線部署都按照圖8.10。至於第28行,DataU1還有 TagU1聯合驅動數碼管基礎模組的iData。換句話說,無視數碼管的1~3位,第4位數碼管顯示組合鍵狀態,第5~6位數碼管則顯示通碼。

編譯完後便下載程式。如果同時按下 <LShift> + <LCtrl> + <LAlt>,第4位數碼管便會顯示 4’h7,亦即 4’b0111,或者說 isTag[2..0] 皆為立旗狀態。如果按下其它按鍵,如 <A>,那麼第5~6位的數碼管便會顯示 8’h1C。假設釋放 <LShift>,第4位數碼管便會顯示4’h3,亦即 4’b0011,或者說 isTag[1..0] 皆為立旗狀態。釋放 <A>,第5~6位數碼管則會顯示 8’h00。

細節一:完整的個體模組

clip_image024

圖8.12 PS/2鍵盤功能模組。

圖8.12是PS/2鍵盤功能模組,內容基本上與PS/2功能模組一模一樣,至於區別就是穿上其它馬甲而已,所以怒筆者不再重複貼上了。

相關推薦

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

實驗八:PS/2模組② — 鍵盤與組合鍵 實驗七之際,我們學習如何讀取PS/2鍵盤傳送過來的通碼與斷碼,不過實驗內容也是一鍵按下然後釋放,簡單按鍵行為而已。然而,實驗八的實驗內容卻是學習組合鍵的按鍵行為。 不知讀者是否有類似的經歷?當我們使用鍵盤的時候,如果5~6按鍵同時按下,電腦隨之便會發出“嗶嗶”的警

黑金原創教程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作為一介儲存資源(儲存器),它的好處就是大容量空間,壞處則就是麻煩的控制規