引言
??不知道你是否和我有過同樣的感受,《計算機組成原理》這門學科學起來如此的艱難:一節課下來,教室黑板上留下了滿滿的 “足跡”,看上去也挺簡單的,不就是 0 和 1 嘛,但這些看起來簡簡單單的 0 1 碼卻成為了我當時學習路上的絆腳石,原始碼、反碼、補碼等等等等,各種的碼制轉換令我一頭霧水,我曾一度懷疑這就是計算機干的活兒嗎?
??隨著后面慢慢了解《計算機組成原理》后,我愿稱計算機為世界上最麻煩的電子產品,也形象的將計算機描述為一套有電源、有身體、有框架,但就是沒有思想的空殼兒,這時候,我們的人類社會才萌生了許許多多“ 利用 ”它們的主人—程式“ 猿 ”,
??程式員就是要為計算機這個富有 ” 聰明 “潛質的伙伴撰寫一套一套的 “程式” ,告訴它們應該去做什么亦或是怎么去做,正是由于它們能吃苦、不怕累的精神再加上完美程式的契合,我們的生活質量得以大幅度提升,

??即使你不是計算機專業的學生,相信對于CPU你也有所了解,正所謂CPU(Central Processing Unit),也就是中央處理器,負責解釋計算機指令以及處理計算機軟體中的資料,中央處理器主要包含控制器、運算器兩部分,其中還包括cache以及實作它們之間資訊互換的資料、總線,
??可千萬別小看這個不起眼的 “小東西” ,它可是程式執行、機器正常運轉必不可少的元器件,作為電子計算機三大核心部件(CPU、記憶體、I/O設備)之一的CPU,在計算機體系結構中承載著控制調配硬體資源、執行通用運算等重要職責,下面我們來了解較為簡單的單周期CPU功能指令,
上機實驗
分析實作單周期CPU的14條指令計算結果,比較理論與實踐結果的正確性,
Addi:
??分析第一個周期,指令地址為041008,在程式測驗段中,可以看到,本條指令為addi,那么現在開始檢驗指令addi的實作程序:指令addi的功能是rt←rs + (sign-extend)immediate; immediate符號擴展再參加“加”運算,
??首先找到rs在本周期中存放的源運算元地址,rs=00;然后在Objects中添加immediate組件,找到立即數的值,immediate=8;最后進入ALU分析計算結果,在ALU的代碼檔案中有兩個引腳,ALUSrcA和ALUSrcB,它們在第一個周期中的值分別是0和1,則A埠進行ReadData1,B埠進行extend,計算結果為result=8,指令執行正確,可以實作資料相加功能,

Ori:

??分析第二個周期,指令地址為40020002,在程式測驗段中,可以看到,本條指令為ori,那么現在開始檢驗指令ori的實作程序:指令ori的功能是rt←rs | (zero-extend)immediate; immediate符號擴展再參加“或”運算,暫存器源運算元地址:rs=0,immediate=2;
進行zero-extend后,值為2

進行“或”運算,ALU兩個引腳輸入埠值為

計算結果為
指令計算結果無誤,指令運行正常,
Add:

??分析第三個周期,指令地址為0411800,在程式測驗段中,可以看到,本條指令為add,那么現在開始檢驗指令add的實作程序:指令add的功能是rd←rs + rt,源運算元地址:rs=2,rt=1;ALU兩個引腳值都是0,讀暫存器中的值,此時存入結果為03,程式運行正常,功能實作,

Sub:
??分析第四個周期,指令地址為08622800,在程式測驗段中,可以看到,本條指令為sub,那么現在開始檢驗指令sub的實作程序:指令sub的功能是rd←rs - rt,源運算元地址:rs=3,rt=2;ALU兩個引腳值皆為0,程式讀取暫存器中的值,此時存入結果為5,程式運行正常,功能完好,

and:

??分析第五個周期,指令地址為44a22000,在程式測驗段中,可以看到,本條指令為and,那么現在開始檢驗指令and的實作程序:指令and的功能是rd←rs & rt;(邏輯與運算),源運算元暫存器地址:rs=5,rt=2;ALU引腳值為0,讀取ALU計算結果為00000000,分別對源運算元5和2轉為2進制為:0101、0010按位與后值為0,結果吻合,該單元作業正常,功能實作,

or:

??分析第六個周期,指令地址為48824000,在程式測驗段中,可以看到,本條指令為or,那么現在開始檢驗指令or的實作程序:指令or的功能是rd←rs | rt;(邏輯或運算),源運算元暫存器地址:rs=04,rt=02;ALU雙引腳值為0,讀取暫存器堆中的值,可以看到存放真值為0和2(取最后結果),讀取值為2,
??分別對源運算元4和2轉為2進制并按位或后值為2,與程式運行結果吻合,該單元作業正常,功能實作,

sll:

??分析第七個周期,指令地址為60084040,在程式測驗段中,可以看到,本條指令為sll,那么現在開始檢驗指令sll的實作程序:指令sll的功能是rd<-rt<<(zero-extend)sa,左移sa位 ,(zero-extend)sa,源運算元暫存器地址:rt=08 ,尋求真值,移位數sa=1,程式運行后 ,在二進制資料計算中,左移一位就相當于乘以2,故程式結果正確,該單元作業正常,
bne:

??分析第八個周期,指令地址為c501fffe,在程式測驗段中,可以看到,本條指令為bne,那么現在開始檢驗指令bne的實作程序:指令bne的功能是:if(rs!=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4【與beq不同:不等時轉移,相等時順序執行,】在暫存器堆中找到源運算元地址,尋得真值,找尋計算結果,結果吻合,單元作業正常,

slti:

??分析第九個周期,指令地址為6c460008,在程式測驗段中,可以看到,本條指令為slti,那么現在開始檢驗指令slti的實作程序:指令slti的功能是:if (rs <(sign-extend)immediate) rt =1 else rt=0,源運算元地址找到后,對立即數進行sign-extend,然后判斷是否滿足if()中的給定條件,程式結果完整無誤,本單元作業正常,

beq:

??第14個周期中,指令地址為c0e1fffe,在程式測驗段中,可以看到,本條指令為beq,那么現在開始檢驗指令beq的實作程序:指令beq的功能是:if(rs=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4,immediate是從PC+4地址開始和轉移到的指令之間指令條數,
??immediate符號擴展之后左移2位再相加,左移2位是由于跳轉到的指令地址肯定是4的倍數(每條指令占4個位元組),最低兩位是“00”,因此將immediate放進指令碼中的時候,已經右移兩位,這與上文 “指令之間指令條數”相契合,運算結果符合事實,單元作業正常,

sw:

??第19個周期中,指令地址為98220004,在程式測驗段中,可以看到,本條指令為sw,那么現在開始檢驗指令sw的實作程序:指令sw的功能是:memory[rs+ (sign-extend)immediate]←rt;immediate符號擴展再相加,
??將rt暫存器的內容保存到rs暫存器內容和立即數符號擴展后的數相加作為地址的記憶體單元中,同樣的依次找到源運算元在暫存器中的值,進入ALU運算后,檢驗結果,程序圖展示如下,結果無誤,單元功能實作完好,

lw:

??第20個周期中,指令地址為9c290004,在程式測驗段中,可以看到,本條指令為lw,那么現在開始檢驗指令lw的實作程序:指令lw的功能是:rt ← memory[rs + (sign-extend)immediate];immediate符號擴展再相加,
??讀取rs暫存器內容和立即數符號擴展后的數相加作為地址的記憶體單元中的數,然后保存到rt暫存器中,同樣的依次找到源運算元在暫存器中的值,進入ALU運算后,檢驗結果,程序圖展示如下,結果無誤,單元功能實作完好,

j:

??第21個周期中,指令地址為e0000010,在程式測驗段中,可以看到,本條指令為j,那么現在開始檢驗指令j的實作程序:指令j的功能是:pc <-{(pc+4)[31..28],addr[27..2],2{0}},無條件跳轉,
??由于MIPS32的指令代碼長度占4個位元組,所以指令地址二進制數最低2位均為0,將指令地址放進指令代碼中時,可省掉!這樣,除了最高6位操作碼外,還有26位可用于存放地址,事實上,可存放28位地址了,剩下最高4位由pc+4最高4位拼接上,指令驗證程序如下,最后結論為:單元作業正常,功能實作完好,

halt:

??第22個周期中,指令地址為fc000000,在程式測驗段中,可以看到,本條指令為Halt,那么現在開始檢驗指令Halt的實作程序:指令Halt的功能是:停機;不改變PC的值,PC保持不變,從仿真后的波形圖中,可以清晰看到,波形圖在本指令后,電平恒定,不再發生變化,所以本指令功能實作,模塊單元作業正常,
總結
??深刻了解了一個簡單單周期CPU的設計方法,無論是復雜亦或是簡單的系統,最好的辦法就是采用分層和模塊化的設計方法,在眾多信號狀態中,首先從最高層開始梳理邏輯,劃分模塊,進而到每個模塊的內部核心處繼續劃分,這樣就避免了在信號條件變動很多的情況下不能夠清晰的理清的問題,
??硬體設施的不足讓人感覺整個課程在“云端”,講授的內容不能很好的和現有知識的應用契合,雖然第一次接觸VerilogHDL硬體描述語言,但是這門語言的思想和我所學的C++語言使用了同樣的邏輯架構,采用了自頂向下、分而治之的思想逐步剖析,正所謂“大廈的建立絕非一朝一夕”,采用“分步”的設計思想完成最終單周期CPU的設計與實作,
??有些許遺憾的是未能在硬體上實作,如果能在開發板上燒寫程式,接觸到實物,應該能有更為深刻的理解,在模塊呼叫使用埠系結時,有一個小技巧:勿完全按照順序賦值;因為這樣的方法可以盡量減少程式出錯的概率,而對于我們后期檢查源檔案時也無需完全分辨每一個引數的值,減少作業量,
??維基百科、谷歌學術是非常不錯的平臺,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/296039.html
標籤:Verilog
上一篇:Verilog實體陣列
