目录
引言
致谢
流水线的数据相关问题
问题分析
RAW类型
1、相邻指令数据相关
2、间隔1条指令数据相关
3、间隔2条指令数据相关
修改后的代码
译码模块
指令执行模块
顶层模块
测试
测试代码
生成.data初始化文件
仿真结果
引言
随章节进度继续推进,本章继续实现其他操作指令。
致谢
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
流水线的数据相关问题
问题分析
概念解释:
数据相关问题分类:
根据 MIPS 工作阶段的相对独立性,其仅存在 RAW 数据相关问题。
RAW类型
1、相邻指令数据相关
例:
时序图说明:
2、间隔1条指令数据相关
例:
时序图说明:
3、间隔2条指令数据相关
时序图分析:
此类型的数据相关/读写冲突问题,在第四章写的 GPR_WR_RD_MDL 得到解决:
另外对于前两种数据冲突问题,书本也给出了如下的解决方案:
这三种方式中,书本选用了第三种方法,数据前推。
即,将指令执行模块、访存模块输出的结果,直接送入指令译码模块。
指令执行模块的端口信号:
访存模块的端口信号:
译码模块增加的输入端口:
修改后的代码
此处仅给出有变动的模块源码:
译码模块
// |------------------------------ ================================== ------------------------------
// |============================== 指令-译码模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// | 思路参考《自己动手写CPU》5.2节
// | 增加模块端口:Line 48 - 54
// | 增加条件分支:Line 141 - 148 、171 - 178
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module 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,
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
input I_DST_GPR_WR_EN_FROM_EXE_MDL,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_EXE_MDL,
input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_EXE_MDL,
// 来自访存模块
input I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL,
input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
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)
begin
if(~I_CPU_RSTN)
begin
O_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;
end
else
begin
case(W_ISTC_TYPE)
`DEF_ISTC_ORI:// ori指令
begin
O_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};
end
default:
begin
O_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;
end
endcase
end
end
// | 数据输出
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
end
else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
begin
O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
end
else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
begin
O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
end
else if(O_GPR_RD_EN_A)
begin
O_SRC_OPR_DATA_A <= I_GPR_RD_DATA_A;
end
else if(~O_GPR_RD_EN_A)
begin
O_SRC_OPR_DATA_A <= R_IMM_DATA_32BIT;
end
else
begin
O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
end
else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
begin
O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
end
else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
begin
O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
end
else if(O_GPR_RD_EN_B)
begin
O_SRC_OPR_DATA_B <= I_GPR_RD_DATA_B;
end
else if(~O_GPR_RD_EN_B)
begin
O_SRC_OPR_DATA_B <= R_IMM_DATA_32BIT;
end
else
begin
O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
end
end
endmodule
指令执行模块
// |------------------------------ ================================== ------------------------------
// |============================== 指令-执行模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// | 增加模块端口:Line 42 - 44
// | 两部分输出区别:组合逻辑输出和时序逻辑输出
// | 代码变动行编号:Line 73、77、84、88、103、111、115、116
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module 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,
// 反馈至 译码模块
output O_DST_GPR_WR_EN_2_ID_MDL,
output [`DEF_GPR_ADDR_WIDTH-1:0] O_DST_GPR_WR_ADDR_2_ID_MDL,
output reg [`DEF_GPR_DATA_WIDTH-1:0] O_DST_GPR_WR_DATA_2_ID_MDL
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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)
begin
if(~I_CPU_RSTN)
begin
R_I_ALU_OP_TYPE <= 0;
end
else
begin
R_I_ALU_OP_TYPE <= I_ALU_OP_TYPE;
end
end
// | 计算单元
// 组合逻辑
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
end
else
begin
case(R_I_ALU_OP_TYPE)
`DEF_ALU_OR_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B;
end
default:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
end
endcase
end
end
// | 写操作打拍
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_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;
O_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;
end
else
begin
R_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;
O_DST_GPR_WR_DATA <= O_DST_GPR_WR_DATA_2_ID_MDL;
end
end
assign O_DST_GPR_WR_EN_2_ID_MDL = R_I_DST_GPR_WR_EN ;
assign O_DST_GPR_WR_ADDR_2_ID_MDL = R_I_DST_GPR_WR_ADDR;
endmodule
顶层模块
// |------------------------------ ================================== ------------------------------
// |============================== 指令-执行模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// | 顶层文件配合改动
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module 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;
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
wire W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 输出
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),
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
.I_DST_GPR_WR_EN_FROM_EXE_MDL (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ),
.I_DST_GPR_WR_ADDR_FROM_EXE_MDL (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
.I_DST_GPR_WR_DATA_FROM_EXE_MDL (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL),
// 来自访存模块
.I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL (W_DST_GPR_WR_EN_MEM_MDL_IN ),
.I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
.I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL (W_DST_GPR_WR_DATA_MEM_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),
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 送至指令译码模块
.O_DST_GPR_WR_EN_2_ID_MDL (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ),
.O_DST_GPR_WR_ADDR_2_ID_MDL (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
.O_DST_GPR_WR_DATA_2_ID_MDL (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL)
);
// | 存储器存取模块例化
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
测试
利用上一篇搭建的编译环境,将下面的程序转化为ROM的初始化文件:
测试代码
示例:
.org 0x0
.global _start
.set noat
_start:
ori $1,$0,0x1100
ori $1,$1,0x0020
ori $1,$1,0x4400
ori $1,$1,0x0044
nop
nop
ori $2,$8,0x0020
ori $2,$2,0xFF00
ori $2,$2,0xFFFF
生成.data初始化文件
步骤见上篇:《自己动手写CPU》学习记录(4)——第4章/Part 2
注意:ROM初始化模块记得改路径L:
仿真结果
情形一:相邻指令冲突
情形二:间隔一条指令冲突