diff --git a/Defines.v b/Defines.v new file mode 100644 index 0000000..951a26f --- /dev/null +++ b/Defines.v @@ -0,0 +1,109 @@ +//global +`define RstEnable 1'b1 +`define RstDisable 1'b0 +`define ZeroWord 32'h00000000 +`define WriteEnable 1'b1 +`define WriteDisable 1'b0 +`define ReadEnable 1'b1 +`define ReadDisable 1'b0 +`define AluOpBus 7:0 +`define AluSelBus 2:0 +`define InstValid 1'b0 +`define InstInvalid 1'b1 +`define Stop 1'b1 +`define NoStop 1'b0 +`define InDelaySlot 1'b1 +`define NotInDelaySlot 1'b0 +`define Branch 1'b1 +`define NotBranch 1'b0 +`define InterruptAssert 1'b1 +`define InterruptNotAssert 1'b0 +`define TrapAssert 1'b1 +`define TrapNotAssert 1'b0 +`define True_v 1'b1 +`define False_v 1'b0 +`define ChipEnable 1'b1 +`define ChipDisable 1'b0 + + +//instruction +`define EXE_ORI 6'b001101 // ORI +`define EXE_AND 6'b100100 // AND +`define EXE_OR 6'b100101 // OR +`define EXE_XOR 6'b100110 // XOR +`define EXE_NOR 6'b100111 // NOR +`define EXE_ANDI 6'b001100 // ANDI +`define EXE_ORI 6'b001101 // ORI +`define EXE_XORI 6'b001110 // XORI +`define EXE_LUI 6'b001111 // LUI + +`define EXE_SLL 6'b000000 // SLL +`define EXE_SLLV 6'b000100 // SLLV +`define EXE_SRL 6'b000010 // SRL +`define EXE_SRLV 6'b000110 // SRLV +`define EXE_SRA 6'b000011 // SRA +`define EXE_SRAV 6'b000111 // SRAV +`define EXE_SYNC 6'b001111 // SYNC +`define EXE_PREF 6'b110011 // PREF + +`define EXE_NOP 6'b000000 // NOP +`define EXE_SPECIAL_INST 6'b000000 // SPECIAL 类 + +`define EXE_MOVZ 6'b001010 +`define EXE_MOVN 6'b001011 +`define EXE_MFHI 6'b010000 +`define EXE_MTHI 6'b010001 +`define EXE_MFLO 6'b010010 +`define EXE_MTLO 6'b010011 + +//AluOp +`define EXE_AND_OP 8'b00100100 +`define EXE_OR_OP 8'b00100101 +`define EXE_XOR_OP 8'b00100110 +`define EXE_NOR_OP 8'b00100111 +`define EXE_ANDI_OP 8'b01011001 +`define EXE_ORI_OP 8'b01011010 +`define EXE_XORI_OP 8'b01011011 +`define EXE_LUI_OP 8'b01011100 + +`define EXE_SLL_OP 8'b01111100 +`define EXE_SLLV_OP 8'b00000100 +`define EXE_SRL_OP 8'b00000010 +`define EXE_SRLV_OP 8'b00000110 +`define EXE_SRA_OP 8'b00000011 +`define EXE_SRAV_OP 8'b00000111 + +`define EXE_NOP_OP 8'b00000000 + +`define EXE_MOVZ_OP 8'b00001010 +`define EXE_MOVN_OP 8'b00001011 +`define EXE_MFHI_OP 8'b00010000 +`define EXE_MTHI_OP 8'b00010001 +`define EXE_MFLO_OP 8'b00010010 +`define EXE_MTLO_OP 8'b00010011 + +//AluSel +`define EXE_RES_LOGIC 3'b001 +`define EXE_RES_SHIFT 3'b010 +`define EXE_RES_MOVE 3'b011 + +`define EXE_RES_NOP 3'b000 + + +//inst_rom +`define InstAddrBus 31:0 +`define InstBus 31:0 +`define InstMemNum 131071 +`define InstMemNumLog2 17 + + +//regfile +`define RegAddrBus 4:0 +`define RegBus 31:0 +`define RegWidth 32 +`define DoubleRegWidth 64 +`define DoubleRegBus 63:0 +`define RegNum 32 +`define RegNumLog2 5 +`define NOPRegAddr 5'b00000 + diff --git a/Src/ex.v b/Src/ex.v new file mode 100644 index 0000000..48ac3f7 --- /dev/null +++ b/Src/ex.v @@ -0,0 +1,46 @@ +`include "../Defines.v" + +module ex(input wire rst, + input wire[`AluOpBus] aluop_i, + input wire[`AluSelBus] alusel_i, + input wire[`RegBus] reg1_i, + input wire[`RegBus] reg2_i, + input wire[`RegAddrBus] wd_i, + input wire wreg_i, + output reg[`RegAddrBus] wd_o, + output reg wreg_o, + output reg[`RegBus] wdata_o); + + reg[`RegBus] logicout; + always @ (*) begin + if (rst == `RstEnable) begin + logicout <= `ZeroWord; + end else begin + case (aluop_i) + `EXE_OR_OP: + begin + logicout <= reg1_i | reg2_i; + end + default: + begin + logicout <= `ZeroWord; + end + endcase + end + end + + + always @ (*) begin + wd_o <= wd_i; + wreg_o <= wreg_i; + case (alusel_i) + `EXE_RES_LOGIC: begin + wdata_o <= logicout; + end + default: begin + wdata_o <= `ZeroWord; + end + endcase + end + +endmodule diff --git a/Src/ex_mem.v b/Src/ex_mem.v new file mode 100644 index 0000000..baf3573 --- /dev/null +++ b/Src/ex_mem.v @@ -0,0 +1,27 @@ +`include "../Defines.v" + +module ex_mem(input wire clk, + input wire rst, + input wire[`RegAddrBus] ex_wd, + input wire ex_wreg, + input wire[`RegBus] ex_wdata, + output reg[`RegAddrBus] mem_wd, + output reg mem_wreg, + output reg[`RegBus] mem_wdata); + + + always @ (posedge clk) begin + if (rst == `RstEnable) begin + mem_wd <= `NOPRegAddr; + mem_wreg <= `WriteDisable; + mem_wdata <= `ZeroWord; + end + else begin + mem_wd <= ex_wd; + mem_wreg <= ex_wreg; + mem_wdata <= ex_wdata; + end + end + + +endmodule diff --git a/Src/id.v b/Src/id.v new file mode 100644 index 0000000..63965e9 --- /dev/null +++ b/Src/id.v @@ -0,0 +1,88 @@ +`include "../Defines.v" + +module id(input wire rst, + input wire[`InstAddrBus] pc_i, + input wire[`InstBus] inst_i, + input wire[`RegBus] reg1_data_i, + input wire[`RegBus] reg2_data_i, + output reg reg1_read_o, + output reg reg2_read_o, + output reg[`RegAddrBus] reg1_addr_o, + output reg[`RegAddrBus] reg2_addr_o, + output reg[`AluOpBus] aluop_o, + output reg[`AluSelBus] alusel_o, + output reg[`RegBus] reg1_o, + output reg[`RegBus] reg2_o, + output reg[`RegAddrBus] wd_o, + output reg wreg_o); + + wire[5:0] op = inst_i[31:26]; + wire[4:0] op2 = inst_i[10:6]; + wire[5:0] op3 = inst_i[5:0]; + wire[4:0] op4 = inst_i[20:16]; + reg[`RegBus] imm; + reg instvalid; + + + always @ (*) begin + if (rst == `RstEnable) begin + aluop_o <= `EXE_NOP_OP; + alusel_o <= `EXE_RES_NOP; + wd_o <= `NOPRegAddr; + wreg_o <= `WriteDisable; + instvalid <= `InstValid; + reg1_read_o <= 1'b0; + reg2_read_o <= 1'b0; + reg1_addr_o <= `NOPRegAddr; + reg2_addr_o <= `NOPRegAddr; + imm <= 32'h0; + end else begin + aluop_o <= `EXE_NOP_OP; + alusel_o <= `EXE_RES_NOP; + wd_o <= inst_i[15:11]; + wreg_o <= `WriteDisable; + instvalid <= `InstInvalid; + reg1_read_o <= 1'b0; + reg2_read_o <= 1'b0; + reg1_addr_o <= inst_i[25:21]; + reg2_addr_o <= inst_i[20:16]; + imm <= `ZeroWord; + case (op) + `EXE_ORI: begin + wreg_o <= `WriteEnable; aluop_o <= `EXE_OR_OP; + alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0; + imm <= {16'h0, inst_i[15:0]}; wd_o <= inst_i[20:16]; + instvalid <= `InstValid; + end + default: begin + end + endcase + end + end + + + always @ (*) begin + if (rst == `RstEnable) begin + reg1_o <= `ZeroWord; + end else if (reg1_read_o == 1'b1) begin + reg1_o <= reg1_data_i; + end else if (reg1_read_o == 1'b0) begin + reg1_o <= imm; + end else begin + reg1_o <= `ZeroWord; + end + end + + always @ (*) begin + if (rst == `RstEnable) begin + reg2_o <= `ZeroWord; + end else if (reg2_read_o == 1'b1) begin + reg2_o <= reg2_data_i; + end else if (reg2_read_o == 1'b0) begin + reg2_o <= imm; + end else begin + reg2_o <= `ZeroWord; + end + end + +endmodule diff --git a/Src/id_ex.v b/Src/id_ex.v new file mode 100644 index 0000000..be4e063 --- /dev/null +++ b/Src/id_ex.v @@ -0,0 +1,36 @@ +`include "../Defines.v" + +module id_ex(input wire clk, + input wire rst, + input wire[`AluOpBus] id_aluop, + input wire[`AluSelBus] id_alusel, + input wire[`RegBus] id_reg1, + input wire[`RegBus] id_reg2, + input wire[`RegAddrBus] id_wd, + input wire id_wreg, + output reg[`AluOpBus] ex_aluop, + output reg[`AluSelBus] ex_alusel, + output reg[`RegBus] ex_reg1, + output reg[`RegBus] ex_reg2, + output reg[`RegAddrBus] ex_wd, + output reg ex_wreg); + + always @ (posedge clk) begin + if (rst == `RstEnable) begin + ex_aluop <= `EXE_NOP_OP; + ex_alusel <= `EXE_RES_NOP; + ex_reg1 <= `ZeroWord; + ex_reg2 <= `ZeroWord; + ex_wd <= `NOPRegAddr; + ex_wreg <= `WriteDisable; + end else begin + ex_aluop <= id_aluop; + ex_alusel <= id_alusel; + ex_reg1 <= id_reg1; + ex_reg2 <= id_reg2; + ex_wd <= id_wd; + ex_wreg <= id_wreg; + end + end + +endmodule diff --git a/Src/if_id.v b/Src/if_id.v new file mode 100644 index 0000000..e13e86a --- /dev/null +++ b/Src/if_id.v @@ -0,0 +1,20 @@ +`include "../Defines.v" + +module if_id(input wire clk, + input wire rst, + input wire[`InstAddrBus] if_pc, + input wire[`InstBus] if_inst, + output reg[`InstAddrBus] id_pc, + output reg[`InstBus] id_inst); + + always @ (posedge clk) begin + if (rst == `RstEnable) begin + id_pc <= `ZeroWord; + id_inst <= `ZeroWord; + end else begin + id_pc <= if_pc; + id_inst <= if_inst; + end + end + +endmodule diff --git a/Src/inst_rom.v b/Src/inst_rom.v new file mode 100644 index 0000000..e68cd76 --- /dev/null +++ b/Src/inst_rom.v @@ -0,0 +1,19 @@ +`include "../Defines.v" + +module inst_rom(input wire ce, + input wire[`InstAddrBus] addr, + output reg[`InstBus] inst); + + reg[`InstBus] inst_mem[0:`InstMemNum-1]; + + initial $readmemh ("D:/Codings/Vivado/MIPS/inst_rom.data", inst_mem); + + always @ (*) begin + if (ce == `ChipDisable) begin + inst <= `ZeroWord; + end else begin + inst <= inst_mem[addr[`InstMemNumLog2+1:2]]; + end + end + +endmodule diff --git a/Src/mem.v b/Src/mem.v new file mode 100644 index 0000000..2c82dc6 --- /dev/null +++ b/Src/mem.v @@ -0,0 +1,26 @@ +`include "../Defines.v" + +module mem(input wire rst, + input wire[`RegAddrBus] wd_i, + input wire wreg_i, + input wire[`RegBus] wdata_i, + output reg[`RegAddrBus] wd_o, + output reg wreg_o, + output reg[`RegBus] wdata_o); + + + always @ (*) begin + if (rst == `RstEnable) begin + wd_o <= `NOPRegAddr; + wreg_o <= `WriteDisable; + wdata_o <= `ZeroWord; + end + else begin + wd_o <= wd_i; + wreg_o <= wreg_i; + wdata_o <= wdata_i; + end + end + + +endmodule diff --git a/Src/mem_wb.v b/Src/mem_wb.v new file mode 100644 index 0000000..57c294d --- /dev/null +++ b/Src/mem_wb.v @@ -0,0 +1,26 @@ +`include "../Defines.v" + +module mem_wb(input wire clk, + input wire rst, + input wire[`RegAddrBus] mem_wd, + input wire mem_wreg, + input wire[`RegBus] mem_wdata, + output reg[`RegAddrBus] wb_wd, + output reg wb_wreg, + output reg[`RegBus] wb_wdata); + + + always @ (posedge clk) begin + if (rst == `RstEnable) begin + wb_wd <= `NOPRegAddr; + wb_wreg <= `WriteDisable; + wb_wdata <= `ZeroWord; + end else begin + wb_wd <= mem_wd; + wb_wreg <= mem_wreg; + wb_wdata <= mem_wdata; + end + end + + +endmodule diff --git a/Src/Core/pc_reg.v b/Src/pc_reg.v similarity index 68% rename from Src/Core/pc_reg.v rename to Src/pc_reg.v index 46c86d5..5cafd96 100644 --- a/Src/Core/pc_reg.v +++ b/Src/pc_reg.v @@ -1,9 +1,9 @@ -`include "defines.v" +`include "../Defines.v" -module pc_reg(input wire clk, - input wire rst, - output reg[`InstAddrBus] pc, - output reg ce); +module pc_reg(input wire clk, + input wire rst, + output reg[`InstAddrBus] pc, + output reg ce); always @ (posedge clk) begin if (ce == `ChipDisable) begin diff --git a/Src/regfile.v b/Src/regfile.v new file mode 100644 index 0000000..ad56ae7 --- /dev/null +++ b/Src/regfile.v @@ -0,0 +1,55 @@ +`include "../Defines.v" + +module regfile(input wire clk, + input wire rst, + input wire we, + input wire[`RegAddrBus] waddr, + input wire[`RegBus] wdata, + input wire re1, + input wire[`RegAddrBus] raddr1, + output reg[`RegBus] rdata1, + input wire re2, + input wire[`RegAddrBus] raddr2, + output reg[`RegBus] rdata2); + + reg[`RegBus] regs[0:`RegNum-1]; + + always @ (posedge clk) begin + if (rst == `RstDisable) begin + if ((we == `WriteEnable) && (waddr != `RegNumLog2'h0)) begin + regs[waddr] <= wdata; + end + end + end + + always @ (*) begin + if (rst == `RstEnable) begin + rdata1 <= `ZeroWord; + end else if (raddr1 == `RegNumLog2'h0) begin + rdata1 <= `ZeroWord; + end else if ((raddr1 == waddr) && (we == `WriteEnable) + && (re1 == `ReadEnable)) begin + rdata1 <= wdata; + end else if (re1 == `ReadEnable) begin + rdata1 <= regs[raddr1]; + end else begin + rdata1 <= `ZeroWord; + end + end + + always @ (*) begin + if (rst == `RstEnable) begin + rdata2 <= `ZeroWord; + end else if (raddr2 == `RegNumLog2'h0) begin + rdata2 <= `ZeroWord; + end else if ((raddr2 == waddr) && (we == `WriteEnable) + && (re2 == `ReadEnable)) begin + rdata2 <= wdata; + end else if (re2 == `ReadEnable) begin + rdata2 <= regs[raddr2]; + end else begin + rdata2 <= `ZeroWord; + end + end + +endmodule diff --git a/Src/yunmips.v b/Src/yunmips.v new file mode 100644 index 0000000..89f4ec3 --- /dev/null +++ b/Src/yunmips.v @@ -0,0 +1,182 @@ +`include "../Defines.v" + +module yunmips(input wire clk, + input wire rst, + input wire[`RegBus] rom_data_i, + output wire[`RegBus] rom_addr_o, + output wire rom_ce_o); + + wire[`InstAddrBus] pc; + wire[`InstAddrBus] id_pc_i; + wire[`InstBus] id_inst_i; + + wire[`AluOpBus] id_aluop_o; + wire[`AluSelBus] id_alusel_o; + wire[`RegBus] id_reg1_o; + wire[`RegBus] id_reg2_o; + wire id_wreg_o; + wire[`RegAddrBus] id_wd_o; + + wire[`AluOpBus] ex_aluop_i; + wire[`AluSelBus] ex_alusel_i; + wire[`RegBus] ex_reg1_i; + wire[`RegBus] ex_reg2_i; + wire ex_wreg_i; + wire[`RegAddrBus] ex_wd_i; + + wire ex_wreg_o; + wire[`RegAddrBus] ex_wd_o; + wire[`RegBus] ex_wdata_o; + + wire mem_wreg_i; + wire[`RegAddrBus] mem_wd_i; + wire[`RegBus] mem_wdata_i; + + wire mem_wreg_o; + wire[`RegAddrBus] mem_wd_o; + wire[`RegBus] mem_wdata_o; + + wire wb_wreg_i; + wire[`RegAddrBus] wb_wd_i; + wire[`RegBus] wb_wdata_i; + + wire reg1_read; + wire reg2_read; + wire[`RegBus] reg1_data; + wire[`RegBus] reg2_data; + wire[`RegAddrBus] reg1_addr; + wire[`RegAddrBus] reg2_addr; + + pc_reg pc_reg0( + .clk(clk), + .rst(rst), + .pc(pc), + .ce(rom_ce_o) + + ); + + assign rom_addr_o = pc; + + if_id if_id0( + .clk(clk), + .rst(rst), + .if_pc(pc), + .if_inst(rom_data_i), + .id_pc(id_pc_i), + .id_inst(id_inst_i) + ); + + id id0( + .rst(rst), + .pc_i(id_pc_i), + .inst_i(id_inst_i), + + .reg1_data_i(reg1_data), + .reg2_data_i(reg2_data), + + .reg1_read_o(reg1_read), + .reg2_read_o(reg2_read), + + .reg1_addr_o(reg1_addr), + .reg2_addr_o(reg2_addr), + + .aluop_o(id_aluop_o), + .alusel_o(id_alusel_o), + .reg1_o(id_reg1_o), + .reg2_o(id_reg2_o), + .wd_o(id_wd_o), + .wreg_o(id_wreg_o) + ); + + regfile regfile1( + .clk (clk), + .rst (rst), + .we (wb_wreg_i), + .waddr (wb_wd_i), + .wdata (wb_wdata_i), + .re1 (reg1_read), + .raddr1 (reg1_addr), + .rdata1 (reg1_data), + .re2 (reg2_read), + .raddr2 (reg2_addr), + .rdata2 (reg2_data) + ); + + id_ex id_ex0( + .clk(clk), + .rst(rst), + + .id_aluop(id_aluop_o), + .id_alusel(id_alusel_o), + .id_reg1(id_reg1_o), + .id_reg2(id_reg2_o), + .id_wd(id_wd_o), + .id_wreg(id_wreg_o), + + .ex_aluop(ex_aluop_i), + .ex_alusel(ex_alusel_i), + .ex_reg1(ex_reg1_i), + .ex_reg2(ex_reg2_i), + .ex_wd(ex_wd_i), + .ex_wreg(ex_wreg_i) + ); + + ex ex0( + .rst(rst), + + .aluop_i(ex_aluop_i), + .alusel_i(ex_alusel_i), + .reg1_i(ex_reg1_i), + .reg2_i(ex_reg2_i), + .wd_i(ex_wd_i), + .wreg_i(ex_wreg_i), + + .wd_o(ex_wd_o), + .wreg_o(ex_wreg_o), + .wdata_o(ex_wdata_o) + + ); + + ex_mem ex_mem0( + .clk(clk), + .rst(rst), + + .ex_wd(ex_wd_o), + .ex_wreg(ex_wreg_o), + .ex_wdata(ex_wdata_o), + + + .mem_wd(mem_wd_i), + .mem_wreg(mem_wreg_i), + .mem_wdata(mem_wdata_i) + + + ); + + mem mem0( + .rst(rst), + + .wd_i(mem_wd_i), + .wreg_i(mem_wreg_i), + .wdata_i(mem_wdata_i), + + .wd_o(mem_wd_o), + .wreg_o(mem_wreg_o), + .wdata_o(mem_wdata_o) + ); + + mem_wb mem_wb0( + .clk(clk), + .rst(rst), + + .mem_wd(mem_wd_o), + .mem_wreg(mem_wreg_o), + .mem_wdata(mem_wdata_o), + + .wb_wd(wb_wd_i), + .wb_wreg(wb_wreg_i), + .wb_wdata(wb_wdata_i) + + ); + +endmodule diff --git a/Src/yunmips_min_sopc.v b/Src/yunmips_min_sopc.v new file mode 100644 index 0000000..8e53f14 --- /dev/null +++ b/Src/yunmips_min_sopc.v @@ -0,0 +1,28 @@ +`include "../Defines.v" + +module yunmips_min_sopc(input wire clk, + input wire rst); + + wire[`InstAddrBus] inst_addr; + wire[`InstBus] inst; + wire rom_ce; + + + yunmips yunmips0( + .clk(clk), + .rst(rst), + + .rom_addr_o(inst_addr), + .rom_data_i(inst), + .rom_ce_o(rom_ce) + + ); + + inst_rom inst_rom0( + .addr(inst_addr), + .inst(inst), + .ce(rom_ce) + ); + + +endmodule diff --git a/Testbench/yunmips_min_sopc_tb.v b/Testbench/yunmips_min_sopc_tb.v new file mode 100644 index 0000000..a8cce2f --- /dev/null +++ b/Testbench/yunmips_min_sopc_tb.v @@ -0,0 +1,26 @@ +`include "../Defines.v" +`timescale 1ns/1ps + +module yunmips_min_sopc_tb(); + + reg CLOCK_50; + reg rst; + + + initial begin + CLOCK_50 = 1'b0; + forever #10 CLOCK_50 = ~CLOCK_50; + end + + initial begin + rst = `RstEnable; + #195 rst= `RstDisable; + #1000 $stop; + end + + yunmips_min_sopc yunmips_min_sopc0( + .clk(CLOCK_50), + .rst(rst) + ); + +endmodule \ No newline at end of file