ROM实现指令寄存器
上一篇中实现的五级流水线需要一个输入,这个输入是指令数据,而指令数据是通过取指阶段的PC控制的,PC会一直循环的取指令。
指令寄存器实现:
//指令寄存器 module inst_rom(input clk,input rden,input [`InstAddrBus] addr,output reg [`InstDataBus] inst);reg [`InstDataBus] inst_mem [0:3]; initial $readmemh ( "C:/C_extend/OpenMIPS_CPU_FPGA/inst_rom.data", inst_mem );always @ (*) beginif (rden == 0) begininst <= 32'd0;end else begininst <= inst_mem[addr[3:2]]; //PC每加4对应指令寄存器的下一条指令 addr为0时表示第一条指令end endendmodule
设计一个inst_rom.data的数据文件,其中存放4条16进制的32位指令,通过PC恰好可以循环遍历这些指令。addr低两位为0因为PC是4的倍数。
流水线顶层设计
//流水线的顶层模块 module openmips(input clk,input rst,input [`RegDataBus] rom_data,output [`RegAddrBus] rom_addr,output rom_rden);pc u_pc(.clk (clk),.rst (rst),.pc (rom_addr),.pc_en (rom_rden));wire [`InstAddrBus] id_pc;wire [`InstDataBus] id_inst;if_id u_if_id(.clk (clk),.rst (rst),.if_pc (rom_addr),.if_inst (rom_data),.id_pc (id_pc),.id_inst (id_inst)); wire [`RegDataBus] reg1_data;wire [`RegDataBus] reg2_data;wire [`RegAddrBus] reg1_addr;wire [`RegAddrBus] reg2_addr;wire reg1_rden;wire reg2_rden;wire [`RegDataBus] reg1;wire [`RegDataBus] reg2;wire reg_wb;wire [`RegAddrBus] reg_wb_addr;wire [`AluOpBus] aluop;id u_id(.rst (rst),.pc (id_pc),.inst (id_inst),.reg1_data (reg1_data),.reg1_addr (reg1_addr),.reg1_rden (reg1_rden),.reg2_data (reg2_data),.reg2_addr (reg2_addr),.reg2_rden (reg2_rden),.reg1 (reg1),.reg2 (reg2),.reg_wb (reg_wb),.reg_wb_addr (reg_wb_addr),.aluop (aluop));wire wr_en;wire [`RegAddrBus] wr_addr;wire [`RegDataBus] wr_data;id_reg u_id_reg(.clk (clk),.rst (rst),.reg1_data (reg1_data),.reg1_addr (reg1_addr),.reg1_rden (reg1_rden),.reg2_data (reg2_data),.reg2_addr (reg2_addr),.reg2_rden (reg2_rden),.wr_en (wr_en),.wr_addr (wr_addr),.wr_data (wr_data));wire [`RegDataBus] ex_reg1;wire [`RegDataBus] ex_reg2;wire ex_reg_wb;wire [`RegAddrBus] ex_reg_wb_addr;wire [`AluOpBus] ex_aluop;id_ex u_id_ex(.clk (clk),.rst (rst),.id_reg1 (reg1),.id_reg2 (reg2),.id_aluop (aluop),.id_reg_wb (reg_wb),.id_reg_wb_addr (reg_wb_addr),.ex_reg1 (ex_reg1),.ex_reg2 (ex_reg2),.ex_aluop (ex_aluop),.ex_reg_wb (ex_reg_wb),.ex_reg_wb_addr (ex_reg_wb_addr));wire ex_reg_wb_o;wire [`RegAddrBus] ex_reg_wb_addr_o;wire [`RegDataBus] ex_reg_wb_data_o;ex u_ex(.rst (rst),.reg1 (ex_reg1),.reg2 (ex_reg2),.aluop (ex_aluop),.reg_wb_i (ex_reg_wb),.reg_wb_addr_i (ex_reg_wb_addr),.reg_wb_o (ex_reg_wb_o),.reg_wb_addr_o (ex_reg_wb_addr_o),.reg_wb_data (ex_reg_wb_data_o));wire mem_reg_wb;wire [`RegAddrBus] mem_reg_wb_addr;wire [`RegDataBus] mem_reg_wb_data;ex_mem u_ex_mem(.clk (clk),.rst (rst),.ex_reg_wb (ex_reg_wb_o),.ex_reg_wb_addr (ex_reg_wb_addr_o),.ex_reg_wb_data (ex_reg_wb_data_o),.mem_reg_wb (mem_reg_wb),.mem_reg_wb_addr (mem_reg_wb_addr),.mem_reg_wb_data (mem_reg_wb_data));wire mem_reg_wb_o;wire [`RegAddrBus] mem_reg_wb_addr_o;wire [`RegDataBus] mem_reg_wb_data_o;mem u_mem(.rst (rst),.reg_wb_i (mem_reg_wb),.reg_wb_addr_i (mem_reg_wb_addr),.reg_wb_data_i (mem_reg_wb_data),.reg_wb_o (mem_reg_wb_o),.reg_wb_addr_o (mem_reg_wb_addr_o),.reg_wb_data_o (mem_reg_wb_data_o));mem_wb u_mem_wb(.clk (clk),.rst (rst),.mem_reg_wb (mem_reg_wb_o),.mem_reg_wb_addr (mem_reg_wb_addr_o),.mem_reg_wb_data (mem_reg_wb_data_o),.wb_reg (wr_en),.wb_reg_addr (wr_addr),.wb_reg_data (wr_data)); endmodule
最小SOPC实现
//基于MIPS五级流水线的最小sopc实现 module openmips_sopc(input clk,input rst);wire rom_rden;wire [4:0] rom_addr;wire [31:0] rom_data;inst_rom inst_rom(.clk (clk),.rden (rom_rden),.addr (rom_addr),.inst (rom_data) );openmips openmips(.clk (clk),.rst (rst),.rom_data (rom_data),.rom_addr (rom_addr),.rom_rden (rom_rden)); endmodule
最小SOPC实现之后,就可以开始仿真测试了。
仿真测试
`timescale 1ns / 1psmodule openmips_sopc_tb;reg clk; reg rst;initial beginclk = 0;forever #10 clk = ~clk; //时钟周期20ns 50MHz endinitial beginrst = 1;#200rst = 0;#1000$finish(2); endopenmips_sopc u_openmips_sopc(.clk (clk),.rst (rst) );endmodule
仿真结果
由图可知,在210ns时,开始了第一次取指令操作pc=0,230ns时开始了第二次的取指令pc=4,同时进行指令1的译码操作,以此类推;在290ns时是指令1的写回阶段,此时的结果是reg1(来源初始寄存器全0)和reg2(来源指令中的立即数)的或运算结果,结果写回指定的地址寄存器;在310ns时,地址为1的寄存器被正确写入了指令1的计算结果。
至此,CPU中第一条指令ORI设计完成,后续将实现更多指令!