【正文】
039。039。039。039。039。039。039。039。039。039。039。039。039。data=x01。data=x0e。 if cp5039。 process(clk) begin if (clk39。 when 0011 =d=x33。 when 0101 =c=x35。 when 0111 =b=x37。 when 1001 =a=x39。139。 data_ascii:in std_logic_vector(7 downto 0)。 when01=sg=b。 end process。 when 0010 =d=1011011。 when 0100 =c=1100110。 when 0110 =b=1111101。 when 1000 =a=1111111。event and clk=39。 entity leddisp is port(rst:in std_logic。 end if。 else conv_std_logic_vector(tmpAscii,8)when duanma=39。139。139。139。139。139。)else capslocked。 end ponent。 signal duanma_D:std_logic:=39。 end if。139。 end if。 datascan:out std_logic_vector(7 downto 0)。這四個(gè)功能的設(shè)計(jì),基本上涵蓋了平時(shí)講課的大部分內(nèi)容 。當(dāng)時(shí)鐘到來時(shí),我們要決定是送指令還是數(shù)據(jù),是讀還是寫,還要送入相應(yīng)的指令或數(shù)據(jù)信息。如果我們都一一轉(zhuǎn)換的話會(huì)出錯(cuò)。當(dāng)檢測(cè)到有這兩個(gè)按鍵按下時(shí),就把相應(yīng)的 Shifted_D 或 Capslocked_D 置為 1,然后再通過 D觸發(fā)器把這兩個(gè)鍵的狀態(tài)鎖存起來。 擴(kuò)展按鍵的斷碼通常有三個(gè)字節(jié),它們前兩個(gè)字節(jié)是 E0h,F0h ,最后一個(gè)字節(jié)是這個(gè)按鍵通碼的最后一個(gè)字節(jié)。 每當(dāng)有按鍵按下或彈起時(shí)鍵盤都會(huì)發(fā)出一幀或幾幀數(shù)據(jù),每一幀數(shù)據(jù)一共都 2 12 位,其數(shù)據(jù)格式如下表所示: 1個(gè)起始位 總是邏輯 0 8個(gè)數(shù)據(jù)位 ( LSB)低位在前 1 個(gè)奇偶校驗(yàn)位 奇校驗(yàn) 1個(gè)停止位 總是邏輯 1 1個(gè)應(yīng)答位 僅用在主機(jī)對(duì)設(shè)備的通訊中 從鍵盤發(fā)出的數(shù)據(jù)是在時(shí)鐘信號(hào)的下降沿的時(shí)候才被讀取, FPGA 要想接收到鍵盤發(fā)出的數(shù)據(jù)就要配合 PS2 的時(shí)序 。具體設(shè)計(jì)思路如下: 首先我們來定義幾個(gè)端口。 鍵盤每個(gè)按鍵被分配了唯一的通碼和斷碼。鎖存后為 Shifted 和 Capslocked。注意到如果我們?cè)凇?F0”掃描碼到來時(shí)才進(jìn)行轉(zhuǎn)換就可以 解決問題了。 根據(jù)要求,我們要在上面一行顯示 “ Scancode: **”,第二行顯示:“ ASCIIcode:**”。 對(duì)我們 來說這是一次很好的鍛煉機(jī)會(huì),也使我們對(duì)實(shí)際系統(tǒng)的設(shè)計(jì)掌握了一定的經(jīng)驗(yàn), 提升了我們對(duì)這門課的理解, 同時(shí) 培養(yǎng)了我們編程和寫論文的能力。 interrupt1:out std_logic)。 end process。datascan=tmpdata(8 downto 1)。 end process。039。 begin duanma_D=39。 tmpAscii= 1609 when scan=00001101 else 1660 when scan=00001110 and shifted=39。 else 1633 when scan=00100101 and shifted=39。 else 1638 when scan=00111110 and shifted=39。 else 162E when scan=01001001 and shifted=39。 else 1627 when scan=01010010 and shifted=39。 else 165C when scan=01011101 and shifted=39。139。 end if。 enabl:in std_logic。139。 when 1001 =a=1101111。 when 0111 =b=0100111。 when 0101 =c=1101101。 when 0011 =d=1001111。 process(enabl,clk) begin if(rst=39。 when10=sg=c。 data:out std_logic_vector(7 downto 0)。)then data_scan_h=data_scan(7 downto 4)。 when 1010 =a=x41。 when 1000 =b=x38。 when 0110 =c=x36。 when 0100 =d=x34。event and clk=39。event and cp50=39。 end if。 end if。data=x80。data=x63。data=x6E。data=x6F。data=x65。data=a。data=xc0。data=x53。data=x49。data=x63。data=x64。data=x3A。data=d。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。rw=39。039。039。 end if。 end process。 when 0010 =d=x32。 when 0100 =c=x34。 when 0110 =b=x36。 when 1000 =a=x38。)then if(enabl=39。 data_scan:in std_logic_vector(7 downto 0)。)then case t is when00=sg=a。 end case。 when 0001 =d=0110000。 when 0011 =c=1001111。 when 0101 =b=1101101。 when 0111 =a=0100111。)then if(clk39。 use 。 end if。139。 else 167D when scan=01011011 and shifted=39。 else 165F when scan=01001110 and shifted=39。 else 1628 when scan=01000110 and shifted=39。 else 1626 when scan=00111101 and shifted=39。 else 1624 when scan=00100101 and shifted=39。139。 q:out std_logic)。 signal ASCII:std_logic_vector(7 downto 0)。)then tmp=d。)then interrupt1=39。 end if。 rst:in std_logic。頂層文件設(shè)計(jì)完成后,整體編譯一遍, 然后進(jìn)行 RTL 級(jí)仿真,便得到如下所示的硬件連接電路: 結(jié)束 語 本次的 PS2 鍵盤接口設(shè)計(jì),總的來說,實(shí)現(xiàn)了 4 大功能: 1,用 FPGA 控制PS2 鍵盤接口,接收鍵盤發(fā)出的掃描碼數(shù)據(jù) ASCII碼 ASCII 碼顯示在數(shù)碼管上 ASCII 碼顯示在 LCD 液晶上。 LCD 接收數(shù)據(jù)有它對(duì)應(yīng)的時(shí)鐘,這個(gè)我們可以通過分頻產(chǎn)生。我們接收到這么些掃描碼,而我們要輸出的 ASCII 碼應(yīng)該為 61( A為小寫時(shí))和 41( A為大寫時(shí))。為了判斷組合鍵有沒有按下,我們?cè)O(shè)計(jì)幾個(gè)觸發(fā)器來保存上一個(gè)時(shí)鐘的特殊組合鍵的狀態(tài),以便后來的 ASCII 碼轉(zhuǎn)換。它們的 3 第一個(gè)字節(jié)是 F0 ,第二個(gè)字節(jié)是這個(gè)鍵的通碼。 PS2 鍵盤接口是 6 芯的插頭,各插 頭定義如下: 1 DATA Key Data 2 n/c Not connected 3 GND Gnd 4 VCC Power , +5 VDC 5 CLK Clock 6 n/c Not connected 在 PS2 的 6個(gè)芯中, 2和 6未定義, 3 和 4 為電源和地,需要用 FPGA 控制的只有 1(數(shù)據(jù))和 5(時(shí)鐘)。首先要有數(shù)據(jù)輸入端口 K_DATA 和鍵盤時(shí)鐘K_CLOCK。這樣,我們通過查找唯一的通碼和斷碼就可以確定按下的是哪一個(gè)鍵。判斷這兩個(gè)鍵按下的依據(jù)是判斷掃描碼的值,若掃描碼的值 對(duì)應(yīng)的是這兩個(gè)按鍵,就可以把相應(yīng)的鍵的狀態(tài)置 1。因此,在轉(zhuǎn)換前先判斷掃描碼是不是為 F0,若是的話就代表斷碼到來了,這時(shí)把定義好的 DUANMA_D 置 1,否則置 0,再把它鎖入鎖存器,輸出為 DUANMA,在進(jìn)行 ASCII 碼轉(zhuǎn)換時(shí),我們都把 DUANMA 等于 1作為轉(zhuǎn)換的一個(gè)條件,這樣就可以得到正確的 ASCII 碼值了。 在 顯示這些字符 之前,必須先做以下準(zhǔn)備: 1 3.清屏 ( 這里用 5*7顯示模式 ) 。 回想自己所設(shè)計(jì)的程序, 里面還有很多瑕疵,比如顯示掃描碼時(shí)部分,每顯示一個(gè)鍵需要接收至少 3 個(gè)字節(jié)(按下時(shí)鍵盤發(fā)出一個(gè)字節(jié)的通碼,彈起時(shí)發(fā)送兩個(gè)字節(jié)的斷碼)的數(shù)據(jù),比如顯示大寫字母 A 的一串掃描碼為 12, 1C, F0,1C, F0, 12。 end keyboard。 7 process(count) begin if(count=10)then flag=39。 end if。 q=tmp。 signal shifted_D:std_logic:=39。139。039。039。039。039。039。039。 else 10000000。 end process。 clk:in std_logic。)then data_scan_h=data_sca