摘 要: 詳細論述了4位RISC" title="RISC">RISC MCU" title="MCU">MCU中斷系統的Verilog" title="Verilog">Verilog設計實現過程。該MCU采用PIC兩級流水線結構,含4個中斷源,2級優先級。最后通過整體的RISC MCU IP核對其中斷系統進行完整的程序測試,完成功能與時序的仿真與驗證。
關鍵詞: verilog;PIC;RISC MCU;仿真;中斷
微控制器(MCU)包括核心指令譯碼電路、寄存器/存儲器模塊和一組輸入/輸出(I/O)模塊。當I/O模塊處于操作進行時,I/O模塊中斷機制使微處理器可以忙于執行其他指令,取消MCU對端口的不必要等待時間,從而大大提高了MCU的執行效率[1]。
在微控制器或微處理器的設計中,控制信號的設計是最復雜的,而在控制信號的設計中,中斷系統的設計又是最困難的部分[1]。本文以自主所開發的4位RISC MCU IP核為載體,采用自上而下的設計方法,給出了其中斷系統的Verilog硬件描述語言的具體實現過程。該系統可以作為一個功能部件, 直接在微控制器中加以運用, 對各種復雜中斷系統的設計具有很好的借鑒意義。
1 中斷系統總體設計
本系統所處的載體是由自身所研發的、采用數據總線和指令總線相互分離的哈佛雙總線和Microchip技術公司的微控制器PIC的兩級流水線機制[2]。中斷系統的主要功能與MCS-51相同,有4個中斷請求源,2個中斷優先級,可實現2級中斷服務程序嵌套。整個中斷系統結構圖如圖1所示。具體的設計主要包含以下四個設計過程[3]:
(1)微控制器如何識別發生了哪個中斷;
(2)出現多個中斷時, 微處理器優先處理哪個中斷;
(3)微控制器如何處理中斷嵌套;
(4)微控制器如何處理中斷執行周期。
其中,(1)是中斷源的問題,(4)是中斷響應時間的考慮,(2)和(3)歸結起來就是中斷優先級單元的設計。
1.1 中斷源
系統的4個中斷源分別是:外部中斷SE(由I/O提供);片內的定時/計數器T0的溢出中斷請求ST;片內基準定時器BT0的溢出中斷請求SB;液晶驅動模塊的中斷請求SL和中斷系統相關的特殊功能寄存器及有中斷允許控制寄存器IE,中斷優先級控制寄存器IP和中斷請求標志寄存器IF。IF、IE、IP寄存器中的中斷源排位順序一致,它們都可通過字節的指令操作來進行讀寫,MCU復位時,全部為0。當MCU同時收到幾個同一優先級的中斷請求時,由同級內的優先查詢順序確定哪個中斷請求得到響應。各中斷源得相應中斷入口地址、默認同級優先級及IF/IE/IP寄存器的各位名稱如表1所示。
IE的相應位置1,表明相應的中斷源為允許,為0時,則是屏蔽;IF的相應位置1,表明相應的中斷源有請求,為0,則沒有中斷源請求;IP的相應位為1,表明相應的中斷源為高優先級中斷,為0,則為低優先級中斷。該部分的相關Verilog代碼如下(以基準定時中斷為例):
//基準定時模塊中斷源信號(高電平脈沖)的系統時鐘同步;
always@(sysclk) begin
int_base1<=int_base;
int_base2<=int_base1;end
assign SB=!int_base1&int_base2;
//中斷請求標志位:可由中斷源SB觸發,也可通過對IF
//的字節操作對其置位或清零,其余情況下則保持原狀態
//不變。
assign FB=(resetn==0)? 1′b0:
(SB==1)? 1′b1:
(IF_wr)? IF[2]:
LF;
//把中斷請求標志位寫回中斷請求暫存寄存器IF_out,若有
//對IF進行寫操作(IF_wr=1),則把IF_out寫回。
assign IF_out={FB,FT,FE,FL};
//中斷請求響應條件位
assign FB_f=FB&IE[2];
1.2 中斷優先級設計
系統設置有2個中斷優先級,對于每一個中斷請求源可編程為高優先級中斷或低優先級中斷。中斷系統中有2個不可尋址的優先級狀態編碼器,一個指出MCU是否有高優先級的中斷信號,另一個指出MCU是否有低優先級的中斷信號。可根據這兩個編碼器的值來判斷系統所處的中斷狀態。此部分為設計的重點。
如圖1所示,把高、低優先級的中斷分別歸類到高優先級編碼器(encoder2)和低優先級編碼器(encoder1),無中斷時,兩編碼器值都為零。若有一個不為零或兩個都不為零,則會產生一中斷信號(int_out),且會根據兩優先編碼器的值來確定中斷入口地址(int_pc)、中斷嵌套(int_nesting)、中斷嵌套返回(int_nest_back)等信號,并將它們送入PC與堆棧處理模塊。當然PC與堆棧模塊也會產生相應的反饋信號以處理多種中斷情況。相關的重點實現代碼如下:
//低優先級編碼器的輸入端選擇
assign encoder1_in[0]=(int_pri[0]==0)?FL:1′b0;
assign encoder1_in[1]=(int_pri[1]==0)?FE:1′b0;
assign encoder1_in[2]=(int_pri[2]==0)?FT:1′b0;
assign encoder1_in[3]=(int_pri[3]==0)?FB:1′b0;
//高優先級編碼器的輸入端選擇
assign encoder2_in[0]=(int_pri[0]==1)?FL:1′b0;
assign encoder2_in[1]=(int_pri[1]==1)?FE:1′b0;
assign encoder2_in[2]=(int_pri[2]==1)?FT:1′b0;
assign encoder2_in[3]=(int_pri[3]==1)?FB:1′b0;
//低優先級編碼器的實現:無中斷時,值為0,進中斷時優先
//編碼賦值。其中把值寄存一次,用以辨別中斷源變化時的
//編碼狀態,做為中斷嵌套等多種中斷情況的信號辨別條
//件;高優先級編碼器的實現與低優先級類同,結果為out2
//和out2_pre。
always@(encoder1_in or out1)
begin
out1_pre<=out1;
casex(encoder1_in)
4′b0000:out1=3′b000;
4′b0001:out1=3′b001;
4′b001x:out1=3′b010;
4′b01xx:out1=3′b011;
4′b1xxx:out1=3′b100;
default:out1=3′b000;
endcase
end
//根據高低編碼器出來的結果辨別優先級,即該跳轉的中斷
//向量地址。先僅取用到的5位數,用時再與前面補零;其
//中也已包含了同級默認優先級的功能;
assign int_pc= (out2==3′b100) ? 4′b0011:
(out2==3′b011) ? 4′b0101:
(out2==3′b010) ? 4′b0111:
(out2==3′b001) ? 4′b1001:
(out1==3′b100) ? 4′b0011:
(out1==3′b011) ? 4′b0101:
(out1==3′b010) ? 4′b0111:
(out1==3′b001) ? 4′b1001:
4′b0000;
//中斷信號的產生,int_out_clear為PC和堆棧模塊的反饋信
//號;
assign int_out=(int_out_clear==1)? 1′b0:
((out2!=3′b000)||(out1!=3′b000))? 1′b1:1′b0;
//中斷嵌套信號的條件是通過兩編碼器輸出結果的變化推
//斷出來的,且已通過驗證證明是正確的。中斷嵌套返回的
//方法與此同,不細述。
assign
int_nest=(((out1!=3′b000)&(out2_pre==3′b000)&(out2!=
3′b000))==1′b1)?1′b1:1′b0;
//int_nest為一辨別信號,將其轉換為系統脈沖信號;
always@(posedge sysclk) begin
int_nest1<=int_nest;
int_nest2<=int_nest1;
if(!int_nest2&int_nest)
int_nesting<=1;
else int_nesting<=0;end
1.3 中斷響應
中斷延遲是MCU的一個重要參數, 通常是指在最壞情況下響應中斷的最長時間。因系統屬于RISC單周期指令,也就不存在CISC中存在的指令未執行完而被打斷的情況。當然MCU也是在現行一條指令執行完畢即下一個指令周期的Q1才開始響應中斷的,并不是在一條指令執行期間響應中斷,這樣MCU才能正確返回斷點繼續執行原來的程序。由此也可知道系統大部分時刻中斷響應時間為1個指令周期;除非正在執行的指令是現場保護(入棧)、現場恢復(出棧),則需要等這些指令執行完之后,再去響應新的中斷請求,這一點本系統是通過軟件程序來實現。軟件程序的具體編寫步驟與MCS-51相似,見參考文獻[4]。
1.4 PC與堆棧模塊
PC與堆棧模塊通過接收來自中斷優先級模塊的信號處理多種中斷情況的發生,并產生相應的反饋信號,且完成了現場保護(入棧)、現場恢復(出棧)、PC預取值等重要操作。除了跳轉地址須等指令周期的Q4外,其余的大部分操作皆于Q1時刻完成。
always@(posedge clk1 or posedge int_nesting or negedge resetn) begin
if(resetn==0)
……
//中斷嵌套信號需把int_out_clear清零,以辨別新中斷信號;
//當有中斷信號后的下一個Q1,置int_out_clear為1;中斷
//返回指令RTI時置其為0;其余時刻保持不變。
else if(int_nesting) int_out_clear<=0;
else begin
pc_plus1<=pc_fetch+1;
pc<=pc_fetch;
casex({int_out,inst[15:12]})
5′b1xxxx:begin
int_out_clear<=1
//pc_int:中斷發生標志;pc_pop:中斷返回標志
pc_int<=1;
pc_pop<=0;
//中斷嵌套返回時刻并不執行壓棧操作,而應返回原壓棧值
if(int_nest_back==0)
……//壓棧
5′b01111:begin
pc_pop<=1;
pc_int<=0;
int_out_clear<=0;
……//進棧
default:begin
pc_pop<=0;
pc_int<=0;end
//預取值地址的辨別
assign pc_fetch=(resetn==0) ? 12′b0000_0000_0000:
(pc_pop==1) ? pc_fetch_pop:
(int_nest_back&pc_int) ? pc_fetch_pop:
(pc_int==1) ? {8′b00000000,int_pc}:
(sys_jmp==1) ? pc_jmp:
pc_plus1;
2 系統的測試與驗證
本中斷系統屬于自主設計的RISC MCU IP核的子模塊,其功能與時序仿真也是在整個IP核上進行的。經過六個含中斷程序的下載驗證和不斷完善,整個中斷系統是完全正確且可行的。功能仿真時,采取了將測試向量(匯編代碼)通過虛擬ROM進行驗證的方式;時序仿真則是利用Altera公司的LPM ROM/RAM模塊完成。前者的平臺是modelsim 6.0se,后者是quartus6.0。現舉例詳細說明:設置IE為0111,IP為0110。步驟如下:
(1)運行主程序,等待中斷信號;
(2)先獲得液晶中斷源SL并執行相應的中斷源程序,但在其中斷程序未執行完之前,又來外部中斷源SE,此時因中斷源有高低優先級之別,應有中斷嵌套狀況;
(3)系統轉而執行外部中斷程序,但又在外部中斷程序未執行完之前,獲得定時/計數器中斷源ST,此時因中斷源同是高優先級中斷,故不予理睬,但定時/技術中斷器請求信號卻一直保持,直至外部中斷程序完畢后,系統緊接著響應定時/技術器中斷;
(4)定時/技術器中斷程序執行完畢后,系統返回液晶中斷程序繼續執行;
(5)待液晶中斷程序執行完后,系統跳回主程序。
具體的仿真結果完全符合功能要求,時序圖如圖2所示。
隨著微電子技術的飛速發展,微控制器以其性能好、體積小、價格優、功能齊全等突出優點被廣泛應用于家用電器、計算和外設、通訊、工業控制、自動化生產、智能化設備以及儀器儀表等領域,在國內具有良好的應用前景,其設計也日益受到人們的重視。中斷系統是微控制器設計的難點,本文介紹的中斷系統設計方法具有很好的借鑒意義。采用這種用Verilog實現的自頂向下的方法,使問題在RTL級就暴露出來,便于及時修改,大大減少了開發時間。包含上述中斷系統的4位RISC MCU IP核也已測試及驗證成功。
參考文獻
[1] 胡永華,高明倫,王銳.微處理器中中斷電路的高層設計[J].微電子學與計算機,2001,(4).
[2] 2004 Microchip Technology Inc.PICmicro中檔單片機系列參考手冊.http://www.microchip.com,2004,9.
[3] 朱良辰,胡越黎,冉峰.高速MCU核中并行優先級中斷系統的設計與實現[J].微電子學,2004,34(4):482.
[4] 張毅剛.單片機原理與應用(第1版)[M].北京:高等教育出版社,2004,(1):112.