前兩天剛做完了計(jì)算機(jī)組成原理的課設(shè)泰鸡。其實(shí)這個(gè)課設(shè)并不是特別的難,但是這一年我們整個(gè)專業(yè)算上我,也只有兩個(gè)人做完了這個(gè)課設(shè)的所有部分缅糟。主要是這個(gè)課設(shè)里面存在好多個(gè)剛開始做的人難以避開的坑。做完了之后也是實(shí)在不想讓其他的學(xué)弟學(xué)妹們?cè)僭谖矣龅竭^(guò)的坑里面掙扎祷愉,所以就趁著剛做完窗宦,把常見(jiàn)的幾個(gè)可能遇到的問(wèn)題列了一下,以供參考二鳄。
如需轉(zhuǎn)載請(qǐng)先征得本人同意赴涵,謝謝
總之最后就是這么個(gè)效果。道理上來(lái)講直接寫一個(gè)專門的Verilog代碼實(shí)現(xiàn)這個(gè)效果是完全可以的订讼,這個(gè)相當(dāng)于繞了一大圈髓窜,通過(guò)用Verilog寫的MIPS系統(tǒng),加上自己編寫的匯編代碼配合實(shí)驗(yàn)箱上的硬件實(shí)現(xiàn)這個(gè)功能躯嫉。
這篇文章主要分三個(gè)部分:
第一部分是關(guān)于project1中l(wèi)ogisim的一點(diǎn)使用上的說(shuō)明和技巧纱烘。沒(méi)有制作思路的分析是因?yàn)闀线€有課件上還有老師的ppt上面都有
第二部分是關(guān)于project2和project3的一點(diǎn)注意事項(xiàng)杨拐,Verilog常見(jiàn)的一些使用誤區(qū)以及開始使用的時(shí)候不容易注意到的使用方法。還有一些調(diào)試技巧擂啥,可以加快你的調(diào)試進(jìn)度
第三部分是和計(jì)算機(jī)組成原理課設(shè)相關(guān)哄陶,內(nèi)容主要ISE軟件的使用方法,如何使用ISE軟件進(jìn)行仿真哺壶,64位系統(tǒng)如何使用ISE軟件屋吨,下載到實(shí)驗(yàn)箱的時(shí)候關(guān)于實(shí)驗(yàn)箱的一些注意事項(xiàng)等等。
【這里先強(qiáng)調(diào)一下山宾,從project2開始至扰,請(qǐng)一定要先畫圖再做設(shè)計(jì),畫圖的時(shí)候盡量在電腦上面畫资锰,最理想的方式是每添加一個(gè)接口敢课,每添加一根線,都在自己的設(shè)計(jì)圖上做出對(duì)應(yīng)的修改绷杜,這樣到了后面會(huì)有很大的幫助(一些辨識(shí)度特別明顯的線可以省掉)直秆。如果要從project2做設(shè)計(jì)圖,記得部件之間的空隙留得大一些鞭盟,因?yàn)榈搅藀roject3的時(shí)候是需要在部件之間添加鎖存器的圾结,空隙太小就加不進(jìn)去了(我就是當(dāng)初沒(méi)有畫圖……到了后面理思路的時(shí)候麻煩死)】
第一部分:
其實(shí)和后面的幾個(gè)project相比,project1可以說(shuō)絕對(duì)難度是最高的齿诉,主要是project1的時(shí)候我們剛開始接觸MIPS系統(tǒng)筝野,偶爾靈光一閃經(jīng)常一臉懵逼,所以這個(gè)時(shí)候格外需要一個(gè)靠譜的方法來(lái)輔助調(diào)試工作粤剧。所以我也把我在logisim里面常用的幾個(gè)調(diào)試方法說(shuō)一下歇竟。(截圖湊合著看吧……貌似java的圖形界面對(duì)于高分屏的支持一般,所以顯示出來(lái)的東西總是有點(diǎn)怪怪的抵恋,好在勉強(qiáng)能看清途蒋。)
-
探針。真的發(fā)現(xiàn)很多人不用探針這個(gè)好東西啊……隨便接到哪一根線上都可以自動(dòng)顯示線上傳輸?shù)闹挡黾牵€可以切換二進(jìn)制十進(jìn)制十六進(jìn)制,調(diào)試必備懊烤。
探針就是這東西:
添加到電路中梯醒,效果如圖
圖中被我圈起來(lái)的都是探針。
選中一個(gè)探針腌紧,在左邊可以調(diào)整探針的顯示模式:
來(lái)個(gè)二進(jìn)制和十進(jìn)制的對(duì)比茸习。顯示指令的時(shí)候記得把探針的顯示格式調(diào)成16進(jìn)制的,要不然根本看不懂
2. 我們用logisim做MIPS系統(tǒng)的時(shí)候需要將每一個(gè)有獨(dú)立功能的部件封裝成一個(gè)模塊壁肋。具體做法就是在project里面号胚,選擇add circuit即可添加電路
設(shè)置好電路中的邏輯功能還有輸入輸出端口之后籽慢,右鍵選擇edit circuit appear****ance
之后就可以直接點(diǎn)擊這個(gè)電路的文件名,然后添加到其它的電路圖中進(jìn)行使用猫胁。不過(guò)默認(rèn)生成的電路是這個(gè)樣子的:
端口少的時(shí)候還好箱亿,端口多一點(diǎn),比如ctrl模塊弃秆,還是這樣的話就是這個(gè)效果:
嗯届惋,我能感覺(jué)到你很緊張
這特么都是啥(摔
不玩了不玩了,這根本記不住哪個(gè)口是哪個(gè)口啊
來(lái)菠赚,不哭不哭脑豹。其實(shí)稍作修改,這個(gè)模塊就可以做成這個(gè)樣子:
放到電路中就是這個(gè)樣子:
logisim在電路封裝方面做得還是挺人性化的衡查,編輯電路外觀的時(shí)候签餐,模塊的大小可以直接拖動(dòng)調(diào)整,輸入和輸出端口的初始順序就是按照你電路里面的上下順序排序的普监,同時(shí)端口也可以拖動(dòng)調(diào)整位置逢捺。而且在編輯電路外觀的時(shí)候,左上角還有一個(gè)文字工具可以添加注釋们拙,就是這個(gè):
添加的文字顏色字體還有大小都是可以調(diào)整的稍途。只要稍做一下修改,就可以讓你的電路變得條理清晰砚婆,調(diào)試方便看著也舒服械拍。所有調(diào)整屬性的方式都在左下角的屬性欄里面:
3. 做好了的MIPS系統(tǒng)需要的外界輸入無(wú)非就是一個(gè)reset還有一個(gè)clock。reset按鈕有的人用的就是一個(gè)普通的input接口装盯,通過(guò)用鼠標(biāo)連續(xù)點(diǎn)擊切換狀態(tài)產(chǎn)生reset信號(hào)坷虑。其實(shí)logisim提供了一個(gè)button部件,相當(dāng)于一個(gè)按動(dòng)式的開關(guān)埂奈,鼠標(biāo)單擊的時(shí)候按下產(chǎn)生1信號(hào)迄损, 松開鼠標(biāo)的時(shí)候松開變?yōu)?信號(hào),可以更方便的實(shí)現(xiàn)reset功能账磺。而且還可以換顏色芹敌,像這樣:
不但顯得更加正式,而且還可以提升調(diào)試時(shí)候的用戶體驗(yàn)垮抗。
4. 還有一個(gè)就是時(shí)鐘信號(hào)氏捞。大家應(yīng)該都知道時(shí)鐘信號(hào)是一個(gè)單獨(dú)的時(shí)鐘模塊產(chǎn)生的,但是如果需要觀察部件內(nèi)部的變化冒版,有的同學(xué)會(huì)先切換到主電路液茎,調(diào)整一下時(shí)鐘,然后再返回到部件內(nèi)部,觀察部件的信號(hào)變化捆等,麻煩不說(shuō)滞造,來(lái)回切換的時(shí)候如果你的部件內(nèi)容比較多,很可能自己就先亂了栋烤。
其實(shí)logisim的時(shí)鐘也有一個(gè)單獨(dú)的控制方式:
不但可以直接控制時(shí)鐘谒养,而且還有對(duì)應(yīng)的快捷鍵。Tick Once可以讓時(shí)鐘翻轉(zhuǎn)一次班缎,Ticks Enabled可以讓時(shí)鐘按照Tick Frequency里面設(shè)置的頻率自行變化蝴光,不管你是在主電路里還是在部件內(nèi)部,都可以使用這個(gè)功能达址。這樣你就不用頻繁切換各個(gè)部件蔑祟,也不用總是手動(dòng)去點(diǎn)那個(gè)clock,只要按一下ctrl+T就可以讓時(shí)鐘自己進(jìn)行翻轉(zhuǎn)沉唠,你要做的就是觀察電路中的信號(hào)是如何變化疆虚,如果出錯(cuò)了是哪里出錯(cuò)的就行了。你說(shuō)不知道怎么觀察满葛?往上翻径簿,用探針。
5. 電路的多級(jí)封裝嘀韧。其實(shí)只有自己做全加器的時(shí)候需要用到這個(gè)篇亭。做全加器的時(shí)候,需要用一位的全加器拼成32位锄贷,如果你一個(gè)個(gè)拼的話译蒂,就需要拼32個(gè),很累是不是谊却?所以我們并不需要拼那么多次柔昼。一位的全加器做完了,用一位的全加器拼成兩位炎辨,然后用兩個(gè)兩位的拼成四位的……拼不了幾次就拼完了捕透,而且即使哪里出了錯(cuò)誤也可以很容易的找出來(lái),想象一下用32個(gè)一位全加器拼出來(lái)的32位全加器一旦哪里出錯(cuò)了碴萧,查起來(lái)的感覺(jué)……
6. 還有一些重復(fù)度特別高的模塊乙嘀,比如GPR,我做的GPR是這樣的:
是不是特別好看(呵呵)
像這種模塊破喻,如果你是一個(gè)一個(gè)做的乒躺,做完之后眼睛都能累瞎十分鐘。但是考慮到里面的模塊基本是重復(fù)的低缩,所以我們可以進(jìn)行規(guī)則排列,先列出幾個(gè),然后直接批量復(fù)制咆繁,只要幾下就能做好了讳推。你們看我的線是不是排列得特別整齊?以為我是故意的嗎玩般?其實(shí)這就是批量作業(yè)的結(jié)果银觅,整齊干凈省心省力出錯(cuò)率還低。從元器件到線都是可以批量進(jìn)行復(fù)制的坏为。(其實(shí)在quartus的圖形化設(shè)計(jì)里面也可以用類似的方式去做那些重復(fù)率特別高的元器件)
第二部分:
一些我認(rèn)為比較實(shí)用的modelsim調(diào)試方法究驴。截圖我都是在modelsim里面截圖的,但是ISE同樣有仿真功能匀伏,而且和modelsim基本相似洒忧,所以用ISE調(diào)試的時(shí)候可以直接參照modelsim的調(diào)試過(guò)程。怎么寫testbench文件還有怎么調(diào)試够颠,直接上網(wǎng)搜就行了熙侍,網(wǎng)上的教程寫得還是很清晰的。比如這個(gè)(可直接復(fù)制打開):
做project2履磨,project3的時(shí)候最好畫設(shè)計(jì)圖蛉抓!畫設(shè)計(jì)圖的時(shí)候可以直接用logisim來(lái)畫,不需要做部件內(nèi)部的結(jié)構(gòu)剃诅,只需要把輸入輸出端口弄出來(lái)巷送,然后獨(dú)立封裝成一個(gè)模塊,標(biāo)好模塊名稱矛辕,每一個(gè)端口的功能就行笑跛,連接修改的時(shí)候都特別的方便。
-
調(diào)試的時(shí)候記得把你添加的波形的指令部分調(diào)成16進(jìn)制如筛,要不然看的時(shí)候特別累堡牡。
選擇一個(gè)或者多個(gè)信號(hào),右鍵杨刨,選中這個(gè)hexadecimal
image
2. modelsim在進(jìn)行仿真的時(shí)候晤柄,是可以在編輯界面中顯示當(dāng)前每一個(gè)寄存器、線變量的值的妖胀,就像是一些高級(jí)語(yǔ)言的IDE一樣芥颈。如下圖:
善用這一點(diǎn),可以直接查看當(dāng)前時(shí)刻的問(wèn)題是什么赚抡,一級(jí)一級(jí)地追蹤是哪里出的問(wèn)題爬坑。
3. 接著上面的,盡管modelsim可以直接顯示當(dāng)前各部件中每個(gè)變量的值涂臣,但是只能顯示當(dāng)前仿真的時(shí)刻的值盾计,如果你連續(xù)點(diǎn)了一路的run售担,然后悲催發(fā)現(xiàn)出錯(cuò)誤的部分已經(jīng)過(guò)了,然后你又要從頭開始點(diǎn)起……循環(huán)下去一定特別不爽(手動(dòng)微笑)
其實(shí)這個(gè)時(shí)候署辉,你可以看一下下面的時(shí)間軸族铆,比如說(shuō)你是在這個(gè)位置出的錯(cuò)誤:
我們可以看到這里大概是4000000ps,也就是4000ns左右的位置哭尝。我仿真的周期設(shè)置的是200ns哥攘,可是現(xiàn)在仿真進(jìn)度已經(jīng)到了4800ns。如果我想看4000ns位置的部件各變量的情況材鹦,我就需要重新開始逝淹,然后數(shù)著我進(jìn)行了多少周期…………當(dāng)然不用這么麻煩,你只需要記住時(shí)間桶唐,然后在這里輸入你要看的時(shí)間點(diǎn)栅葡,比如我要輸入的是4000ns,接著運(yùn)行一次就OK:
怎么樣是不是很機(jī)智
4. 看著自己那一大堆寄存器是不是特別頭疼莽红?不知道哪里引用哪一根線妥畏?忘了自己部件是怎么連接的?用ctrl+F搜索功能去搜索你的變量名安吁,很快就可以找到你所有的變量是如何連接的了
5. 看寄存器組的時(shí)候是不是很頭疼醉蚁,32個(gè)寄存器的GPR看著還好,但是1024個(gè)寄存器的dm根本看不過(guò)來(lái)是不是鬼店?記得用memory list网棍,一次讓你看個(gè)夠。
記得右鍵右邊的寄存器數(shù)據(jù)妇智,在屬性中改成16進(jìn)制的顯示方式
6. 記得上網(wǎng)查一下$monitor和$display的用法滥玷,比如這個(gè)教程(直接復(fù)制然后打開,里面的圖有問(wèn)題不過(guò)看的時(shí)候看前面的文字足夠了):
http://www.eefocus.com/liuyuxue/blog/13-11/300152_6e55c.html
仿真的時(shí)候可以直接在屏幕下面的仿真信息里面按照你想要的格式輸出你設(shè)置好的要顯示的變量巍棱,比如我寫了這樣的語(yǔ)句:
仿真的時(shí)候下面的效果是這樣的:
怎么樣惑畴,如果你把你所有要查看的東西都用這樣的方式顯示出來(lái),是不是比之前的一個(gè)一個(gè)查還要方便航徙?關(guān)鍵是不需要再重新來(lái)一遍看唄自己跳過(guò)的步驟如贷,因?yàn)槟阆胍榭吹淖兞恐灰l(fā)生變化就一定會(huì)被顯示出來(lái),而且所有的變化都不會(huì)錯(cuò)過(guò)到踏。心動(dòng)了嗎杠袱?那就趕快行動(dòng)吧(感覺(jué)好勉強(qiáng)hhhhhh)
PS:我做課設(shè)的時(shí)候嫌麻煩沒(méi)用這個(gè),寫教程的時(shí)候試了一下窝稿,并不麻煩而且弄好了之后會(huì)方便很多楣富。
7. 還有一個(gè)比較常見(jiàn)的連接的時(shí)候位數(shù)不匹配的錯(cuò)誤,出現(xiàn)這個(gè)錯(cuò)誤并不會(huì)報(bào)error伴榔,有的時(shí)候會(huì)出現(xiàn)在warning里面纹蝴,然而warning經(jīng)常會(huì)被人無(wú)視庄萎,加上warning本身也充斥著很多無(wú)關(guān)的信息,所以大多數(shù)情況沒(méi)啥用骗灶,只有實(shí)在不行的時(shí)候才回去翻一遍warning里面到底有什么東西(我擦怎么扯遠(yuǎn)了)
強(qiáng)行回歸主題惨恭。如果仿真的時(shí)候發(fā)現(xiàn)波形是一道藍(lán)色的線,而且這個(gè)藍(lán)色的線的數(shù)值是類似于
xxxxxxx0
xxxxxxxxx1111
這樣的xxxxxxxxxxxx接上數(shù)值的形式耙旦,你就需要考慮一下是不是存在位數(shù)不匹配的問(wèn)題了。
第三部分:
首先是ISE軟件要怎么用
很多人打開ISE軟件之后最尷尬的事情就是發(fā)現(xiàn)自己完全不會(huì)用這玩意萝究。雖說(shuō)這種工程上的工具軟件是直接面對(duì)商業(yè)上的設(shè)計(jì)者免都,包含的功能自然特別多,但是對(duì)于我們學(xué)生來(lái)說(shuō)帆竹,絕大多數(shù)功能是完全用不到的绕娘。下面我著重說(shuō)一下【和我們的課設(shè)相關(guān)的ISE軟件的用法】
首先,是64位系統(tǒng)如何使用ISE栽连。
在安裝路徑下险领,找到ISE\14.5\ISE_DS\ISE\lib\nt64文件夾,將里面的libPortabilityNOSH.dll復(fù)制秒紧,重命名為libPortability.dll并將原來(lái)的libPortability.dll替換掉绢陌。然后即可正常在64位系統(tǒng)下使用ISE,不需要安裝虛擬機(jī)熔恢。
打開軟件的時(shí)候脐湾,記得打開這個(gè)圖標(biāo):
而不是這個(gè)圖標(biāo):
前一個(gè)是ISE的圖標(biāo),后一個(gè)是用來(lái)給工程分配引腳的軟件叙淌,我們可能會(huì)用到秤掌,但是不需要在這里打開。
打開軟件之后鹰霍,你會(huì)看到這么個(gè)東西闻鉴,然后new一個(gè)project
然后就是給工程選路徑,命名茂洒,設(shè)置屬性孟岛。到了屬性那里,記得把型號(hào)設(shè)置為XC6SLX45(如果情況沒(méi)有變化的話获黔,每一屆箱子的型號(hào)用的是一樣的蚀苛,如果有變化的話,可以看芯片上面寫著的型號(hào)玷氏,以那個(gè)為準(zhǔn))堵未,然后就是一路下一步,然后finish即可盏触。
新建完工程之后渗蟹,我們需要將我們之前編輯好的Verilog文件導(dǎo)入到工程當(dāng)中块饺。右鍵新建的工程,add source
然后就是選擇你的Verilog文件雌芽,然后逐個(gè)或批量添加授艰。
或者你想要新建一些Verilog文件,那就new source世落,記得選擇Verilog module淮腾,別選錯(cuò)了。
然后就可以正常進(jìn)行修改屉佳,仿真谷朝,綜合等操作了。
不過(guò)這個(gè)時(shí)候你可能會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題:就是現(xiàn)在工程的頂層文件不是你想要的頂層文件(頂層文件就是包含了所有需要的模塊的總的模塊的文件)武花,所以根本沒(méi)有辦法編譯圆凰。不要急,右鍵選中你想要設(shè)置為頂層文件的文件体箕,選擇set as top module就可以啦~
接下來(lái)的綜合和布線部分都是在這下面進(jìn)行:
是不是覺(jué)得眼花繚亂我就做個(gè)課設(shè)干啥要有這么多選項(xiàng)(摔
如果你沒(méi)有太多的好奇心的話专钉,其實(shí)只需要這幾個(gè)選項(xiàng)就夠了,其他的都可以無(wú)視掉累铅。
編譯綜合點(diǎn)這里(就是你把你的.v程序跃须,按照語(yǔ)法規(guī)則生成電路)
理論上來(lái)說(shuō)只要編譯綜合完了,就可以生成.bit文件直接下載到板子上了争群,可是為了從板子上的部件接收信號(hào)以及控制板子上的信號(hào)回怜,你需要分配引腳,這個(gè)時(shí)候你需要點(diǎn)這里(至于點(diǎn)完之后要怎么做后面再說(shuō)):
分配完了引腳之后换薄,你需要點(diǎn)擊這個(gè)把你綜合好的電路生成可以直接下載到電路板的里面的.bit文件:
然后就是我上面視頻的那個(gè)把程序下載到電路板上的窗口玉雾。以上所有的地方,不是雙擊就是單擊轻要,點(diǎn)擊一下不成就兩下复旬,肯定沒(méi)錯(cuò)就對(duì)啦~
成功生成完可以下載到板子上的.bit文件之后,會(huì)出現(xiàn)這樣的一個(gè)窗口冲泥,雙擊boundary scan:
選擇initialize chain(請(qǐng)確保你在箱子斷電的狀態(tài)下把箱子連接到電腦的USB接口上同時(shí)安裝好驅(qū)動(dòng)的前提下驹碍,已經(jīng)把箱子連接到電腦的USB接口,打開了箱子的電源)
然后彈出一個(gè)窗口嚼酝,選擇No(一定要選擇No)
然后右鍵那個(gè)可愛(ài)的綠色的圖標(biāo),選擇program即可將你的程序下載到箱子上闽巩,如果一切順利的話就大功告成了钧舌。
不過(guò)一般來(lái)說(shuō)呢担汤,只有少數(shù)的人是一次編譯能過(guò)的,你在modelsim里面可以通過(guò)編譯的敵方洼冻,到了ISE里面一綜合就告訴你有一大堆error崭歧。盡管我開始做的時(shí)候已經(jīng)很注意語(yǔ)法問(wèn)題,但是編譯的時(shí)候還是有一些小的bug撞牢。遇到了bug的時(shí)候下面都會(huì)有提示率碾,一般來(lái)說(shuō)只要按照那個(gè)提示就可以把你的程序改成沒(méi)有error(可沒(méi)說(shuō)你沒(méi)有error就可以正常按照預(yù)想運(yùn)行了)。
我們編譯的時(shí)候可能遇到的error差不多有這么幾種(如果你在做課設(shè)之前就看到個(gè)屋彪,在最開始做的時(shí)候就可以直接避免掉)
一個(gè)wire被多個(gè)端口驅(qū)動(dòng)播掷。說(shuō)白了就是你一個(gè)wire,或者一個(gè)reg用多種方式被驅(qū)動(dòng)了
input和output寫錯(cuò)了撼班。很奇怪的是這種方式在modelsim里面一點(diǎn)問(wèn)題都沒(méi)有,仿真的時(shí)候也不會(huì)有任何問(wèn)題垒酬,尤其是input端口砰嘁,好像一個(gè)個(gè)都是雙向端口
wire的名字寫錯(cuò)了。這個(gè)在modelsim里面和ISE里面都不會(huì)報(bào)錯(cuò)勘究,但是實(shí)際上modelsim和ISE里面矮湘,所有的沒(méi)定義過(guò)的變量全部都被系統(tǒng)默認(rèn)為是一個(gè)一位的變量,而Verilog是區(qū)分變量的大小寫的口糕,所以哪怕是你定義了一個(gè)regFile變量缅阳,后來(lái)寫成了regfile,編譯器也不會(huì)報(bào)錯(cuò)景描,而是會(huì)當(dāng)成一個(gè)全新的一位變量十办,然后就是莫名其妙的錯(cuò)誤。
對(duì)于一個(gè)變量超棺,阻塞賦值和非阻塞賦值混合使用向族,即既對(duì)一個(gè)變量用了=賦值,也用了<=賦值棠绘。
這樣就結(jié)束了嗎件相?當(dāng)然不是的。對(duì)于實(shí)際的硬件下載而言氧苍,還有兩個(gè)很重要的事情:
在modelsim的時(shí)候夜矗,老師會(huì)讓我們用code.txt來(lái)向寄存器中加載十六進(jìn)制的MIPS指令,但是$readmemh()指令實(shí)際上是一個(gè)只有仿真的時(shí)候才能使用的指令让虐,到了實(shí)際下載的時(shí)候紊撕,如果你沒(méi)有做出改進(jìn),那么到你的板子上的就是一大堆沒(méi)有任何內(nèi)容的寄存器而已澄干。
同理逛揩,初始化指令柠傍,即initial指令也是只有在仿真的時(shí)候才有效的指令,據(jù)說(shuō)有的板子支持辩稽,但至少我們的板子是不支持的惧笛。
所以,我們不能用寄存器去存儲(chǔ)我們的MIPS指令逞泄,而要用到IP核來(lái)制作im患整,儲(chǔ)存MIPS指令,同時(shí)dm最好也用IP核喷众。不過(guò)project4中需要下到實(shí)驗(yàn)箱上的實(shí)驗(yàn)不需要dm也可以實(shí)現(xiàn)各谚,所以理論上來(lái)說(shuō)dm不做都可以,但是你還需要把所有涉及到dm的端口都去掉到千,不然可能連編譯都過(guò)不去……所以還是不要和自己作對(duì)昌渤,乖乖的用IP核吧。
下面說(shuō)一下IP核怎么使用憔四,先說(shuō)一下如何用IP核制作im:
首先膀息,右鍵你的工程,add new source了赵,打開新建窗口之后潜支,按照?qǐng)D中選擇,輸入文件名
然后在新建的窗口中做如圖所示選擇:
然后就是下一步柿汛,finish冗酿。
隨后等待系統(tǒng)生成IP核,具體時(shí)長(zhǎng)隨電腦的性能不同而不同络断,一般來(lái)說(shuō)十幾秒足夠了裁替,然后你會(huì)看到這個(gè)窗口,按照下圖做選擇:
下一步妓羊。
這里注意胯究,Memory type要選single port rom,同時(shí)不要選中那個(gè)32bit address躁绸,不然會(huì)出問(wèn)題裕循。
然后下一步中,read width輸入32净刮,即指令寬度為32位剥哑。read depth輸入1024,即支持1024條指令(其實(shí)這一個(gè)輸入其他的數(shù)字也可以淹父,理論上只要可以容納下你的所有指令就沒(méi)問(wèn)題株婴,不過(guò)設(shè)置成1024可以和你之前設(shè)計(jì)好的MIPS系統(tǒng)配合的更好,不需要進(jìn)行太多的改動(dòng),所以不推薦設(shè)置成其他的數(shù)值)
隨后是加載包含指令的coe文件困介,加載完之后大审,生成的ip核中即會(huì)自動(dòng)包含你的指令。coe文件的編輯方法老師會(huì)提供資料座哩,因此這里不再贅述徒扶,實(shí)在沒(méi)有的也可以來(lái)找我要。后面也還有一點(diǎn)關(guān)于coe文件制作的注意事項(xiàng)根穷。
之后還有兩步姜骡,不用管,直接選擇generate就可以屿良。加載coe文件的地方有一個(gè)show按鈕圈澈,可以顯示當(dāng)前coe文件中的指令以及對(duì)應(yīng)的條數(shù),因此generate之前可以看一下自己寫入的指令是否正確尘惧。
設(shè)置好了之后康栈,你就會(huì)看到你的文件列表中多了一個(gè)小燈泡圖標(biāo)的ip核,可是這個(gè)時(shí)候還是不能用喷橙。打開你的工程文件夾谅将,找到ipcore_dir目錄,直接打開和你剛才編輯好的ip核同名的.v文件重慢,即可看到你生成的IP核的接口,按照普通的im進(jìn)行調(diào)用就好逊躁。
打開這個(gè)文件就可以看到里面的接口定義似踱,然后當(dāng)成一般的模塊進(jìn)行調(diào)用就OK,如果你之前設(shè)計(jì)的im模塊正確的話稽煤,這個(gè)im的功能和你自己設(shè)計(jì)的都是一樣的核芽,可能端口的位數(shù)都一樣。至于內(nèi)部的邏輯是怎么寫的就不用管了酵熙,寫好的IP核以我們大部分人對(duì)于verilog語(yǔ)言的掌握水平是看不懂的(不用好奇為什么看起來(lái)和ISE的界面不一樣轧简,因?yàn)槲沂怯胢odelsim打開的這個(gè)文件)
在你的MIPS模塊中添加了用IP核構(gòu)建的im模塊后,你會(huì)發(fā)現(xiàn)那個(gè)im模塊就跑到了你的MIPS模塊下面匾二,說(shuō)明你的添加成功了哮独。
【需要注意一點(diǎn),IP核的im是有時(shí)鐘的察藐,所以用了IP核的im皮璧,需要讓狀態(tài)機(jī)多出一個(gè)狀態(tài)讀取im指令,只需要簡(jiǎn)單的修改一下你的狀態(tài)機(jī)就可以了】
關(guān)于coe文件分飞,編寫的時(shí)候需要做到行數(shù)和指令的地址相對(duì)應(yīng)悴务。所以編寫的時(shí)候需要注意你的指令放在了coe文件的多少行。如果你是用記事本編輯的譬猫,那么記事本下面的狀態(tài)欄就有行數(shù)顯示讯檐。如果發(fā)現(xiàn)狀態(tài)欄沒(méi)有行數(shù)顯示棺耍,而且不能在選項(xiàng)里勾選狀態(tài)欄,只需要把自動(dòng)換行取消就可以解決問(wèn)題纺棺。
coe文件的指令地址是從0開始的携栋,而記事本的行數(shù)是從1開始的,計(jì)算指令的地址的時(shí)候記得在記事本顯示的行數(shù)上減1(因?yàn)橛浭卤撅@示行數(shù)還有上面兩行聲明格式的語(yǔ)句蕉拢,所以實(shí)際上不只是減1特碳,到時(shí)候自己看一下就明白了)
還需要注意的一點(diǎn)就是PC的起始地址和中斷指令的地址。做MIPS系統(tǒng)的時(shí)候晕换,老師會(huì)要求你把你的起始地址設(shè)置為0x0000_3000午乓,把中斷服務(wù)程序的起始地址設(shè)置為0x0000_3180。但是在coe文件中闸准,你的中斷服務(wù)程序和主程序放在了同一個(gè)文件里面益愈,中斷服務(wù)程序和主程序之間需要有一些間隔,所以主程序和中斷服務(wù)程序之間就需要用一些程序語(yǔ)句隔開(直接用00000000指令就可以)夷家,如果你是按照3180來(lái)做的話蒸其,中斷服務(wù)程序應(yīng)該是從程序的96行開始,一定要注意中間填充的行數(shù)不要出錯(cuò)库快∶或者也可以手動(dòng)修改一下中斷服務(wù)程序的起始地址,如果你的主程序只有20行义屏,你可以把中斷服務(wù)程序設(shè)計(jì)在第25行靠汁,也就是0x0000_3064的位置,這樣中間就可以少幾個(gè)間隔的代碼闽铐。我覺(jué)得兩種方式都差不多蝶怔,用哪一種都是可以的。
dm模塊的添加和im模塊的添加類似兄墅,主要區(qū)別有兩個(gè)踢星,一個(gè)是這里要選擇的是single port ram:
還有就是dm就不要加載coe文件了。不過(guò)就像是我之前說(shuō)的隙咸,可能是用不到dm的(如果我們的課設(shè)題目一樣的話)沐悦,所以你的dm怎么設(shè)置都不要緊,定義成一個(gè)空的模塊都行hhhh(不過(guò)要是題目變了可能就不是這么簡(jiǎn)單了五督,所以還是推薦老老實(shí)實(shí)的把dm模塊定義好)
還有一個(gè)是用來(lái)分頻的clk模塊所踊,我們的系統(tǒng)提供的是100MHz的時(shí)鐘,但是并不是所有的模塊都需要用到這么高的頻率概荷,比如動(dòng)態(tài)數(shù)碼管顯示模塊就需要稍微低一些的頻率保證刷新時(shí)候的穩(wěn)定性秕岛,這個(gè)時(shí)候我們就需要對(duì)時(shí)鐘進(jìn)行分頻。有兩個(gè)方式可以進(jìn)行分頻,一個(gè)時(shí)鐘IP核模塊继薛,一個(gè)是自己手寫分頻模塊修壕。手寫分頻模塊就是一個(gè)簡(jiǎn)單的計(jì)數(shù)器,這里不再贅述遏考,主要說(shuō)一下如何調(diào)用IP核模塊進(jìn)行分頻慈鸠。
進(jìn)行分頻的IP核模塊最多只能把100MHz的始終分頻成3.125MHz,需要再低的頻率還是需要手寫分頻模塊灌具。盡管當(dāng)時(shí)老師說(shuō)的是100MHz的頻率太快青团,我們需要降頻,但我特意測(cè)試了一下直接用100MHz咖楣,并沒(méi)有什么問(wèn)題督笆,所以這個(gè)IP核降頻模塊其實(shí)可以省了。
具體的添加步驟如下诱贿。和之前要做的工作一樣娃肿,new source,選擇IP核珠十,之后選擇clocking wizard:
之后next到這一步料扰,在圖中的輸入你的輸入時(shí)鐘的頻率,這里輸入100MHz即可
之后next焙蹭,輸入你想要分頻的時(shí)鐘頻率晒杈。需要注意的是request里面是你輸入的值,actual里面是時(shí)鐘實(shí)際上可以分頻的值孔厉,如果你輸入的值小于3.125桐智,那么你會(huì)發(fā)現(xiàn)actual里面的值就是3.125,使用的時(shí)候你分頻的時(shí)鐘頻率也是3.125MHz而不是你輸入的數(shù)值烟馅,這是需要注意的。
再下一步然磷,建議這里把reset和lock接口都取消掉郑趁,避免發(fā)生未知的意外。再之后一路下一步姿搜,最后generate就OK寡润。
生成clock模塊之后,在MIPS或者minimaching模塊中調(diào)用的方式和調(diào)用im舅柜,dm的時(shí)候是一樣的梭纹,重復(fù)上面的過(guò)程即可。
接下來(lái)是引腳分配軟件的使用方法致份。還記得上面的這張圖嗎
雙擊這里之后变抽,會(huì)彈出一個(gè)獨(dú)立的窗口,專門負(fù)責(zé)引腳的分配。其實(shí)還可以通過(guò)ucf文件直接分配绍载,而且如果ucf文件用的好的話诡宗,是比軟件直接分配效果要好的(就像你用命令行操作軟件能實(shí)現(xiàn)的功能一般都比圖形化能實(shí)現(xiàn)的要多),但是這個(gè)貴在直觀击儡,誰(shuí)都能用塔沃,沒(méi)啥水平要求。
打開之后阳谍,經(jīng)過(guò)了短暫的加載蛀柴,會(huì)出現(xiàn)一個(gè)這樣的界面:
看見(jiàn)我的圈的那一堆東西了嗎
這些東西啊
都沒(méi)用
你需要的是下面這部分:
下面我拿一個(gè)端口舉例如何進(jìn)行引腳的分配:
左邊第一個(gè)紅圈里面圈的是一個(gè)引腳的輸出/輸入屬性,即output矫夯,input鸽疾,這個(gè)不用多說(shuō),你們懂的茧痒。第二個(gè)紅圈里面的是對(duì)應(yīng)的分配到FPGA芯片上面的引腳肮韧。具體如何分配這一對(duì)引腳,哪一個(gè)引腳對(duì)應(yīng)的是什么功能接下來(lái)會(huì)說(shuō)旺订。
所有的引腳都按照這種方式分配完畢弄企,別的都可以保持默認(rèn)設(shè)置不動(dòng),分配完之后区拳,點(diǎn)擊左上角的保存即可將你分配好的引腳配置文件保存起來(lái)拘领,然后退出或者不退出都隨你。
至于引腳到底要怎么分配呢樱调?很遺憾的是這個(gè)箱子并沒(méi)有幫助文件约素,所以我們是不能通過(guò)看文檔了解里面的引腳分配情況的。不過(guò)老師給了我們一個(gè)廠家做好的測(cè)試文件笆凌,打開那個(gè)測(cè)試文件圣猎,可以看到對(duì)應(yīng)的引腳分配情況。只要按照那個(gè)引腳分配文件進(jìn)行分配就可以了乞而。
如果你還嫌麻煩的話送悔,下面是我在做這個(gè)課設(shè)的時(shí)候需要的所有引腳分配表,也可以直接用爪模。(為什么我沒(méi)有列一個(gè)表呢……這樣方便你批量用文本編輯軟件替換扒菲 )
NET "reset" LOC = AE9; //reset按鍵,是哪個(gè)按鍵下面會(huì)說(shuō)
NET "clk" LOC = D14; //時(shí)鐘屋灌,默認(rèn)100MHz
NET "dcom1" LOC = AA11; ** //靜態(tài)數(shù)碼管的總使能**
NET "ledout[7]" LOC = AB17;//以下的ledout分別對(duì)應(yīng)靜態(tài)數(shù)碼管的各個(gè)數(shù)碼管洁段,具體的顯示數(shù)字代碼后面會(huì)發(fā)
NET "ledout[6]" LOC = AF15;
NET "ledout[5]" LOC = AD17;
NET "ledout[4]" LOC = AC16;
NET "ledout[3]" LOC = AD15;
NET "ledout[2]" LOC = AC17;
NET "ledout[1]" LOC = AC15;
NET "ledout[0]" LOC = V15;
NET "dout1[7]" LOC = AB15;//dout1對(duì)應(yīng)的是右側(cè)的一組動(dòng)態(tài)數(shù)碼管,具體的顯示數(shù)字代碼一樣在后面有
NET "dout1[6]" LOC = Y15;
NET "dout1[5]" LOC = AD14;
NET "dout1[4]" LOC = Y14;
NET "dout1[3]" LOC = AA15;
NET "dout1[2]" LOC = AC14;
NET "dout1[1]" LOC = AF14;
NET "dout1[0]" LOC = AA14;
NET "dout2[7]" LOC = AC13;//dout2對(duì)應(yīng)的是左側(cè)一組的動(dòng)態(tài)數(shù)碼管
NET "dout2[6]" LOC = AD12;
NET "dout2[5]" LOC = AA12;
NET "dout2[4]" LOC = AA13;
NET "dout2[3]" LOC = AF12;
NET "dout2[2]" LOC = AD13;
NET "dout2[1]" LOC = AC12;
NET "dout2[0]" LOC = AB13;
NET "dsel1[3]" LOC = V12;//右側(cè)一組動(dòng)態(tài)數(shù)碼管的掃描信號(hào)接入端
NET "dsel1[2]" LOC = W12;
NET "dsel1[4]" LOC = AD11;
NET "dsel1[1]" LOC = AE11;
NET "dsel2[4]" LOC = AB11;//左側(cè)一組動(dòng)態(tài)數(shù)碼管的掃描信號(hào)接入端
NET "dsel2[3]" LOC = V13;
NET "dsel2[1]" LOC = AC11;
NET "dsel2[2]" LOC = W14;
NET "switch[0]" LOC = C7;//32個(gè)撥動(dòng)開關(guān)
NET "switch[1]" LOC = A6;
NET "switch[2]" LOC = B6;
NET "switch[3]" LOC = A5;
NET "switch[4]" LOC = C5;
NET "switch[5]" LOC = A4;
NET "switch[6]" LOC = B4;
NET "switch[7]" LOC = A2;
NET "switch[8]" LOC = C11;
NET "switch[9]" LOC = C6;
NET "switch[10]" LOC = D6;
NET "switch[11]" LOC = A9;
NET "switch[12]" LOC = C9;
NET "switch[13]" LOC = A8;
NET "switch[14]" LOC = B8;
NET "switch[15]" LOC = A7;
NET "switch[16]" LOC = C15;
NET "switch[17]" LOC = C14;
NET "switch[18]" LOC = B14;
NET "switch[19]" LOC = A13;
NET "switch[20]" LOC = C13;
NET "switch[21]" LOC = A12;
NET "switch[22]" LOC = B12;
NET "switch[23]" LOC = A11;
NET "switch[24]" LOC = D21;
NET "switch[25]" LOC = C18;
NET "switch[26]" LOC = D18;
NET "switch[27]" LOC = A17;
NET "switch[28]" LOC = C17;
NET "switch[29]" LOC = A16;
NET "switch[30]" LOC = B16;
NET "switch[31]" LOC = A15;
以上內(nèi)容是從ucf文件中直接復(fù)制過(guò)來(lái)的共郭,想要直接編輯ucf文件的祠丝,選中你的ucf文件疾呻,然后雙擊下面的edit contraints
然后請(qǐng)自便hhh
其實(shí)箱子上還有兩個(gè)需要我們注意的地方。第一點(diǎn)就是箱子上的白色按鍵(不是撥動(dòng)開關(guān))按下的時(shí)候是斷開纽疟,松開的時(shí)候是連通狀態(tài)罐韩,放到電路中就是說(shuō)不按下的時(shí)候?yàn)?,按下的時(shí)候?yàn)?污朽。同時(shí)按下按鍵的時(shí)候可以提供一個(gè)下降沿散吵,但是松開的時(shí)候是沒(méi)有上升沿的。關(guān)于這個(gè)蟆肆,我們有兩個(gè)解決方式矾睦,一種是在reset部分,將所有的reset條件0與1互換炎功,同時(shí)上升沿觸發(fā)改為下降沿觸發(fā)枚冗,但是這樣非常的麻煩;另一種方式就是在你的top level模塊下單獨(dú)做一個(gè)用來(lái)翻轉(zhuǎn)reset信號(hào)的wire變量蛇损,比如resetwire赁温,然后用:
assign resetwire=~reset
語(yǔ)句實(shí)現(xiàn)reset信號(hào)的翻轉(zhuǎn),這樣其他的設(shè)計(jì)就不用變了淤齐。
對(duì)了股囊,有人可能會(huì)問(wèn)reset按鍵是啥,就是紅圈里的這個(gè)按鍵:
另外還有一點(diǎn)更啄,就是箱子上的數(shù)碼管為1亮0滅稚疹,在上學(xué)期做過(guò)數(shù)字邏輯實(shí)驗(yàn)的都知道數(shù)字邏輯實(shí)驗(yàn)箱子上的數(shù)碼管是0亮1滅。因此你不能直接照搬數(shù)字邏輯實(shí)驗(yàn)的時(shí)候使用的數(shù)碼管顯示模塊祭务,還是需要自己寫一個(gè)的内狗。
這里附上一個(gè)寫好的數(shù)字顯示模塊,里面有0~F所有的數(shù)碼管顯示編碼义锥,拿來(lái)直接用就好柳沙,不能直接用的也省得你一個(gè)個(gè)試一個(gè)個(gè)算。
(這里感謝一下降云鵬同學(xué)給我做的數(shù)碼管顯示模塊拌倍,當(dāng)時(shí)我忙于調(diào)試我的主程序赂鲤,沒(méi)有時(shí)間做那個(gè)數(shù)碼管的部分,他把他做好的數(shù)碼管模塊直接給了我贰拿,真的是幫了大忙了)
assign dout = (now_num == 4'h0) ? (8'b11111100) :
(now_num == 4'h1) ? (8'b01100000):
(now_num == 4'h2) ? (8'b11011010):
(now_num == 4'h3) ? (8'b11110010):
(now_num == 4'h4) ? (8'b01100110):
(now_num == 4'h5) ? (8'b10110110):
(now_num == 4'h6) ? (8'b10111110):
(now_num == 4'h7) ? (8'b11100000):
(now_num == 4'h8) ? (8'b11111110):
(now_num == 4'h9) ? (8'b11110110):
(now_num == 4'hA) ? (8'b11101110):
(now_num == 4'hB) ? (8'b00111110):
(now_num == 4'hC) ? (8'b10011100):
(now_num == 4'hD) ? (8'b01111010):
(now_num == 4'hE) ? (8'b10011110):
(now_num == 4'hF) ? (8'b10001110):
8'b11111111;
我們?cè)谙渥由险{(diào)試程序的時(shí)候,最麻煩的就是當(dāng)我們的箱子不能正常工作的情況比較嚴(yán)重的時(shí)候熄云,我們不能像仿真的時(shí)候一樣去查看每一條線的信號(hào)情況膨更,去看每一個(gè)寄存器中的數(shù)據(jù)到底是什么,究竟是哪一步出了錯(cuò)誤缴允。所以我們開始的時(shí)候可以先做好靜態(tài)數(shù)碼管和動(dòng)態(tài)數(shù)碼管顯示的部分荚守,之后就可以利用八位數(shù)字的動(dòng)態(tài)數(shù)碼管珍德,直接顯示某一條線(比如PC輸出的指令地址,比如im輸出的指令信息矗漾,比如ALU的計(jì)算結(jié)果锈候,比如從GPR中取出的數(shù)據(jù)等等)的32位信號(hào)情況,同時(shí)可以用靜態(tài)數(shù)碼管連接狀態(tài)機(jī)敞贡,顯示當(dāng)前的狀態(tài)泵琳,根據(jù)你的指令和狀態(tài)機(jī)設(shè)計(jì)情況,即可觀察出執(zhí)行到了哪一步指令的時(shí)候誊役,你想要觀察的線是什么信號(hào)获列,然后繼續(xù)推測(cè)出究竟是哪里出了問(wèn)題(干這個(gè)之前一定要確定你的引腳是不是分配錯(cuò)了啊,要是引腳都分配錯(cuò)了那可是怎么調(diào)都沒(méi)用的)蛔垢。
根據(jù)這個(gè)還可以衍生出一種方法击孩,即可以把一些32位信號(hào)的一部分接到動(dòng)態(tài)數(shù)碼管的一部分上,這樣一個(gè)動(dòng)態(tài)數(shù)碼管就可以顯示多個(gè)信號(hào)鹏漆,這樣你就可以同時(shí)觀察多個(gè)信號(hào)了巩梢。但是自己要記得你設(shè)置的顯示順序,自己亂了就不好了艺玲。
你說(shuō)頻率太快了括蝠,接到數(shù)碼管上也看不清?頻率太快了咱們可以分頻啊板驳,難不成分到1Hz你還看不清么
還有又跛,用這個(gè)方法之前,請(qǐng)保證你的仿真沒(méi)有問(wèn)題若治,仿真都不對(duì)就不要下箱子啊
除了這個(gè)之外慨蓝,上箱子調(diào)試的時(shí)候還有一些需要注意的地方。我們的MIPS系統(tǒng)做完了之后是需要執(zhí)行MIPS匯編指令的端幼,即使MIPS系統(tǒng)做的沒(méi)有問(wèn)題礼烈,但是指令寫錯(cuò)了也會(huì)造成你的運(yùn)行結(jié)果不對(duì),一定要根據(jù)你的各個(gè)部件設(shè)計(jì)以及運(yùn)行規(guī)則婆跑,好好弄清楚每一個(gè)指令的作用此熬,保證不同的寄存器之間沒(méi)有沖突,指令的順序也要正確滑进。
如果不能保證你的所有指令都是正確的犀忱,可以先把你的指令簡(jiǎn)化,分成幾個(gè)部分或者編寫一些獨(dú)立的小程序測(cè)試某幾條指令是否正確扶关,一步一步化解問(wèn)題阴汇。
不同的人設(shè)計(jì)的外設(shè)部件可能不一樣,尤其是Timer节槐,需要裝載計(jì)時(shí)初值和計(jì)時(shí)方式搀庶,如果你的模塊設(shè)計(jì)的不是特別完善的話拐纱,裝載計(jì)時(shí)器初值和計(jì)時(shí)方式的順序也可能對(duì)你的程序運(yùn)行是否正確產(chǎn)生影響,所以這個(gè)的順序也要列入考慮之中哥倔。
還有一個(gè)很多人可能會(huì)忽視的秸架,就是"偽指令"帶來(lái)的影響。比如如果你寫了一個(gè)這樣的指令:
編譯之后咆蒿,實(shí)際上指令是三條:
這是因?yàn)?strong>MIPS最多只支持16位的立即數(shù)相加东抹,當(dāng)立即數(shù)超過(guò)16位時(shí),就會(huì)翻譯成多條其它指令來(lái)滿足你的要求蜡秽。一般來(lái)說(shuō)是不會(huì)出問(wèn)題的府阀,可是本來(lái)一條add指令,需要用到lui芽突,ori试浙,add三條指令,如果你其中的某一條指令有問(wèn)題寞蚌,而在你自己寫的主程序里面沒(méi)有用到但是卻在翻譯偽代碼的時(shí)候被用到了田巴,那么也可能會(huì)出現(xiàn)一些不可預(yù)知的問(wèn)題。
這種偽指令還有另一種可能的情況挟秤,如果是這種的話就更復(fù)雜了壹哺。請(qǐng)看如下測(cè)試代碼:
我們期望的結(jié)果是
$1=1
$8=0x500001
但是實(shí)際上翻譯成的指令是這樣的:
最后的結(jié)果是$1=$8=0x500001
注意到了嗎,翻譯的偽指令用到了$1寄存器艘刚,所以你在開始的時(shí)候設(shè)置的$1=1被后來(lái)的偽指令改寫了管宵。如果出現(xiàn)了這樣的問(wèn)題,那么即使你的所有指令都能正確執(zhí)行攀甚,也不能保證你最后的結(jié)果完全正確箩朴。其實(shí)這個(gè)很簡(jiǎn)單,因?yàn)樵贛IPS中秋度,每一個(gè)寄存器都是有自己的功能的炸庞,所以翻譯成偽指令的時(shí)候,調(diào)用的就是$1來(lái)保存臨時(shí)值荚斯,如果我們嚴(yán)格按照MIPS的標(biāo)準(zhǔn)進(jìn)行編程的話埠居,這個(gè)也不是問(wèn)題,但是我們往往做不到這一點(diǎn)事期,所以還是盡量避免偽指令的生成比較好滥壕。
解決方法很簡(jiǎn)單,我們只需要人工執(zhí)行兩條指令兽泣,就可以避免偽指令給我們帶來(lái)隱患了:
lui $8,0x50
ori $8,$8,0x1
這下就不涉及到其他的寄存器操作绎橘,同時(shí)編譯器也不會(huì)把一條指令翻譯成多條指令執(zhí)行
這里再簡(jiǎn)單的說(shuō)一下外設(shè)的運(yùn)行方式以及操作外設(shè)的方法。
有的人剛接觸到外設(shè)的時(shí)候會(huì)比較茫然撞叨,又是LED又是定時(shí)器又是開關(guān)金踪,但是MIPS里面有沒(méi)有針對(duì)于那幾個(gè)外設(shè)的操作語(yǔ)句,所以完全摸不到頭腦應(yīng)該如何控制外設(shè)牵敷。
其實(shí)老師上課的時(shí)候說(shuō)過(guò)胡岔,外設(shè)其實(shí)就是另外一種形式的dm。我們實(shí)現(xiàn)的時(shí)候枷餐,是用lw靶瘸,sw來(lái)實(shí)現(xiàn)對(duì)dm的讀寫,所以對(duì)于外設(shè)毛肋,我們也用lw怨咪,sw來(lái)實(shí)現(xiàn)對(duì)外設(shè)的讀寫。
對(duì)于一個(gè)已經(jīng)寫好了的計(jì)時(shí)器模塊润匙,我們需要在MIPS中進(jìn)行的操作其實(shí)只有這么幾種:對(duì)計(jì)時(shí)器的計(jì)數(shù)模式寄存器寫入計(jì)數(shù)模式诗眨,對(duì)計(jì)時(shí)器的初值模塊寫入初值。如果把計(jì)時(shí)器的寄存器全都理解成dm孕讳,就可以特別清楚的發(fā)現(xiàn)其實(shí)就是用sw語(yǔ)句去往計(jì)時(shí)器中寫入數(shù)據(jù)匠楚,至于寫入數(shù)據(jù)的地址和寫入的數(shù)據(jù)就通過(guò)各種運(yùn)算儲(chǔ)存在GPR的寄存器當(dāng)中。那么如何區(qū)別什么時(shí)候?qū)懭雂m厂财,什么時(shí)候?qū)懭胗?jì)時(shí)器呢芋簿?我們做dm的時(shí)候,只用到了指令中的10位璃饱,算上低兩位一共是12位与斤,還有20位沒(méi)有使用。所以當(dāng)我們需要操作的地址高20位全0的時(shí)候荚恶,我們操作的就是dm撩穿,如果高20位是我們?cè)O(shè)置好的某一個(gè)數(shù)值,那么操作的就是外設(shè)裆甩。具體的實(shí)現(xiàn)是在ctrl和bridge里面共同實(shí)現(xiàn)的冗锁。開關(guān)和LED顯示模塊也是一樣,其中開關(guān)涉及到的只有讀取操作嗤栓,畢竟你不能向開關(guān)中寫入數(shù)據(jù)冻河;LED涉及到的只有寫入操作。
這個(gè)教程就到這里啦茉帅。
除了這個(gè)之外叨叙,我還寫了一篇文章,主要關(guān)于Verilog以及quartus軟件的一些使用上可能出現(xiàn)的疑問(wèn)堪澎,有需要的可以去我的主頁(yè)查看擂错。