《自己动手写CPU》学习记录(3)——第4章/Part 1
创始人
2024-03-27 00:09:16
0




目录

引言

致谢

平台

ori 指令

流水线结构建立

模型

简单的MIPS五级流水线结构

设计

宏定义

程序计数器

译码

通用寄存器

指令执行

内存访问

指令ROM

顶层文件

处理器顶层

SOPC顶层 

功能仿真

TestBench

仿真结果

执行时间

时序细节


 


引言

本篇学习书本的第四章,实现 ori 指令。

致谢

感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。

平台

开发环境:Vivado IDE 2018.3

FPGA芯片型号:xc7a35tfgg484-2



ori 指令

指令格式:

指令用法:

ori rs, rt,immediate

其作用是将指令中的16位立即数进行无符号数扩展至 32 位,然后与索引号为 rs 的通用寄存器的值进行逻辑或运算,运算的结果保存到索引号为 rt 的寄存器内。

符号扩展示例:

流水线结构建立

模型

简单的MIPS五级流水线结构

设计

声明:

设计思路基本借鉴书本,但是具体的模块代码编写,与作者有较大不同

宏定义

此文件主要定义了一些与设计相关的宏,当设计的参数需要更改时,在此文件修改即可,不需要改动内部设计文件。方便代码维护,也增强了代码的可读性。

// |------------------------------ ================================== ------------------------------
// |============================== MIPS32 CPU SYSTEM ALL MACRO DEFINE ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |// |--------------------------------------  系统级全局宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 0字
`define 							DEF_ZERO_WORD						32'd0				// 0字// | 关于译码
`define 							DEF_ALU_OPR_BUS						7:0					// 译码输出 O_ALU_OPR 总线
`define 							DEF_ALU_SEL_BUS 					2:0					// 译码输出 O_ALU_SEL 总线// | 逻辑 0 1
`define 							DEF_LOG_TRUE						1'b1				// 逻辑 真
`define 							DEF_LOG_FALSE						1'b0				// 逻辑 假// | 芯片使能
`define 							DEF_CHIP_EN							1'b1				// 芯片使能
`define 							DEF_CHIP_DIS						1'b0				// 芯片不使能// |--------------------------------------  指令相关的宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令码
`define 							DEF_ISTC_ORI						6'b001101 			// ori
`define 							DEF_ISTC_NOP						6'd0				// nop// | ALU操作码
`define 							DEF_ALU_OR_OPR						8'b00100101			// ALU 或 操作码
`define 							DEF_ALU_NOP_OPR						8'd0				// ALU 空 操作码// | ALU 选择
`define 							DEF_ALU_SEL_LOGIC					3'b001
`define 							DEF_ALU_SEL_NOP						3'b000				// | 操作数
`define 							DEF_SRC_OPR_DATA_BUS				31:0
`define 							DEF_IMM_DATA_BUS					15:0// |--------------------------------------  指令存储器宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
`define 							DEF_ISTC_ADDR_BUS					31:0				// 地址线总线
`define 							DEF_ISTC_DATA_BUS 					31:0				// 数据线总线
`define 							DEF_ISTC_CACH_DEPTH					2**17-1				// 缓存深度/地址最大值
`define 							DEF_ISTC_ADDR_WIDTH_ACTUAL			17					// 实际使用的缓存地址线宽度// |--------------------------------------  通用寄存器宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
`define 							DEF_GPR_ADDR_WIDTH					5					// 通用寄存器地址位宽(32个)
`define 							DEF_GPR_DATA_WIDTH					32					// 通用寄存器数据位宽
`define 							DEF_GPR_NUM							32					// 通用寄存器数目
`define 							DEF_GPR_ADDR_NOP					5'd0				// 空操作 GPR 地址

程序计数器

该模块在时钟节拍下,给出程序指令寄存器要读取的地址,以及读使能信号。输出接口对接指令存储器ROM模块。

// |------------------------------ ================================== ------------------------------
// |============================== 		   程序计数寄存器模块		  ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-12-06
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule PC_REG_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
input														  I_CPU_CLK,
input 														  I_CPU_RSTN,output 		reg 	[`DEF_ISTC_ADDR_BUS]					  O_PC,
output		reg 											  O_ISTC_ROM_CE);// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// CE
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_ISTC_ROM_CE <= `DEF_CHIP_DIS;endelsebeginO_ISTC_ROM_CE <= `DEF_CHIP_EN;end
end// PC
always @ (posedge I_CPU_CLK)
beginif(O_ISTC_ROM_CE == `DEF_CHIP_DIS)beginO_PC <= 32'd0;endelsebeginO_PC <= O_PC + 32'd4;end
endendmodule

译码

此模块主要接收来自指令存储器ROM模块输出的指令,并且按照指令编码规则进行指令译码,为后续的指令执行模块提供必要的计算信息。

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-译码模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule ID_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 指令
input 		[`DEF_ISTC_DATA_BUS]								I_ISTC,
// | GPR读写控制
output 	reg														O_GPR_RD_EN_A,
output	reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_GPR_RD_ADDR_A,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_GPR_RD_DATA_A,
output reg														O_GPR_RD_EN_B,
output reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_GPR_RD_ADDR_B,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_GPR_RD_DATA_B,
// | 译码输出相关 对接 ALU 运算单元
// output  reg [`DEF_ALU_SEL_BUS]									O_ALU_SEL,
output	reg [`DEF_ALU_OPR_BUS]									O_ALU_OP_TYPE,
output  reg	[`DEF_SRC_OPR_DATA_BUS]								O_SRC_OPR_DATA_A,
output  reg	[`DEF_SRC_OPR_DATA_BUS]								O_SRC_OPR_DATA_B,
output  reg 													O_DST_GPR_WR_EN,
output  reg [`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR);
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
wire		[5:0]												W_ISTC_TYPE;
wire		[`DEF_GPR_ADDR_WIDTH-1:0]							W_SRC_GPR_ADDR;
wire 		[`DEF_GPR_ADDR_WIDTH-1:0]							W_DST_GPR_ADDR;
wire		[`DEF_IMM_DATA_BUS]									W_ISTC_IMM_DATA;// | 32位立即数
reg			[31:0]												R_IMM_DATA_32BIT;// | 指令有效信号
reg																R_ISTC_VAL;// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
assign 		W_ISTC_TYPE			=		I_ISTC[31:26];
assign 		W_SRC_GPR_ADDR  	=       I_ISTC[25:21];
assign		W_DST_GPR_ADDR  	=       I_ISTC[20:16];
assign 		W_ISTC_IMM_DATA		=		I_ISTC[15:0] ;// | 指令译码
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_GPR_RD_EN_A	  <= 1'b0;O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;O_GPR_RD_EN_B	  <= 1'b0;O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;O_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;O_DST_GPR_WR_EN   <= 1'b0;O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;R_ISTC_VAL		  <= 1'b0;R_IMM_DATA_32BIT  <= 32'd0;endelsebegincase(W_ISTC_TYPE)`DEF_ISTC_ORI:// ori指令beginO_GPR_RD_EN_A	  <= 1'b1;O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;O_GPR_RD_EN_B	  <= 1'b0;O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;O_ALU_OP_TYPE     <= `DEF_ALU_OR_OPR;// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;O_DST_GPR_WR_EN   <= 1'b1;O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;R_ISTC_VAL		  <= 1'b1;R_IMM_DATA_32BIT  <= {16'd0,W_ISTC_IMM_DATA};enddefault:beginO_GPR_RD_EN_A	  <= 1'b0;O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;O_GPR_RD_EN_B	  <= 1'b0;O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;O_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;O_DST_GPR_WR_EN   <= 1'b0;O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;R_ISTC_VAL		  <= 1'b0;R_IMM_DATA_32BIT  <= 32'd0;endendcaseend
end// | 数据输出
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;endelse if(O_GPR_RD_EN_A)beginO_SRC_OPR_DATA_A <= I_GPR_RD_DATA_A;endelse if(~O_GPR_RD_EN_A)beginO_SRC_OPR_DATA_A <= R_IMM_DATA_32BIT;endelsebeginO_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;end
endalways @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;endelse if(O_GPR_RD_EN_B)beginO_SRC_OPR_DATA_B <= I_GPR_RD_DATA_B;endelse if(~O_GPR_RD_EN_B)beginO_SRC_OPR_DATA_B <= R_IMM_DATA_32BIT;endelsebeginO_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;end
endendmodule

通用寄存器

此模块主要负责32位通用寄存器的初始化、读写等操作。可当作RAM理解。

// |------------------------------ ================================== ------------------------------
// |============================== 		   取指-译码接口模块	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-12-06
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule GPR_WR_RD_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 写
input 															I_GPR_WR_EN,
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_GPR_WR_ADDR,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_GPR_WR_DATA,
// |读
input 															I_GPR_RD_EN_A,
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_GPR_RD_ADDR_A,
output	reg	[`DEF_GPR_DATA_WIDTH-1:0]							O_GPR_RD_DATA_A,
input 															I_GPR_RD_EN_B,
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_GPR_RD_ADDR_B,
output	reg	[`DEF_GPR_DATA_WIDTH-1:0]							O_GPR_RD_DATA_B);
// |--------------------------------------  GPR-寄存器组定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
reg 		[`DEF_GPR_DATA_WIDTH-1:0]							R_GPR [`DEF_GPR_NUM-1:0];// |--------------------------------------  GPR-寄存器初始化  --------------------------------------
// |------------------------------------------------------------------------------------------------
initial $readmemh("D:/VIVADO_WORK_SPACE/CPU_MIPS32/DATA_FILE/GPR_INIT.txt",R_GPR);// |--------------------------------------  GPR-寄存器写操作  --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (posedge I_CPU_CLK)
beginif(I_CPU_RSTN)beginif(I_GPR_WR_EN && I_GPR_WR_ADDR != `DEF_GPR_ADDR_WIDTH'd0)beginR_GPR[I_GPR_WR_ADDR] <= I_GPR_WR_DATA;endend
end// |--------------------------------------    PORT A 读操作   --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (*)
beginif(~I_CPU_RSTN)beginO_GPR_RD_DATA_A = `DEF_ZERO_WORD;endelse if(I_GPR_WR_EN && I_GPR_RD_EN_A && (I_GPR_RD_ADDR_A == I_GPR_WR_ADDR))beginO_GPR_RD_DATA_A = I_GPR_WR_DATA;endelse if(I_GPR_RD_EN_A)beginO_GPR_RD_DATA_A = R_GPR[I_GPR_RD_ADDR_A];endelsebeginO_GPR_RD_DATA_A = `DEF_ZERO_WORD;end
end// |--------------------------------------    PORT B 读操作   --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (*)
beginif(~I_CPU_RSTN)beginO_GPR_RD_DATA_B = `DEF_ZERO_WORD;endelse if(I_GPR_WR_EN && I_GPR_RD_EN_B && (I_GPR_RD_ADDR_B == I_GPR_WR_ADDR))beginO_GPR_RD_DATA_B = I_GPR_WR_DATA;endelse if(I_GPR_RD_EN_B)beginO_GPR_RD_DATA_B = R_GPR[I_GPR_RD_ADDR_B];endelsebeginO_GPR_RD_DATA_B = `DEF_ZERO_WORD;end
endendmodule

初始化文件:

 

说明:此处文中的示例代码存在如下问题:

1、模块输出一般不选择组合逻辑输出;

2、always快描述组合逻辑时,要用阻塞赋值 “=”

指令执行

此模块是CPU的核心运算模块,将译码阶段传递的运算指令执行,并且完成数据的写请求。

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-执行模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule EXE_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 操作指令
// input		[`DEF_ALU_SEL_BUS]									I_ALU_SEL,		
input 		[`DEF_ALU_OPR_BUS]									I_ALU_OP_TYPE,	
// | 源操作数
input 		[`DEF_SRC_OPR_DATA_BUS]								I_SRC_OPR_DATA_A,
input 		[`DEF_SRC_OPR_DATA_BUS]								I_SRC_OPR_DATA_B,
// | 目的寄存器写
input 															I_DST_GPR_WR_EN,
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_DST_GPR_WR_ADDR,
// | 输出 
output 	reg														O_DST_GPR_WR_EN,   //输入打一拍
output 	reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR, //输入打一拍
output  reg [`DEF_GPR_DATA_WIDTH-1:0]							O_DST_GPR_WR_DATA);
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍
reg 		[`DEF_ALU_OPR_BUS]									R_I_ALU_OP_TYPE;
reg         													R_I_DST_GPR_WR_EN;
reg         [`DEF_GPR_ADDR_WIDTH-1:0]							R_I_DST_GPR_WR_ADDR;// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍对齐时序
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginR_I_ALU_OP_TYPE <= 0;endelsebeginR_I_ALU_OP_TYPE <= I_ALU_OP_TYPE;end
end
// | 计算单元
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;endelsebegincase(R_I_ALU_OP_TYPE)`DEF_ALU_OR_OPR:beginO_DST_GPR_WR_DATA <= I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B;enddefault:beginO_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;endendcaseend
end// | 写操作打拍
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_DST_GPR_WR_EN <= 1'b0;O_DST_GPR_WR_ADDR <= 5'd0;R_I_DST_GPR_WR_EN <= 1'b0;R_I_DST_GPR_WR_ADDR <= 5'd0;endelsebeginR_I_DST_GPR_WR_EN <= I_DST_GPR_WR_EN;R_I_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR;O_DST_GPR_WR_EN <= R_I_DST_GPR_WR_EN;O_DST_GPR_WR_ADDR <= R_I_DST_GPR_WR_ADDR;end
end
endmodule

内存访问

此模块主要是一些内存访问的操作,由于 ori 指令暂时不需要访存,所以该模块目前只有写使能传递功能。

// |------------------------------ ================================== ------------------------------
// |============================== 		     -执行模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule MEM_ACS_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 前接指令执行模块输出
input 															I_DST_GPR_WR_EN,  
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_DST_GPR_WR_ADDR,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_DST_GPR_WR_DATA,// | 后接写回模块
output reg  													O_DST_GPR_WR_EN,  
output reg  [`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR,
output reg  [`DEF_GPR_DATA_WIDTH-1:0]							O_DST_GPR_WR_DATA);
// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 目的寄存器写操作传递/打拍
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_DST_GPR_WR_EN   <= 1'b0;  O_DST_GPR_WR_ADDR <= 5'd0;O_DST_GPR_WR_DATA <= 32'd0;		endelsebeginO_DST_GPR_WR_EN   <= I_DST_GPR_WR_EN  ;  O_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR;O_DST_GPR_WR_DATA <= I_DST_GPR_WR_DATA;		end
endendmodule

指令ROM

此模块存放程序指令。

// |------------------------------ ================================== ------------------------------
// |============================== 		   程序计数寄存器模块		  ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-08
// |Finish Date : 2022-12-08
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule ROM_ISTC_MDL(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
input														  I_CPU_CLK,
input 														  I_CPU_RSTN,input														  I_RD_EN,
input 			[`DEF_ISTC_ADDR_BUS]						  I_RD_ADDR,output	reg		[`DEF_ISTC_DATA_BUS]						  O_ISTC);// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | ROM空间开辟
reg				[`DEF_ISTC_DATA_BUS]						  R_ROM_DATA [`DEF_ISTC_CACH_DEPTH:0];
// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | ROM初始化
initial $readmemh("D:/VIVADO_WORK_SPACE/CPU_MIPS32/DATA_FILE/ISTC_ROM.txt",R_ROM_DATA);
// | 数据读取
always @ (posedge I_CPU_CLK)
beginif(~I_CPU_RSTN)beginO_ISTC <= `DEF_ZERO_WORD;endelsebeginif(I_RD_EN)beginO_ISTC <= R_ROM_DATA[I_RD_ADDR[`DEF_ISTC_ADDR_WIDTH_ACTUAL+1:2]];endelsebeginO_ISTC <= `DEF_ZERO_WORD;endend
end
endmodule

程序代码示例:(此处借鉴书本的方法,仅为了完成仿真)

顶层文件

处理器顶层

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-执行模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule TOP_MIPS32(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 指令取
input			[`DEF_ISTC_DATA_BUS]							I_ISTC_FROM_ROM,
output			[`DEF_ISTC_ADDR_BUS]							O_ISTC_ADDR_2_ROM,
// | 指令存储器使能
output															O_ISTC_ROM_CE);// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | PC_REG_MDL 输出
wire			[`DEF_ISTC_ADDR_BUS]							W_PC;
// | IF_ID_MDL 输出
wire 			[`DEF_ISTC_ADDR_BUS] 							W_ID_ADDR;
wire 			[`DEF_ISTC_DATA_BUS] 							W_ID_DATA;
// ID_MDL 端口信号(GPR相关)
wire															W_GPR_RD_EN_A;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_GPR_RD_ADDR_A;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_GPR_RD_DATA_A;
wire															W_GPR_RD_EN_B;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_GPR_RD_ADDR_B;
wire 			[`DEF_GPR_DATA_WIDTH-1:0]						W_GPR_RD_DATA_B;
// ID_MDL 端口信号(EXE 相关)
wire			[`DEF_ALU_OPR_BUS]								W_ALU_OP_TYPE;
wire			[`DEF_SRC_OPR_DATA_BUS]							W_SRC_OPR_DATA_A;
wire			[`DEF_SRC_OPR_DATA_BUS]							W_SRC_OPR_DATA_B;
// GPR_WR_RD_MDL 写操作端口(EXE 相关)
wire															W_DST_GPR_WR_EN_EXE_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_EXE_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(MEM 相关)
wire															W_DST_GPR_WR_EN_MEM_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_MEM_MDL_IN;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_DST_GPR_WR_DATA_MEM_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(GPR 相关)
wire															W_DST_GPR_WR_EN_GPR_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_GPR_MDL_IN;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_DST_GPR_WR_DATA_GPR_MDL_IN;// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 输出
assign 			O_ISTC_ADDR_2_ROM		=		W_PC;// |--------------------------------------      子模块例化    --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 程序计数器模块PC_REG_MDL INST_PC_REG_MDL(.I_CPU_CLK     (I_CPU_CLK),.I_CPU_RSTN    (I_CPU_RSTN),.O_PC          (W_PC),.O_ISTC_ROM_CE (O_ISTC_ROM_CE));
// | 译码模块例化ID_MDL INST_ID_MDL(.I_CPU_CLK         (I_CPU_CLK),.I_CPU_RSTN        (I_CPU_RSTN),.I_ISTC            (I_ISTC_FROM_ROM),.O_GPR_RD_EN_A     (W_GPR_RD_EN_A),.O_GPR_RD_ADDR_A   (W_GPR_RD_ADDR_A),.I_GPR_RD_DATA_A   (W_GPR_RD_DATA_A),.O_GPR_RD_EN_B     (W_GPR_RD_EN_B),.O_GPR_RD_ADDR_B   (W_GPR_RD_ADDR_B),.I_GPR_RD_DATA_B   (W_GPR_RD_DATA_B),.O_ALU_OP_TYPE     (W_ALU_OP_TYPE),.O_SRC_OPR_DATA_A  (W_SRC_OPR_DATA_A),.O_SRC_OPR_DATA_B  (W_SRC_OPR_DATA_B),.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_EXE_MDL_IN),.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN));
// | 通用寄存器模块例化GPR_WR_RD_MDL INST_GPR_WR_RD_MDL(.I_CPU_CLK       (I_CPU_CLK),.I_CPU_RSTN      (I_CPU_RSTN),.I_GPR_WR_EN     (W_DST_GPR_WR_EN_GPR_MDL_IN),.I_GPR_WR_ADDR   (W_DST_GPR_WR_ADDR_GPR_MDL_IN),.I_GPR_WR_DATA   (W_DST_GPR_WR_DATA_GPR_MDL_IN),.I_GPR_RD_EN_A   (W_GPR_RD_EN_A),.I_GPR_RD_ADDR_A (W_GPR_RD_ADDR_A),.O_GPR_RD_DATA_A (W_GPR_RD_DATA_A),.I_GPR_RD_EN_B   (W_GPR_RD_EN_B),.I_GPR_RD_ADDR_B (W_GPR_RD_ADDR_B),.O_GPR_RD_DATA_B (W_GPR_RD_DATA_B));
// | 执行模块例化EXE_MDL INST_EXE_MDL(.I_CPU_CLK         (I_CPU_CLK),.I_CPU_RSTN        (I_CPU_RSTN),.I_ALU_OP_TYPE     (W_ALU_OP_TYPE),.I_SRC_OPR_DATA_A  (W_SRC_OPR_DATA_A),.I_SRC_OPR_DATA_B  (W_SRC_OPR_DATA_B),.I_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_EXE_MDL_IN),.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN),.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_MEM_MDL_IN),.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN));
// | 存储器存取模块例化MEM_ACS_MDL INST_MEM_ACS_MDL(.I_CPU_CLK         (I_CPU_CLK),.I_CPU_RSTN        (I_CPU_RSTN),.I_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_MEM_MDL_IN),.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),.I_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN),.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_GPR_MDL_IN),.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_GPR_MDL_IN),.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_GPR_MDL_IN));endmodule

SOPC顶层 

// |------------------------------ ================================== ------------------------------
// |============================== 		     MIPS32 SOPC 系统  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1psmodule TOP_MIPS32_SOPC(// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN);
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | TOP_MIPS32 模块端口
// | 指令取
wire			[`DEF_ISTC_DATA_BUS]							W_ISTC_FROM_ROM;
wire			[`DEF_ISTC_ADDR_BUS]							W_ISTC_ADDR_2_ROM;
// | 指令存储器使能
wire															W_ISTC_ROM_CE;// |--------------------------------------      子模块例化    --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 处理器模块TOP_MIPS32 INST_TOP_MIPS32(.I_CPU_CLK         (I_CPU_CLK),.I_CPU_RSTN        (I_CPU_RSTN),.I_ISTC_FROM_ROM   (W_ISTC_FROM_ROM),.O_ISTC_ADDR_2_ROM (W_ISTC_ADDR_2_ROM),.O_ISTC_ROM_CE     (W_ISTC_ROM_CE));
// | 指令存储模块ROM_ISTC_MDL INST_ROM_ISTC_MDL(.I_CPU_CLK  (I_CPU_CLK),.I_CPU_RSTN (I_CPU_RSTN),.I_RD_EN    (W_ISTC_ROM_CE),.I_RD_ADDR  (W_ISTC_ADDR_2_ROM),.O_ISTC     (W_ISTC_FROM_ROM));endmodule

功能仿真

TestBench

// |------------------------------ ================================== ------------------------------
// |============================== 		    顶层模块仿真平台  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-08
// |Finish Date : 2022-12-08
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |Change History:
// |`timescale 1ns / 1ps
`define 	CLK_PERIOD 		20module TB_TOP_MIPS32();
reg 						I_CPU_CLK;
reg 						I_CPU_RSTN;
// 产生时钟
initial 	I_CPU_CLK	=	0;
always #(`CLK_PERIOD/2) I_CPU_CLK = ~I_CPU_CLK;
// 产生复位
initial
beginI_CPU_RSTN <= 0;#(`CLK_PERIOD*3);@(posedge I_CPU_CLK);I_CPU_RSTN <= 1;#(`CLK_PERIOD*10);$finish;
end
// 顶层例化TOP_MIPS32_SOPC INST_TOP_MIPS32_SOPC (.I_CPU_CLK(I_CPU_CLK), .I_CPU_RSTN(I_CPU_RSTN));endmodule

仿真结果

执行时间

从取到第一条指令,到第一条指令完成并写入寄存器,共耗费100纳秒=5个时钟周期。

时序细节



相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...