<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > 16位CPU怎么做,DIY大神給你支支招兒

          16位CPU怎么做,DIY大神給你支支招兒

          作者: 時間:2019-03-19 來源:電子工程世界 收藏

            狀態(tài)機(jī)基本上與系統(tǒng)所有的組件都連接到一起了,因為上面所說的所有動作的執(zhí)行,都需要狀態(tài)機(jī)的控制,狀態(tài)機(jī)其實就是由一部分觸發(fā)器構(gòu)成的記憶電路和另外一部 分組合邏輯構(gòu)成的次態(tài)譯碼電路構(gòu)成,還有根據(jù)當(dāng)前狀態(tài)和輸入進(jìn)行譯碼的部分用于控制各個部件,下面是教科書上的典型FSM結(jié)構(gòu):

          本文引用地址:http://www.ex-cimer.com/article/201903/398604.htm
          16位CPU怎么做,DIY大神給你支支招兒

            而我們用的狀態(tài)機(jī)狀態(tài)轉(zhuǎn)移圖如下:

          16位CPU怎么做,DIY大神給你支支招兒

            因為這個處理器設(shè)計的很簡單,所以沒有出現(xiàn)很多狀態(tài),當(dāng)處理器經(jīng)歷完以上的狀態(tài)之后,處理器就執(zhí)行完了一條指令。

            有的CISC的處理器用微指令進(jìn)行控制,作用和狀態(tài)機(jī)相近,這種結(jié)構(gòu)出現(xiàn)在一些比較古老的處理器上,因為那個時候的設(shè)計工具和方法沒有現(xiàn)在的先進(jìn),所以往往 改動硬件是困難的和高成本的,所以用微指令的話,做好了硬件的結(jié)構(gòu),要是需要改動只要修改微指令就好了,而現(xiàn)在的電子技術(shù)很發(fā)達(dá),設(shè)計工具也很完備,所以 就有很多直接通過硬連線實現(xiàn)的處理器。

            好馬配好鞍,有了處理器,我們就得給它配上一個好的程序,下面我們就用自己設(shè)計的處理器進(jìn)行求和,從1加到100,因為我們沒有設(shè)計編譯器,也沒有設(shè)計匯編器,所以程序只能用機(jī)器碼寫出,示例程序如下:

            我們不妨先寫出程序的匯編代碼:

            mov [ADDR],r0;r0 = 0

            mov r1,100

            lop:add r2,r1

            sub r1,1

            cmp r1,0

            jz ext

            mov r4,4

            jmp r4(lop)

            ext:mov [ADDR],r2

            jmp $

            先將內(nèi)存中存放數(shù)據(jù)的地址清零,這樣才能存放等下送來的結(jié)果,然后將r1寄存器存入循環(huán)次數(shù)(也就是求和的上限)。然后再將r1的值加到r2中來,r2其實就是放求和的寄存器,最后我們會將r2中的值送到內(nèi)存中的某個地址存放的。

            然 后將r1減去1,看看是否為0?如果為0則說明求和結(jié)束了,如果不是0則說明還要繼續(xù),結(jié)束后程序就跳到ext部分將結(jié)果存放到內(nèi)存中某個地址(例子中給 的是49152也就是二進(jìn)制的1100000000000000b),最后jmp $是為了讓程序停在這一行,防止程序跑飛(跑飛的程序危害很大!有可能吧數(shù)據(jù)當(dāng)代碼或者把代碼當(dāng)數(shù)據(jù)!)

            轉(zhuǎn)換成VerilogHDL語言如下:

            module memory

            (

            input [15:0] addr,

            inout [15:0] data,

            input rw

            );

            reg [15:0] data_ram[0:16'b1111_1111_1111_1111];

            integer i;

            initial begin

            for (i = 0; i <= 16'b1111_1111_1111_1111; i = i + 1)

            data_ram[i] = $random();

            data_ram[0] = 16'b1000000100000000; //mov [ADDR],r0;r0 = 0

            data_ram[1] = 16'b1100000000000000; //ADDR

            data_ram[2] = 16'b1000000010001000; //mov r1,100

            data_ram[3] = 100; //100

            //data_ram[2] = 16'b1110011001000000;

            data_ram[4] = 16'b0010000100010001; //lop:add r2,r1

            data_ram[5] = 16'b1110000011001000; //sub r1,1

            data_ram[6] = 16'b0000000000000001; //1

            data_ram[7] = 16'b1110000000001000; //cmp r1,0

            data_ram[8] = 16'b0000000000000000; //0

            data_ram[9] = 16'b1110011010000000; //jz ext

            data_ram[10] = 16'b0000000000000011; //+3 offset(ext)

            data_ram[11] = 16'b1000000010100000;//mov r4,4

            data_ram[12] = 16'b0000000000000100;

            data_ram[13] = 16'b0110011001100000;//jmp r4(lop)

            data_ram[14] = 16'b1000000100000010;//ext:mov [ADDR],r2

            data_ram[15] = 16'b1100000000000000;//ADDR

            data_ram[16] = 16'b1110011001000000;//jmp $

            data_ram[17] = 16'b1111111111111110;//-2 offset($)

            /*data_ram[0] = 16'b1000000010000000; //mov r0,imm

            data_ram[1] = 16'b0011111111111111; //imm

            data_ram[2] = 16'b0000000001111000; //mov r7,r0

            data_ram[3] = 16'b1000000010011000; //mov r3,0

            data_ram[4] = 16'b0000000000000000;

            data_ram[5] = 16'b1000000010100000; //mov r4,code of jmp r5

            data_ram[6] = 16'b0110011001101000; //jmp r5

            data_ram[7] = 16'b0000000101011100; //mov [r3],r4

            data_ram[8] = 16'b1000000011110000; //mov r6,[0]

            data_ram[9] = 16'b0000000000000000; //[0]

            data_ram[10]= 16'b1000000100000110; //mov [255],r6

            data_ram[11]= 16'b0000000011111111;

            data_ram[12]= 16'b0110011001011000; //jmp r3

            */

            end

            always @ (addr or rw or data)

            if (rw)

            data_ram[addr] = data;

            assign data = rw ? 16'hzzzz : data_ram[addr];

            endmodule

            設(shè)計中外圍還需要一個內(nèi)存設(shè)備(Memory),我用HDL對其建模,初始化的時候每個內(nèi)存地址上對應(yīng)的數(shù)據(jù)都初始化為隨機(jī)的,然后只有從0開始的一系列地址被初始化為我寫的代碼,機(jī)器碼對應(yīng)的匯編指令在注釋中已經(jīng)給出。

            然后是結(jié)果,結(jié)果應(yīng)該是r2從0變化到5050(1+2+3+......+100=5050)

            而r1則從100變化到0,變化到0后程序?qū)⑦M(jìn)入死循環(huán),停止在jmp $那一條。這是仿真開始的時候:

          16位CPU怎么做,DIY大神給你支支招兒

            大家可以看到初始化后,d0~d7都變成了0,這是r0~r7寄存器的Q端,而state_current和state_next則是狀態(tài)機(jī)的現(xiàn)態(tài)和狀態(tài)機(jī) 的次態(tài),cpu的各個部件都通過這個狀態(tài)機(jī)受到控制。狀態(tài)名出現(xiàn)的順序和上面的FSM Viewer的連線順序是一樣的。

            而且大家可以看到,d2從0變化到了0x64也就是十進(jìn)制100,說明已經(jīng)執(zhí)行了第一次加法了。

            再來看看仿真結(jié)束:

          16位CPU怎么做,DIY大神給你支支招兒

            這時候d1變化到了0而d2變化到了0x13ba(十進(jìn)制的5050),說明程序已經(jīng)在我們設(shè)計的處理器里面運行并且成功的得出了結(jié)果!

            最后給出一些我用到的指令(跟x86的很像):

            add dst,src 將src和dst相加并且送到dst寄存器中

            mov [addr],src 將src的值送到以addr位地址的內(nèi)存單元

            sub dst,src 將dst減去src并且送到dst中去

            cmp dst,src 將dst減去src 然后不送到dst中 只改變標(biāo)志位

            jz dst 當(dāng)zf=1時(即上次的算術(shù)操作結(jié)果為0)則跳轉(zhuǎn)到dst中去

            最后再提一下:

            我是用synplify綜合的電路,然后用debussy+modelsim仿真的。


          上一頁 1 2 3 下一頁

          關(guān)鍵詞: CPU RISC

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();