綜合性比較強(qiáng)的大實(shí)驗(yàn),先是在實(shí)驗(yàn)室完成前面三個(gè)小實(shí)驗(yàn),最后再三個(gè)結(jié)合完成最后的16位CPU的設(shè)計(jì),需要軟硬件結(jié)合一起。
部分代碼如下:
process(RST, CLK)
begin
if RST = '0' then state <= 0; a<="0000000000000000"; b<="0000000000000000"; opCode<="0000"; output <= (others=>'0'); stateCnt <= not "0000000";
elsif CLK'event and CLK = '1' then
case state is
when 0 => state <= 1; a <= INPUT; stateCnt <= not "1000000";OUTPUT<=a;
when 1 => state <= 2; b <= INPUT; stateCnt <= not "1111001";OUTPUT<=b;
when 2 => state <= 3; opCode <= input(3 downto 0); stateCnt <= not "0100100"; OUTPUT <= input;
when 3 => state <= 4; OUTPUT<= y; stateCnt <= not "0110000";
when 4 => state <= 0; output<= outout; stateCnt <= not "0011001";
end case;
end if;
end process;
process(RST, opCode)
begin
cflag <= '0';
oflag <= '0';
zflag <= '0';
sflag <= '0';
case opCode is
-- 加法
when "0000" => y<= a + b;
if(y = "0000000000000000") then
zflag <= '1';
end if;
if(a(15) = '1' and b(15) = '1') then
cflag <= '1';
if(y(15) = '0') then
oflag <= '1';
end if;
end if;
if(a(15) = '0' and b(15) = '0' and y(15) = '1') then
oflag <= '1';
end if;
if(y(15) = '1') then
sflag <= '1';
end if;
temp <= "1111111111111111" - a;
if(b > temp) then
cflag <= '1';
end if;
-- 減法
when "0001" => y<= a + (not b) + 1;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
temp <= (not b) + 1;
if(a(15) = '1' and temp(15) = '1') then
cflag <= '1';
if(y(15) = '0') then
oflag <= '1';
end if;
end if;
if(a(15) = '0' and temp(15) = '0' and y(15) = '1') then
oflag <= '1';
end if;
if(a < b) then
cflag <= '1';
end if;
-- 加減,邏輯與,或,亦或,非,邏輯、循環(huán)、算數(shù)
when "0010" => y<= a and b;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
when "0011" => y<= a or b;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
when "0100" => y<= a xor b;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
when "0101" => y<= not a;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
-- 邏輯
when "0110" => y<= to_stdlogicvector(to_bitvector(a) sll conv_integer(b));
when "0111" => y<= to_stdlogicvector(to_bitvector(a) srl conv_integer(b));
-- 算數(shù)
when "1000" => y<= to_stdlogicvector(to_bitvector(a) sll conv_integer(b));
when "1001" => y<= to_stdlogicvector(to_bitvector(a) sra conv_integer(b));
-- 循環(huán)
when "1010" => y<= to_stdlogicvector(to_bitvector(a) rol conv_integer(b));
when "1011" => y<= to_stdlogicvector(to_bitvector(a) ror conv_integer(b));
-- when "0010" => y<= a + b + Cin;
-- when "0011" => y<= a - b - Cin;
3.實(shí)驗(yàn)拓展(實(shí)現(xiàn)ADC和SBB指令,已經(jīng)驗(yàn)收通過)
-- ADC(帶進(jìn)位加)
初始進(jìn)位,A異或B異或C(三個(gè)里面有奇數(shù)個(gè)1則為1),向高一位的進(jìn)位,AB或AC或BC(至少有兩個(gè)1則有進(jìn)位)
when "1100" => y<= a + b+cflag;
if(y = "0000000000000000") then
zflag <= '1';
end if;
if(a(15) = '1' and b(15) = '1') then
cflag <= '1';
if(y(15) = '0') then
oflag <= '1';
end if;
end if;
if(a(15) = '0' and b(15) = '0' and y(15) = '1') then
oflag <= '1';
end if;
if(y(15) = '1') then
sflag <= '1';
end if;
temp <= "1111111111111111" - a;
if(b > temp) then
cflag <= '1';
end if;
-- SBB帶借位減(A-B-C)
初始借位,A異或B異或C(三個(gè)里面有奇數(shù)個(gè)1則為1),向高一位的借位,(BC均為1或BC有一個(gè)為1同時(shí)A為0就要借位即借位為1)
when "1101" => y<= a + (not b) -cflag;
if(y(15) = '1') then
sflag <= '1';
end if;
if(y = "0000000000000000") then
zflag <= '1';
end if;
temp <= (not b) + 1;
if(a(15) = '1' and temp(15) = '1') then
cflag <= '1';
if(y(15) = '0') then
oflag <= '1';
end if;
end if;
if(a(15) = '0' and temp(15) = '0' and y(15) = '1') then
oflag <= '1';
end if;
if(a < b) then
cflag <= '1';
end if;
when others=> y<="0000000000000000";
end case;
outout(15) <= oflag;
outout(14) <= cflag;
outout(13) <= zflag;
outout(12) <= sflag;
end process;
- 實(shí)驗(yàn)截圖
黃色圈的地方是輸入步驟顯示
藍(lán)色圈的地方是標(biāo)志位和結(jié)果顯示的LED燈
紅色圈的地方是輸入決定ALU功能的操作碼的地方,以及輸入計(jì)算的數(shù)據(jù)的地方。
(需要小心的是0~15是從左到右,撥上去是0,撥下來(lái)是1)
三、綜合實(shí)驗(yàn)總結(jié)
1.實(shí)驗(yàn)難點(diǎn)
(1) 在輸出標(biāo)志位時(shí),如何通過操作數(shù)和操作結(jié)果判斷標(biāo)志位:
(2)在判斷進(jìn)位標(biāo)志位cFlags時(shí),需要仔細(xì)考慮指令對(duì)標(biāo)志位的影響和影響的原理,尤其是ADC指令和SBB指令,需要記錄每一位的進(jìn)位并利用循環(huán)結(jié)構(gòu)得到最終結(jié)果和進(jìn)位標(biāo)志位(類似全加器原理)。
(3)在判斷溢出標(biāo)志位oFlags時(shí),要靈活掌握操作數(shù)和運(yùn)算結(jié)果之間符號(hào)位的變化與OF標(biāo)志位的關(guān)系,以便正確設(shè)置標(biāo)志位。
(4)在進(jìn)行移位運(yùn)算時(shí),要將需要被移位的操作數(shù)(即A)的數(shù)據(jù)類型轉(zhuǎn)換為位矢量類型后才可以移位,將移位操作數(shù)轉(zhuǎn)換成整數(shù)。
2.心得體會(huì)
略
四、思考題
(1)ALU進(jìn)行算術(shù)邏輯運(yùn)算所使用的電路是組合邏輯電路還是時(shí)序邏輯電路?
答:組合邏輯電路,沒有記憶功能,此時(shí)刻輸入只取決于此時(shí)刻輸出。
(2)如果給定了A和B的初值,且每次運(yùn)算完后結(jié)果都寫入到B中,再進(jìn)行下次運(yùn)算。這樣一個(gè)帶暫存功能的ALU要增加一些什么電路來(lái)實(shí)現(xiàn)?
答: 增加暫存器TMP和累加器AC。
六.部分代碼展示
begin
process(RST,ctrl_r)
begin
if RST='0' then
ctrl_state<=N;
elsif rising_edge(ctrl_r)then
case ctrl_state is
when N=>
ctrl_state<=W;
when W=>
ctrl_state<=R;
when R=>
ctrl_state<=W;
end case;
end if;
end process;
process(RST,CLK,ctrl_state)
begin
if RST='0' then
tmp_data<=x"0000";
tmp_read_addr<=x"0000";
tmp_addr<=x"0000";
to_light<=x"0000";
RAM1_EN<='1';
RAM1_OE<='0';
RAM1_We<='0';
address_state<=waiting;
write_state<=waiting;
read_state<=waiting;
elsif rising_edge(CLK) then
case ctrl_state is
when N=>
ADDR<=Input_data;
SEG <= not"1000000";
tmp_addr<=Input_data;
tmp_read_addr<=Input_data;
when W=>
case write_state is
when waiting =>
address_state<=waiting ;
write_state<=start;
read_state<=waiting;
SEG <= not"1000000";
when start=>
--tmp_data<=Input_data;
ADDR<=tmp_addr;
DATA<=Input_data;
RAM1_EN<='0';
RAM1_OE<='1';
RAM1_We<='0';
SEG<=not"1111001";
write_state<=over;
when over=>
write_state<=waiting;
tmp_addr<=tmp_addr+1;
SEG <= not "0100100";
end case;
when r=>
case read_state is
when waiting=>
address_state<=waiting;
read_state<=start;
write_state<=waiting;
SEG <= not"1000000";
when start=>
RAM1_EN<='0';
RAM1_OE<='1';
RAM1_We<='1';
ADDR<=tmp_read_addr;
DATA<=(others=>'Z');
read_state<=read;
SEG<=not"1111001";
when read=>
RAM1_OE<='0';
RAM1_We<='1';
to_light<=DATA;
SEG <=not "0100100";
read_state<=over;
when over=>
SEG <= not"0110000";
read_state<=waiting;
tmp_read_addr<=tmp_read_addr+1;
end case;
end case;
end if;
dbc<='1';
end process;
light<=to_light;
end Behavioral;
三、綜合實(shí)驗(yàn)總結(jié)
1.實(shí)驗(yàn)難點(diǎn)
略
2.心得體會(huì)
略
四、思考題
靜態(tài)存儲(chǔ)器的讀、寫時(shí)序各有什么特點(diǎn)?
答:如圖所示,特點(diǎn)如下:
3.部分代碼展示
architecture Behavioral of unit is
signal bzero : std_logic;(布爾)------------------------
type shower_state is (PC,ALU,Mem,Reg);--------枚舉類型,有四種狀態(tài)---計(jì)數(shù),加法器,內(nèi)存,寄存器
signal shower : shower_state;--------------------
type controler_state is
(instruction_fetch,decode,execute,mem_control,write_reg);
signal state : controler_state;
signal PCWrite : std_logic;-------------------是否改寫PC
signal PCWriteCond : std_logic;--------------------轉(zhuǎn)移指令的條件
signal PCSource : std_logic;------------------------新的PC來(lái)源選擇
signal ALUOp : std_logic_vector(1 downto 0);-----ALU運(yùn)算功能選擇
signal ALUSrcA : std_logic;---------------------------ALU源操作數(shù)A的選擇
signal ALUSrcB : std_logic_vector(1 downto 0);
signal MemRead : std_logic;--------------------------是否讀寄存器
signal MemWrite : std_logic;--------------------------是否寫寄存器
signal IRWrite : std_logic;-----------------------------寫IR
signal MemtoReg : std_logic_vector(1 downto 0);---寫入寄存器堆的數(shù)據(jù)來(lái)源選擇
signal RegWrite : std_logic_vector(2 downto 0);------寫寄存器控制
signal RegDst : std_logic_vector(1 downto 0);--------選擇目的寄存器
signal IorD : std_logic;-----------------存儲(chǔ)器地址來(lái)源
signal tmpb_zero : std_logic;
signal tmp_light : std_logic_vector(15 downto 0);
begin
light <= tmp_light;----燈
process(clk,rst,showCtrl)---------按鈕
begin
if rst='0' then
shower<=PC;
elsif rising_edge(showCtrl) then-----按
case shower is -----跳轉(zhuǎn)四個(gè)狀態(tài)
when PC=>
shower<=ALU;
when ALU=>
shower<=Mem;
when Mem=>
shower<=Reg;
when Reg=>
shower<=PC;
end case;
end if;
end process;
process(clk0,rst,state)
begin
if rst='0' then
tmp_light<=x"0000";
elsif rising_edge(clk0) then
case shower is
when PC=>
tmp_light(15 downto 0)<=x"0000";
tmp_light(15)<=PCWrite;
tmp_light(11)<=PCSource;
tmp_light(7)<=PCWriteCond;
when ALU=>
tmp_light(15 downto 0)<=x"0000";
tmp_light(15 downto 14)<=ALUOp;
tmp_light(11)<=ALUSrcA;
tmp_light(7 downto 6)<=ALUSrcB;
when Mem=>
tmp_light(15 downto 0)<=x"0000";
tmp_light(15)<=MemRead;
tmp_light(11)<=MemWrite;
tmp_light(7)<=IRWrite;
tmp_light(3 downto 2)<=MemtoReg;
when Reg=>
tmp_light(15 downto 0)<=x"0000";
tmp_light(15 downto 13)<=RegWrite;
tmp_light(11 downto 10)<=RegDst;
tmp_light(7)<=IorD;
end case;
end if;
end process;
process(rst,bzero_Ctrl)
begin
if rst = '0' then
bzero<='0';
elsif rising_edge (bzero_Ctrl) then
if bzero <= '0' then
bzero <= '1';
tmpb_zero<='0';
elsif bzero = '1' then
tmpb_zero<='1';
bzero<='0';
end if;
end if;
end process;
process (bzero)
begin
if bzero = '1' then
PCWriteCond<='1';
elsif bzero = '0' then
PCWriteCond<='0';
end if;
end process;
process (rst,clk)
begin
if(rst = '0') then
state<=instruction_fetch;
IorD<='0';
IRWrite<='0';
MemRead<='0';
MemWrite<='0';
MemtoReg<="00";
ALUOp<="00";
ALUSrcA<='0';
ALUSrcB<="00";
PCWrite<='0';
PCSource<='0';
RegDst<="00";
RegWrite<="000";
elsif rising_edge (clk) then
case state is
when instruction_fetch=>--------------取指
MemRead<='1';
ALUSrcA<='0';
IorD<='0';
ALUSrcB<="01";
ALUOp<="00";
PCWrite<='1';
PCSource<='0';
IRWrite<='1';
RegWrite<="000";
state<=decode;
when decode=>----------------譯碼
IRWrite<='0';
MemRead<='0';
PCWrite<='0';
ALUSrcA<='0';
ALUSrcB<="10";
ALUOp<="00";
state<=execute;
when execute=>---------------執(zhí)行
case instructions(15 downto 11) is
when "00100" =>
ALUSrcA<='1';
ALUOp<="10";
PCSource<='1';
state<=instruction_fetch;
when "10011"=>
ALUSrcA<='1';
ALUSrcB<="10";
ALUOp<="00";
state<=mem_control;
when "11011"=>
ALUSrcA<='1';
ALUSrcB<="10";
ALUOp<="00";
state<=mem_control;
when "11100" =>
case instructions (1 downto 0) is
when "01" => -----addu
ALUSrcA<='1';
ALUSrcB<="00";
ALUOp<="00";
when "11" => -----subu
ALUSrcA<='1';
ALUSrcB<="00";
ALUOp<="01";
when others =>
null;
end case;
state <=write_reg;
when "11101" =>
case instructions(4 downto 0) is
when "01101" =>
ALUSrcA<='1';
ALUSrcB<="00";
ALUOp<="10";
state<=write_reg;
when "00000" =>
case instructions(7 downto 5) is
when "000"=>
ALUSrcA<='1';
ALUOp<="10";
PCWrite<= '1';
PCSource <= '0';
state<= instruction_fetch;
when others=>
null;
end case;
when others =>
null;
end case;
when others=>
null;
end case;
when mem_control =>---------------訪存
PCWrite<= '0';
RegWrite<="000";
case instructions(15 downto 11) is
when "10011" =>
MemRead <= '1';
IorD <= '1';
state <= write_reg;
when "11011" =>
MemWrite <= '1';
IorD <= '1';
state <= write_reg;
when others =>
null;
end case;
when write_reg=>----------------寫入
Memwrite <= '0';
MemRead <= '0';
case instructions (15 downto 11) is
when "10011" =>
RegDst <= "10";
RegWrite <= "001";
MemtoReg <= "01";
when "11011" =>
MemWrite <= '0';
IorD <= '0';
when "11100" =>
case instructions (1 downto 0) is
when "01" =>
RegDst<= "01";
RegWrite<= "001";
MemtoReg <= "00";
when "11" =>
RegDst <="01";
RegWrite<= "001";
MemtoReg <= "00";
when others =>
null;
end case;
when "11101" =>
case instructions (4 downto 0) is
when "01101"=>
RegDst <="00";
RegWrite<= "001";
MemtoReg <= "00";
when others =>
null;
end case;
when others=>
null;
end case;
state <= instruction_fetch;
end case;
end if;
end process;
end Behavioral;
三.執(zhí)行階段實(shí)現(xiàn)的七條指令
七條指令分別為:ADDU SUBU BNEZ JR OR LW SW。
前面演示了取值,譯碼,到執(zhí)行的時(shí)候,需要參考實(shí)驗(yàn)書上的131頁(yè)到133頁(yè)的七條指令格式的設(shè)計(jì),這時(shí)候?qū)?yīng)的代碼會(huì)有指令的指示跳轉(zhuǎn)到各自的指令執(zhí)行的地方,LED燈會(huì)有各自的位置亮起。至于指令的數(shù)據(jù)通路和解釋,將在下一個(gè)實(shí)驗(yàn)CPU中給出。
下面給出實(shí)驗(yàn)時(shí)候執(zhí)行階段手寫的指令:
驗(yàn)截圖
紅色部分是演示時(shí)候LED燈亮的位置
黃色部分是執(zhí)行階段輸入的指令代表的數(shù)字
藍(lán)色部分三個(gè)按鈕有重置,跳轉(zhuǎn)狀態(tài)(ALU,Mem,Reg,PC),跳轉(zhuǎn)周期(取值,譯碼,執(zhí)行,訪存,寫回)的功能,即CLK,RST和右邊第一個(gè)紅色小按鈕。
四、綜合實(shí)驗(yàn)總結(jié)
1.實(shí)驗(yàn)難點(diǎn)
略
2.心得體會(huì)
略
實(shí)驗(yàn)四 16位CPU設(shè)計(jì)實(shí)驗(yàn)
一、目的與要求
實(shí)現(xiàn)一個(gè)基于MIPS指令集的CPU,數(shù)據(jù)總線16位,地址總線16位,具有8個(gè)16位的通用寄存器。指令包括訪存指令(如LW,SW),傳送指令(如LI,MOVE),算術(shù)運(yùn)算指令(如ADDU,SUBU),邏輯運(yùn)算指令(NOT,OR),移位運(yùn)算指令(如SLL),具體指令見實(shí)驗(yàn)指導(dǎo)書P23-P32。
具體要求:
(1)完成7條指令,必須包括訪存指令LW和SW,其余每類指令最多2條。
(2)按照取指、譯碼、執(zhí)行、訪存和寫回五個(gè)工作周期,分析每條指令的指令流程。
(3)根據(jù)指令流程,設(shè)計(jì)每條指令的CPU數(shù)據(jù)通路,定義涉及的所有微操作控制信號(hào)。然后逐一合并數(shù)據(jù)通路,說(shuō)明增加或減少處理器功能部件的理由。給出控制器的完整設(shè)計(jì)過程。
(4)編寫VHDL程序?qū)崿F(xiàn)CPU,并通過實(shí)驗(yàn)板驗(yàn)證。
二、實(shí)驗(yàn)正文
1.實(shí)驗(yàn)內(nèi)容
(1)實(shí)現(xiàn)一個(gè)基于MIPS指令集的多周期CPU
(2)設(shè)計(jì)完成7條指令,必須包括訪存指令LW和SW,其余每類指令最多2條
(3)按照取指、譯碼、執(zhí)行、訪存和寫回五個(gè)工作周期,分析每條指令的指令流程
(4)根據(jù)指令流程,設(shè)計(jì)每條指令的CPU數(shù)據(jù)通路,定義涉及的所有微操作控制信號(hào)。然后逐一合并數(shù)據(jù)通路,說(shuō)明增加或減少處理器功能部件的理由。給出控制器的完整設(shè)計(jì)過程。
(5)編寫VHDL程序?qū)崿F(xiàn)CPU,并通過實(shí)驗(yàn)板驗(yàn)證。
(6)給出完整的設(shè)計(jì)報(bào)告,包括基本部件設(shè)計(jì),如寄存器組、特殊寄存器、多路選擇器等;每一條指令的數(shù)據(jù)通路圖,以及CPU總數(shù)據(jù)通路圖;控制器的設(shè)計(jì)等。
(2)SUBU
數(shù)據(jù)通路分析過程:
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼,同時(shí)要將PC當(dāng)前內(nèi)容加2送給PC寄存器,使其指向下一條指令。
②譯碼階段:需要從指令中得到Rs寄存器和Rt寄存器的編號(hào),送給寄存器組RegisterFiles的Ra和Rb輸入端,從輸出端A、B取出其中內(nèi)容即源操作數(shù),送給運(yùn)算器輸入端以便于下一步進(jìn)行減法運(yùn)算,同時(shí)需要從指令中取出Rd寄存器編號(hào)送給寄存器組Rw輸入端作為目的地址,以便之后將運(yùn)算器運(yùn)算結(jié)果送給寄存器組的輸入端W,寫入寄存器Rd。
③計(jì)算階段:A、B通過運(yùn)算部件ALU進(jìn)行減法運(yùn)算。
④寫回寄存器階段:將ALU輸出端得到的運(yùn)算結(jié)果送給寄存器組的輸入端W,寫入寄存器Rd。
控制信號(hào):
RegWrite:由于加法功能需要讀出寄存器Ra和Rb的內(nèi)容還需要向Rw寄存器寫入內(nèi)容,所以需要增加一個(gè)控制信號(hào)控制寄存器組的讀/寫。
ALUop:由于ALU的功能有多種,故增加一個(gè)控制信號(hào)控制ALU功能選擇。
(3)LW
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼,同時(shí)將PC加2送給PC,指向下一條指令。
②譯碼階段:需要從指令中的第11位到第9位取出Rs寄存器編號(hào)送給寄存器組Ra輸入端,從輸出端A取出Rs寄存器內(nèi)容送給運(yùn)算器A輸入端,第5位到第0位取出6位立即數(shù)經(jīng)過擴(kuò)展送給運(yùn)算器B輸入端,同時(shí)還要將指令第8位到第6位送給Rw輸入端作為目的寄存器編號(hào)。
③計(jì)算階段:A、B輸入的內(nèi)容送給運(yùn)算器進(jìn)行加法運(yùn)算。
④讀存儲(chǔ)器:ALU輸出內(nèi)容送給數(shù)據(jù)存儲(chǔ)器地址輸入端addr。
⑤寫回寄存器:數(shù)據(jù)存儲(chǔ)器數(shù)據(jù)輸出端D送給寄存器組數(shù)據(jù)寫入端W,根據(jù)Rw中存放的Rt寄存器編號(hào),將數(shù)據(jù)寫入Rt寄存器。
控制信號(hào):
ALUop:控制選擇ALU功能為加法。
ALUsrcB:控制選擇運(yùn)算器B輸入端的內(nèi)容來(lái)源,本指令中來(lái)源于指令低6位擴(kuò)展到16位后的立即數(shù)。
RegWrite:控制寄存器組的讀出和寫入。
RegDsrc:控制選擇寄存器組Rw輸入端的來(lái)源,本指令中應(yīng)選擇指令8到6位作為寄存器編號(hào)。
Jump、PCsource:控制下一條指令的轉(zhuǎn)移。
RWmem:控制數(shù)據(jù)存儲(chǔ)器的讀出和寫入。
Wsrc:控制選擇寫入寄存器的數(shù)據(jù)來(lái)源,本指令來(lái)源于數(shù)據(jù)存儲(chǔ)器輸出數(shù)據(jù)。
(4)SW
數(shù)據(jù)通路分析過程:
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼,同時(shí)將PC加2送給PC,指向下一條指令。
②譯碼階段:需要從指令中的第11位到第9位取出Rs寄存器編號(hào)送給寄存器組Ra輸入端,從輸出端A取出Rs寄存器內(nèi)容送給運(yùn)算器A輸入端,第5位到第0位取出6位立即數(shù)經(jīng)過擴(kuò)展送給運(yùn)算器B輸入端,同時(shí)還要將指令第8位到第6位送給Rb輸入端作為輸入數(shù)據(jù)寄存器編號(hào)。
③計(jì)算階段:運(yùn)算器對(duì)A、B輸入的內(nèi)容進(jìn)行加法運(yùn)算,運(yùn)算后結(jié)果為目的地址需要送給數(shù)據(jù)存儲(chǔ)器地址端addr。
④讀寄存器:寄存器組B輸出端內(nèi)容輸入數(shù)據(jù),將其送給數(shù)據(jù)存儲(chǔ)器數(shù)據(jù)輸入端W。
⑤寫回存儲(chǔ)器:將數(shù)據(jù)存儲(chǔ)器輸入端W的數(shù)據(jù)寫入目的地址addr。
控制信號(hào):
ALUop:控制選擇ALU功能為加法。
ALUsrcB:控制選擇運(yùn)算器B輸入端的內(nèi)容來(lái)源,本指令中來(lái)源于指令低6位擴(kuò)展到16位后的立即數(shù)。
RegWrite:控制寄存器組的讀出和寫入。
Jump、PCsource:控制下一條指令的轉(zhuǎn)移。
RWmem:控制數(shù)據(jù)存儲(chǔ)器的讀出和寫入。
Wsrc:控制選擇寫入寄存器的數(shù)據(jù)來(lái)源,本指令來(lái)源于數(shù)據(jù)存儲(chǔ)器輸出數(shù)據(jù)。
(5)ADDIU
數(shù)據(jù)通路分析過程:
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼,同時(shí)將PC加2送給PC,指向下一條指令。
②譯碼階段:需要從指令中的第11位到第9位取出Rs寄存器編號(hào)送給寄存器組Ra輸入端,從輸出端A取出Rs寄存器內(nèi)容送給運(yùn)算器A輸入端,第11位到第9位取出Rs寄存器編號(hào)還要送給Rw輸入端作為運(yùn)算后的目的寄存器編號(hào),取出指令的8到0位送給運(yùn)算器B輸入端,。
③計(jì)算階段:A、B輸入的內(nèi)容送給運(yùn)算器進(jìn)行加法運(yùn)算。
④寫回階段:ALU輸出內(nèi)容送給寄存器組W輸入端寫回Rw所存的編號(hào)的寄存器。
控制信號(hào):
ALUop:控制選擇ALU功能為加法。
ALUsrcB:控制選擇運(yùn)算器B輸入端的內(nèi)容來(lái)源,本指令中來(lái)源于指令低9位擴(kuò)展到16位后的立即數(shù)。
RegWrite:控制寄存器組的讀出和寫入。
RegDsrc:控制選擇寄存器組Rw輸入端的來(lái)源,本指令中應(yīng)選擇指令11到9位作為寄存器編號(hào)。
Jump、PCsource:控制下一條指令的轉(zhuǎn)移。
(6)B
數(shù)據(jù)通路分析過程:
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼。
②譯碼階段:需要從指令中的低12位擴(kuò)展成16位與當(dāng)前PC內(nèi)容相加送回PC。
控制信號(hào):
Jump:由于PC的值和當(dāng)前執(zhí)行指令有關(guān),故增加一個(gè)控制信號(hào)Jump通過一個(gè)多路選擇器控制PC的選擇。
(7)JR
數(shù)據(jù)通路分析過程:
①取指令階段:需要從程序寄存器PC中取出當(dāng)前指令地址送給指令存儲(chǔ)器InstructionMemory的地址輸入端,然后從指令存儲(chǔ)器數(shù)據(jù)輸出端口得到指令內(nèi)容以便下一周期譯碼。
②譯碼階段:需要從指令中的第11位到第9位取出Rs寄存器編號(hào)送給寄存器組Ra輸入端,從輸出端A取出Rs寄存器內(nèi)容以便下一步根據(jù)指令功能通過運(yùn)算器運(yùn)算。
③計(jì)算階段:寄存器取出的內(nèi)容送給ALU輸入端A,通過ALUop控制信號(hào)選擇直接輸出源操作數(shù)A的功能。
④寫回階段:ALU輸出內(nèi)容送給PC。
控制信號(hào):
RegWrite:由于需要將讀出Rs寄存器內(nèi)容,所以需要一個(gè)寄存器讀信號(hào),將內(nèi)容從寄存器組輸出端口A輸出。
ALUop:此指令運(yùn)算器需要新的功能,故用ALUop信號(hào)控制運(yùn)算器功能選擇,這條指令中應(yīng)該選擇輸出Y=A。
PCsource:PC的內(nèi)容又增加了新的選擇,故需要一個(gè)OPsource信號(hào)通過多路選擇器控制PC的輸入選擇。
(5)根據(jù)CPU總數(shù)據(jù)通路圖設(shè)計(jì)控制器:列出控制信號(hào)表格以及每條指令在每個(gè)指令周期控制信號(hào)的值,完成控制器完整設(shè)計(jì):
(7)部分代碼展示
process(RST,showCtrl) -----狀態(tài)轉(zhuǎn)換
begin
if RST = '0' then
State_show <= PC;
stateCnt_L <= "0111001";
elsif showCtrl'event and showCtrl = '1' then
case State_show is
when PC =>
stateCnt_L <= "0000110";
State_show <= ALU;
when ALU =>
stateCnt_L <= "1011011";
State_show <= M;
when M =>
stateCnt_L <= "1001111";
State_show <= REG;
when REG =>
stateCnt_L <= "1100110";
State_show <= PC;
end case;
end if;
end process;
......
when decode =>
stateCnt_R <= "1011011";
AluSrcA <= '0';
ALUSrcB <= "10";
ALUOp <= "00";
MemRead <= '0';
IRWrite <= '0';
PcWrite <= '0';
CU_state <= execute;
case instruction(15 downto 11) is
when "11100" =>
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
rz <= instruction(4 downto 2);
when "00100" => --BEQZ
rx <= instruction(10 downto 8);
IMD <= instruction(7 downto 0);
when "11101" =>
case instruction(4 downto 0) is
when "00000" => --JR
rx <= instruction(10 downto 8);
when "01110" => --XOR
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
when others =>
null;
end case;
when "10011" => --LW
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
im <= instruction(4 downto 0);
when "11011" => --SW
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
im <= instruction(4 downto 0);
when others =>
null;
end case;
when execute =>
stateCnt_R <= "1001111";
control_state <= 0;
case instruction(15 downto 11) is
when "11100" =>
if instruction(1 downto 0) = "01" then --ADDU
ALUSrcA <= '1';
ALUSrcB <= "00";
ALUOp <= "00";
elsif instruction(1 downto 0) = "11" then --SUBU
ALUSrcA <= '1';
ALUSrcB <= "00";
ALUOp <= "01";
end if;
CU_state <= write_reg;
when "00100" => --BEQZ
ALUSrcA <= '1';
ALUOp <= "10";
PCSource <= '1';
CU_state <= instruction_fetch;
when "11101" =>
case instruction(4 downto 0) is
when "00000" => --JR
ALUSrcA <= '1';
ALUOp <= "10";
PcWrite <= '1';
PCSource <= '0';
CU_state <= instruction_fetch;
when "01110" => --XOR
ALUSrcA <= '1';
ALUSrcB <= "00";
ALUOp <= "10";
CU_state <= write_reg;
when others =>
null;
end case;
when "10011" => --LW
ALUSrcA <= '1';
ALUSrcB <= "10";
ALUOp <= "00";
CU_state <= write_reg;
when "11011" => --SW
ALUSrcA <= '1';
ALUSrcB <= "10";
ALUOp <= "00";
CU_state <= write_reg;
when others =>
null;
end case;
when mem_control =>
stateCnt_R <= "1100110";
case instruction(15 downto 11) is
when "10011" => --LW
RegWrite <= "000";
MemRead <= '1';
IorD <= '1';
PcWrite <= '0';
case control_state is
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
DATA(4 downto 0) <= DATA(4 downto 0) + im;
tmp_read_addr <= DATA;
CU_state <= mem_control;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 4;
when others =>
null;
end case;
when "11011" => --SW
RegWrite <= "000";
MemWrite <= '1';
IorD <= '1';
PcWrite <= '0';
case control_state is
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
DATA(4 downto 0) <= DATA(4 downto 0) + im;
tmp_addr <= DATA;
CU_state <= mem_control;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <= write_reg;
control_state <= 0;
when others =>
null;
end case;
when others =>
null;
end case;
when write_reg =>
stateCnt_R <= "1101101";
case instruction(15 downto 11) is
when "11100" =>
case instruction(1 downto 0) is
when "01" => --ADDU
RegDst <= "01";
RegWrite <= "001";
MemtoReg <= "00";
MemRead <= '0';
MemWrite <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr1 <= "0000000000000000";
tmp_read_addr1 <="0000000000000000";
tmp_read_addr1(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr1;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 2;
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data1 <= DATA;
tmp_read_addr1<="0000000000000000";
tmp_read_addr1(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr1;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 4;
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data1 <= DATA + tmp_data1;
tmp_addr1(2 downto 0) <= rz;
CU_state <= write_reg;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr1;
DATA <= tmp_data1;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state<=instruction_fetch;
control_state <= 0;
when others =>
null;
end case;
when "11" => --SUBU
RegDst <= "01";
RegWrite <= "001";
MemtoReg <= "00";
MemRead <= '0';
MemWrite <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr<="0000000000000000";
tmp_read_addr<="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 2;
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_read_addr<="0000000000000000";
tmp_read_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 4;
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= tmp_data - DATA;
tmp_addr(2 downto 0) <= rz;
CU_state <= write_reg;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <=instruction_fetch;
control_state <= 0;
when others =>
null;
end case;
when others =>
null;
end case;
when "11101" => --XOR
RegDst <= "00";
RegWrite <= "001";
MemtoReg <= "00";
MemRead <= '0';
MemWrite <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr <= "0000000000000000";
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 2;
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 4;
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= tmp_data xor DATA;
tmp_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <= instruction_fetch;
control_state <= 0;
when others =>
null;
end case;
when "10011" => --LW
RegDst <= "10";
RegWrite <= "001";
MemtoReg <= "01";
MemRead <= '0';
MemWrite <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr <= "0000000000000000";
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= mem_control;
control_state <= 2;
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <= instruction_fetch;
control_state <= 0;
when others =>
null;
end case;
when "11011" => --SW
MemRead <= '0';
MemWrite <= '0';
IorD <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr <= "0000000000000000";
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 2;
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= mem_control;
control_state <= 4;
when others =>
null;
end case;
when others =>
null;
end case;
end case;
end if;
end process;
三、綜合實(shí)驗(yàn)總結(jié)
1.實(shí)驗(yàn)難點(diǎn)
略
2.心得體會(huì)
略
四.思考題
設(shè)計(jì)完成后,給出每條指令輸入后在數(shù)據(jù)通路中的執(zhí)行過程。
如上面實(shí)驗(yàn)步驟給出來(lái)的數(shù)據(jù)通路圖,七條指令的都已經(jīng)給出執(zhí)行過程。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-401565.html
XXX申請(qǐng)驗(yàn)優(yōu)!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-401565.html
到了這里,關(guān)于計(jì)算機(jī)組成與結(jié)構(gòu)綜合大實(shí)驗(yàn)驗(yàn)優(yōu):16位運(yùn)算器設(shè)計(jì)實(shí)驗(yàn)、存儲(chǔ)器實(shí)驗(yàn)、控制器實(shí)驗(yàn)、16位CPU設(shè)計(jì)實(shí)驗(yàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!