不得不說,SDRAM的設計是我接觸FPGA以來調試最困難的一次設計,早在一個多月以前,我就開始著手想做一個SDRAM方面的教程,受特權同學影響,開始學習《高手進階,終極內存技術指南》這篇論文,大家都知道這篇文章是學習內存入門的必讀文章,小墨同學花了一些時間在這上面,說實話看懂這篇文章是沒什么問題的,文件講的比較直白,通俗易懂,很容易入手。當了解了SDRAM工作方式之后,我便開始寫代碼,從特權同學的那篇經典教程里面,我認真研讀代碼的來龍去脈,終于搞懂了特權同學的設計思想,并花了一些時間將代碼自己敲一遍,并加上自己的注釋 然而設計并沒有像我想象的那么簡單,代碼設計好之后還要經過仿真,時序約束,仿真總體來說還好,但是時序約束我接觸的很少,于是又去學時序約束方面的知識,由于控制SDRAM時鐘跑到了100MHZ,時序約束對這個設計來說可以算是關鍵部分了,之前的設計由于對時序要求的不高,所以不用約束就可以實現。學習時序約束可以算是一個漫長的過程,經過這段時間的學習,小墨同學也開始反思,是不是自己的跨度有點大,設計SDRAM的過程確實有些吃力,所以,小墨同學決定暫時放棄SDRAM的教學,等以后發Nios II的文章的時候再來談SDRAM。 這次我們先來學習一個CPU的設計,這個設計看似簡單,但是真要一步步做完還是需要點耐心和精力的。本篇文章我們主要介紹Risc_CPU的設計過程以及代碼分析,下一篇文章小墨同學主要和大家分享test bench的書寫與仿真測試,幫助大家一步一步學會這個cpu的設計,那么,我們開始今天的教學吧~ 一、 設計前的準備 設計開始之前,我們得先知道什么是CPU,cpu即中央處理器,是計算機的核心部件。cpu的工作過程,小墨同學簡單說一下。首先我們計算機的程序和數據是存在我們計算機的內存中的,上電后cpu就需要從第一條指令的地址開始取指令,即取指令。取出的指令需要經過指令譯碼來告訴cpu這條指令是用來干什么的,即分析指令。當得知指令內容以后,cpu需要產生操作指令來完成相應的操作,即執行指令。所以,任何一種CPU內部,至少應該包含下列這些部件: 1.算數運算器 2.累加器 3.指令計數器 4.指令寄存器和譯碼器 5.時序控制器 二. 工作原理 在本次設計中,我們假設ROM中裝的是我們的程序指令,等會我們會往里面裝數據,程序指令是16位的,cpu每次讀取8位,分兩次讀完,讀出來的數據存到指令寄存器中。 這16位數據的高三位代表指令碼 HLT = 3'b000, SKZ = 3'b001, ADD = 3'b010, AND = 3'b011, XOR = 3'b100, LDA = 3'b101, STO = 3'b110, JMP = 3'b111; 后13位代表地址碼,指令寄存器將讀回來的數據分成指令碼opcode[2:0]和地址碼ir_addr[12:0],狀態控制器讀回指令碼進行譯碼,看是什么指令,然后根據指令的內容操作其他部件,若為寫數據則打開RAM進行寫數據,若為計算則將數據送到算數運算器進行算數運算,若為跳轉指令則地址指向下一地址,下次讀取指令的時候就跳過一個地址執行等等 三、各模塊精講 本次設計的cpu共包含8個模塊,下面我來一一講解 1.時鐘發生器 本模塊的用來產生分頻信號,外部50M的時鐘,做8分頻輸出,此8分頻信號用來控制地址多路器的輸出,由于之后我們要用到8狀態的狀態機,因此這里做成8分頻,至于具體原因,我們后面再講,然后是一個算數運算器的使能信號,每一個8分頻信號到來之前有一個算術運算器使能信號的高脈沖,意思就是,每一此狀態機循環開始之前做一次運算 才有狀態機的方式來設計分頻信號避免了使用計數器計數的方法來延時,提高了程序的可讀性和速度 2.指令寄存器 本模塊的作用是將來自ROM的16位數據寄存并分為高三位的指令碼和低13位的地址碼 指令寄存器分兩次讀取ROM中的數據 3.累加器 算數運算器的初值位0,來自ROM的數據經算數運算器處理之后輸出到累加器,累加器使能信號到來時,再將這份數據送到算數運算器作為初值,與下次從ROM中讀回的數據進行算數運算 4.算數運算器 算術運算器先判斷來自ROM的高三位指令碼是何種指令,然后將來自ROM中的數據和來自累加器中的數據進行算數運算,并將結果輸出。如果算數運算器中的數據是0的話,那么有一個高脈沖zero輸出 5.數據控制器 如果想將算數運算器的結果保存起來,輸出到RAM,那么可以選通數據控制器,將數據輸出到RAM,配合指令STO 6.地址多路器 8分頻時鐘的前半周期用來讀取ROM中指定地址的數據,后半周期用來進行指令操作,所以前半個周期需要從指定ROM中讀數據,所以輸出地址應為pc_addr,后半個周期用來處理指令,那么要操作的肯定是從ROM中讀回的13位地址,即ir_addr,并將其輸出 7.程序計數器 剛開始從ROM中讀取數據的地址是pc_addr,是0地址,若為跳轉指令,則需要將從ROM中讀回的13位地址碼作為新地址給pc_addr,等下一個8分頻時鐘到來時就讀取該地址的指令,實現跳轉指令的目的。如果不是跳轉指令,那么pc_addr加1指向下一地址,繼續執行 8.狀態控制器 狀態控制器,即我們的狀態機,使我們本次設計的核心部件,狀態機共用了8個狀態 前兩個狀態用來讀取ROM中的16位數據,需要兩個時鐘,也就是需要兩個狀態。 第三個狀態等待一個時鐘周期,目的是要湊夠8個狀態,因為8分頻時鐘的后半個周期需要4個狀態來完成,故前半周期也需要4個狀態,由于前半周期只需要讀取數據和地址指向下一地址即可,故需湊一個狀態 第四個狀態地址加1 ,指向下一地址 第五到八個狀態用來分析指令和執行指令,若為跳轉指令,則控制程序計數器改變目標地址,若為跳過下一條指令,則控制程序計數器pc_addr地址加4,若為運算指令,則將控算數運算器進行相應的邏輯運算,若為LDA寫入指令,則將讀回的數據放入累加器中等等,具體操作指令的含義見下圖 各個模塊設計好之后將其組裝便完成了我們的cpu設計,組裝后的頂層模塊見下圖 這樣,我們的cpu就設計完成了,當然設計完成之后還要進行仿真,要仿真就還需要外圍電路,包括存期指令程序ROM,存取數據的RAM,地址譯碼器等,由于ROM和RAM是不可綜合的,但是我們可以在仿真的時候模擬。 由于每篇文章最多只能上傳20張圖片,所以今天的教程就到此為止吧,具體的仿真過程和ROM、RAM的設計小墨同學將在下一篇文章中介紹,下一篇文章中將會提到modolsim SE的使用,test bench的書寫,前面的博客中雖然也略有提及,但并不系統,下一篇文章將會以本次設計為例,給大家介紹仿真的全過程,希望大家大力支持,下面附上部分仿真的圖片和測試結果供大家參考 波形仿真 謝謝各位大神的支持,這篇文章寫了幾個小時,純手打~ |