单周期CPU实验

注:为了老师的教学正常进行,不上传代码,只有自己的部分实验报告(不包括实验心得)
注:因为涉及到很多截图,为了节省时间,直接采用截图的方式

1.数据通路图

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

2.实验设计与分析

这里写图片描述
这里写图片描述

对每一条指令的理解

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

3.实验结果截图(略)

4.实验中遇到的问题

(1)PC子模块中最开始的时候没有使用非阻塞赋值,导致PC一直出错。非阻塞赋值使得在结构块结束的时候才进行赋值,而不是立即赋值,后来使用非阻塞赋值后解决了这个错误。
(2)if(PCSrc==1) assign NextPC = PC + 4;将这样的if语句放在过程块中一直出错,一直弄不懂原因,后来请教同学,发现将其放在always结构块中并且检查NextPC的类型就可以解决问题。
(3)若将assign用在过程块initial和always中,此时只支持reg类型,但是对于非过程块中连续赋值,assign支持net型。
(4)对于Extend子模块,我将sa的符号位扩展桶16为立即数的扩展放在一起,使得在执行sll指令的时候能够保证sa扩展为32位。
(5)对于sll,实现起来遇到的麻烦比较大,因为需要同时控制ALUSrcA和ALUSrcB,最终是在CPU主模块中添加了ALUSrcA来作为判断,当执行的ALUSrcA为1的时候,送入到ALU中的data1不再是rs中的数据而是扩展后的sa.
(6) 最开始的时候只写了if语句而对else语句不做处理,本来觉着没什么问题,但是执行后却发现当sll执行过后ALUSrcA就一直为1,不改变,最后添加了else语句使问题得到解决。
这里写图片描述
(7)最开始的时候对于仿真后出现XXX和ZZZ的结果完全不知所措,因为代码也没有报错。后来发现是因为在CPU中各个子模块中的参数的传递顺序不一致。
这里写图片描述
(8)一些小细节的错误,比如单词拼写错误或者是input后面的“,”写成了“;”之类的,或者是output最后不能有“,”或者是“;”。这种错误报错的时候很不明确,所以检查的时候很麻烦。
这里写图片描述
这里写图片描述

5.小结

关键是理解数据通路图,对每条指令,通过数据通路图完整地走几遍能够有效帮助理解。

  • 0
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
周期CPU实验是数字电路实验教学中的一个重要环节,它可以帮助学生理解计算机的基本原理和组成部分。下面是一个简的Verilog代码示例,用于实现周期CPU。 ``` module SingleCycleCPU ( input clk, input rst, input [31:0] instr, input [31:0] data_in, output reg [31:0] data_out ); // 寄存器声明 reg [31:0] PC; reg [31:0] regA; reg [31:0] regB; reg [31:0] ALU_out; // 控制信号声明 reg RegDst; reg ALUSrc; reg MemtoReg; reg MemRead; reg MemWrite; reg Branch; reg RegWrite; reg [1:0] ALUOp; // 模块声明 ALU alu(.A(regA), .B(regB), .ALUOp(ALUOp), .ALU_out(ALU_out)); Memory mem(.addr(ALU_out), .data_in(data_in), .data_out(data_out), .MemRead(MemRead), .MemWrite(MemWrite)); ControlUnit control_unit(.opcode(instr[31:26]), .RegDst(RegDst), .ALUSrc(ALUSrc), .MemtoReg(MemtoReg), .MemRead(MemRead), .MemWrite(MemWrite), .Branch(Branch), .RegWrite(RegWrite), .ALUOp(ALUOp)); always @(posedge clk or posedge rst) begin if (rst) begin PC <= 32'h00000000; regA <= 32'h00000000; regB <= 32'h00000000; data_out <= 32'h00000000; end else begin PC <= PC + 4; if (Branch & (ALU_out == 0)) begin PC <= PC + instr[15:0] << 2; end if (RegWrite) begin if (RegDst) begin regB <= instr[15:11]; end else begin regB <= instr[20:16]; end regA <= data_out; end if (ALUSrc) begin regB <= instr[15:0]; end end end endmodule ``` 在这个代码中,我们定义了一个名为SingleCycleCPU的模块,它有四个输入和一个输出端口。输入端口包括时钟信号clk、复位信号rst、32位指令instr和32位数据data_in。输出端口为32位数据data_out。 模块内部声明了一些寄存器和控制信号,包括PC、regA、regB、ALU_out、RegDst、ALUSrc、MemtoReg、MemRead、MemWrite、Branch、RegWrite和ALUOp。其中,PC、regA、regB和ALU_out是用于存储数据和计算ALU输出的寄存器;RegDst、ALUSrc、MemtoReg、MemRead、MemWrite、Branch、RegWrite和ALUOp是用于控制周期CPU执行流程的控制信号。 在always块中,我们定义了周期CPU的执行流程。当rst为1时,所有寄存器被清零。当rst为0时,PC寄存器递增4,指向下一条指令。如果Branch和ALU_out都为1,则PC寄存器指向指令中的偏移地址。如果RegWrite为1,则将data_out写入regA寄存器,同时根据RegDst选择将instr[15:11]或instr[20:16]写入regB寄存器。如果ALUSrc为1,则将instr[15:0]写入regB寄存器。 最后,我们还需要在代码中实例化ALU、Memory和ControlUnit模块,并将它们的输入和输出端口与SingleCycleCPU模块的信号相连。这些模块分别用于计算ALU输出、读写内存和生成控制信号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值