自己动手写CPU(基于FPGA与Verilog)

  大三上学期开展了数字系统设计的课程,下学期便要求自己写一个单周期CPU和一个多周期CPU,既然要学,就记录一下学习的过程。

  CPU——*处理器,顾名思义,是计算机中最重要的一部分,功能就是周而复始地执行指令。其实开始做这部分之前,想到CPU就觉得很麻烦,毕竟时计算机内部最重要的东西,但其实刨开来细看,也就慢慢地接受了,当然我现在也不能说是了如指掌,说简单,毕竟自己还处于学习阶段,甚至可能还没有入门。慢慢来吧,先从简单的开始,一步一个脚印,总能写成的。今天先写在具体写代码之前的思路和设计方案。

  这次的设计是基于FPGA和Verilog设计一个RISC处理器,目前计划指令是14条,最终采用ISE进行代码编写与仿真。

  14条指令分别如下:

  

指令类型

指令名称

指令表示

指令

指令含义

R型

Add

 0 18 19 17 0 32

add rd,rs,rt

两个操作数相加

R型

Subtract

0 18 19 17 0 34

sub rd,rs,rt

两个操作数相减

I型

Load word

35 18 17 100

lw rt,rs,imm16

从内存取一个数写入到寄存器

I型

Store word

43 18 17 100

sw rt,rs,imm16

从寄存器中读出一个数写入到内存

R型

And

0 18 19 17 0 36

and rd,rs,rt

按位与

R型

Or

0 18 19 17 0 37

or rd,rs,rt

按位或

R型

Nor

0 18 19 17 0 39

nor rd,rs,rt

按位非

I型

Ori

13 18 17 100

ori rt,rs,imm16

寄存器和常数按位或

I型

Andiu

12 18 17 100

addiu rt,rs,imm16

寄存器和常数按位与

I型

Beq

4 18 17 100

beq rs,rt,imm16

想等则转移

I型

Bne

5 18 17 100

beq rs,rt,imm16

不相等则转移

R型

Shift left logical

0 0 18 17 10 0

sll rd,rs,rt

逻辑左移

R型

Shift right logical

0 0 18 17 10 2

srl rd,rs,rt

逻辑右移

J型

J

2 2500

j target

跳转目标地址

  确定好CPU可以执行的指令后,就可以具体写设计方案了。从上面的表就可以看出,有三种指令类型,分别是R型、I型和J型,那一个完整的设计方案必须包含这三种指令的执行。下面我给出我的设计方案图以及各个部件的功能。

自己动手写CPU(基于FPGA与Verilog)  

PC存储当前指令地址。

下地址逻辑:计算下一条指令地址。

指令存储器:存储指令。

主控部件:根据操作码判断指令类型是I型还是R型还是J型。

寄存器组:保存参加运算的操作数和中间结果。

ALU算术逻辑单元,通过func选择操作类型,完成基本的算术运算和逻辑运算。

扩展器:将16位立即数进行符号扩展或零扩展得到32位立即数。

数据选择器1根据指令类型选择相应数据进行算术或逻辑运算。指令类型若为R型,则将busb作为ALU的输入进行运算;若为I型,则将imm32作为ALU的输入进行运算。

数据选择器2根据指令类型选择是将ALU运算后的结果写入寄存器组还是将数据存储器中的数据存入寄存器组。指令若为R型,则将ALU运算后的结果写入寄存器组;指令若为I型,则将数据存储器中的数据存入寄存器组。

数据选择器3在overflow的控制下,选择是将rd作为寄存器组的写入地址还是将rt作为寄存器组的写入地址。指令若为R型,则将rd作为寄存器组的写入地址;指令若为I型,则将rt作为寄存器组的写入地址。

  基本的设计方案就是这样,看起来部件或许比一些书上的多一些,是因为我将很多大部件拆成了一个个的小部件,这样看起来会好理解很多。最后给出各个端口的定义。

  接口定义如下:

接口名称

类型

位宽/位

备注

addr

reg

6

指令地址寄存器

rs

reg

5

源操作数寄存器

rt

reg

5

源操作数寄存器

rd

reg

5

目的寄存器

op

reg

6

操作码

func

reg

6

指令操作类型

imm16

reg

16

立即数

imm32

reg

32

扩展后的立即数

busa

reg

32

rs内的数据

busb

reg

32

rt内的数据

R_type

reg

1

R型指令信号

I_type

reg

1

I型指令信号

J_type

reg

1

J型指令信号

data_in

reg

32

数据选择器1选择出来的数据

data_out

reg

32

ALU操作后的结果

Overflow

reg

1

溢出信号

data_I

reg

32

读出的数据存储器内的数据

out

reg

32

写入到寄存器组内的数据

上一篇:[SoapUI]怎样从应答报文中获取某个字段的值,然后用其改写某个变量


下一篇:grep与正则表达式基础