32位MIPS CPU基本部件设计

作者: 时间:2021-01-18 点击数:

实验4-1 32MIPS CPU基本部件设计

1. 实验目的

Ø 了解MIPS-C基本组成部件的工作原理;

Ø 掌握MIPS-C基本组成部件的设计方法。

2. 实验原理

CPU顶层设计是由下层基本部件例会而成的。本节将介绍图4-2中的各个基本部件的接口定义要求、功能及实现示例。

2.1 程序计数器Pc
模块接口

4-1 PC接口信号定义

信号名

方向

描述

Clk

I

MIPS-C处理器时钟

Reset

I

复位信号

PCSource[2:0]

I

下一个PC值的来源编码

BrPC[31:2]

I

分支指令的目标地址

JPC[31:2]

I

跳转指令的目标地址

EPC[31:0]

I

EPC(当发生异常时,当前指令值存储在EPC中)

PCWrite

I

PC写使能

PC[31:0]

O

PC输出

功能定义

PC模块的核心是一个计数器-PC(计数器名称为:PC。除非特殊需求,将不区分这两个PC)。




4-2 PC功能需求定义

编号

功能名称

功能描述

1

初始化

Reset信号有效后,PC=0xBFC00000

2

PC更新时机

当时钟上升沿到来时,检测PCSource,同时更新PC

3

确定NPC

根据来自控制器的PCSource,决定PC取值。

1) PCSource = 001hPC = PC + 4

2) PCSource = 010hPC = BrPC

3) PCSource = 011hPC = JPC

4) PCSource = 100hPC = 0x80000180

5) PCSource = 101hPC = 0x80000200

6) PCSource = 110hPC = EPC

核心代码

module PC(Clk,reset,PCSource,PC4,BrPC,JPC,EPC,PCWrite,PC_out);

input Clk,reset,PCWrite;

input[2:0] PCSource;

input[31:0] PC4;

input[31:2] BrPC,JPC;

input[31:0] EPC;

output[31:0] PC_out;

reg[31:0] PC_out;

`define EXCEPTION 32'h80000180 //define a constant

`define INT 32'h80000200

always @(posedge Clk,posedge reset)

begin

if(reset)

PC_out <= 32'hBFC00000;

else

begin

case(PCSource)

3'b001:if(PCWrite) PC_out <= PC4; //PC = PC + 4

3'b010:if(PCWrite) PC_out <= {BrPC,2'b00}; //PC Branch instruction

3'b011:if(PCWrite) PC_out <= {JPC,2'b00};  //PC Jump instruction

3'b100:if(PCWrite) PC_out <= `EXCEPTION; //Abnormal values

3'b101:if(PCWrite) PC_out <= `INT; //Abnormal return

3'b110:if(PCWrite) PC_out <= EPC; //when abnormal move PC to EPC

default:  ;

endcase

end

end

endmodule

仿真结果

4-5 程序计数器仿真结果

Clk系统时钟信号,Reset复位信号,PCSource[3:0]代表PC写入来源的输入信号,BrPC[31:2]32位的分支地址,EPC异常回复的PC写入,JPC32位跳转地址,PCIn来自ALU计算出的下一条地址,PCWritePC写入使能信号,高电平有效PC程序计数器根据PCSource[20]来判断PC的写入类型,仿真过程中一次仿真的是,复位、PC+4指向下一个地址、PC写入分支地址、PC写入跳转地址、异常地址。

2.2 指令寄存器IR
接口说明

4-3指令寄存器接口信号定义

信号名

方向

描述

Clk

I

MIPS-C处理器时钟

Reset

I

复位信号

MemData[31:0]

I

来自存储器的指令

IRWrite

I

IR写使能

IR[31:0]

O

指令寄存器输出

功能定义

IR内部只包括一个32位寄存器—IR

4-4 指令寄存器功能需求定义

编号

功能名称

功能描述

1.

初始化

Reset信号有效后,IR=0x00000000

2.

IR更新时机

当时钟上升沿到来时,并且IRWrite有效,则IR=MemData

核心代码

module IR(Clk,Reset,MemData,IRWrite,IR);

input  Clk,Reset,IRWrite;

input[31:0] MemData;

output[31:0]IR;

reg[31:0] IR;

always@(posedge Clk)

begin

if(Reset) //initialize the IR

IR = 8'h00000000;

else if(IRWrite) //When IRWrite is valid

 IR = MemData; //move the data from MemData to IR

end

endmodule

仿真结果

4-6 指令寄存器仿真结果

指令寄存器,仿真其指令写入,ClkCPU时钟信号,IR的写入由IRWrite信号控制,在IRWrite高电平时有效,将来自于存储器的指令写入,IR[310]IR寄存器的输出,即控制器的指令来源,CPU工作时,控制器的在第一个周期令IRWrite写使能有效,IR寄存器写入来自于存储器的指令。

2.3 寄存器堆Regfile
接口说明

4-5 寄存器堆接口信号定义

信号名

方向

描述

Clk

I

MIPS-C处理器时钟

Reset

I

复位信号

RS1[4:0]

I

读寄存器文件时的第1个寄存器下标

RS2[4:0]

I

读寄存器文件时的第2个寄存器下标

RD[4:0]

I

写寄存器文件时的寄存器下标

RegWrite

I

寄存器文件写使能

RData1[31:0]

O

读寄存器文件时的第1个寄存器的输出

RData2[31:0]

O

读寄存器文件时的第2个寄存器的输出

WData[31:0]

I

寄存器文件写入数据

功能定义

4-6 寄存器堆功能需求定义

编号

功能名称

功能描述

1

读寄存器

RData1输出RS1[4:0]所寻址的寄存器;

RData2输出RS2[4:0]所寻址的寄存器。

2

写寄存器

当当时钟上升沿到来时,并且RegWrite有效时,WData被写入RD[4:0]所寻址的寄存器

核心代码

module Regfile (Read1,Read2,WriteReg,WriteData,RegWrite,Data1,Data2,clock);

input [4:0] Read1,Read2,WriteReg;  // the registers numbers to read or write

input [31:0] WriteData;   // data to write

input RegWrite,  // The write control

clock;   // the clock to trigger write

output [31:0] Data1, Data2;   // the register values read

reg [31:0] RF [31:0];  // 32 registers each 32 bits long

assign Data1 = RF[Read1];

assign Data2 = RF[Read2];


always begin

// write the register with new value if Regwrite is high

@(posedge clock) begin

if (RegWrite) RF[WriteReg] <= WriteReg ? WriteData : 0;

end

end

endmodule

仿真结果

4-7 寄存器堆仿真结果

ClkCPU时钟信号,RS1,来自指令的第[25:21]位,作为寄存器的标号,RS2来自2016位,代表第二个寄存器标号,RD是要写入的寄存器标号,WData来自于外部的32位数据,因为读取数据是任意时候可以的,所以只仿真了写入和读出,Reset信号后,将WData876A4321H写入RD选中的寄存器06H,将RS106H,将写入的数据读出。


2.4 符号扩展单元
接口说明

4-7 符号扩展单元接口信号定义

信号名

方向

描述

Imm16[15:0]

I

来自指令寄存器的16位立即数

ExtImm32[31:0]

O

符号扩展后的32位立即数


功能定义

4-8 符号扩展单元功能需求定义

编号

功能名称

功能描述

1

符号扩展

16位二进制数经符号扩展后转换成32位二进制数。

1) 如果16位二进制数的最高位为0,则32位二进制的高16位全为0

2) 如果16位二进制数的最高位为1,则32位二进制的高16位全为1

核心代码

module SymbolExpasion(Imm16,ExtImm32);

input[15:0] Imm16;

output[31:0] ExtImm32;

reg[31:0] ExtImm32;

always

begin

if(Imm16[15]==0)

begin

ExtImm32[31:16] <= 16'b0;

ExtImm32[15:0] <= Imm16[15:0];

end

else if(Imm16[15]==1)

begin

ExtImm32[31:16] <= 16'b1111111111111111;

ExtImm32[15:0] <= Imm16[15:0];

end

end

endmodule

仿真结果

4-8 符号扩展单元仿真结果

Imm16是来自指令低16位的立即数,作为符号扩展单元的输入,ExImm32是扩展后的数据首先输入一个高位为0的立即数,扩展后,高16为填零,第二次输入一个最高位为1的立即数,扩展后高16位全部为1

2.5 算术运算器Alu
接口说明

4-9 算术运算器接口信号定义

信号名

方向

描述

ALU_DA[31:0]

I

ALU1个输入(ALU的上部输入)

ALU_DB[31:0]

I

ALU2个输入(ALU的下部输入)

ALU_Func[3:0]

I

ALU运算功能编码

ALU_Zero

O

运算结果0标志

ALU_DC[31:0]

O

ALU运算结果

功能定义

4-10 算术运算器功能需求定义

功能名称

功能描述

ALU_Func编码

运算功能

无操作

0000

ALU_DC = ALU_DB

无符号加运算

0001

ALU_DC = ALU_DA + ALU_DB

有符号加运算

0010

ALU_DC = ALU_DA + ALU_DB

运算

0011

ALU_DC = ALU_DA - ALU_DB

有符号减运算

0100

ALU_DC = ALU_DA - ALU_DB

运算

0101

ALU_DC = ALU_DA & ALU_DB

运算

0110

ALU_DC = ALU_DA | ALU_DB

或非运算

0111

ALU_DC = ~(ALU_DA | ALU_DB)

异或运算

1000

ALU_DC = ALU_DA ^ ALU_DB

小于置位运算

1001

ALU_DC = (ALU_DA < ALU_DB) ? 1 : 0

有符号小于置位运算

1010

ALU_DC = (ALU_DA < ALU_DB) ? 1 : 0

溢出判断:当有符号加减的时候会产生溢出,所以必须做个溢出判断。

核心代码

module ALU(ALU_DA,ALU_DB,ALU_Func,ALU_Zero,ALU_DC,ALU_OverFlow);

input[31:0] ALU_DA,ALU_DB;

input[3:0] ALU_Func;

output ALU_Zero,ALU_OverFlow;

output[31:0] ALU_DC;

wire ALU_Zero;

reg[31:0] ALU_DC;

wire ALU_OverFlow;

integer ALU_SymbolA;

integer ALU_SymbolB;

wire sign;

assign sign = ALU_DC[31];

assign  ALU_Zero = ALU_DC==32'b0 ? 1'b1:1'b0;

always@(ALU_DA,ALU_DB)

begin

ALU_SymbolA = ALU_DA;

ALU_SymbolB = ALU_DB;

end

always

begin

case(ALU_Func)

4'b0000:ALU_DC = ALU_DB;  //no operation

4'b0001:ALU_DC = ALU_DA + ALU_DB; //unsigned addition

4'b0010:ALU_DC = ALU_DA + ALU_DB; //signed addition

4'b0011:ALU_DC = ALU_DA - ALU_DB; //unsigned subtraction

4'b0100:ALU_DC = ALU_DA - ALU_DB; //signed subtraction

4'b0101:ALU_DC = ALU_DA & ALU_DB; //and operation

4'b0110:ALU_DC = (ALU_DA | ALU_DB); //or operation

4'b0111:ALU_DC = ~(ALU_DA | ALU_DB); //nor operation

4'b1000:ALU_DC = ALU_DA ^ ALU_DB; //xor operation

4'b1001:ALU_DC = (ALU_DA < ALU_DB) ? 1:0; //set less than operation

4'b1010:ALU_DC = (ALU_SymbolA < ALU_SymbolB) ? 1:0;

//set less than when the number is signed

4'b1011:ALU_DC = (ALU_SymbolA <= ALU_SymbolB) ? 1:0;

//To Imply all kinds of branches

4'b1100:ALU_DC = {ALU_DB[15:0],16'b0};  //To Imply lui

default:

ALU_DC = ALU_DB;  //assume not happen

endcase

end

assign ALU_OverFlow=((ALU_Func==4'b0010)&&((ALU_DA[31]==0)&&(ALU_DB[31]==0)&&(sign==1)))||((ALU_Func==4'b0010)&&((ALU_DA[31]==1)&&(ALU_DB[31]==1)&&(sign==0)))||((ALU_Func==4'b0100)&&((ALU_DA[31]==1)&&(ALU_DB[31]==0)&&(sign==0)))||((ALU_Func == 4'b0100)&&((ALU_DA[31]==0)&&(ALU_DB[31]==1)&&(sign==1)));

endmodule


仿真结果

4-9 算数运算器仿真结果

ALU_DA[31:0],ALU_DB[31:0]分别是第一、第二个运算数据输入,ALU_DC[31:0]运算结果OverFlow算术异常输出,ALU_Zero,运算结果为0 的标志信号,ALU_FuncALU的操作类型控制信号输入

ALU_Func=2’b0000,ALU_DC=ALU_DB

2’b0001无符号加法FFFFFFFDH+00000100H=000000FDH

0010有符号加法,因为使用补码,所以仍是直接相加000000FDH

0011,无符号加法,FFFFFFFDH-00000100H=FFFFFEFDH

0100,有符号减法

其他类似分析。


2.6 移位单元Shifter
接口说明

4-11 移位单元接口信号定义

信号名

方向

描述

SHT_DA[31:0]

I

被移位的数据(来自寄存器A

SHT_DB[4:0]

I

移位位数(来自寄存器B或指令寄存器[10:6]

SHT_Func[1:0]

I

移位运算功能编码

SHT_DC[31:0]

O

移位运算完成结果

功能定义


4-12 移位单元功能需求定义

功能名称

功能描述

SHT_Func编码

运算功能

无操作

00

SHT_DC = 032

逻辑左移

01

SHT_DC = SHT_DA31-SHT_DB:0 || 0SHT_DB

逻辑右移

10

SHT_DC = 0SHT_DB || SHT_DA31:SHT_DB

算数右移

11

SHT_DC = (SHT_DA31)SHT_DB || SHT_DA31:SHT_DB

核心代码

module Shifter(SHT_DA,SHT_DB,SHT_Func,SHT_DC,);

input[31:0] SHT_DA;

input[4:0] SHT_DB;

input[1:0] SHT_Func;

output[31:0] SHT_DC;

reg[31:0] SHT_DC;

always

begin

case(SHT_Func)

2'b00: SHT_DC = 0;

2'b01: SHT_DC = (SHT_DA<<SHT_DB);

2'b10: SHT_DC = (SHT_DA>>SHT_DB);

2'b11:

begin

if(SHT_DA[31])SHT_DC = ~((~SHT_DA)>>SHT_DB);

else SHT_DC = (SHT_DA>>SHT_DB);

end

endcase

end

endmodule


仿真结果

4-10 移位单元仿真结果

SHT_DA是要被移位的数据输入

SHT_DB是要移位的位数

SHT_Func要移位的类型01左移,10右移11算术右移

2.7 乘法单元Mul
接口说明

4-13 乘法单元接口信号定义

信号名

方向

描述

Clk

I

MIPS-C处理器时钟

Reset

I

复位信号

MUL_DA[31:0]

I

乘法单元第1个输入(来自寄存器A

MUL_DB[31:0]

I

乘法单元第2个输入(来自寄存器B

MUL_SelMD

I

乘法单元运算功能编码

MUL_Start

I

启动运算

MUL_SelHL

I

HI/LO选择

MUL_Write

I

乘法单元HI/LO寄存器写入使能

MUL_Flag

O

运算完成标志

MUL_DC[31:0]

O

乘法/除法运算结果

功能定义

4-14 乘法单元功能需求定义

编号

功能名称

功能描述

1

初始化

Reset信号有效后,内部控制逻辑复位,内部的HI寄存器、LO寄存器清除

操作

控制逻辑复位

LO ß 032

HI ß 032

2

乘法运算

MUL_Start1时,表明需要启动运算。如果MUL_SELMD0时,则执行乘法运算。运算开始前,MUL_Flag0;运算完成后,MUL_Flag1

操作

product ß MUL_DA × MUL_DB

LO ß product31:0

HI ß product63:32

3

除法运算

MUL_Start1时,表明需要启动运算。如果MUL_SELMD1时,则执行除法运算。运算开始前,MUL_Flag0;运算完成后,MUL_Flag1

操作

LO ß MUL_DA / MUL_DB

HI ß MUL_DA % MUL_DB

4

输出HI/LO

MUL_DC ß (MUL_SelHL == 1) ? HI : LO

5

写入HI/LO

MULWrite1时,MUL_DB数据将被写入HI寄存器或LO寄存器(MULSelHL1,选择HI寄存器;MULSelHL0,选择LO寄存器)。

操作

if MULWrite == 1

if MULSelHL == 1 then

HI ß MUL_DB

else

LO ß MUL_DB

核心代码

module MUL(Clk,Reset,MUL_Start,MUL_SelHL,MUL_SelMD,MUL_Write,MUL_Flag,MUL_DB,MUL_DA,MUL_DC);

input Clk,Reset,MUL_Start,MUL_SelHL,MUL_SelMD,MUL_Write;

output MUL_Flag;

input[31:0] MUL_DB,MUL_DA;

output[31:0] MUL_DC;


reg[31:0] hi,lo;

reg working,finish,finish2;

reg[63:0] result;


`define MUL_MUL  'b0

`define MUL_DIV 'b1

`define MUL_SEL_HIGH 'b1

`define MUL_SEL_LOW 'b0



function[63:0] result_mul;

input[31:0] a,b;

begin

result_mul = a*b;


end

endfunction


function[63:0] result_div;

input[31:0] a,b;

begin

result_div[31:0]=a/b;

result_div[63:32]=a%b;

end

endfunction


assign MUL_Flag = finish;

assign MUL_DC = finish ? (MUL_SelHL == `MUL_SEL_HIGH ? hi : lo):0;



always @(posedge Clk)

begin

if(Reset)

begin working <= 0 ;finish <= 0; end

else if(MUL_Start)

begin finish <= 0;working <=1; end

else if(finish2)

begin finish <= 1;working <= 0;end

end

always @(posedge working)

begin

if(working)

if(!finish)

begin

if(MUL_SelMD == 0)

result = result_mul(MUL_DA,MUL_DB);

else

result =result_div(MUL_DA,MUL_DB);


finish2 = 1;

end

else

;

else

;

end


always @(posedge Clk)

begin

if(Reset)

begin

lo <= 0;

hi <= 0;

end

else if(MUL_Write)

begin

if (MUL_SelHL == 1)

hi <= MUL_DA;//In order to ensure mthi/mtlo can get default data from rs(reg A)

else

lo <= MUL_DA;

end

else if(finish)

begin

lo = result[31:0];

hi = result[63:32];

end

end

endmodule


仿真结果

4-11 乘法单元仿真结果

MUL_SelMD=0MUL_Start做乘法运算,运算结束后finish有效2*6=12

2.8 存储器Mem
接口说明

4-15 存储器单元接口信号定义

信号名

方向

描述

Clk

I

MIPS-C处理器时钟

CS

I

使能信号

BE [3:0]

I

存储器功能模式选择信号

RW

I

读写信号

Addr[31:0]

I

输入地址信号

DataIn[31:0]

I

输入数据信号

Reset

I

复位信号

DataOut[31:0]

O

输出数据信号

DataReady

O

数据准备信号

功能定义

4-16 存储器单元功能需求定义

编号

功能描述

BE编码

运算功能

1

1111

/addr26位指示的存储器地址的32位字

2

0111

/addr26位指示的存储器地址的低16位字,高16位置0

3

0011

/addr26位指示的存储器地址的低8位字,高24位置0

4

default

读出0/

写:addr26位指示的存储器地址置0

核心代码

module Mem(Clk,BE,CS,RW,Addr,DataIn,Reset,DataOut,DataReady);

input Clk,CS,RW,Reset;

input[3:0] BE;

input[31:2] Addr;

input[31:0] DataIn;

output[31:0] DataOut;

output DataReady;


(* ram_init_file = "Mem.mif"*)

reg[31:0] memory[31:0];

reg[31:0] DataOut;

assign DataReady = 1;


always@(posedge Clk or posedge Reset)

if(Reset)begin

memory[0] <= 1;

memory[1] <= 2;

memory[2] <= 3;

end

else if(Clk)

begin

if(RW) begin

 memory[Addr[6:2]][31:16] <= (BE[3:2] == 2'b11) ? DataIn[31:16] : 16'b0;

memory[Addr[6:2]][15:8] <= (BE[1] == 1'b1) ? DataIn[15:8] : 8'b0;

memory[Addr[6:2]][7:0] <= DataIn[7:0];

end else begin

DataOut[31:16] <= (BE[3:2] == 2'b11) ? memory[Addr[6:2]][31:16] : 16'b0;

DataOut[15:8] <= (BE[1] == 1'b1) ? memory[Addr[6:2]][15:8] : 8'b0;

DataOut[7:0] <= memory[Addr[6:2]][7:0];

end

end

endmodule


仿真结果

4-12 存储器仿真结果

如图4-12所示,在不同模式下写相同的数据12345678,写入的结果不同。


2.9 多路选择器Multiplexor

多路选择器模块实现一系列的多路选择器,包括:32位的21314151615位的2131。下面以32位的31多路选择器为例说明接口和功能定义。

接口说明

4-17 3231多路选择器接口信号定义

信号名

方向

描述

in0 [31:0]

I

MIPS-C处理器时钟

in1 [31:0]

I

使能信号

in2 [31:0]

I

存储器功能模式选择信号

sel [1:0]

I

读写信号

out [31:0]

O

输入地址信号

功能定义

4-18 3231多路选择器功能需求定义

编号

功能描述

sel编码

运算功能

1

00

out<=   in0;

2

01

out<=   in1;

3

10

out<=   in2;

4

default

out   <= in0;

核心代码

/* 32bit 3 select 1 */

module Mux3to1_32(

in0,

in1,

in2,

sel,

out

);

input [31:0] in0;

input [31:0] in1;

input [31:0] in2;

input [1:0]sel;

output reg[31:0] out;


always@(in0, in1, in2, sel)

case(sel)

0: out<= in0;

1: out<= in1;

2: out<= in2;

default: out <= in0;

endcase


endmodule

仿真结果

4-13 3231多路选择器仿真结果

3. 实验步骤

(1) 根据4.2MIPS-C处理器各组成部件的模块接口与功能定义,依次通过编写verilog程序实现其接口和功能。

(2) 根据每一个MIPS-C处理器各组成部件的功能要求,设计仿真输入波形,并对仿真结构波形进行分析和验证。

(3) 根据不同的组成部件,选择实验电路,并确定部件接口的引脚锁定方案。

(4) 下载硬件到实验台,进行硬件测试。

4. 实验思考

1)绘制每一个MIPS-C处理器组成部件的仿真波形,并对照波形分析和说明其工作过程。

2)设计每一个MIPS-C处理器组成部件的硬件下载验证方案。



 Copyright© 2015 All Rights Reserved. 计算机国家级实验教学示范中心(北京航空航天大学)版权所有  京ICP备15000288 号