找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 1261|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

這是我制作的vhdl CPU

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:764193 發(fā)表于 2020-5-29 13:33 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
附錄A RTL圖A1. 控制器的RTL圖
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
圖A.1 控制器的RTL圖
A2. CPU的RTL圖
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
圖A.2 CPU的RTL圖


附錄B VHDL程序清單
(1)CPU.vhd文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
----頭文件
PACKAGE cpu_defs IS
TYPE opcode IS(load,sta,add,sub,and1,jmp1,nop);   ----枚舉,七組唯一的二進(jìn)制數(shù)值,0-6
CONSTANT word_w : NATURAL := 8;
CONSTANT op_w : NATURAL := 3;
CONSTANT rfill:STD_LOGIC_VECTOR(op_w-1 downto0):= ( others => '0');----三位零常量
--FUNCTIOn slv2op(slv:IN STD_LOGIC_VECTOR)RETURNopcode;
FUNCTION op2slv(op:in opcode)RETURNSTD_LOGIC_VECTOR;
END PACKAGE cpu_defs;
PACKAGE BODY cpu_defs IS
TYPE optable IS ARRAY(opcode) OFSTD_LOGIC_VECTOR(op_w-1 DOWNTO 0);---具有opcode個(gè)元素的數(shù)組,三位數(shù)據(jù)
CONSTANTtrans_table:optable:=("000","001","010","011","100","101","110");---七組二進(jìn)制數(shù)與七個(gè)操作符一一對(duì)應(yīng)
FUNCTION op2slv(op:IN opcode)RETURNSTD_LOGIC_VECTOR IS
BEGIN
RETURN trans_table(op);
END FUNCTION op2slv;----------輸入操作符對(duì)應(yīng)的無(wú)符號(hào)整數(shù)0-6,輸出相對(duì)應(yīng)的二進(jìn)制編碼
END PACKAGE BODY cpu_defs;
----源文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_unsigned.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.CPU_DEFS.ALL;
ENTITY CPU IS
PORT( clock:IN STD_LOGIC;-----------時(shí)鐘輸入
     reset:IN STD_LOGIC;-----------置位輸入
      mode:IN STD_LOGIC_VECTOR(2 DOWNTO 0);--------三位模式輸入
     mem_addr:OUT UNSIGNED(word_w-op_w-3 DOWNTO 0);-------三位內(nèi)存地址的輸入
              output: OUT STD_LOGIC_VECTOR(word_w-1DOWNTO 0);-------八位數(shù)據(jù)輸出
              data_r_out : OUT STD_LOGIC_VECTOR(23DOWNTO 0);--------24位微指令輸出
              reg_out:OUT STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
              regg_out: OUT STD_LOGIC_VECTOR(word_w-1 DOWNTO0);
              op_out: OUT STD_LOGIC_VECTOR(op_w-1DOWNTO 0);----------三位操作碼輸出
              add_r_out:OUT UNSIGNED(4 DOWNTO 0);         ----------五位地址輸出
              segctl:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
              segout:OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
              );
              
END ENTITY;
ARCHITECTURE rtl OF CPU IS
TYPE mem_array IS ARRAY (0 To2**(word_w-op_w-2)-1) OF STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);----八位數(shù)組,每個(gè)元素為八位二進(jìn)制數(shù)
       SIGNALmem : mem_array;--------------------------------存儲(chǔ)器內(nèi)存儲(chǔ)的內(nèi)容,程序和數(shù)據(jù)
       CONSTANTprog: mem_array:=(
     0=>op2slv(load)&STD_LOGIC_VECTOR(TO_UNSIGNED(7,word_w-op_w-2))&"00",  --00011100  4-2加載的對(duì)象  ---------load內(nèi)存中內(nèi)容存到acc
              1=>op2slv(sta)&"001"&"01",                                            --00100101  4-2無(wú)作用      ---------sta把a(bǔ)cc中內(nèi)容存到reg1
              2=>op2slv(add)&STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w-2))&"00",   --01011000                 ---------add把a(bǔ)cc與內(nèi)存中數(shù)據(jù)相加給acc
              3=>op2slv(sub)&"001"&"01",                                            --01100101   4-2無(wú)作用      ---------sub acc中內(nèi)容減去reg1中內(nèi)容 給acc
              4=>op2slv(sta)&"010"&"10",                                            --00101010   4-2無(wú)作用      ---------sta把a(bǔ)cc中內(nèi)容存到men(7)
              --5=> op2slv(and1) &"010" & "10",
              5=>op2slv(jmp1)&STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w-2))&"00",  --10111000                ---------acc結(jié)果為零,跳到空操作,否則跳到第二條指令
              6=>STD_LOGIC_VECTOR(TO_UNSIGNED(4,word_w)),                           --00000010
              7=>STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w)));                          --00000011
               --7-5本條程序的功能 --4-2下一條程序的位置(具體三位二進(jìn)制數(shù)) 或 本條程序的對(duì)象
               -----------------------事先編好的存入存儲(chǔ)器的內(nèi)容
     TYPE microcode_array IS ARRAY (0 To 20) OF STD_LOGIC_VECTOR(23 DOWNTO0);
              CONSTANT code:microcode_array:=(
0=> "000000001001010000000001",
          1=> "000000000000000110000010",
          2=> "000000000110000000000011",
          3=> "000000000001001000011111",
4=>"000000010010000000000000",
          5=>"000100000000000000000000",
6=>"100000000000000000000111",
          7=>"000010000001000000001111",
          8=> "000000000000000110000100",
          9=>"010000000000000000011110",
         10=> "000000000000000110010000",
         11=> "000001000000100000100000",
         12=> "000010000001000000010001",
         13=> "000000000000000110011100",
         14=> "000000000000000000000000",
         15=> "000000000000000100000000",
         16=> "000000000010100001000000",
         17=> "000000000000000110010010",
         18=> "001000000010100000000000",
         19=> "000000100010000000000000",
         20=>"000000000000000000000000");-------------21個(gè)元素,24位二進(jìn)制操作碼數(shù)組
SIGNAL count:UNSIGNED(word_w-op_w-1 DOWNTO0);--------五位計(jì)數(shù)值
SIGNAL op:STD_LOGIC_VECTOR(op_w-1 DOWNTO0);------三位指令碼
SIGNAL z_flag:STD_LOGIC;------ZF
SIGNAL mdr_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);---------八位數(shù)據(jù)寄存器DR的輸出
SIGNAL mar_out:UNSIGNED(word_w-op_w-3 DOWNTO0);----------三位地址寄存器MAR的輸出
SIGNAL IR_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);----------指令寄存器的八位輸出(指令或譯碼后的操作碼)--------波形未輸出
SIGNAL acc_out:UNSIGNED(word_w-1 DOWNTO0);----------八位累加器輸出
SIGNAL reg1_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
SIGNAL reg2_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
SIGNAL sysbus_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);--------八位數(shù)據(jù)總線輸出
SIGNAL mem_addr_r:UNSIGNED(word_w-op_w-3DOWNTO 0);
SIGNAL inclock:STD_LOGIC;-----------內(nèi)部時(shí)鐘
SIGNAL period:integer:=50000000;
SIGNAL hcnt:integer:=25000000;
--SIGNAL period:integer:=16;
--SIGNAL hcnt:integer:=8;
SIGNAL cnt:integer:=0;
SIGNAL inclock_c:STD_LOGIC;-----------內(nèi)部時(shí)鐘
SIGNAL period_c:integer:=125000;
SIGNAL hcnt_c:integer:=62500;
--SIGNAL period_c:integer:=2;
--SIGNAL hcnt_c:integer:=1;
SIGNAL cnt_c:integer:=0;
SIGNAL databuf:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL datain:STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL cnt_show:STD_LOGIC_VECTOR(1 DOWNTO0):="00";
BEGIN
PROCESS(clock)
BEGIN
       IFRISING_EDGE(clock) THEN
              IF cnt>period THEN
                     cnt<=0;
                     inclock<='1';
              ELSIF cnt<hcnt THEN
                     inclock<='1';
                     cnt<=cnt+1;
              ELSE
                     inclock<='0';
                     cnt<=cnt+1;
              END IF;
       ENDIF;
END PROCESS;
PROCESS(clock)
BEGIN
       IFRISING_EDGE(clock) THEN
              IF cnt_c>period_c THEN
                     cnt_c<=0;
                     inclock_c<='1';
              ELSIF cnt_c<hcnt_c THEN
                     inclock_c<='1';
                     cnt_c<=cnt_c+1;
              ELSE
                     inclock_c<='0';
                     cnt_c<=cnt_c+1;
              END IF;
       ENDIF;
END PROCESS;
PROCESS(reset,inclock)
BEGIN
       IFreset='0' THEN
              mem_addr<=(OTHERS =>'0');
              mem_addr_r<=(OTHERS =>'0');
       ELSIFRISING_EDGE(inclock) THEN
              mem_addr_r<=mem_addr_r+1;
              mem_addr<=mem_addr_r;
       endif;
END PROCESS;
PROCESS(reset,inclock)
     VARIABLE instr_reg:STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);-----------指令寄存器中的內(nèi)容
              VARIABLE acc:UNSIGNED(word_w-1 DOWNTO0);----------累加器
     CONSTANT zero:UNSIGNED(word_w-1 DOWNTO 0):=(OTHERS =>'0');----------八位零常量
              VARIABLE mdr:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);----------數(shù)據(jù)寄存器
              VARIABLE reg1:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);-------------?
              VARIABLE reg2:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);------------?
              VARIABLE mar:UNSIGNED(word_w-op_w-3DOWNTO 0);---------三位地址寄存器
     VARIABLE sysbus : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
              VARIABLE microcode :microcode_array;------------24位指令碼數(shù)組
     VARIABLE add_r: UNSIGNED(4 DOWNTO 0);
     VARIABLE data_r: STD_LOGIC_VECTOR(23 DOWNTO 0);--------------24位指令碼
              VARIABLE temp: STD_LOGIC_VECTOR(4 DOWNTO0);-----------五位臨時(shí)變量
BEGIN
     reg2:="00000111";
       IFreset='0' THEN-------------置位端清零
     add_r:=(OTHERS =>'0');
              count<= (OTHERS =>'0');
              instr_reg:=(OTHERS =>'0');
     acc:= (OTHERS =>'0');
              mdr:= (OTHERS =>'0');
              reg1:= (OTHERS =>'0');
              reg2 := (OTHERS =>'0');
              mar := (OTHERS =>'0');
              z_flag<='0';
     mem <= prog;
     sysbus :=(OTHERS=>'0');
       ELSIFRISING_EDGE(inclock) THEN          --microprogram controller 指令控制器
     data_r:=code(TO_INTEGER(add_r));
              IF data_r(4 DOWNTO 0)="11111"THEN   --判斷地址
                     temp:="01"&op(2DOWNTO 0);
                     add_r:=UNSIGNED(temp);
              ELSIF data_r(4 DOWNTO0)="11110" THEN
                     IFIR_out(1 downto 0)="10" THEN
                            add_r :="00110";
                     ELSIFIR_out(1 downto 0)="01" THEN
                            add_r :="00101";
                     ENDIF;
              ELSIF data_r(4 DOWNTO 0)="11100"THEN
                     IFz_flag='0' THEN
                            add_r:="10011";
                     ELSE
                            add_r:="10100";
                     ENDIF;
              ELSE
                     add_r:=UNSIGNED(data_r(4 DOWNTO 0));
              END IF;
              data_r_out<=data_r;
              add_r_out<=add_r;
              
              --PC 程序計(jì)數(shù)器----確定下一條指令的地址
              IF data_r(15)='1' THEN               --PC_bus='T'
                     sysbus:=rfill & STD_LOGIC_VECTOR(count);
              END IF;
              IF data_r(17)='1'THEN              --load_PC='l'  count置數(shù)
                     count<= UNSIGNED(mdr(word_w-op_w-1 DOWNTO 0));----------data_r(17)==?
              ELSIF data_r(10)='1' THEN        --INC_PC='l'  ---------data_r(10)=IPC  決定計(jì)數(shù)器是否加一
                     count<= count+1;
              ELSE
                     count<= count;
     END IF;
              
              --IR 指令寄存器---用來(lái)保存當(dāng)前正在執(zhí)行的指令,如果是操作碼就進(jìn)行譯碼
              IF data_r(14)='1'THEN --load_ IR               data_r(14)==IIR
                     instr_reg:=mdr;     
              END IF;    -----------------------------------------保存當(dāng)前正在執(zhí)行的指令(mdr是計(jì)算的數(shù)據(jù))
              IF data_r(9)='1'THEN  --Addr_ bus='l'       判斷是否是操作碼
                     sysbus:="00"& rfill & instr_reg(word_w-op_w-1 DOWNTO 2);
              END IF;---------------------------------------------------譯操作碼
     op <= instr_reg(word_w-1 DOWNTO word_w-op_w); -----------第七位到第五位  當(dāng)前三位操作碼
              IR_out<=instr_reg;
              op_out<=op;        
              
              --ALU   算術(shù)邏輯單元
     IF data_r(16)='1'THEN --load_ACC='l'     ------------data_r(16)==ESUM 判斷是否給acc
                     acc:=UNSIGNED(mdr);------------計(jì)算數(shù)據(jù)結(jié)果給acc
              ENd if;
     IF data_r(22)='1'THEN    --ACC_bus='l'
                     sysbus:=STD_LOGIC_VECTOR(acc);-------------判斷是否累加結(jié)果acc給數(shù)據(jù)總線
              END IF;
     IF data_r(18)='1'THEN            --REG1_ bus='l'
                     sysbus:=STD_LOGIC_VECTOR(reg1);---------------寄存器reg1的結(jié)果給數(shù)據(jù)總線   
              END IF;
     IF data_r(19)='1'THEN            --REG2_ bus='l'
                     sysbus:= STD_LOGIC_VECTOR(reg2);---------------寄存器reg2的結(jié)果給數(shù)據(jù)總線
              END IF;
     If data_r(20)='1'then          --load_ regl='l'
                     reg1:=sysbus;
                     reg_out<=reg1;----------------reg1獲得數(shù)據(jù)總線上的值并輸出
              END IF;
      IF IR_out(1 downto 0)="00" THEN
                     IFdata_r(11)='1'THEN   --ALU_ ACC='l'        data_r(11)==IA
                            IF data_r(6)='1'THEN            --ALU__add='l'    data_r(6) == Iadd
                                   acc:=acc+UNSIGNED(mdr);
                            END IF;
                     ENDIF;
              ELSIF IR_out(1 downto 0)="01"THEN
                     IFdata_r(11)='1'THEN          --ALU_ ACC='l'
                            IF data_r(5)='1'THEN     --ALU_ _sub='l'    data_r(5) == Isub
                                   acc:=acc-UNSIGNED(reg1_out);
                            END IF;
                     ENDIF;
              ELSIF IR_out(1 downto0)="10"THEN
                     IFdata_r(11)='1' THEN --ALU_ ACC='l'
                            IF data_r(21)='1'THEN  --ALU_ and='1'      ata_r(21) == Iand
                                   acc:= acc and UNSIGNED(mdr);
                            END IF;
                     ENDIF;
          END IF;
     IF acc=zero THEN          --根據(jù)結(jié)果acc設(shè)計(jì)ZF
                     z_flag<='1';
              ELSE
                     z_flag<='0';
              END IF;
              acc_out<=acc;
              
              --RAM 存儲(chǔ)器
              IF data_r(12)='1'THEN           --load_MAR='l'        data_r(12) = IMAR  是否工作
                     mar:=UNSIGNED(sysbus(word_w-op_w-3dOWNTO 0));  ----------獲得地址信息
              ELSIF data_r(23)='1' THEN  --load_ MDR='1'        data_r(23) = IMDR
                     mdr:=sysbus;--------------指令或數(shù)據(jù)給MDR
              ELSIF data_r(8)='1'THEN     --CS='l'
                     IFdata_r(7)='1' THEN          --R_NW='l'讀
                            mdr:= mem(TO_INTEGER(mar));
                     ELSE
                            mem(TO_INTEGER(mar)) <= mdr; -- 寫數(shù)據(jù)或指令  
                     ENDIF;
              END IF;
              IF data_r(13)='1'THEN           --MDR_bus='l'         data_r(13) = EMDR
                     sysbus:=mdr;
              END IF;
     mdr_out<= mdr;
     mar_out<= mar;
       ENDIF;
  sysbus_out <= sysbus;
       reg1_out<= reg1;
       reg2_out<= reg2;
  regg_out <= reg2_out;
END PROCESS;
PROCESS(mode,inclock)
VARIABLE output_t:STD_LOGIC_VECTOR(15 DOWNTO0);
BEGIN
     --mode=0-> sysbus
              --mode=1-> PC
     --mode=2-> result of ALU
              --mode=3-> IR
     --mode=4-> MAR
     --mode=5-> MDR
     --mode=6 -> mem
     output_t := (OTHERS =>'0');
              CASE mode is
     WHEN "000" =>output_t(7 downto 0):=sysbus_out;
     WHEN "001" =>output_t(word_w-op_w-1 DOWNTO 0):=STD_LOGIC_VECTOR(count);
              WHEN "010" =>output_t(7downto 0):=STD_LOGIC_VECTOR(acc_out);
              WHEN "011" =>output_t(7downto 0):= IR_out;
              WHEN "100"=>output_t(word_w-op_w-3 DOWNTO 0):=STD_LOGIC_VECTOR(mar_out);
              WHEN "101" =>output_t(7downto 0) := mdr_out;
              WHEN "110" =>output_t(7downto 0):= mem(TO_INTEGER(mem_addr_r));
              WHEN others =>output_t(7 downto 0):=(OTHERS=>'Z');
              END CASE;
              output<=output_t(7 downto 0);
              datain<=output_t;
END PROCESS;
PROCESS(inclock_c)
BEGIN
      IF RISING_EDGE(inclock_c) THEN  
                     cnt_show<= cnt_show + "01";
              END IF;
END PROCESS;
PROCESS(inclock_c)
BEGIN
     IF RISING_EDGE(inclock_c) THEN  
                     casecnt_show IS
                     when"00"=>
                            databuf<=datain(3 downto 0);
                            segctl<="1110";
                     when"01"=>
                            databuf<=datain(7 downto 4);
                            segctl<="1101";
                     when"10"=>
                            databuf<=datain(11 downto 8);
                            segctl<="1011";
                     when"11"=>
                            databuf<=datain(15 downto 12);
                            segctl<="0111";
                     WHENothers =>segctl<="0000";
                     ENDCASE;
              END IF;
END PROCESS;
PROCESS(databuf)
BEGIN
       casedatabuf IS
       when"0000"=>
              segout<="0000001";
       when"0001"=>
              segout<="1001111";
       when"0010"=>
              segout<="0010010";
       when"0011"=>
              segout<="0000110";
       when"0100"=>
              segout<="1001100";
       when"0101"=>
              segout<="0100100";
       when"0110"=>
              segout<="0100000";
       when"0111"=>
              segout<="0001111";
       when"1000"=>
              segout<="0000000";
       when"1001"=>
              segout<="0000100";
       when"1010"=>
              segout<="0001000";
       when"1011"=>
              segout<="1100000";
       when"1100"=>
              segout<="0110001";
       when"1101"=>
              segout<="1000010";
       when"1110"=>
              segout<="0110000";
       when"1111"=>
              segout<="0111000";
       WHENothers =>segout<= (OTHERS=>'0');
end case;
END PROCESS;
END ARCHITECTURE;


附錄C 微指令解析
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
圖C.121微指令解析
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png
圖C.2 21條微指令的作用
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1 發(fā)表于 2020-6-1 01:28 | 只看該作者
本帖需要重新編輯補(bǔ)全電路原理圖,源碼,詳細(xì)說(shuō)明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)
回復(fù)

使用道具 舉報(bào)

板凳
ID:764193 發(fā)表于 2020-6-1 09:42 | 只看該作者
admin 發(fā)表于 2020-6-1 01:28
本帖需要重新編輯補(bǔ)全電路原理圖,源碼,詳細(xì)說(shuō)明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)

圖片發(fā)不上去啊。。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表