CITIUS-ALTIUS-FORTIUS PROCESSOR Versiyon 1.02 15/04/2008 PROJE SORUMLUSU : BERKAY AYBAR MURAT GOKSEL E-MAIL : baybar@gmail.com, mgoksel@gmail.com
ICINDEKILER Tablo Listesi... Figur Listesi... 1 GIRIS... 1.1 FPGA... 1.2 RISC Islemci... 1.3 EDA Yazilimlari... 2 FPGA ile Fiziksel Islemci Tasarimi Uygulamasi... 2.1 RISC Komut Seti Mimarisi... 2.2 RISC Islemci Mimarisi... 2.3 RISC Islemci Verilog Uygulamasi... 2.3.1 Komut Yakalama Birimi... 2.3.2 Komut Cozumleme Birimi... 2.3.3 Kontrol Unitesi... 2.3.4 Calisma Unitesi... 2.3.5 Hafiza Birimleri... 2.4 16 bitlik Pipeline Islemci Uygulamasi 2.4.1 Pipeline Tehlikeleri... 2.5 Donanim Uygulamasi... 3 Sonuclar... 4 Gelicekte Yapilmasi Gereken Calismalar... 5 Sonuc... Referanslar... Appiks... A. Komut Aciklamari... B. CAF Processor Verilog Kodu... C. CAF Processor Testbench Verilog Kodu... D. Simulasyon Sonuclari... E. Kaynaklar... FPGA ile CPU tasarimi Page 2
CAF PROCESSOR PROJE OZETI Bu proje kapsaminda verilen komut setinin tasarimda oncelikli olarak en verimli sekilde gerceklenmesi on gorulmustur. Tasarimi zenginlestirmek icin verilen komut setine ek olarak guncel islemcilerde kullanilan yaygin komutlar da eklenicektir(orn: POP, PUSH ). Tasarim 16- bitlik pipelined RISC mimarisi gerceklestirilerek uygulanacaktir. CAF_Processor tasariminin dort farkli bolumden olusmasi on gorulmustur, bunlar sirasiyla; 1) Komut Yakalama Bolumu (Instruction Fetch Stage) 2) Komut Cozumleme Bolumu (Instruction Decoding Stage) 3) Calisma Bolumu (Execution Stage) 4) Geri Okuma Bolumu( Write Back Stage) Her bolum bir veya birden fazla verilog modulunden olusacaktir. Projenin iki fazdan olusturulmasi on gorulmustur. Birinci faz verilen komut kumesinin ve buna ek olarak guncel komutlarin kullanilacagi 16-bitlik RISC islemci tasarimidir. Ikinci faz da ek olarak IEEE 754 Floating Point Unitesi nin de donanima entegre edilip komut kumesini zenginlestirmek ayni zamanda tasarlanicak islemcinin islem yapabilme gucunu artirmak olarak hedeflenmistir. Proje kapsamin da tasarlanicak islemci ile ornek bir FIR filtre uygulamasi yapilmasi planlanmaktadir. Proje kapsaminda ozellikle fonksyonel simulasyonlari ve post-synthesis simulasyonlarini gerceklestirmek icin gerekli olan EDA yazilimlari ve bir gelistirme boardi talep edilmektedir. C, A, F harfleri latince Citius- Altius- Fortius kelimelerinin bas harflerinden gelmektedir. Latince de bu kelimeler sirasiyla Daha hizli, Daha Yuksek, Daha Guclu anlamina gelmektedir. Tasarlanicak islemcininde butun bu ozellikleri saglamasi hedefligi icin bu isim proje icin uygun gorulmustur. FPGA ile CPU tasarimi Page 3
1 Add Addition 20 Lw Load word 2 Addi Addition (immediate) 21 Sw Store word 3 Sub Subtraction 22 Mov Move data between registers 4 Subi Subtraction (immediate) 23 Movi Move data (immediate) 5 Mul Multiplication 24 Beq Branch if equal to 0 6 Muli Multiplication (immediate) 25 Bne Branch if not equal to 0 7 Mulu Multiplication (unsigned) 26 Ba Branch always 8 Cmp Compare 27 BL Branch and Link 9 And AND 28 Nop No operation 10 Andi AND (immediate) 29 Hlt Halt 11 Or OR 30 Syscall System call (software interrupt) 12 Ori OR (immediate) 13 Not NOT 14 Xor XOR 15 Xori XOR (immediate) 16 Sll Logical shift left 17 Srl Logical shift right 18 Sla Arithmetic shift left 19 Sra Arithmetic shift right FPGA ile CPU tasarimi Page 4
FPGA ile CPU tasarimi Page 5
1 GIRIS 1.1 FPGA Bu projenin amaci FPGA icerisinde 16 bitlik RISC islemci tasarlamak ve bu islemciyi kullanarak bir uygulama gerceklestirmektir. Bu p roje raporu ileride egitim amacli kullanicagi dusunulerek sayisal tasarim ve FPGA teknolojisi hakkinda genel bilgilerde icermektedir. FPGA teknolojisi sayisal tasarimcilara cok buyuk esneklik saglamaktadir.bunun en buyuk sebeplerinden biri FPGA in tekrar programlanabilmesidir. Ayni zamanda FPGA lerin kismen dusuk fiyatli olmasi ve FPGA sirketlerinin(xilinx, Altera, Actel gibi...) sagladiklari gelismis yazilim araclari sayisal tasarimla ugrasan donanim muhislerinin hayatini kolaylastirir. FPGA ile yeni calismaya baslayan genc muhensdiler genellikle FPGA yi farkli bir tur mikroislemci sanarlar. Fakat FPGA kullanim amaci ile mikroislemcinin kullanim amaci bir cok zaman birbirlerinden cok farklidir. FPGA in iki farkli kullanim alani vardir bunlardan ilki ASIC prototip gerceklemesidir. ASIC tasarimcilari yaptiklari tasarimlari bilgisayar uzerinde yaptiklari simulasyonlardan sonra FPGA uzerine tasirlar. Cunku FPGA uzerine tasinan bir tasarim gercek zamanda fonksyonellik gosterir. Tasarimci kisinden istenen tasarimin kriterleri gerceklesip gerceklesmedigini bu evrede test etme sansi bulunur.tasarim muhisleri icin tasarimlarinin kriterleri olusturup olusturmadigini gormelerini saglayan onemli bir firsattir. Bundan sonraki adim tasarimin ASIC(Chip) in fabrikasyonu icin proses e gonderilmesidir. FPGA baska bir kullanim alani ise dusuk hacimde sistem uretimlerinde ASIC ye bir alternatiftir. ASIC uretimi cok maliyetli bir is oldugu icin ancak yuksek hacimde uretim yapildigi zaman ASIC in birim fiyati makul bir degere ulasir. Ama eger yuksek hacimli bir uretim yapilmayacaksa ASIC uretimi cok pahali olabilir. Bu noktada FPGA boslugu doldurur tasarimcilara hem fiyat hemde tasarim kolayligi acisindan cok fazla avantaj saglar. Tasarlanicak olan spesifik devre FPGA icinde gerceklestirilir ve sistem icinde calistirilir. FPGA ile CPU tasarimi Page 6
1.2 RISC Islemci Bu projede yer alan islemci mimarisi RISC islemci mimarisidir. RISC (Reduced Instruction Set Computer ) Komut Seti Azaltilmis Bilgisayar anlamina gelmektedir. Komut setinin azaltilmasi, cogu zaman islemcinin komut kumesindeki kompleks komutlarin cikartilmasi ile gerceklesir. Bu RISC islemci mimarisini daha az kompleks yapar. RISC islemcilerde asil amac tasarlanan komut kumesini basit yapmak ve bunun sonucunda komutlari hizli isleyen bir islemci elde etmektir. RISC islemcilerde komutlarin islenmesi bir saat cevrimi surer ve komutlarin uzunlugu sabittir. RISC islemci mimarisi bir baska islemci mimarisi olan CISC(Complex Instruction Set Computer) mimarisine alternatif olarak tasarlanmistir. Gunumuzde kullanilan bir cok kisisel bilgasayar CISC mimarisi icerir. 1970 lerin basinda ilk mikroislemci tasarlandiginda hafiza birimleri pahali oldugundan komutlari mumkun oldugu kompleks tasarlayip olusturulucak programlarin hafizada daha az yer kaplanmasi amaclanmistir. O donemde hafiza birimleri maliyetli oldugu icin islemci tasarimcilarini bu yola yoneltmistir. Hafiza maliyetlerinin dusmesi tasarimcilari RISC islemci mimarisine yoneltmistir. RISC ve CISC komut setleri arasindaki iliskiyi guzel bir analoji yaparak aciklamaya calisalim. Ornegin latin alfabesi kullanarak yazilmis bir kitap in toplam sayfa sayisi ile ayni kitabin Cince yazilmis versiyonu ayni sayida degildir. Cince yazilan kitap cok daha az sayfadan olusur bunun sebebi Cın alfabesinde 4000 den fazla farkli sembolun olusudur. Semboller cok spesifik anlamlar icerebilirler fakat bunun sonucunda cok kompleks ve ogrenmesi cok zordur. Latin alfabesinde ise sadece 26 farkli sembol vardir. Bununla beraber ayni kitap cok daha fazla sayfa icermektedir. RISC islemci ve CISC islemci komut seti arasindaki farkda buna cok benzerdir. CISC islemcileri cozumlemek cok daha karisik ve zordur. Genel RISC mimarisi dort bolumden olusmustur. Bunlar sirasiyla 1. Komut Yakalama Evresi(Instruction Fetch Stage) 2. Komut Cozumleme Evresi(Instruction Decode Stage) 3. Komut Calistirma Evresi (Instruction Execution Stage) 4. Geri Yazma Evresi(Write Back) Ilerleyen bolumlerde CAF islemci tasarimi ve mimarisi ile ilgili daha detayli bilgi verilecektir. FPGA ile CPU tasarimi Page 7
1.3 EDA Yazilimlari FPGA ile CPU tasarimi Page 8
2 FPGA ile Fiziksel Islemci Uygulamasi 2.1 Komut Seti Mimarisi Genel olarak RISC islemcilerde basit ve tekduze bir komut formati kullanilir. RISC islemcilerde cok fazla komut formati olmamasi komut cozumlemesini onemli olcude kolaylastirir. CAF islemci komut mimarisi de 30 komut tan olusmustur. Ileride ek komutlarin mimariye eklenmesi planlanmisitir. Genel RISC islemci mimarisinde iki veya uc farkli adresleme teknigi kullanilir ve en genel adresleme teknikleri immediate, direct ve indexed dir. CAF islemci komut setinde de ayni sekilde uc farkli adresleme teknigi kullanilmistir. Diger gerekli adresleme modlari bu temel adresleme modlarindan elde edilebir. CAF islemcisindeki komutlari fonksiyonelliklerine gore gruplandirildiginda dort farkli gruba ayrilir. 1. Brans(Dallanma) Komutlari (Branch Instructions) 2. Veri Isleme Komutlari(Data Processing Instructions) 3. Yukleme ve Depolama Komutlari(Load&Store Instructions) 4. Kesme ve Diger Komutlar(Interrupt) Brans Komutlari: CAF islemcide uc cesit Brans komutu vardir bunlar kosulsuz(branch Always), Kosullu(Branch Equal, Branch Not Equal) ve altprogramlardir(branc&link). Brans komutlari program sayacinin icerigini degistirerek hafiza icerisinde farkli bir bolgeye yonlirirler. Kosullu brans komutlarinda programi yonlirmek icin kosulun saglanmasi gerekir. Kosul saglanirsa program sayaci ana-rutinden cikar ve altprogramin komutlarini islemeye baslar. CAF islemcide kosulsuz brans komutu program sayacini 1Kbyte ileri veya geri goturebilirler. Kosullu brans komutu ise ancak 256 byte ileri veya geri goturebilir. Veri Isleme Komutlari: Yukleme ve Depolama Komutlari: Kesme ve Diger Komutlar: CAF_Processor Komut Kumesi Komut Sembol Ornek Anlam Yorum Toplama add 000001 Toplama addi 000010 Immediate Cikarma sub 000011 Cikarma Immediate Subi 000100 FPGA ile CPU tasarimi Page 9
Carpma Mul 000101 Carpma Muli 000110 Immediate Carpma mulu 000111 Isaretsiz Kiyaslama Cmp 001000 Ve And 001001 Ve Andi 001010 Immediate Veya Or 001011 Veya Ori 001100 Immediate Not Not 001101 Xor Xor 001110 Xor Xori 001111 immediate Mantiksal Sll 010000 sola kaydirma Mantiksal Sri 010001 saga kaydirma Aritmetik Sla 010010 sola kaydirma Aritmetik Sra 010011 saga kaydirma Kelime Lw 010100 Yukleme Kelime Sw 010101 Depolama Tasima mov 010110 Tasima Movi 010111 Immediate Kosul(Eger Beq 011000 0 a esit ise) Kosul (Eger Bne 011001 0 esit degil ise) Kosul her Ba 011010 zaman Kosul ve BL 011011 baglama İslem yok Nop 011100 FPGA ile CPU tasarimi Page 10
Dur Halt 011101 Kesme Syscall 011110 CAF Islemci Ek Komutlar FPGA ile CPU tasarimi Page 11
2.2 RISC Islemci Mimarisi RISC islemcilerin komut setinin basit ve kisa olmasi mimarinin de daha az kompleks olmasinda buyuk bir etkir. RISC mimarisinin bir baska ozelligi, yukleme(load) ve depolama(store) komutlarinin disindaki tum komutlar veriyi islemci icerisindeki yazicilardan okur veya yazarlar. Sadece yukleme(load) ve depolama(store) komutlari disardaki hafiza birimiyle arayuz saglar. Islemcinin icindeki yazicilar(register) disardaki hafiza birimlerinden(ana hafiza veya cache hafiza) cok daha hizli oldugundan komutlarin cok daha hizli ve efektif calistirilmasi mumkun olur. Genel RISC islemci mimarisinde yazici dosyalari(register file) denilen yazici kumesi bulunur. Yazicilar islemci icerisinde gecici olarak sayisal veri depolamasinda kullanilir. RISC islemci mimarisinde cok sayida genel amacli yazici bulundugundan komut isleme sirasinda gerekli olan veriler burada saklanabilir. Bu da ana hafiza birimine olan bagimliligi azaltir ve islemcinin performansini arttirir. Bilindigi gibi islemcinin disinda bulunan hafiza birimine ulasmak icerdeki yazicilara ulasmaktan cok daha fazla zaman alir. Yazici dosyalari ayni zamanda hizli ve efektif altprogram calistirilmasi icinde kullanilir. Genel RISC islemci mimarisinde herhangi bir zamanda anarutin komut sirasinda giderken yazici dosyalarinin belli bir kismina ulasilabilir. Ornegin CAF islemcide 16 tane 16-bitlik genel amacli yazici dosyasi bulunur fakat bunlardan sadece ilk 8 tanesine ulasilabilir. Bir altprogram cagrildigi zaman altprogramin geri kalan 8 yaziciya ulasma hakki vardir. Boylece altprogram cagrildigi zaman anarutindeki veriler yazicilarda tutulur. FPGA ile CPU tasarimi Page 12
2.3 RISC Islemci Verilog Uygulamasi 2.3.1 Komut Yakalama Evresi(Instruction Fetch Unit) Komut yakalama evresinde komut, hafizada program sayacinin gosterdigi yerden alinir ve komut yazicisina yazilir(if_ir). Program sayaci komut adres bilgisini tutar ve komutlar islikce icerigini iki artirir. Her komut 2byte oldugu icin program sayacida iki artirilir. Hafizadan komut okunmasi icin read_instruction_n sinyalide sifira cekilir. Bir sonraki saat cevriminde hafizadan alinan komut, IF_IR yazicisina depolanir. Komut yakalama evresi her saat cevriminde bu operasyonu yeni komutlar icin gerceklestirir. Boylece komut adresi bir sonraki komut icin hazirlanirken ayni zamanda o anda gelen komut da IF_IR yazicisinda depolanir. Eger brans gelmediyse programi olusturan komutlar sirali bir sekilde calisir. Eger bir brans operasyonu calistirilirsa o zaman program_sayicisina brans in oldugu adres aktarilir. Figur 1.1 Komut Yakalama Evresi //Komut_Yakalama: Komut Yakalama Evresi always@(posedge clk or reset_n) begin if(~reset_n) begin PC <= 0; //program sayaci ilk kosulu read_instruction_n <= 0; else begin read_instruction_n <= 0; if(branch_active) begin PC <= branch_pc_reg; IF_IR <= branch_instruction; IF_PC <=branch_pc_reg; else begin PC <= PC + 2; IF_IR <= instruction; // Komut Yakalama Komut Yazicisi IF_IR <= PC + 2; FPGA ile CPU tasarimi Page 13
2.3.2 Komut Cozumleme Evresi Komut cozumleme evresinde IF_IR sayacinda depolanan komut cozumlenir ve genel amacli yazicilarda (yazici dosyasi ) bulunan veri, calistirma evresinde kullanilmak uzere komut cozucu yazicilarina aktarilir. Yazici dosyalarinda bulunan verilerin komut cozucu yazicilarina aktarilmasinin sebebi verilen komutun yazici dosyasi icinden herhangi bir yazicidan veriyi aktarabilmesidir. Bu progamciya esneklik saglar. Asagidaki verilog kodu komut cozumleyici evrenin kodunu gostermistir. Verilog kodunda ornek olmasi icin sadece ADD ve ADDi komutlari cozumlenmistir. Always blogu icinde sadece case statement kullanilmistir. Komut cozumleme evresinin butun kismi Apiks B kisminda bulunabilir. Figur 1.2 Komut Cozumleme Evresi //Komut_Cozucu Evresi always@(posedge clk) begin case(if_ir[15:10]) 6'b00_0001:begin ID_opcode <= `ADD; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_0010:begin ID_opcode <= `ADDi; ID_Ra <= R[10:8]; ID_imm_offset[7:0] <= IF_IR[7:0];.... case // always blok sonu FPGA ile CPU tasarimi Page 14
2.3.3 Calistirma Evresi(Execution Stage) FPGA ile CPU tasarimi Page 15
2.3.4 Geri Yazma Evresi (Write Back Stage) FPGA ile CPU tasarimi Page 16
Apiks A : Komut Aciklamalari CAF Processor Versiyon1.00 1) ADD(Toplama) 0 0 0 0 0 1 X Ra Rb Rc 2 ) Addi(Toplama-Immediate) 0 0 0 0 1 0 Ra Immediate 3)Sub(Cikarma) 0 0 0 0 1 1 X Ra Rb Rc FPGA ile CPU tasarimi Page 17
4)Subi(Cikarma-Immediate) 0 0 0 1 0 0 Ra Immediate 5) Mul(Carpma) 0 0 0 1 0 1 X Ra Rb Rc 6 ) Muli(Carpma-Immediate) 0 0 0 1 1 0 Ra Immediate FPGA ile CPU tasarimi Page 18
7) Mulu(Carpma-Isaretsiz) 0 0 0 1 1 1 X Ra Rb Rc 8)Cmp(Kiyaslama) 0 0 1 0 0 0 X Ra Rb Rc 9)And(Ve) 0 0 1 0 0 1 X Ra Rb Rc 10)Andi(Ve-Immediate) 0 0 1 0 1 0 Ra Immediate FPGA ile CPU tasarimi Page 19
11 )Or(Veya) 0 0 1 0 1 1 X Ra Rb Rc 12)Ori (Veya-Immediate) 0 0 1 1 0 0 Ra Immediate 13)Xori(Exor-Immediate) 0 0 1 1 0 1 Ra Immediate FPGA ile CPU tasarimi Page 20
14)Xor(Exor) 0 0 1 1 1 0 X Ra Rb Rc 15)Sll(Mantiksal Sola Kaydirma) 0 0 1 1 1 1 Immediate Rb Rc 16)Srl(Mantiksal Saga Kaydirma) 0 1 0 0 0 0 Immediate Rb Rc FPGA ile CPU tasarimi Page 21
17)Sra(Aritmatik-Saga Kaydirma) 0 1 0 0 0 1 Immediate Rb Rc 18)Sla(Aritmatik-Sola Kaydirma) 0 1 0 0 1 0 Immediate Rb Rc 19)Not 0 1 0 0 1 1 X Ra Rb Rc FPGA ile CPU tasarimi Page 22
20)Lw(Kelime Yukleme) 0 1 0 1 0 0 X Ra Rb Rc 21)Sw(Kelime Depolama) 0 1 0 1 0 1 X Ra Rb Rc 22) Movi(Veri tasima Immediate) 0 1 0 1 1 1 Ra Immediate FPGA ile CPU tasarimi Page 23
23) Mov(Veri Tasima) 0 1 0 1 1 0 X XXX Rb Rc 24)Beq(Brans Esit) 0 1 1 0 0 0 Kosul Immediate 25)Bnq(Brans Esit Degil) 0 1 1 0 0 1 Kosul Immediate FPGA ile CPU tasarimi Page 24
26)Ba(Branch always) 0 1 1 0 1 0 Immediate 27)Nop(No Operation) 0 1 1 0 1 1 Kosul Immediate 28)Hlt(Halt) 0 1 1 1 0 0 Kosul Immediate FPGA ile CPU tasarimi Page 25
29)Syscall(System calll) 0 1 1 1 0 1 Kosul Immediate FPGA ile CPU tasarimi Page 26
Apiks B : Verilog Kodu CAF Processor Versiyon1.00 Not: Verilog kodunda kullanilan degiskenler verilogdaki anahtar kelimelerle uyum gostermesi icin Ingilizce isimlirme yapilmistir. Yorum satirlarinda degiskenlerle ilgili gerekli Turkce aciklamalar yapilmistir. //CAF_Islemci.v // global_parametreler ` //Komutlar ve lar `define ADD 6'b00_0001 `define ADDi 6'b00_0010 `define SUB 6'b00_0011 `define SUBi 6'b00_0100 `define MUL 6'b00_0101 `define MULi 6'b00_0110 `define MULu 6'b00_0111 `define CMP 6'b00_1000 `define AND 6'b00_1001 `define ANDi 6'b00_1010 `define OR 6'b00_1011 `define ORi 6'b00_1100 `define XORi 6'b00_1101 `define XOR 6'b00_1110 `define SLL 6'b00_1111 `define SRL 6'b01_0000 `define SRA 6'b01_0001 `define SLA 6'b01_0010 `define NOT 6'b01_0011 `define LW 6'b01_0100 `define SW 6'b01_0101 `define MOV 6'b01_0110 `define MOVi 6'b01_0111 `define BEQ 6'b01_1000 `define BNQ 6'b01_1001 `define BA 6'b01_1010 `define NOP 6'b01_1011 `define HLT 6'b01_1100 `define SYSCALL 6'b01_1101 FPGA ile CPU tasarimi Page 27
module CAF ( clk, reset_n, read_instruction_n, instruction_address, instruction, read_data_n, write_data_n, data_address, data_in, data_out ); //Islemcinin giris ve cikis sinyalleri input clk; input reset_n; output read_instruction_n; output [15:0] instruction_address; input [15:0] instruction; output read_data_n; output write_data_n; output [15:0] data_address; input [15:0] data_in; output [15:0] data_out; //Islemcinin yazicilari reg [15:0] data; reg read_instruction_n; reg read_data_n; reg write_data_n; reg [15:0] PC; //Program Sayaci reg [15:0] LR; //Link Yazicisi reg [15:0] SP; //Stack Gostericisi reg [15:0] R[15:0];// general regs reg N_Flag; //condition flags (N = negative) reg Z_Flag; //Zero reg C_Flag; //Carry reg V_Flag; //Overflow reg branch_taken; FPGA ile CPU tasarimi Page 28
reg [15:0] branch_target; reg [32:0] ALU_out_reg; reg [15:0] DR; integer i, ex_i; integer found_i, found_ex_i; //pipeline yazicilari reg [15:0] IF_IR; reg [15:0] IF_PC; reg [15:0] ID_PC; reg [15:0] ID_Ra; reg [15:0] ID_Rb; reg [15:0] ID_Rc; reg [32:0] EX_ALU_out; reg [5:0] ID_opcode; reg [5:0] EX_opcode; reg [10:0] ID_imm_offset; reg [7:0] EX_imm_offset; reg [3:0] ID_cond; reg [2:0] ID_Rd_code; reg [2:0] EX_Rd_code; //// assign instruction_address = PC; assign dataout = (~write_data_n)? DR : 16'bZZZZZZZZZZZZZZZZ; //tri-state //Fonksiyon Tanimlari function condition_satisfy; input [3:0] cond_code; begin case(cond_code) 4'b0000 : condition_satisfy = Z_Flag; 4'b0001 : condition_satisfy = ~Z_Flag; 4'b0010 : condition_satisfy = C_Flag; 4'b0011 : condition_satisfy = ~C_Flag; 4'b0100 : condition_satisfy = N_Flag; 4'b0101 : condition_satisfy = ~N_Flag; 4'b0110 : condition_satisfy = V_Flag; 4'b0111 : condition_satisfy = ~V_Flag; 4'b1000 : condition_satisfy = (C_Flag & (~Z_Flag)); 4'b1001 : condition_satisfy = ((~C_Flag) & Z_Flag); 4'b1010 : condition_satisfy = (N_Flag == V_Flag); 4'b1011 : condition_satisfy = (N_Flag!= V_Flag); 4'b1100 : condition_satisfy = Z_Flag & (N_Flag == V_Flag); 4'b1101 : condition_satisfy = Z_Flag & (N_Flag!= V_Flag); 4'b1110 : condition_satisfy = 1'b1; default: condition_satisfy = 1'b1; FPGA ile CPU tasarimi Page 29
case function //////////////////////////////////////////////////// //Komut_Yakalama: Komut Yakalama Evresi always @ (posedge clk ) begin if(reset_n == 0) begin PC = 0; //program sayaci ilk kosulu read_instruction_n = 0; else begin read_instruction_n = 0; PC = PC + 2; IF_IR = instruction; // Komut Yakalama Komut Yazicisi IF_IR = PC + 2; //Komut_Cozucu Evresi always@(posedge clk) begin case(if_ir[15:10]) 6'b00_0001:begin ID_opcode <= `ADD; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_0010:begin ID_opcode <= `ADDi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b00_0011:begin ID_opcode <=`SUB; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_0100:begin ID_opcode <= `SUBi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset[7:0] <= IF_IR[7:0]; FPGA ile CPU tasarimi Page 30
6'b00_0101:begin ID_opcode <= `MUL; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_0110:begin ID_opcode <= `MULi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset <= R[IF_IR[7:0]]; 6'b00_0111:begin ID_opcode <= `MULu; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_1000:begin ID_opcode <= `CMP; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_1001:begin ID_opcode <= `AND; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_1010:begin ID_opcode <= `ANDi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset <= R[IF_IR[7:0]]; 6'b00_1011:begin ID_opcode <= `OR; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_1100:begin ID_opcode <= `ORi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b00_1101:begin FPGA ile CPU tasarimi Page 31
ID_opcode <= `XOR; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b00_1110:begin ID_opcode <= `XORi; ID_Ra <= R[IF_IR[10:8]]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b00_1111:begin ID_opcode <= `SLL; ID_imm_offset[4:0] <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0000:begin ID_opcode <= `SRL; ID_imm_offset[4:0] <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0001:begin ID_opcode <= `SLA; ID_imm_offset[4:0] <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0010:begin ID_opcode <= `SRA; ID_imm_offset[4:0] <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0011:begin ID_opcode <= `NOT; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0100:begin ID_opcode <= `LW; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; FPGA ile CPU tasarimi Page 32
6'b01_0101:begin ID_opcode <= `SW; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_0110:begin ID_opcode <= `MOVi; ID_Ra <= R[IF_IR[8:6]]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b01_0111:begin ID_opcode <= `MOV; ID_Ra <= R[IF_IR[5:3]]; ID_Rb <= R[IF_IR[2:0]]; 6'b01_1000:begin ID_opcode <= `BEQ; ID_cond <= IF_IR[11:8]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b01_1001:begin ID_opcode <= `BNQ; ID_cond <= IF_IR[11:8]; ID_imm_offset[7:0] <= IF_IR[7:0]; 6'b01_1010:begin ID_opcode <= `BA; ID_imm_offset[9:0] <= IF_IR[9:0]; 6'b01_1011:begin ID_opcode <= `NOP; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_1100:begin ID_opcode <= `HLT; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; ID_Rc <= R[IF_IR[2:0]]; 6'b01_1101:begin ID_opcode <= `SYSCALL; ID_Ra <= R[IF_IR[8:6]]; ID_Rb <= R[IF_IR[5:3]]; FPGA ile CPU tasarimi Page 33
ID_Rc <= R[IF_IR[2:0]]; case //Calisma Evresi always@(posedge clk)begin if(~reset_n)begin read_data_n <= 1'b1; write_data_n <= 1'b1; else begin read_data_n <= 1'b1; write_data_n <= 1'b1; if(branch_taken)begin // EX_opcode <=6'b000000; branch_taken <= 1'b0; else begin case(id_opcode) // `ADD : ALU_out_reg <= ID_Rb + ID_Rc; `ADDi : ALU_out_reg <= ID_Ra + ID_imm_offset; `SUB : ALU_out_reg <= ID_Rb - ID_Rc; `SUBi : ALU_out_reg <= ID_Ra - ID_imm_offset; `MUL : ALU_out_reg <= ID_Rb * ID_Rc; `MULi : ALU_out_reg <= ID_Ra * ID_imm_offset; `MULu : ALU_out_reg <= ID_Ra * ID_imm_offset; `CMP : ALU_out_reg <= ID_Rb - ID_Rc; `ANDi : ALU_out_reg <= ID_Ra & ID_imm_offset; `AND : ALU_out_reg <= ID_Rb & ID_Rc; `ORi : ALU_out_reg <= ID_Ra ID_imm_offset; `OR : ALU_out_reg <= ID_Rb ID_Rc; `XORi : ALU_out_reg <= ID_Ra ^ ID_imm_offset; `XOR : ALU_out_reg <= ID_Rb ^ ID_Rc; `SLL : ALU_out_reg <= ID_Rb << ID_imm_offset[9:6]; `SRL : ALU_out_reg <= ID_Rb >> ID_imm_offset[9:6]; `SRA : ALU_out_reg <= ID_Rb >> ID_imm_offset[9:6]; `SLA : ALU_out_reg <= ID_Rb >> ID_imm_offset[9:6]; `NOT : ALU_out_reg <= 0 - ID_Ra; `LW : ALU_out_reg <= ID_Ra + ID_Rb; `SW : ALU_out_reg <= ID_Ra + ID_Rb; `MOVi : ALU_out_reg <= {24'b0, ID_imm_offset}; `MOV : ALU_out_reg <= {R[IF_IR], R[IF_IR]}; `BEQ : begin FPGA ile CPU tasarimi Page 34
if(condition_satisfy(id_cond))begin for(i = 15; i > 8; i = i-1) ALU_out_reg[i] <= ID_imm_offset[7]; ALU_out_reg[8:1] <= ID_imm_offset[7:0]; ALU_out_reg[0] <=1'b0; branch_taken <= 1'b1; branch_target <= (ID_PC +2) + ALU_out_reg[15:0]; `BNQ : begin if(~condition_satisfy(id_cond))begin for(i = 15; i > 8; i = i-1) ALU_out_reg[i] <= ID_imm_offset[7]; ALU_out_reg[8:1] <= ID_imm_offset[7:0]; ALU_out_reg[0] <=1'b0; branch_taken <= 1'b1; branch_target <= (ID_PC +2) + ALU_out_reg[15:0]; `BA : begin for(i = 15; i > 8; i = i-1) ALU_out_reg[i] <= ID_imm_offset[7]; ALU_out_reg[8:1] <= ID_imm_offset[7:0]; ALU_out_reg[0] <=1'b0; branch_taken <= 1'b1; branch_target <= (ID_PC +2) + ALU_out_reg[15:0]; `NOP : begin branch_taken <= 1'b1; branch_target <= ID_PC - 2; `HLT : begin branch_taken <= 1'b1; branch_target <= ID_PC - 2; `SYSCALL :begin branch_taken <= 1'b1; branch_target <= ID_PC - 2; case // Bu bolum Flag operasyonlarini kontrol etmek icin yazilmistir. // FPGA ile CPU tasarimi Page 35
case(id_opcode)//2nd part of operation `ADD, `SUB, `CMP, `MUL : begin EX_ALU_out[15:0] <= ALU_out_reg[15:0]; N_Flag <= ALU_out_reg[15]; Z_Flag <= (ALU_out_reg[15:0] == 0); //if(id_imm_offset[2:0]!= 3'b000) begin C_Flag <= ALU_out_reg[16]; V_Flag <= (ALU_out_reg[16]!= ALU_out_reg[15]); // if; `ADDi, `SUBi : begin EX_ALU_out[15:0] <= ALU_out_reg[15:0]; N_Flag <= ALU_out_reg[15]; Z_Flag <= (ALU_out_reg[15:0] == 0); if(id_imm_offset[2:0]!= 3'b000) begin C_Flag <= ALU_out_reg[16]; V_Flag <= (ALU_out_reg[16]!= ALU_out_reg[15]); `MULi : begin EX_ALU_out[31:0] <= ALU_out_reg[31:0]; N_Flag <= ALU_out_reg[31]; Z_Flag <= (ALU_out_reg[31:0] == 0); if(id_imm_offset[2:0]!= 3'b000) begin C_Flag <= ALU_out_reg[16]; V_Flag <= (ALU_out_reg[32]!= ALU_out_reg[31]); `AND, `XOR, `XORi, `OR, `NOT: begin EX_ALU_out[15:0] <= ALU_out_reg[15:0]; N_Flag <= ALU_out_reg[15]; Z_Flag <= (ALU_out_reg[15:0] == 0); case EX_opcode = ID_opcode; EX_Rd_code = ID_Rd_code; // process sonu // calisma evresi sonu /////////////////////////////////////////////////////////////////////////// //Geri Yazma /////////////////////////////////////////////////////////////////////////// always@(posedge clk)begin FPGA ile CPU tasarimi Page 36
if(~reset_n) for( i = 0; i <16 ; i = i + 1) R[i]<= 0; else begin case (EX_opcode) `ADD, `ADDi, `SUB, `SUBi, `AND, `ANDi, `OR, `ORi, `XOR, `XORi, `MUL, `MULi, `MULu, `CMP, `SLL, `SRL, `SRA, `SRL, `NOT : begin R[EX_Rd_code] <= EX_ALU_out; `LW : R[EX_Rd_code] <= data; `MOVi : R[EX_Rd_code] <= data; case module FPGA ile CPU tasarimi Page 37
FPGA ile CPU tasarimi Page 38