《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第15章_第1頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第15章_第2頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第15章_第3頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第15章_第4頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第15章_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第十五章PicoBlaze接口開發(fā)15.1輸出端口15.2輸入端口15.3求平方和電路接口開發(fā)本章小結(jié)15.1輸出端口15.1.1輸出指令和時(shí)序輸出指令output寫數(shù)據(jù)到輸出端口。它有兩種格式:

outputsX,(sY) outputsX,端口名稱

第一種格式,端口的id存儲(chǔ)在sY寄存器中;第二種格式,端口名稱特指端口的id號(hào),它可以是兩位的十六進(jìn)制數(shù)或者預(yù)定義的符號(hào)常量。輸出數(shù)據(jù)通常存儲(chǔ)在sX寄存器中。如圖15-1所示是輸出指令為“outputs0,02”的時(shí)序圖。PicoBlaze指令執(zhí)行時(shí)間為兩個(gè)時(shí)鐘周期,指令執(zhí)行時(shí),s0內(nèi)容輸出到輸出端口以及02輸出到端口id,一共需要兩個(gè)時(shí)鐘周期。write_strobe信號(hào)在第二個(gè)時(shí)鐘周期有效,它可以作為存儲(chǔ)輸出寄存器的使能信號(hào)或者用來初始化指定接口操作。圖15-1輸出指令時(shí)序圖15.1.2輸出接口

PicoBlaze與輸出外設(shè)之間的接口通常由譯碼電路和輸出緩沖器組成。譯碼電路針對(duì)端口id號(hào)譯碼并產(chǎn)生相對(duì)應(yīng)的使能信號(hào)。在output指令執(zhí)行后,數(shù)據(jù)存儲(chǔ)到相應(yīng)的緩沖器當(dāng)中。為了理解輸出接口的電路結(jié)構(gòu),假設(shè)PicoBlaze接口包含四個(gè)輸出緩沖器,輸出端口id號(hào)分別定義為0016、0116、0216、0316。注意:端口地址的高六位都是一樣的,只是通過低兩位來區(qū)別不同的端口。電路的結(jié)構(gòu)框圖如圖15-2所示。電路的關(guān)鍵部分是譯碼電路,其真值表如表15-1所示。譯碼電路為一個(gè)2-4譯碼器,在輸出指令的第二個(gè)時(shí)鐘周期,write_strobe信號(hào)有效,并且四位en_d信號(hào)中有一位有效。僅僅一個(gè)時(shí)鐘周期的使能信號(hào)能激活對(duì)應(yīng)輸出寄存器從輸出端口接收數(shù)據(jù)。輸出指令為“outputs0,02”的譯碼指令時(shí)序如圖15-1所示,在輸出指令執(zhí)行的第二個(gè)時(shí)鐘周期,en_d[2]信號(hào)有效,輸出端口數(shù)據(jù)在下一個(gè)時(shí)鐘上升沿存儲(chǔ)到對(duì)應(yīng)的數(shù)據(jù)緩沖器中。圖15-2電路的結(jié)構(gòu)框圖一旦理解了基本的操作,便可以設(shè)計(jì),HDL代碼如下:

always@*

if(write_strobe)

case(port_id[1:0])

2'b00:en_d=4'b0001;

2'b01:en_d=4'b0010;

2'b10:en_d=4'b0100;

2'b11:en_d=4'b1000;

endcase

else

en_d=4'b0000;

以上解決方法可以應(yīng)用在任何輸出端口。有時(shí)要求編口地址可改變??梢栽谇懊娴睦又惺褂枚M(jìn)制編碼。如果輸出端口地址小于8,則可以用一位熱碼簡(jiǎn)化譯碼電路。比如,可以定義4個(gè)端口id為:0116(000000012)、0216(000000102)、0416(000001002)和0816(000010002),這時(shí)譯碼邏輯被簡(jiǎn)化為

always@*

if(write_strobe)

en_d=port_id[3:0];

else

en_d=4'b0000;需要注意的是,如果只有一個(gè)輸出端口,那么無需譯碼邏輯。write_strobe信號(hào)可以直接連接在寄存器使能信號(hào)上。

采用偽代碼表示I/O口在代碼中對(duì)應(yīng)的復(fù)雜設(shè)計(jì)非常有用。在文件開頭聲明二進(jìn)制地址,例如,初始化輸出地址可以聲明如下:

;-----------------------------輸出端口定義----------------------------

constantout_port_a,00

constantout_port_b,01

constantout_port_c,02

constantout_port_d,03

如果賦值改變,則僅需要修改文件頭。清晰的文件頭往往在開發(fā)HDL代碼時(shí)用于端口id號(hào)分辨。 15.2輸入端口

15.2.1輸入指令和時(shí)序

輸入指令input從輸入端口讀回?cái)?shù)據(jù)。與輸出指令相似,輸入指令也有兩種格式:

inputsX,(sY);

inputsX,端口名稱

其中,sY寄存器或者端口名稱表示端口id號(hào)。接收回來的數(shù)據(jù)保存在sX寄存器中。輸入指令為“inputs0,02”的時(shí)序圖如圖15-3所示。當(dāng)指令執(zhí)行時(shí),02輸出到端口id,兩個(gè)時(shí)鐘周期后,輸入端口數(shù)據(jù)在時(shí)鐘上升沿時(shí)被采樣并存儲(chǔ)到s0寄存器,外部電路必須確保在采樣期間輸入數(shù)據(jù)穩(wěn)定,以防數(shù)據(jù)采集錯(cuò)誤。

與輸出指令相同,read_strobe信號(hào)在第二個(gè)時(shí)鐘周期有效。read_strobe信號(hào)的功能與write_strobe的相似,在15.3節(jié)將詳細(xì)介紹。圖15-3輸入指令接口時(shí)序15.2.2輸入接口

PicoBlaze與輸入外設(shè)之間的接口通常需要一個(gè)多路選擇電路,根據(jù)port_id選擇相應(yīng)的值送往in_port。有時(shí)還需要類似于輸出接口的譯碼電路,它在輸入接口中用于數(shù)據(jù)獲取。

在輸入接口電路中,輸入端口經(jīng)常被分成連續(xù)存取端口和單次存取端口兩種。對(duì)于連續(xù)存取端口,數(shù)據(jù)不斷產(chǎn)生,如14.3.2節(jié)的撥碼開關(guān)輸入;對(duì)于單次存取端口,輸入端口輸入數(shù)據(jù)操作由單個(gè)不連續(xù)事件觸發(fā)。比如,從UART數(shù)據(jù)緩沖器讀取一個(gè)字符,當(dāng)獲取數(shù)據(jù)時(shí),必須將其從緩沖區(qū)移除,以免該數(shù)據(jù)被重新處理。通常采用一個(gè)時(shí)鐘周期的脈沖來清除寄存器標(biāo)志或者從FIFO緩沖器移除一個(gè)數(shù)據(jù)單元。連續(xù)讀取端口的接口電路僅包含一個(gè)多路選擇電路。如圖15-4所示為包含四個(gè)端口的連續(xù)讀取端口電路。

單次讀取端口電路接口在input指令執(zhí)行結(jié)束時(shí),需要一個(gè)從緩沖區(qū)“移除”接收數(shù)據(jù)的機(jī)制。這時(shí)可以采用譯碼電路,根據(jù)端口id號(hào)與read_strobe信號(hào)進(jìn)行譯碼。與輸出接口的譯碼電路結(jié)構(gòu)一樣,僅僅是將write_strobe信號(hào)替換成了read_strobe信號(hào)。譯碼輸出信號(hào)可以認(rèn)為是“移除”信號(hào),在一個(gè)有效時(shí)鐘周期內(nèi)“移除”讀取的數(shù)據(jù)。如圖15-5所示為接口帶有FIFO的譯碼和多路選擇電路。圖15-4四路持續(xù)讀取端口框圖圖15-5四輸入單次讀取端口框圖

rv信號(hào)為譯碼移除信號(hào),在input指令執(zhí)行結(jié)束時(shí),四位信號(hào)中選擇一位并使對(duì)應(yīng)的FIFO執(zhí)行一次讀操作,從緩沖區(qū)“移除”一個(gè)數(shù)據(jù)單元。如果定義0016、0116、0216、0316作為端口id,則接口代碼如下:

//多路選擇電路

always@*

case(port_id[1:0])

2'b00:data=in_data0;

2'b01:data=in_data1;

2'b10:data=in_data2;

2'b11:data=in_data3;

endcase

//譯碼電路

always@*

if(read_strobe)

case(port_id[1:0])

2'b00:rv=4'b0001;

2'b01:rv=4'b0010;

2'b10:rv=4'b0100;

2'b11:rv=4'b1000;

endcase

else

rv=4'b0000;

15.3求平方和電路接口開發(fā)

15.3.1輸出接口

在驗(yàn)證板上4個(gè)七段數(shù)碼管數(shù)據(jù)顯示端口共享同樣的輸入管腳,所以需要一個(gè)動(dòng)態(tài)掃描電路來完成數(shù)碼管的動(dòng)態(tài)顯示。對(duì)于基于PicoBlaze的設(shè)計(jì)來說,設(shè)計(jì)動(dòng)態(tài)掃描電路可以通過軟件來實(shí)現(xiàn),也可以在微處理器外設(shè)接口電路中實(shí)現(xiàn)。選用外設(shè)接口電路的方法來實(shí)現(xiàn),相對(duì)于匯編語言開發(fā)要簡(jiǎn)單一些,而且前面設(shè)計(jì)的動(dòng)態(tài)掃描電路也可以直接搬用。若電路不考慮所有時(shí)序信息,那么對(duì)于外部系統(tǒng)來說,就是四個(gè)獨(dú)立的七段數(shù)碼管。PicoBlaze輸出接口的框圖如圖15-6所示,接口包含4個(gè)八位的輸出端口,每個(gè)端口代表一個(gè)七段數(shù)碼管。圖15-6求平方和電路輸出接口

在匯編代碼中,4個(gè)LED數(shù)據(jù)存儲(chǔ)在PicoBlaze中并以地址偽代碼命名為led0、led1、led2和led3的數(shù)據(jù)RAM中,對(duì)應(yīng)的代碼為

;數(shù)據(jù)RAM地址偽代碼

constantled0,10

constantled1,11

constantled2,12

constantled3,13

;輸出端口定義

constantsseg0_port,00 ;七段數(shù)碼管led0

constantsseg1_port,01 ;七段數(shù)碼管led1

constantsseg2_port,02 ;七段數(shù)碼管led2

constantsseg3_port,03 ;七段數(shù)碼管led3

disp_led:

fetchdata,led0

outputdata,sseg0_port

fetchdata,led1

outputdata,sseg1_port

fetchdata,led2

outputdata,sseg2_port

fetchdata,led3

outputdata,sseg3_port

return

15.3.2輸入接口

輸入接口包含一個(gè)8位的撥碼開關(guān)和兩個(gè)1位的按鍵。前者由于其輸入值一直存在,所以為連續(xù)讀入端口;后者由于每次按鍵僅觸發(fā)一次單獨(dú)操作,所以為單次存儲(chǔ)電路。由于機(jī)械按鍵存在抖動(dòng),所以按鍵信號(hào)需要經(jīng)過按鍵防抖動(dòng)電路,變成一個(gè)干凈的單時(shí)鐘脈沖信號(hào)。由于PicoBlaze端口為8位數(shù)據(jù),所以輸入的兩位按鍵信號(hào)可以打包成一個(gè)輸入端口輸入。輸入接口的框圖如圖15-7所示。圖15-7求平方電路輸入接口框圖

接口包括兩個(gè)防抖動(dòng)電路、一個(gè)2選1選擇器、一個(gè)譯碼電路和兩個(gè)觸發(fā)器。兩個(gè)觸發(fā)器提供了設(shè)置和清零按鍵功能,當(dāng)按鈕按下時(shí),防抖動(dòng)電路輸出標(biāo)志設(shè)置有效,一直等到input指令執(zhí)行。設(shè)置選擇器的選擇信號(hào)使得數(shù)據(jù)到達(dá)PicoBlaze的輸入端口,并觸發(fā)清零信號(hào)。為了描述清楚,定義按鍵1為s按鍵,用來設(shè)置值;而按鍵0定義為c按鍵,用來對(duì)數(shù)據(jù)RAM清零。其處理過程可以用下面的偽代碼描述:

;輸入按鍵標(biāo)志

ifc=1then

;調(diào)用數(shù)據(jù)RAM清零電路

ifs=1then

;輸入撥碼開關(guān)值

;存儲(chǔ)到數(shù)據(jù)RAM當(dāng)中由于s按鍵輸入值a和b可選,因而采用一個(gè)全局寄存器switch_a_b追蹤當(dāng)前讀入值為a還是b。這個(gè)寄存器還作為數(shù)據(jù)RAM地址的偏移地址,其值可以為0或者2。當(dāng)s按鍵按下時(shí)鎖存該值。對(duì)應(yīng)的匯編代碼子程序?yàn)?/p>

;------------輸入端口定義---------------------

constantrd_flag_port,00 ;?2位標(biāo)志位(xxxxxxsc)

constantsw_port,01 ;?8位輸入撥碼開關(guān)

...

proc_btn:

inputs3,rd_flag_port ;獲取標(biāo)志

;檢查和處理按鍵c

tests3,01 ;檢查按鍵c標(biāo)志位

jumpz,chk_btns ;標(biāo)志未設(shè)置

callinit ;標(biāo)志已設(shè)置,執(zhí)行初始化程序

jumpproc_btn_done

chk_btns:

;檢查和處理按鍵s

tests3,02 ;檢查按鍵s標(biāo)志位

jump

z,proc_btn_done ;標(biāo)志位未設(shè)置

inputdata,sw_port ;獲取撥碼開關(guān)值

loadaddr,a_lsb ;獲取地址a

addaddr,switch_a_b ;?a地址與偏移地址相加

storedata,(addr) ;寫數(shù)據(jù)到RAM當(dāng)中

;更新當(dāng)前顯示位置

xorswitch_a_b,02 ;?switch_a_b在00和02之間變化

proc_btn_done:

return

15.3.3匯編程序設(shè)計(jì)

設(shè)計(jì)好I/O接口之后,可以開始設(shè)計(jì)匯編程序。按照第十四章介紹的逐個(gè)攻克法將主程序劃分成若干個(gè)子程序。主程序如下:

callinit ;初始化程序

forever:

;mainloopbody

callproc_btn ;檢查和處理按鍵

callsquare ;計(jì)算平方值

callload_led_pttn ;存儲(chǔ)LED顯示模式值到RAM中

calldisp_led ;輸出LED顯示模式值

jumpforever求平方和子程序來自于第十四章我們?cè)瓉淼脑O(shè)計(jì)。proc_btn和disp_led子程序在前面的章節(jié)中討論過。init子程序執(zhí)行系統(tǒng)初始化,其作用是用循環(huán)寫0的方式清零RAM并且設(shè)置switch_a_b寄存器為0(讀a)。load_led_pttn子程序讀切換輸入,首先從數(shù)據(jù)RAM獲取需要的值并轉(zhuǎn)換成七段數(shù)碼管可識(shí)別的格式,然后存儲(chǔ)到對(duì)應(yīng)的數(shù)據(jù)RAM中。disp_led子程序?qū)@示值寫到輸出端口上。load_led_pttn子程序包含get_upper_nibble和get_lower_nibble兩個(gè)子程序,用來提取2個(gè)四位十六進(jìn)制數(shù),hex_to_led子程序?qū)⑹M(jìn)制數(shù)轉(zhuǎn)換成七段數(shù)碼管顯示格式。

程序中所用到的寄存器比較多。除了平方和子程序需要數(shù)據(jù)存儲(chǔ)器之外,還有一個(gè)全局寄存器switch_a_b追蹤讀取a還是b的值。另外,還有4B的RAM用來存儲(chǔ)4個(gè)七段數(shù)碼管的顯示值,分別用led0、led1、led2和led3表示。

【程序15-1】求平方和子程序。

;===============================================

;帶七段數(shù)碼管接口的平方和電路

;===============================================

;程序功能:

;從撥碼開關(guān)讀取a和b的值

;計(jì)算a?×?a+b?×?b的結(jié)果

;顯示結(jié)果在七段數(shù)碼管上

;===============================================

;數(shù)據(jù)RAM地址定義

;===============================================

constanta_lsb,00

constantb_lsb,02

constantaa_lsb,04

constantaa_msb,05

constantbb_lsb,06

constantbb_msb,07

constantaabb_lsb,08

constantaabb_msb,09

constantaabb_cout,0A

constantled0,10

constantled1,11

constantled2,12

constantled3,13

;=============================================

;定義寄存器

;=============================================

;通用邏輯變量

nameregs0,data ;臨時(shí)數(shù)據(jù)寄存器

nameregs1,addr ;臨時(shí)存儲(chǔ)器或者I/O端口地址

nameregs2,i ;循環(huán)變量索引

;全局變量

nameregsf,switch_a_b;當(dāng)前開關(guān)輸入選擇以及RAM偏移地址

;==================================================

;端口變量定義

;==================================================

;------------輸入端口定義---------------------

constantrd_flag_port,00 ;?2位標(biāo)志位

constantsw_port,01 ;?8位撥碼開關(guān)

;------------輸出端口定義---------------------

constantsseg0_port,00 ;?led0

constantsseg1_port,01 ;?led1

constantsseg2_port,02 ;?led2

constantsseg3_port,03 ;?led3

;==============================================

;主程序

;==============================================

callinit ;程序初始化

forever:

;主程序循環(huán)體

callproc_btn ;檢查和處理按鍵

callsquare ;計(jì)算平方和

callload_led_pttn ;存儲(chǔ)顯示值到RAM中

calldisp_led ;顯示LED顯示值

jumpforever

;==============================================

;子程序名:init

;程序功能:執(zhí)行初始化并清零寄存器和RAM,并對(duì)switch_a_b清零

;臨時(shí)寄存器:data,i

;==================================================

init:

;清零寄存器

loadi,40 ;循環(huán)索引值為64

loaddata,00

clr_mem_loop:

storedata,(i)

subi,01 ;循環(huán)減1

jump

nz,clr_mem_loop ;重復(fù),直到i=0

;清零寄存器

loadswitch_a_b,00

return

;================================================

;子程序名:proc_btn

;程序功能:檢查兩個(gè)按鍵并處理顯示

;輸入寄存器:switch_a_b:ram地址偏移(a為0,b為2)

;輸出寄存器:s3:存儲(chǔ)輸入端口id

;臨時(shí)寄存器:data,addr

;================================================

proc_btn:

inputs3,rd_flag_port`` ;獲取標(biāo)志

;檢查和處理按鍵c

tests3,01 ;檢查按鍵c標(biāo)志位

jumpz,chk_btns ;標(biāo)志未設(shè)置

callinit ;標(biāo)志已設(shè)置,執(zhí)行初始化程序

jumpproc_btn_done

chk_btns:

;檢查和處理按鍵s

tests3,02 ;檢查按鍵s標(biāo)志位

jump

z,proc_btn_done ;標(biāo)志位未設(shè)置

inputdata,sw_port ;獲取撥碼開關(guān)值

loadaddr,a_lsb ;獲取地址a

addaddr,switch_a_b ;?a地址與偏移地址相加

storedata,(addr) ;寫數(shù)據(jù)到RAM中

;更新當(dāng)前顯示位置

xorswitch_a_b,02 ;?switch_a_b在00和02之間變化

proc_btn_done:

return

;================================================

;子程序名:load_led_pttn

;程序功能:讀取撥碼開關(guān)低三位輸入并將對(duì)應(yīng)顯示值轉(zhuǎn)換成數(shù)碼管顯示形式,裝

載到RAM中

;撥碼開關(guān)輸入譯碼值:000:a;001:b;010:a^2;011:b^2;其他a^2+b^2

;臨時(shí)寄存器:data,addr

;s6:從sw輸入數(shù)據(jù)

;================================================

load_led_pttn:

inputs6,sw_port ;獲取撥碼開關(guān)輸入

sl0s6 ;?s6內(nèi)容右移一位,獲取地址偏移值

compares6,08 ;判斷sw是否大于100

jumpc,sw_ok ;否

loads6,08 ;是,sw出錯(cuò),按默認(rèn)執(zhí)行sw_ok:

;處理字0節(jié)低四位

loadaddr,a_lsb

addaddr,s6 ;獲取低地址

fetchdata,(s6) ;獲取低字節(jié)

callget_lower_nibble ;獲取低4位

callhex_to_led ;轉(zhuǎn)換成led顯示模式

storedata,led0

;處理0字節(jié)高四位

fetchdata,(addr)

callget_upper_nibble

callhex_to_led

storedata,led1

;處理1字節(jié)低四位

addaddr,01 ;獲取高地址

fetchdata,(addr)

callget_lower_nibble

callhex_to_led

storedata,led2

;處理1字節(jié)高四位

fetchdata,(addr)

callget_upper_nibble

callhex_to_led

;檢查sw是否等于100來處理led小數(shù)點(diǎn)的進(jìn)位

compares6,08 ;是否顯示最終結(jié)果

jump

nz,led_done ;否

addaddr,01 ;獲取進(jìn)位地址

fetchs6,(addr) ;寄存器存儲(chǔ)進(jìn)位

tests6,01 ;測(cè)試進(jìn)位寄存器是否為1

jump

z,led_done ;否

anddata,7F ;是,賦值最高位(dp)為0

led_done:

storedata,led3

return

;=================================================

;子程序:disp_led

;功能:輸出四位led顯示值

;臨時(shí)寄存器:data

;==============================================

disp_led:

fetchdata,led0

outputdata,sseg0_port

fetchdata,led1

outputdata,sseg1_port

fetchdata,led2

outputdata,sseg2_port

fetchdata,led3

outputdata,sseg3_port

return

;===============================================

;子程序:hex_to_led

;功能:轉(zhuǎn)換十六進(jìn)制數(shù)為七段數(shù)碼顯示模式

;輸入寄存器:data

;輸出寄存器:data

;================================================

hex_to_led:

comparedata,00

jumpnz,comp_hex_1

loaddata,81 ;顯示0

jumphex_done

comp_hex_1:

comparedata,01

jumpnz,comp_hex_2

loaddata,CF ;顯示1

jumphex_done

comp_hex_2:

comparedata,02

jumpnz,comp_hex_3

loaddata,92 ;顯示2

jumphex_done

comp_hex_3:

comparedata,03

jump

nz,comp_hex_4

loaddata,86 ;顯示3

jumphex_done

comp_hex_4:

comparedata,04

jump

nz,comp_hex_5

loaddata,CC ;顯示4

jumphex_done

comp_hex_5:

comparedata,05

jump

nz,comp_hex_6

loaddata,A4 ;顯示5

jumphex_done

comp_hex_6:

comparedata,06

jump

nz,comp_hex_7

loaddata,A0 ;顯示6

jumphex_done

comp_hex_7:

comparedata,07

jump

nz,comp_hex_8

loaddata,8F ;顯示7

jumphex_done

comp_hex_8:

comparedata,08

jump

nz,comp_hex_9

loaddata,80 ;顯示8

jumphex_done

comp_hex_9:

comparedata,09

jump

nz,comp_hex_a

loaddata,84 ;顯示9

jumphex_done

comp_hex_a:

comparedata,0A

jump

nz,comp_hex_b

loaddata,88 ;顯示A

jumphex_done

comp_hex_b:

comparedata,0B

jump

nz,comp_hex_c

loaddata,E0 ;顯示B

jumphex_done

comp_hex_c:

comparedata,0C

jump

nz,comp_hex_d

loaddata,B1 ;顯示C

jumphex_done

comp_hex_d:

comparedata,0D

jump

nz,comp_hex_e

loaddata,C2 ;顯示D

jumphex_done

comp_hex_e:

comparedata,0E

jump

nz,comp_hex_f

loaddata,B0 ;顯示E

jumphex_done

comp_hex_f:

loaddata,B8 ;顯示F

hex_done:

return

;====================================

;子程序:get_lower_nibble

;功能:獲取數(shù)據(jù)低4位

;輸入寄存器:data

;輸出寄存器:data

;===============================================

get_lower_nibble:

anddata,0F ;清零高4位

return

;================================================

;子程序:get_upper_nible

;子程序功能:獲取輸入數(shù)據(jù)in_data的高4位

;輸入寄存器::data

;輸出寄存器:data

;=============================================

get_upper_nibble:

sr0data ;右移四次

sr0data

sr0data

sr0data

return

;==============================================

;子程序:square

;子程序功能:計(jì)算a?×?a+b?×?b

;數(shù)據(jù)結(jié)果存儲(chǔ)的RAM開始地址為SQ_BASE_ADDR

;臨時(shí)變量:s3,s4,s5,s6,data

;=============================================

square:

;計(jì)算a?×?a

fetchs3,a_lsb ;裝載a值

fetchs4,a_lsb ;裝載a值

callmult_soft ;計(jì)算a?×?a

stores6,aa_lsb ;存儲(chǔ)a?×?a結(jié)果的低字節(jié)

stores5,aa_msb ;存儲(chǔ)a?×?a結(jié)果的高字節(jié)

;計(jì)算b?×?b

fetchs3,b_lsb ;裝載b值

fetchs4,b_lsb ;裝載b值

callmult_soft ;計(jì)算b?×?b

stores6,bb_lsb ;存儲(chǔ)b?×?b結(jié)果的低字節(jié)

stores5,bb_msb ;存儲(chǔ)b?×?b結(jié)果的高字節(jié)

;計(jì)算a?×?a+b?×?b

fetchdata,aa_lsb ;獲取a?×?a的低字節(jié)

adddata,s6 ;計(jì)算a?×?a?+?b?×?b的低字節(jié)之和

storedata,aabb_lsb ;存儲(chǔ)a?×?a?+?b?×?b的低字節(jié)

fetchdata,aa_msb ;獲取a?×?a的高字節(jié)

addcydata,s5 ;計(jì)算a?×?a?+?b?×?b的高字節(jié)之和

storedata,aabb_msb ;存儲(chǔ)a?×?a?+?b?×?b的高字節(jié)

loaddata,00 ;清零數(shù)據(jù),但是保持進(jìn)位

addcydata,00 ;獲取前一次加法的進(jìn)位值

storedata,aabb_cout ;存儲(chǔ)a?×?a?+?b?×?b的進(jìn)位值

return

;================================================

;子程序:mult_soft

;程序功能:使用移位和與操作的8位無符號(hào)乘法器

;輸入寄存器:s3—被乘數(shù);s4—乘數(shù)

;輸出寄存器:s5—乘積高字節(jié);s6—乘積低字節(jié)

;臨時(shí)寄存器:i

;================================================

mult_soft:

loads5,00 ;清零s5寄存器

loadi,08 ;初始化循環(huán)變量i

mult_loop:

sr0s4 ;移位最低位到進(jìn)位寄存器

jump

nc,shift_prod;最低位是0

adds5,s3 ;最低位是1

shift_prod:

sras5 ;右移高字節(jié),進(jìn)位寄存器移位到最高位

;最低位移位到進(jìn)位寄存器

sras6 ;右移低字節(jié)

;?s5的低位移位到s6的高位

subi,01 ;循環(huán)減

jump

nz,mult_loop;重復(fù),直到i=0

return

15.3.4HDL程序開發(fā)

完整的HDL程序包括PicoBlaze、指令ROM、輸入接口,如圖15-7所示的外設(shè)、輸出接口,以及圖15-6所示的外設(shè)等。完整的程序如程序15-2所示。

【程序15-2】接口HDL程序。

modulepico_btn

(

input

wireclk,reset,

input

wire[7:0]sw,

input

wire[1:0]btn,

output

wire[3:0]an,

output

wire[7:0]sseg

);

//信號(hào)聲明

//KCPSM3以及ROM信號(hào)

wire[9:0]address;

wire[17:0]instruction;

wire[7:0]port_id,out_port;

reg[7:0]in_port;

wirewrite_strobe,read_strobe;

//I/O端口信號(hào)

//輸出使能

reg[3:0]en_d;

//4位七段數(shù)碼管顯示

reg[7:0]ds3_reg,ds2_reg,ds1_reg,ds0_reg;

//兩個(gè)按鈕

regbtnc_flag_reg,btns_flag_reg;

wirebtnc_flag_next,btns_flag_next;

wireset_btnc_flag,set_btns_flag,clr_btn_flag;

//主體

//===========================================

//I/O模塊

//==================================================

disp_muxdisp_unit

(.clk(clk),.reset(reset),

.in3(ds3_reg),.in2(ds2_reg),.in1(ds1_reg),

.in0(ds0_reg),.an(an),.sseg(sseg));

debouncebtnc_unit

(.clk(clk),.reset(reset),.sw(btn[0]),

.db_level(),.db_tick(set_btnc_flag));

debouncebtns_unit

(.clk(clk),.reset(reset),.sw(btn[1]),

.db_level(),.db_tick(set_btns_flag));

//===========================================

//例化KCPSM和ROM模塊

//===========================================

kcpsm3proc_unit

(.clk(clk),.reset(1'b0),.address(address),

.instruction(instruction),.port_id(port_id),

.write_strobe(write_strobe),.out_port(out_port),

.read_strobe(read_strobe),.in_port(in_port),

.interrupt(1'b0),.interrupt_ack());

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論