• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

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

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

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

      狀態機基本上與系統所有的組件都連接到一起了,因為上面所說的所有動作的執行,都需要狀態機的控制,狀態機其實就是由一部分觸發器構成的記憶電路和另外一部 分組合邏輯構成的次態譯碼電路構成,還有根據當前狀態和輸入進行譯碼的部分用于控制各個部件,下面是教科書上的典型FSM結構:

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

      而我們用的狀態機狀態轉移圖如下:

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

      因為這個處理器設計的很簡單,所以沒有出現很多狀態,當處理器經歷完以上的狀態之后,處理器就執行完了一條指令。

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

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

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

      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 $

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

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

      轉換成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

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

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

      而r1則從100變化到0,變化到0后程序將進入死循環,停止在jmp $那一條。這是仿真開始的時候:

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

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

      而且大家可以看到,d2從0變化到了0x64也就是十進制100,說明已經執行了第一次加法了。

      再來看看仿真結束:

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

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

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

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

      mov [addr],src 將src的值送到以addr位地址的內存單元

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

      cmp dst,src 將dst減去src 然后不送到dst中 只改變標志位

      jz dst 當zf=1時(即上次的算術操作結果為0)則跳轉到dst中去

      最后再提一下:

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


    上一頁 1 2 3 下一頁

    關鍵詞: CPU RISC

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 安庆市| 绥江县| 临安市| 永善县| 天峻县| 恩平市| 敦煌市| 榆社县| 万宁市| 扎兰屯市| 城口县| 湄潭县| 民乐县| 景谷| 陆川县| 富裕县| 江安县| 临泉县| 陆川县| 金华市| 安庆市| 天峻县| 兴海县| 新和县| 新巴尔虎右旗| 柞水县| 炎陵县| 罗江县| 通河县| 凤山县| 象山县| 思南县| 甘南县| 古丈县| 浑源县| 海门市| 高州市| 古蔺县| 汉阴县| 西昌市| 景泰县|