module mipscore_testbench;
 reg reset_; initial begin reset_=0; #22 reset_=1; #300; $stop; end
 reg clock;  initial clock=0; always #5 clock<=(!clock);
 wire[31:0] PC=mc.pc;
 reg[31:0] IR; reg[31:0] DI;
 wire WE=mc.memwrite;
 wire[31:0] DO=mc.writedata; wire[31:0] A=mc.aluout;
 initial begin 
 wait(reset_==1);
 @(posedge clock); IR<=32'h20020005; DI<=32'h00000001;
 @(posedge clock); IR<=32'h2003000c; DI<=32'h00000002;
 @(posedge clock); IR<=32'h2067fff7; DI<=32'h00000003;
 @(posedge clock); IR<=32'h00e22025; DI<=32'h00000004;
 @(posedge clock); IR<=32'h00642824; DI<=32'h00000005;
 @(posedge clock); IR<=32'h00a42820; DI<=32'h00000006;
 @(posedge clock); IR<=32'h10a70007; DI<=32'h00000007;
 @(posedge clock); IR<=32'h0064202a; DI<=32'h00000008;
 @(posedge clock); IR<=32'h10800001; DI<=32'h00000009;
 @(posedge clock); IR<=32'h20050000; DI<=32'h0000000A;
 @(posedge clock); IR<=32'h00e2202a; DI<=32'h0000000B;
 @(posedge clock); IR<=32'h00853820; DI<=32'h0000000C;
 @(posedge clock); IR<=32'h00e23822; DI<=32'h0000000D;
 @(posedge clock); IR<=32'hac670044; DI<=32'h0000000E;
 @(posedge clock); IR<=32'h8c020050; DI<=32'h0000000F;
 @(posedge clock);
 $finish;
 end
 mipscore mc(clk,reset_,PC,IR,WE,A,DO,DI);
endmodule

module mipscore(clk, reset, pc, instr, memwrite, aluout, writedata, readdata);
input clk, reset;
output [31:0] pc;
input [31:0] instr;
output memwrite;
output [31:0] aluout, writedata;
input [31:0] readdata;
wire memtoreg, alusrc, regdst, regwrite, pcsrc, zero;
wire [2:0] alucontrol;
controller c(instr[31:26], instr[5:0], zero, memtoreg, memwrite, pcsrc, alusrc, regdst, regwrite, alucontrol);
datapath dp(clk, reset, memtoreg, pcsrc,alusrc, regdst, regwrite, alucontrol, zero, pc, instr, aluout, writedata, readdata);
endmodule

module controller(opcode, funct, zero, memtoreg, memwrite, pcsrc, alusrc, regdst, regwrite, alucontrol);
 input [5:0] opcode; input [5:0] funct; input zero; output [2:0] alucontrol;
 output memtoreg, memwrite, pcsrc, alusrc, regdst, regwrite;
 reg[8:0] CR;
 assign {memwrite,memtoreg,pcsrc,alusrc,regdst,regwrite,alucontrol}=CR;
 always@(opcode) $display("opcode=%b funct=%b zero=%b   CR=%b",opcode,funct,zero,CR);
 always@(opcode) CR<=9'b010101010;
endmodule

module datapath(clk, reset, memtoreg, pcsrc, alusrc, regdst, regwrite, alucontrol, zero, pc, instr, aluout, writedata, readdata);
 input clk, reset, memtoreg, pcsrc, alusrc, regdst, regwrite;
 output [31:0] writedata; output zero; output [31:0] pc; output [31:0] aluout;
 input [31:0] readdata; input [31:0] instr; input [2:0] alucontrol;
 reg[31:0] MAR; reg Z; reg[31:0] IP; reg MDR;
 assign aluout=MAR, writedata=MDR, zero=Z, pc=IP;
 always@(instr) begin
   $display("memtoreg=%b pcsrc=%b alusrc=%b regdst=%b regwrite=%b alucontrol=%b instr=%h readdata=%h",
     memtoreg,pcsrc,alusrc,regdst,regwrite,alucontrol,instr,readdata);
   MAR<=32'h0000002F; MDR<=32'h12345678; Z<=1; IP<=32'h00000010;
 end
endmodule
