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

下載本文檔

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

文檔簡介

第十六章PicoBlaze中斷16.1PicoBlaze中斷處理機制16.2外部中斷接口16.3軟件開發(fā)16.4設(shè)計舉例本章小結(jié)

16.1PicoBlaze中斷處理機制

16.1.1軟件中斷處理過程

與中斷相關(guān)的指令在13.2.9節(jié)中討論過。enableinterrupt和disableinterrupt指令使能和禁止中斷請求,對應(yīng)地,還有兩個返回中斷指令:returnienable和returnidisable指令,用來返回到原來的中斷點。

典型的帶有中斷服務(wù)程序流程的軟件執(zhí)行過程如圖16-1所示。它主要包括如下幾個部分:

(1)初始化enableinterrupt指令:用來允許中斷服務(wù)請求。由于中斷請求默認是禁止的,所以在初始化時需要打開。

(2)跳轉(zhuǎn)(jump)到指令存儲器最后一條指令(如3FF):跳轉(zhuǎn)到中斷服務(wù)子程序。

(3)中斷服務(wù)子程序:執(zhí)行中斷請求服務(wù),中斷服務(wù)程序必須以returni指令結(jié)束。假設(shè)正在執(zhí)行adds0,s3指令時,有外部I/O有效中斷發(fā)生,則PicoBlaze執(zhí)行中斷的步驟如下:

(1)完成當(dāng)前執(zhí)行指令;

(2)保存程序計數(shù)器內(nèi)容,清除中斷標志i(置為0),保存零標志和進位標志,程序計數(shù)器置為3FF;

(3)在3FF地址執(zhí)行jumpisr指令;

(4)執(zhí)行中斷服務(wù)子程序;

(5)執(zhí)行returni指令,恢復(fù)程序計數(shù)器和標志位;

(6)重新開始執(zhí)行subs5,01指令。圖16-1中斷流程圖16.1.2中斷時序描述

中斷程序執(zhí)行詳細的時序參數(shù)的描述如圖16-2所示。按照如圖16-2所示時序標注時間點描述基本時序如下:

(1)在t1時刻,外部中斷接口置位中斷信號,PicoBlaze此時繼續(xù)正常操作,執(zhí)行完當(dāng)前adds0,s3指令。

(2)在t2時刻,PicoBlaze發(fā)現(xiàn)有中斷信號來了,所以放棄執(zhí)行下一條指令(subs5,01),而去執(zhí)行call3FF指令。

(3)在t3時刻,PicoBlaze置位中斷響應(yīng)信號,表示要對中斷請求進行處理,同時保存subs5,01指令的地址以及清零標志和進位標志,清除中斷。

(4)在t4時刻,PicoBlaze裝載并執(zhí)行地址3FF的跳轉(zhuǎn)指令jumpisr,外部中斷接口電路響應(yīng)中斷響應(yīng)信號并撤銷中斷信號。

(5)在t5時刻,PicoBlaze開始執(zhí)行中斷服務(wù)程序。圖16-2PicoBlaze中斷時序描述圖 16.2外部中斷接口

16.2.1單個中斷請求

如果在PicoBlaze系統(tǒng)外設(shè)中僅有一個I/O接口能夠產(chǎn)生中斷請求,中斷接口電路僅需要一個標志寄存器,如圖16-3所示。當(dāng)中斷請求后,外部I/O接口電路置位中斷請求信號一個時鐘周期,置位中斷標志寄存器激活PicoBlaze的中斷輸入。如果PicoBlaze中斷允許,則它便通過置位中斷響應(yīng)信號一個時鐘周期來響應(yīng)中斷并清零中斷標志位。圖16-3單個請求中斷接口圖16.2.2多個中斷請求

在PicoBlaze系統(tǒng)中處理兩個或者多個中斷請求比較復(fù)雜。PicoBlaze必須決定處理哪個中斷請求,然后在接收中斷請求后清零對應(yīng)的中斷標志寄存器,這就需要協(xié)調(diào)硬件接口和中斷服務(wù)子程序。

帶有兩個中斷請求的中斷接口如圖16-4所示。兩個獨立的中斷請求intrequest0和intrequest1連接兩個中斷標志觸發(fā)器。中斷標志觸發(fā)器的輸出通過一個或門產(chǎn)生最終的中斷請求信號。除此之外,這兩個信號同時連接到一個2選1選擇器的輸入端。當(dāng)PicoBlaze發(fā)現(xiàn)中斷請求時,它不知道是哪個外設(shè)發(fā)出請求或者是否是兩個外設(shè)同時發(fā)出請求,中斷服務(wù)子程序必須首先輸入兩個請求信號,檢查其中斷優(yōu)先級值,然后執(zhí)行對應(yīng)的服務(wù)程序。圖16-4多個中斷請求接口圖除此之外,PicoBlaze還需要清零對應(yīng)的中斷標志觸發(fā)器。interrupt_ack信號不能直接用來清零中斷標志觸發(fā)器,因為它不知道哪一個外設(shè)請求剛才被PicoBlaze接受了。需要采用特殊的輸出邏輯譯碼電路產(chǎn)生一個清零脈沖信號clr。每個中斷標志觸發(fā)器的清零信號對應(yīng)唯一的端口id號。在中斷服務(wù)子程序中,在決定接受哪一個中斷請求后,增加一條output指令。該指令實際上并不輸出任何數(shù)據(jù),而是產(chǎn)生一個周期的脈沖信號,用來清零對應(yīng)的中斷標志觸發(fā)器。 16.3軟件開發(fā)

16.3.1中斷處理主程序

基于微處理器的應(yīng)用通常都采用下面軟件結(jié)構(gòu):

call

初始化程序

forever:

call

子程序任務(wù)1;

call

子程序任務(wù)2;

...

call

子程序任務(wù)n;

jumpforever;一些任務(wù)有可能包括I/O操作。在執(zhí)行過程中,微處理器輪流檢查I/O狀態(tài)并對應(yīng)進行處理。程序結(jié)構(gòu)執(zhí)行按照輪流循環(huán)處理的方式來操作,每個任務(wù)都在等待輪流到自己才能被執(zhí)行。如果微處理器循環(huán)周期足夠短,以至于每個I/O請求都可以被檢查并及時執(zhí)行,則這種輪換處理的方案可以正常運行。在有些應(yīng)用中,存在一到兩個需要立即執(zhí)行的請求,需要中斷機制來保證該請求得到及時處理。

由于中斷任何時候都可能發(fā)生,因而原始的輪流機制需要考慮中斷頻率并且每次中斷請求需要一定的執(zhí)行時間。如果有多個中斷請求,則服務(wù)子程序就比較復(fù)雜。16.3.2中斷服務(wù)程序

中斷服務(wù)程序和子程序相類似,它掛起正常程序執(zhí)行,先執(zhí)行一個獨立的任務(wù),然后再重新返回到原來的操作。然而,與子程序調(diào)用不同點在于中斷可以在任何時間發(fā)生,為了后來能夠返回到原來程序執(zhí)行的地方,中斷服務(wù)程序必須保存PicoBlaze處理器的當(dāng)前狀態(tài)。也就是說,中斷服務(wù)程序必須在返回正常程序流程之前保存在中斷服務(wù)子程序中所用到的臨時計算值或寄存器值。這個過程就稱為內(nèi)容交換。由于PicoBlaze是一個8位微處理器,硬件支持的前后交換和時間片輪轉(zhuǎn)功能非常有限,所以通常需要在程序中完成這些功能并且保證中斷結(jié)構(gòu)比較簡單。為了防止前后交換,可以將一些特定的寄存器在中斷程序中作為專用寄存器。 16.4設(shè)計舉例

16.4.1中斷接口

如圖16-5所示,框圖包括了硬件計數(shù)器和中斷接口以及新添加的輸出緩沖器。計數(shù)器為模500計數(shù)器,每500個時鐘周期產(chǎn)生一個單時鐘脈沖。由于計數(shù)器時鐘為50MHz,所以該時鐘脈沖的周期為0.1ms。由于僅有一個中斷請求,因而在中斷接口應(yīng)設(shè)計標志觸發(fā)器。計數(shù)器產(chǎn)生的時鐘脈沖觸發(fā)標志寄存器,從而激活中斷信號。16.4.2中斷服務(wù)子程序開發(fā)

在中斷服務(wù)子程序中,使用兩個寄存器count_msb和count_lsb合并成一個16位的寄存器,來追蹤PicoBlaze產(chǎn)生的脈沖信號,當(dāng)每次計數(shù)器中斷信號到來時,該寄存器加1,總共可以計數(shù)的最大時間為0.6s(216?×?1.01ms)。中斷相關(guān)代碼如下:

nameregse,count_msb;

nameregsf,count_lsb;

int_service_routine:

addcount_lsb,01;

addcycount_msb,00

returni

enable

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

;interruptvector

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

address3FF

jumpint_service_routine16.4.3匯編程序開發(fā)

根據(jù)設(shè)計目的,熟悉時序信息之后,可以針對LED顯示設(shè)計一個新的子程序display_mux_out來替換在第十五章中用到的disp_led子程序。如圖16-5所示,兩個輸出緩沖器用來存儲an和sseg信號,子程序的主要任務(wù)是存儲an模式,包括“1110”、“1101”、“1011”和“0111”,對應(yīng)的七段數(shù)碼管模式周期性地輸出到相應(yīng)寄存器,刷新率在幾百赫茲到1000Hz,每210個時鐘脈沖更新一次寄存器值,大約10ms。我們同樣使用led_pos寄存器來跟蹤顯示位置。使用中斷實現(xiàn)程序15-3,代碼需要做如下修改:

(1)增加定義新的端口和寄存器;

(2)用display_mux_out子程序替換原來的disp_led子程序;

(3)增加enableinterrupt指令在init子程序中使能中斷處理;

(4)在初始化程序中初始化led_pos、count_msb和count_lsb寄存器;

(5)增加中斷服務(wù)子程序。

修改之后的匯編代碼如程序16-1所示。圖16-5帶計數(shù)器的中斷接口圖

【程序16-1】帶硬件乘法器和UART接口的求平方電路。

;程序操作:

;從撥碼開關(guān)讀取a和b,計算a?×?a+b?×?b并在超級終端顯示結(jié)果和七段數(shù)碼管值

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

;數(shù)據(jù)常數(shù)

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

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ù)據(jù)寄存器

nameregs1,addr ;臨時存儲器和I/O端口地址

nameregs2,i ;通用循環(huán)計數(shù)器變量

;全局變量定義

nameregsc,switch_a_b ;當(dāng)前撥碼開關(guān)輸入作為RAM存儲偏移地址

nameregsb,led_pos ;?LED顯示位置(0,1,2或3)

nameregse,count_msb ;計數(shù)脈沖計數(shù)器高8位

nameregsf,count_lsb ;計數(shù)脈沖計數(shù)器低8位

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

;端口定義

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

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

constantrd_flag_port,00

;2位flag標志

(xxxxxxsc):

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

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

constantan_port,00

constantsseg_port,01

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

;主程序

callinit ;初始化

forever:

;主程序循環(huán)

callproc_btn ;檢查和處理按鈕

callsquare ;計算求平方

callload_led_pttn ;存儲LED顯示模式值到RAM中

calldisplay_mux_out ;動態(tài)掃描顯示LED

jumpforever

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

;子程序:?init

;功能:執(zhí)行初始化并清零寄存器和RAM值

;輸出寄存器:

;?switch_a_b:清零clearedto0

;臨時寄存器:data,i

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

init:

enableinterrupt

;清零寄存器

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

loadled_pos,00

loadcount_msb,00

loadcount_lsb,00

return

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

;子程序:proc_btn

;功能:檢查兩個按鍵并處理顯示

;輸入寄存器:

;switch_a_b:ramoffset(0為a,2為b)

;輸出寄存器:

;s3:存儲輸入端口標志

;switch_a_b:可交替鎖存0和2

;臨時寄存器:data,addr

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

proc_btn:

inputs3,rd_flag_port ;獲取標志

;checkandprocesscbutton

tests3,01 ;檢查按鍵c標志

jumpz,chk_btns ;若未設(shè)置,則跳轉(zhuǎn)到chk_btns

callinit ;若設(shè)置,則執(zhí)行初始化程序int

jumpproc_btn_done

chk_btns:

;檢查和處理按鍵s

tests3,02 ;檢查按鈕s標志位

jumpz,proc_btn_done ;標志未設(shè)置

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

loadaddr,a_lsb ;獲取數(shù)據(jù)a地址

addaddr,switch_a_b ;獲取地址偏移

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)低三位輸入并將對應(yīng)顯示值轉(zhuǎn)換成數(shù)碼管顯示形式,裝載到RAM中

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

;臨時寄存器:data,addr

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

;其中所調(diào)用的hex_to_led、get_lower_nibble、get_lupper_nible可參考求平方和子程序

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

load_led_pttn:

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

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

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

jumpc,sw_ok ;否

loads6,08 ;是,sw出錯,按默認執(zhí)行

sw_ok:

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

loadaddr,a_lsb

addaddr,s6 ;獲取低地址

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

callget_lower_nibble ;獲取低4位

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

storedata,led0

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

fetchdata,(addr)

callget_upper_nibble

callhex_to_led

storedata,led1

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

addaddr,01 ;獲取高地址

fetchdata,(addr)

callget_lower_nibble

callhex_to_led

storedata,led2

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

fetchdata,(addr)

callget_upper_nibble

callhex_to_led

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

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

jump

nz,led_done ;否

addaddr,01 ;獲取進位地址

fetchs6,(addr) ;寄存器存儲進位

tests6,01 ;測試進位寄存器是否為1

jump

z,led_done ;否

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

led_done:

storedata,led3

return

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

;子程序:square

;功能:計算a?×?a+b?×?b

;數(shù)據(jù)/結(jié)果存儲RAM起始地址為SQ_BASE_ADDR

;臨時寄存器:s3,s4,s5,s6,data

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

square:

;計算a?×?a

fetchs3,a_lsb ;取a值

fetchs4,a_lsb ;取b值

callmult_hard ;計算a?×?a值

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

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

;計算b?×?b

fetchs3,b_lsb ;取b值

fetchs4,b_lsb ;取b值

callmult_hard ;計算b?×?b值

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

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

;計算a?×?a+b?×?b

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

adddata,s6 ;求和a?×?a?+?b?×?b的低字節(jié)

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

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

addcydata,s5 ;求和a?×?a?+?b?×?b的高字節(jié)

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

loaddata,00 ;清零data,但是保持進位寄存器值

addcydata,00 ;從前一次加法運算獲取進位值

storedata,aabb_cout ;存儲a?×?a?+?b?×?b的進位值

return

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

;程序名稱:mult_soft

;功能:利用移位和加法運算完成8位的無符號整數(shù)乘法

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

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

;臨時寄存器:i

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

mult_soft:

loads5,00 ;清零s5

loadi,08 ;初始化循環(huán)次數(shù)

mult_loop:

sr0,s4 ;?s4最低位移位至進位寄存器

jump

nc,shift_prod ;最低位是0

adds5,s3 ;最低位是1

shift_prod:

sras5 ;右移高字節(jié)

sras6 ;右移低字節(jié)

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

jump

nz,mult_loop

return

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

;子程序名:display_mux_out

;程序功能:產(chǎn)生4位七段數(shù)碼管的使能和顯示模式信號

;輸入寄存器:

;count_msb,count_lsb:16位計數(shù)器

;led_pos:當(dāng)前LED位置

;輸出寄存器:

;led_pos:更新LED位置

;臨時寄存器:data,addr

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

display_mux_out:

comparecount_msb,02 ;計數(shù)器賦值為00000100_00000000

jumpc,mux_out_done

;如果count大于20,則清零計數(shù)器

loadcount_lsb,00

loadcount_msb,00

;更新七段數(shù)碼管顯示位置

addled_pos,01

compareled_pos,04

jumpnz,gen_an_signal

loadled_pos,00 ;?led位置循環(huán)顯示

gen_an_signal:

;產(chǎn)生4位使能信號

loaddata,0E ;?xxxx_1110

compareled_pos,00

jumpz,shift_an_0

compareled_pos,01

jumpz,shift_an_1

compareled_pos,02

jumpz,shift_an_2

sl1data ;移位1110三次

shift_an_2:

sl1data ;移位1110兩次

shift_an_1:

sl1data ;移位1110一次

shift_an_0:

outputdata,an_port

;輸出七段數(shù)碼管顯示模式

loadaddr,led0

addaddr,led_pos

fetchdata,(addr)

outputdata,sseg_port

mux_out_done:

return

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

;子程序名:interruptserviceroutine

;功能:16位加法器

;輸入寄存器:

;count_msb,count_lsb:timercount

;輸出寄存器:

;count_msb,count_lsb:incremented

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

int_service_routine:

addcount_lsb,01;16位加法器

addcycount_msb,00

returnienable

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

;中斷向量

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

address3FF

jumpint_service_routine16.4.4HDL代碼開發(fā)

基于中斷的求平方電路I/O接口包括三個部分,輸入接口與圖15-4相似,輸出接口包括一個譯碼電路和兩個針對an和sseg信號的輸出寄存器,中斷接口包括一個計數(shù)器和標志寄存器,如圖16-5所示。HDL描述如程序16-2所示。

【程序16-2】基于中斷的求平方電路HDL描述。

modulepico_int

(

input

wireclk,reset,

input

wire[7:0]sw,

input

wire[1:0]btn,

output

wire[3:0]an,

output

wire[7:0]sseg

);

//信號聲明

//KCPSM3/ROM信號

wire[9:0]address;

wire[17:0]instruction;

wire[7:0]port_id,out_port;

reg[7:0]in_port;

wirewrite_strobe,read_strobe;

wireinterrupt,interrupt_ack;

//I/O端口信號

//輸出使能

reg[1:0]en_d;

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

reg[7:0]sseg_reg;

reg[3:0]an_reg;

//兩個按鍵

regbtnc_flag_reg,btns_flag_reg;

wirebtnc_flag_next,btns_flag_next;

wireset_btnc_flag,set_btns_flag,clr_btn_flag;

//中斷相關(guān)信號

reg[8:0]timer_reg;

wire[8:0]timer_next;

wireten_us_tick;

regtimer_flag_reg;

wiretimer_flag_next;

//程序主體

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

//I/O模塊

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

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));

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

//KCPSM3和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(interrupt),.interrupt_ack(interrupt_ack));

int_romrom_unit

(.clk(clk),.address(address),

.instruction(instruction));

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

//輸出接口

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

//輸出端口id:

//0x00:an

//0x01:ssg

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

//寄存器

always@(posedgeclk)

begin

if(en_d[0])

an_reg<=out_port[3:0];

if(en_d[1])

sseg_reg<=out_port;

end

assignan=an_reg;

assignsseg=sseg_reg;

//使能信號譯碼電路

always

@*

if(write_strobe)

case(port_id[0])

1'b0:en_d=2'b01;

1'b1:en_d=2'b10;

endcas

溫馨提示

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

評論

0/150

提交評論