您的位置:首页 > 汽车 > 新车 > 自己动手写CPU_step2_构建SOPC

自己动手写CPU_step2_构建SOPC

2025/1/8 3:35:15 来源:https://blog.csdn.net/qq_44830822/article/details/141334784  浏览:    关键词:自己动手写CPU_step2_构建SOPC

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设计完成,后续将实现更多指令!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com