天天看點

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

  1. 指令分析

指令分析是第一步:MIPS指令集一共有三種指令。

R型(寄存器型):由Op(6位,下同)操作碼,Rs(5),Rt(5),Rd(5),shamt(5)移位位,func(6)功能碼組成

I型(立即數型):由Op(6),Rs(5),Rt(5),imm16(16)16位立即數組成

J型(跳轉型):由Op(6),imm26(26)26位立即數組成

下面是我選的一部分指令的分析

助記符 指令格式 示例 示例含義 操作及解釋
R-型 op rs rt rd shamt func 操作 解釋
Addu 000000 rs rt rd 100001 addu $1,$2,$3 $1=$2+$3 (rd)<-(rs)+(rt);rs=$2,rt=$3,rd=$1
Subu 000000 rs rt rd 100011 subu $1,$2,$3 $1=$2-$3 (rd)<-(rs)-(rt);rs=$2,rt=$3,rd=$1
or 000000 rs rt rd 100101 or   $1,$2,$4 $1=$2|$3 (rd)<-(rs)|(rt);rs=$2,rt=$3,rd=$1
sltu 000000 rs rt rd 101011 sltu $1,$2,$3 If($2<$3) $1=1else$1=0 if(rs<rt)rd=1else rd=0;rs=$2,rt=$3,rd=$1
syscall 000000 rs rt rd
I-型 Op rs rt immediate 示例 示例含義 操作及解釋
Addiu 001001 Rs Rt immediate Addiu $1,$2,10 $1=$2+10 (rt)<-(rs)+(sign-extend)immediate,rt=$1,rs=$2
Andi 001100 Rs Rt immediate Andi   $1,$2,10 $1=$2&10 (rt)<-(rs)&(zero-extend)immediate,rt=$1,rs=$2
Lw 100011 Rs Rt immediate Lw $1,10($2) $1=Memory[$2+10] (rt)<-Memory(rs)+(sign_extend)offset),rt=$1,rs=$2
Sw 101011 Rs Rt immediate Sw $1,10($2) MeMORY[$2+10]=$1 Memory[(rs)+(sign_extend)offset]<-(rt),rt=$1,rs=$2
Beq 000100 Rs Re immediate Beq $1,$2,40 If($1=$2) goto PC+4+40 If((rt)=(rs))then (PC)<-(PC)+((sign_extend)offset<<2),rs=$1,rt=$2
J-型 op address 示例 示例含義 操作及解釋
Jal 000011 address Jal 10000 $31=PC+4 goto 10000 ($31)<-(PC)+4;(PC)<-((zero_extend)address<<2),address=10000/4

2.基本資料通路設計

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. 注意:此處NPC和PC合二為一成為PC

運作流程:pc開始->指令存儲器->取指令->控制器->分析指令->得到操作的控制信号->發送到各個器件

取完指令之後->IR送寄存器組->選擇通路->送到ALU進行計算->進行後續操作。

1.時序子產品設計與仿真

(1)原理圖
基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳
  1. H_RUN輸入引腳,L_STEP輸入引腳,時序控制信号。
H_RUN L_STEP 功能
X 時序電路不輸出節拍信号
低變高 時序電路僅輸出一組節拍信号,供單步調試用。
1 1 時序電路輸出連續節拍信号
  1. CLK輸入引腳,主時鐘信号。
  2. RST1輸入引腳,主複位控制信号,低電平複位。
  • 輸出引腳

共4個節拍信号T1、T2、T3、T4。

(3)仿真圖
基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

  1. 寄存器堆子產品

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

clkread是寄存器堆的讀時鐘,clkwr是寄存器堆的寫時鐘,Reset是寄存器堆的複位信号,Regwr是寄存器堆的讀寫控制信号,高電平寫,低電平讀,RA[4..0]寄存器堆端口的輸入端,RB[4..0]寄存器堆端口的輸入端,RW[4..0]是寄存器堆的輸出端,BusW[31..0]是寄存器堆的輸入端,readnum[4..0]是寄存器堆的輸入端,j是jal型指令的控制信号。

  • 輸出引腳

BusA[31..0]和BusB[31..0]是寄存器堆的通道輸出端,readdata[31..0]是讀取寄存器内容的輸出端。

  1. 仿真
    基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. 資料存儲器ROM和程式存儲器RAM子產品

(1)原理圖

ROM

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

RAM

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

address是RAM存儲器的位址輸入端口,clock是RAM存取器的讀寫時鐘控制信号。

data[31..0]是RAM存儲器的資料輸入端口,wren是讀寫控制信号,高電平寫,低電平讀,address[7..0]是RAM存儲器的位址輸入端口,clock是RAM存儲器的讀寫時鐘控制信号。

  • 輸出引腳

q[31..0]是RAM和ROM存儲器的資料輸出端口。

(3)仿真圖

ROM

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

RAM

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

3.ALU運算部件

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

A[31..0]和B[31..0]是運算器的輸入端,ALUop[2..0]是運算器的控制信号

  • 輸出引腳

 ALUout[31..0]是運算器輸出結果,zero是做減法時,結果為零時發出的信号

(3)仿真

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. PC程式計數器

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

reset是重置運算器的控制信号,enable是運算器的使能信号,clk是時鐘脈沖信号,PCop[1..0]是控制控制PC進行不同操作的信号,imm26[25..0]是傳輸的立即數,zero是ALU做減法時零标志位,beq是進行beq操作時發出的信号

  • 輸出引腳

PCout[31..0]輸出下條指令的位址,PC4用于Jal操作時,下條指令位址的輸出。

(3)仿真

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. MUX多路選擇器

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

A0[31..0]、A1[31..0]、A2[31..0]、A3[31..0]是四個資料輸入端,S是控制選擇的控制信号。

  • 輸出引腳

Y[31..0]是資料輸出端。

(3)仿真

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. EXT拓展電路

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

(2)功能

  • 輸入引腳

imm16[15..0]是16立即數資料輸入輸入端,Extop是控制ext拓展器進行符号拓展或者零拓展的控制信号。

  • 輸出引腳

Extout[31..0]是資料輸出端,是拓展後輸出的數值。

(3)仿真

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. 控制器的設計

(1)原理圖

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

  1. 功能
  • 輸入引腳

op[5..0]和func[5..0]是資料輸入端,決定控制信号。

  • 輸出引腳

ALUop[2..0]、PCop[1..0]、MUX_alub、MUX_busw[1..0]、MUX_rw[1..0]、extop、Regwr、DMwr、Beq、halt、j是資料輸出端,分别控制ALU的操作,控制PC做不同的指令跳轉,控制進入alu的線路,busw的輸出端,控制不同信号的讀寫功能,拓展

仿真

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v
  1. 完整資料通路設計
  1. 各子產品的連接配接分析
指令 PC Im RF EXT ALU DM
輸入引腳 PCin Imm26 Imaddr RA RB RW BusW Imm16 BusA BusB Dmaddr Dmin
subu PC.pcout PC.pcout IR[25:21] IR[20:16] IR[15:11] ALU.aluout RF.BusA RF.BusB
addiu PC.pcout PC.pcout IR[25:21] IR[20:16] ALU.aluout IR[15:0] RF.BusA EXT.extout
beq PC.pcout IR[25:0] PC.pcout IR[25:21] IR[20:16] RF.BusA RF.BusB
lw PC.pcout PC.pcout IR[25:21] IR[20:16] DM.dmout IR[15:0] RF.BusA EXT.extout ALU.aluout
sw PC.pcout PC.pcout IR[25:21] IR[20:16] IR[15:0] RF.BusA EXT.extout ALU.aluout RF.BusB
jal PC.pcout IR[25:0] PC.pcout 0x1F PC.pc4
合并 PC.pcout IR[25:0] PC.pcout IR[25:21] IR[20:16] 0:IR[15:11] 1:IR[20:16] 2:OX1F 0:ALU.aluout 1:DM.dmout 2:PC.pc4 IR[15:0] RF.BusA 0:RF.BusB 1:EXT.extout ALU.aluout RF.BusB
  1. 控制信号分析
Regwr DMwr Beq halt EXtop MUX_alub ALU_op J PCop MUX_busw MUX_RW
addu 1 000 10 00 00
subu 1 001 10 00 00
sltu 1 100 10 00 00
or 1 010 10 00 00
syscall 1 000 10 00 00
addiu 1 1 1 000 10 00 01
lw 1 1 1 000 10 01 01
sw 1 1 1 000 10 01 01
beq 1 1 1 001 00 01 01
andi 1 1 1 011 10 00 01
jal 1 000 1 01 10 10
addu+subu+sltu+or+addiu+lw+andi+jal sw beq halt addiu+lw+sw+beq+andi addiu+lw+sw+bqe+andi 000:addu+syscall+addiu+lw+sw+andi+jal,001:subu+beq,010:or,011:andi,100:sltu jal 10:addu+subu+sltu+or+syscall+addiu+lw+sw+andi,00:beq,01:jal 00:addu+subu+sltu+or+syscal+addiu,01:lw+sw+beq,10:jal 00:addu+subu+sltu+or+syscall+sw,01addiu+sw+lw+andi+beq,10:jal

1、測試程式

       為了驗證CPU的正确性,編寫了表6.1測試程式,其中的寄存器編碼、立即數、位址等指令格式中的資訊必須具體化。

表6.1  測試程式

序号 彙編語言 操作碼 位址碼 16進制機器編碼 功能
Op function
1 addu $s0,$zero,$zero 000000 100001 00008021 $s0=$zero+$zero
2 addiu $s1,$zero,5 001001 4 24110005   $s1=$zero+5
3 subu $s2,$s1,$s0 000000 100001 8 02309023   $s2=$s1-$s0
4 or $s3,$s1,$s2 000000 100101 12 02329825   $s3=$s1|$s2
5 lw $s4,4($s0) 100011 16 8e140004   $s4=memory[$s0+4]
6 sltu $s5,$s1,$s2 000000 101011 18 0232a82b   If($s1<$s2)$s5=1else$s5=0
7 sw $s6,8($s0) 101011 24 ae160008   Memory[($s0+8)/4]=$s6
8 andi $s7,$s0,5 001100 28 32170005   $s7=$s0&5
9 beq $s1,$s2,4 000100 32 12320004 If($s1=$s2)pc=pc+4+16else pc=pc+4
10 Jal 9 000011 40 0c000009 Pc=36
11 syscall 000000 001100 36 0000000c Halt

2、仿真圖

測試程式的仿真結果如圖6.1所示。

基于MIPS指令集單周期CPU設計與實作——硬布線式alut.vcontroll.v EXT.vMUX2.vMUX4_r.v MUX4.v pcall.v RegisterFile.v

圖6.1 程式運作仿真圖

從仿真圖可見,程式運作完全正确,執行停機指令HALT時,指令不再跳轉。

alut.v

module alut(A,B,ALUop,ALUout,zero);

input [31:0] A,B;

input [2:0] ALUop;

output [31:0] ALUout;

output zero;

reg [31:0] res;

assign zero=(res==0)?1:0;

assign ALUout=res;

always @*

begin

case(ALUop)

3'b000:res<=A+B;

3'b001:res<=A-B;

3'b010:res<=A|B;

3'b011:res<=A&B;

3'b100:res<=A<B?1:0;

endcase

end

Endmodule

controll.v

module Controll(op,func,ALUop,PCop,MUX_alub,MUX_busw,MUX_rw,extop,Regwr,DMwr,Beq,halt,j);

input [5:0] op;

input [5:0] func;

output Regwr,DMwr,Beq,halt,extop,MUX_alub,j;

output [1:0] PCop,MUX_busw,MUX_rw;

output [2:0] ALUop;

//R

wire addu   = (op == 6'b000000 & func == 6'b100001)?1:0;

wire subu   = (op == 6'b000000 & func == 6'b100011)?1:0;

wire Or     = (op == 6'b000000 & func == 6'b100101)?1:0;

wire sltu   = (op == 6'b000000 & func == 6'b101011)?1:0;

wire syscall= (op == 6'b000000 & func == 6'b001100)?1:0;

//I

wire addiu= (op == 6'b001001)?1:0;

wire andi = (op == 6'b001100)?1:0;

wire lw   = (op == 6'b100011)?1:0;

wire sw   = (op == 6'b101011)?1:0;

wire beq  = (op == 6'b000100)?1:0;

//J

wire jal  = (op == 6'b000011)?1:0;

assign Regwr=addu | subu | Or | sltu | addiu | lw | andi | jal;

assign DMwr=sw;

assign Beq=beq;

assign halt=syscall;

assign extop=addiu | lw | sw | andi;

assign MUX_alub=addiu | lw | sw | andi;

assign j=jal;

assign ALUop[2]=sltu;

assign ALUop[1]=Or | andi;

assign ALUop[0]=subu | andi | beq;

assign PCop[1]=addu | subu | Or | sltu | syscall | addiu | andi | lw | sw;

assign PCop[0]=jal;

assign MUX_busw[1]=beq | jal ;

assign MUX_busw[0]=lw | sw;

assign MUX_rw[1]=jal;

assign MUX_rw[0]=addiu | andi | lw | sw | beq ;

endmodule

 EXT.v

module EXT(imm16,Extop,Extout);

 input [15:0] imm16;

 input  Extop;

 output reg [31:0] Extout;

  always @(imm16 or Extop)

      if(Extop)

if(~imm16[15])

begin

Extout<={{16{1'b0}},imm16[15:0]};

end

else

begin

Extout<={{16{imm16[15]}},imm16[15:0]};

end

endmodule

MUX2.v

module MUX2(A0,A1,S,Y);

    input [31:0]A0,A1;

    input S;

    output [31:0]Y;

    function [31:0]select;

        input [31:0]A0,A1;

        input S;

        case(S)

            1'b0:select=A0;

            1'b1:select=A1;

        endcase

    endfunction

    assign Y = select(A0,A1,S);

Endmodule

MUX4_r.v

module MUX4_r (A0, A1, A2, A3, S, Y);

    input [4:0] A0, A1, A3;

 input [1:0] A2;

    input [1:0] S;

    output [4:0] Y;

    function [31:0] select;

        input [4:0] A0, A1, A3;

  input [1:0] A2;

        input [1:0] S;

            case(S)

                2'b00: select = A0;

                2'b01: select = A1;

                2'b10: select = A2;

                2'b11: select = A3;

            endcase

    endfunction

    assign Y = select (A0, A1, A2, A3, S);

endmodule

 MUX4.v

module MUX4 (A0, A1, A2, A3, S, Y);

    input [31:0] A0, A1, A2, A3;

    input [1:0] S;

    output [31:0] Y;

    function [31:0] select;

        input [31:0] A0, A1, A2, A3;

        input [1:0] S;

            case(S)

                2'b00: select = A0;

                2'b01: select = A1;

                2'b10: select = A2;

                2'b11: select = A3;

            endcase

    endfunction

    assign Y = select (A0, A1, A2, A3, S);

endmodule

 pcall.v

module pcall(reset,enable,clk,PCop,imm26,zero,beq,PCout,PC4);

 input enable,reset,clk,zero,beq;

 input [1:0] PCop;

 input [25:0] imm26;

 output reg [31:0]  PC4;

 output  reg[31:0]  PCout;

  initial

    begin

 PCout<=32'h00000000;

 end

  always @(posedge clk or posedge reset )

begin

   if (reset)

   begin

PCout<=32'h00000000;

end

 else

   if (enable)

if(PCop==2'b00&&beq&&zero)

begin

PCout<=PCout+32'h00000004+{{16{imm26[15]}},imm26[15:0],2'b00};

end

else if(PCop==2'b01)

begin

PC4<=PCout+32'h00000004;

PCout<={PCout[31:28],imm26,2'b00};

end

else if(PCop==2'b10)

begin

PCout<=PCout+32'h00000004;

end

else

begin

PCout<=PCout+32'h00000004;

end

end

endmodule

 RegisterFile.v

module RegisterFile(clkread,clkwr,Reset,RegWr,RA,RB,RW,BusW,BusA,BusB,readnum,readdata,j);

input clkread,clkwr,Reset,RegWr,j;

input [4:0] RA,RB,RW,readnum;

input [31:0] BusW;

output reg [31:0] BusA,BusB;

output  [31:0] readdata;

reg [31:0] regfile[31:0];

integer i;

initial

 begin

   regfile[0]=32'h00000000;

  end

 assign readdata=regfile[readnum];

 always @(posedge clkwr or posedge Reset)

   begin

    if (Reset)

         begin

        for (i=1;i<=31;i=i+1)

     regfile[i]<=0;

      end

    else

        begin

   if (RegWr)

 if(j)

 begin

 regfile[31]<=BusW;

 end

 else

 begin

       regfile[RW]<=BusW;

    end

     end

  end

  always @(posedge clkread)

  begin

       BusA<=regfile[RA];

       BusB<=regfile[RB];

  end

endmodule

繼續閱讀