单周期CPU设计目录
一、前言(一些废话)
封面与内容无关!侵权必删!
这是笔者学校暑期学期的必修课,难度并不高(仅追求及格的话),但相当耗时,对于在硬件设计方面完全不感冒的同学更是一场避不开的折磨,所以笔者想通过自己的成果和被折磨经验来帮助有此方面需求的同学,或是对于CPU设计有浓厚兴趣的人。
这是笔者在CSDN上第一篇博客,若有不足请多海涵
若有源码需求或对本文章有所见解者,请不吝赐教
二、知识预备
如果在编写Verilog这类硬件编程语言时出现没有思路等现象时,可尝试反思对于设计所要求的理论知识是否牢固。
编写CPU的预备知识如下:
- 对数字逻辑设计有一定了解或更深层次的学习
- 对硬件原理有较好的基础并且能加以运用
- 对《计算机组成原理》理论至少要有所涉猎
- 对《计算机组成原理》教材(国内外皆可)中的CPU工作原理比较熟悉,并且能够自行构思其完整工作过程
三、整体构造图及开发板型号

- 本设计基于开发板为Xilinx的xc7a100tfgg484系列
四、将CPU工作分解
4.1取指(IF)
4.1.1 PC模块
我们知道CPU要取出指令,所依靠的计数器就是PC,通过PC的值pc,CPU可确定取指令的位置,所以此模块负责传输pc值。
4.1.2 NPC模块
在单周期模型中,PC需要在每个时钟上升沿到来之际进行相应更新,我们可以把这个逻辑单元单独拿出来,向PC模块传输下一个pc的值npc,同时此模块也接受一些后序模块数据,因为这些数据可能影响到如何选择npc的正确值。
4.1.3 IROM模块
该模块使用vivado平台提供的IP核实现,通过预先存入16进制指令序列,并且接受PC模块的pc值作为地址寻址取指令,并将取出的指令inst传送至后序模块(inst可以说是CPU最重要的变量了,没有inst一切工作都不可能进行)。
4.2译码(ID)
4.2.1 CU模块
控制单元(control unit)的简称,CU是CPU的“大脑”,负责解析从IROM模块传来的inst指令,并且生成各类控制信号,用于调遣其余部件进行工作。
4.2.2 RF模块
寄存器堆(register file)的简称,寄存器堆是CPU负责高速存储运算结果以及一些常用数据的存储设备,有读\写两种功能,为正确读写数据并且尽可能使CPU实际性能提示,采用组合逻辑读,时序逻辑写操作。
4.2.3 SEXT模块
符号扩展单元(sign extend),负责对risv-v指令的“可能”立即数位置所表示的立即数进行符号扩展为32位宽的数据,该行为受CU单元的sext_op信号所控制。
4.3执行(EXE)
4.3.1 ALU模块
ALU是算数逻辑单元,负责CPU内部绝大部分运算任务(所以主频的提高关键跟ALU性能有着偌大的关系),接受前面IF阶段和ID阶段的各类信号以及数据输入,通过CU单元的控制信号选择第一、第二运算数以及运算类型。
4.4访存(MEM)
4.4.1 DRAM模块
DRAM模块是使用vivado平台提供的IP核搭建的模拟主存,读写接口会有所提示。
4.5写回(WB)
4.5.1 WB模块
其实单周期CPU中的写回模块就是一个多路选择器,通过CU单元的控制信号wd_sel决定写回数据的选择,备选的数据有:ALU运算结果,pc值,符号扩展结果imm,主存读取输出ramdout。
4.6显示(DISPLAY)
4.6.1 display模块
此模块是为了实际下板而设立的,主要负责控制开发板上的LED灯,拨码开关和数码管。
4.7各模块逻辑类型总结
- 组合逻辑:NPC, IROM, SEXT, CU, ALU, WB
- 时序逻辑:PC, DRAM, DISPLAY
- 混合逻辑:RF(逻辑读,时序写)
五、各模块关键代码
5.1取指(IF)
5.1.1 PC模块
module PC(
input clk ,//CPU时钟
input rst ,//复位信号,高电平有效
input [31:0] npc ,//NPC模块的npc值
output reg [31:0] pc //PC模块的输出值pc
);
always @(posedge clk, posedge rst)
begin
if(rst) pc <= 32'h0ffff_fffc;//方便复位之后的第一个pc将为全0
else pc <= npc; //不复位时将npc作为pc的新值
end
endmodule
4.1.2 NPC模块
module NPC(
input [31:0] imm ,//符号扩展结果
input [31:0] rD1 ,//寄存器的第一输出
input pc_sel ,//来自CU单元,用于分支和跳转指令
input npc_op ,//同pc_sel来源相同
input [31:0] pc ,
output [31:0] npc
);
//npc_op为0时pc+4,为1时有跳转(pc_sel为0时pc + imm,为1时pc = rD1 + imm)
assign npc = npc_op ? (pc_sel ? rD1 + imm : pc + imm) : pc + 4;
endmodule
5.1.3 IROM模块
module inst_mem(
input [15:2] addr,//是pc信号的部分截取,可以思考一下为什么只需要2~15bit位?
output [31:0] inst //32位risv-v架构的指令
);
//program为vivado对应IP核的实例化,大小为16384*32bit
program U0_irom
(
.a (addr[15:2]),
.spo
2702





被折叠的 条评论
为什么被折叠?



