16位CPU怎么做,DIY大神給你支支招兒
狀態(tài)機(jī)基本上與系統(tǒng)所有的組件都連接到一起了,因?yàn)樯厦嫠f的所有動(dòng)作的執(zhí)行,都需要狀態(tài)機(jī)的控制,狀態(tài)機(jī)其實(shí)就是由一部分觸發(fā)器構(gòu)成的記憶電路和另外一部 分組合邏輯構(gòu)成的次態(tài)譯碼電路構(gòu)成,還有根據(jù)當(dāng)前狀態(tài)和輸入進(jìn)行譯碼的部分用于控制各個(gè)部件,下面是教科書上的典型FSM結(jié)構(gòu):
本文引用地址:http://butianyuan.cn/article/201903/398604.htm而我們用的狀態(tài)機(jī)狀態(tài)轉(zhuǎn)移圖如下:
因?yàn)檫@個(gè)處理器設(shè)計(jì)的很簡單,所以沒有出現(xiàn)很多狀態(tài),當(dāng)處理器經(jīng)歷完以上的狀態(tài)之后,處理器就執(zhí)行完了一條指令。
有的CISC的處理器用微指令進(jìn)行控制,作用和狀態(tài)機(jī)相近,這種結(jié)構(gòu)出現(xiàn)在一些比較古老的處理器上,因?yàn)槟莻€(gè)時(shí)候的設(shè)計(jì)工具和方法沒有現(xiàn)在的先進(jìn),所以往往 改動(dòng)硬件是困難的和高成本的,所以用微指令的話,做好了硬件的結(jié)構(gòu),要是需要改動(dòng)只要修改微指令就好了,而現(xiàn)在的電子技術(shù)很發(fā)達(dá),設(shè)計(jì)工具也很完備,所以 就有很多直接通過硬連線實(shí)現(xiàn)的處理器。
好馬配好鞍,有了處理器,我們就得給它配上一個(gè)好的程序,下面我們就用自己設(shè)計(jì)的處理器進(jìn)行求和,從1加到100,因?yàn)槲覀儧]有設(shè)計(jì)編譯器,也沒有設(shè)計(jì)匯編器,所以程序只能用機(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其實(shí)就是放求和的寄存器,最后我們會(huì)將r2中的值送到內(nèi)存中的某個(gè)地址存放的。
然 后將r1減去1,看看是否為0?如果為0則說明求和結(jié)束了,如果不是0則說明還要繼續(xù),結(jié)束后程序就跳到ext部分將結(jié)果存放到內(nèi)存中某個(gè)地址(例子中給 的是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è)計(jì)中CPU外圍還需要一個(gè)內(nèi)存設(shè)備(Memory),我用HDL對其建模,初始化的時(shí)候每個(gè)內(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 $那一條。這是仿真開始的時(shí)候:
大家可以看到初始化后,d0~d7都變成了0,這是r0~r7寄存器的Q端,而state_current和state_next則是狀態(tài)機(jī)的現(xiàn)態(tài)和狀態(tài)機(jī) 的次態(tài),cpu的各個(gè)部件都通過這個(gè)狀態(tài)機(jī)受到控制。狀態(tài)名出現(xiàn)的順序和上面的FSM Viewer的連線順序是一樣的。
而且大家可以看到,d2從0變化到了0x64也就是十進(jìn)制100,說明已經(jīng)執(zhí)行了第一次加法了。
再來看看仿真結(jié)束:
這時(shí)候d1變化到了0而d2變化到了0x13ba(十進(jìn)制的5050),說明程序已經(jīng)在我們設(shè)計(jì)的處理器里面運(yùn)行并且成功的得出了結(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í)(即上次的算術(shù)操作結(jié)果為0)則跳轉(zhuǎn)到dst中去
最后再提一下:
我是用synplify綜合的電路,然后用debussy+modelsim仿真的。
評論