THE MINI-MIPS VERILOG CODE AND THE TEST-BENCH Verilog: Top with Data Memory

module top( input clk, reset, output [31:0] WriteData,DataAdr, output MemWrite); wire [31:0] Pcnext, Instr, Readdata; // instantiate processor and memories mips mips (clk,reset,Instr,Readdata,Pcnext,DataAdr,WriteData,MemWrite); instructmem instructmem (Pcnext[7:2],Instr); datamem datamem (clk,MemWrite,DataAdr,WriteData,Readdata); endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////// module datamem( input clk, we, input [31:0] a, wd, output [31:0] rd); reg [31:0] RAM[63:0]; assign rd = RAM[a[31:2]]; // word aligned always @(posedge clk) if (we) RAM[a[31:2]] <= wd; endmodule

Verilog: Instruction Memory
module instructmem(input [5:0] a, output [31:0] rd); reg [31:0] RAM[63:0]; initial begin $readmemh("memfile.dat",RAM); end assign rd = RAM[a]; // word aligned endmodule

Verilog: Mips
module mips( input clk,reset, input [31:0] InstrF,ReaddataM, output [31:0] PcnextFD, output [31:0] ALUoutM,WriteDataM, output MemWriteM); wire wire wire wire wire wire wire [5:0] opcodeD,functD; zeroM; RegWriteW,MemtoRegW; [3:0] ALUcontrolE; [1:0] ALUSrcE,RegDstE; [1:0] jumpD; PcSrcM;

controller CONTROLLER (clk,reset,opcodeD,functD,zeroM,RegWriteW,MemtoRegW, MemWriteM,ALUcontrolE,ALUSrcE,RegDstE,jumpD,PcSrcM); datapath DATAPATH (clk,reset,RegWriteW,MemtoRegW,ALUcontrolE,ALUSrcE, RegDstE,jumpD,PcSrcM,InstrF,ReaddataM,zeroM, PcnextFD,ALUoutM,WriteDataM,opcodeD,functD);

endmodule

Verilog: Controller
module controller( input clk,reset, input [5:0] opcodeD,functD, CHAPTER 9: TESTING AND DEBUGGING input zeroM, output RegWriteW, output MemtoRegW, output MemWriteM, output [3:0] ALUcontrolE, output [1:0] ALUSrcE, output [1:0] RegDstE, output [1:0] jumpD, output PcSrcM); wire [2:0] ALUopD; wire [1:0] ALUSrcD,RegDstD; wire [3:0] ALUcontrolD; wire MemWriteD,RegWriteD,MemtoRegD; wire MemWriteE,RegWriteE,MemtoRegE; wire RegWriteM,MemtoRegM; wire BeqD,BeqE,BneD,BneE,BeqM,BneM;

maindec maindec (opcodeD,RegWriteD,MemtoRegD,MemWriteD,BeqD,BneD,ALUSrcD,RegDstD,jumpD,ALUopD); ALUdec ALUdecoder (functD,ALUopD,ALUcontrolD); assign PcSrcM = (BeqM & zeroM) | (BneM & ~zeroM); //pipelined registers flopr registerE (clk,reset, {RegWriteD,MemtoRegD,MemWriteD,BeqD,BneD,ALUcontrolD,ALUSrcD,RegDstD}, {RegWriteE,MemtoRegE,MemWriteE,BeqE,BneE,ALUcontrolE,ALUSrcE,RegDstE}); (clk,reset, {RegWriteE,MemtoRegE,MemWriteE,BeqE,BneE}, {RegWriteM,MemtoRegM,MemWriteM,BeqM,BneM});

flopr register

flopr registerW (clk,reset, {RegWriteM,MemtoRegM}, {RegWriteW,MemtoRegW}); endmodule

Testbench: Controller
module controller_TB; // Inputs reg clk; reg reset; reg zeroM; reg [5:0] opcodeD; reg [5:0] functD; // Outputs wire [3:0] ALUcontrolE; wire MemWriteM; wire PcSrcM; wire MemtoRegW; wire RegWriteW; wire [1:0] jumpD; wire [1:0] ALUSrcE; wire [1:0] RegDstE; // Instantiate the Unit Under Test (UUT) controller uut ( .clk(clk), .reset(reset), .zeroM(zeroM), .opcodeD(opcodeD), .functD(functD), .ALUcontrolE(ALUcontrolE), .MemWriteM(MemWriteM), .PcSrcM(PcSrcM), .MemtoRegW(MemtoRegW), .RegWriteW(RegWriteW), .jumpD(jumpD), .ALUSrcE(ALUSrcE), .RegDstE(RegDstE)); initial begin // Initialize Inputs clk = 0; reset = 0; zeroM = 0; opcodeD = 0; functD = 0; end initial #10 opcodeD = 6'b000100; initial #10 functD = 6'bXXXXXX; initial forever # 10 clk =! clk; endmodule

CHAPTER 10: RECOMENDATION

Verilog: Main Decoder
module maindec( input [5:0] opcode, output RegWrite, output MemtoReg, output MemWrite, output Beq,Bne, output [1:0]ALUSrc, output [1:0]RegDst, output [1:0]jump, output [2:0]ALUop); reg [13:0] controlunit; assign {RegWrite,RegDst,ALUSrc,Beq,Bne,MemWrite,MemtoReg,jump,ALUop} = controlunit; always @ (*) case (opcode) //Arithmetic Instruction 6'b000000: controlunit <= 14'b10100000000010; //R-type 6'b001000: controlunit <= 14'b10001000000000; //Addi //Data Transfer Instruction 6'b100011: controlunit <= 14'b10001000100000; //lw 6'b101011: controlunit <= 14'b00001001000000; //sw 6'b001111: controlunit <= 14'b10001000000000; //lui //Logical Instruction 6'b001100: controlunit <= 14'b10001000000100; //ANDi 6'b001101: controlunit <= 14'b10001000000101; //ORi //Conditional Branch Instruction 6'b000100: controlunit <= 14'b00000100000001; //BEQ 6'b000101: controlunit <= 14'b00000010000001; //BNE 6'b001010: controlunit <= 14'b10001000000001; //SLTi // Unconditional Jump Instruction 6'b000010: controlunit <= 14'b00000000001000; //J //6'b000000: controlunit <= 9'b100001100; //Jr 6'b000011: controlunit <= 14'b11000000010000; //Jal default: controlunit <= 14'bXXXXXXXXXXXXXX; //??? endcase

Testbench: Main Decoder
module maindec_TB; // Inputs reg [5:0] opcode; // Outputs wire [1:0] jump; wire [1:0] RegDst; wire [1:0] ALUSrc; wire [2:0] ALUop; wire RegWrite; wire Beq; wire Bne; wire MemWrite; wire MemtoReg; // Instantiate the Unit Under Test (UUT) maindec uut ( .opcode (opcode), .jump(jump), .RegDst(RegDst), .ALUSrc(ALUSrc), .ALUop(ALUop), .RegWrite(RegWrite), .Beq(Beq), .Bne(Bne), .MemWrite(MemWrite), .MemtoReg(MemtoReg)); initial begin // Initialize Inputs opcode = 0; end initial #10 opcode = 6'b000000; initial #20 opcode = 6'b001000; initial #30 opcode = 6'b100011; initial #40 opcode = 6'b101011; initial #50 opcode = 6'b001111; initial #60 opcode = 6'b001100; initial #70 opcode = 6'b001101; initial #80 opcode = 6'b000100; initial #90 opcode = 6'b000101; initial #100 opcode = 6'b001010; initial #110 opcode = 6'b000010; initial #120 opcode = 6'b000011; endmodule

Verilog: ALU Decoder
module ALUdec( input [5:0] functD, input [2:0] ALUopD, output reg [3:0] ALUcontrolD); always @ (*) case (ALUopD) 3'b000: ALUcontrolD <= 4'b0010; //Add 3'b001: ALUcontrolD<= 4'b1010; //Sub default: case (functD) //R-TYPE //Arithmetic Instruction 6'b100000: ALUcontrolD <= 4'b0010; 6'b100010: ALUcontrolD <= 4'b1010; //Logical Instruction 6'b100100: ALUcontrolD <= 4'b0000; 6'b100101: ALUcontrolD <= 4'b0001; 6'b100111: ALUcontrolD <= 4'b1001; 6'b000000: ALUcontrolD <= 4'b0100; 6'b000010: ALUcontrolD <= 4'b0101; //Conditional Branch Instruction 6'b101010: ALUcontrolD <= 4'b1011; default: ALUcontrolD <= 4'bXXXX; endcase endcase endmodule

//ADD //SUB

//AND //OR //NOR //SLL //SRL

//SLT //???

Testbench: ALU Decoder
module ALUdec_TB; // Inputs reg [5:0] funct; reg [2:0] ALUop; // Outputs wire [3:0] ALUcontrol; // Instantiate the Unit Under Test (UUT) ALUdec uut ( .funct(funct), .ALUop(ALUop), .ALUcontrol(ALUcontrol)); initial begin // Initialize Inputs funct = 0; ALUop = 0; end initial #0 ALUop = 3'b000; initial #0 funct=6'bxxxxxx; initial #10 ALUop = 3'b001; initial #10 funct=6'bxxxxxx; initial #20 ALUop = 3'b010; initial #20 funct = 6'b100000; initial #30 ALUop = 3'b010; initial #30 funct = 6'b100010; initial #40 ALUop = 3'b010; initial #40 funct = 6'b100100; initial #50 ALUop = 3'b010; initial #50 funct = 6'b100101; initial #60 ALUop = 3'b010; initial #60 funct = 6'b100111; initial #70 ALUop = 3'b010; initial #70 funct = 6'b000000; initial #80 ALUop = 3'b010; initial #80 funct = 6'b000010; initial #90 ALUop = 3'b010; initial #90 funct = 6'b101010; endmodule

Verilog: Datapath module datapath( input clk,reset, input RegWriteW, input MemtoRegW, input [3:0] ALUcontrolE, input [1:0] ALUSrcE,RegDstE,jumpD, input PcSrcM, input [31:0] InstrF,ReaddataM, output zeroM, output [31:0]PcnextFD,ALUoutM,WriteDataM, output [5:0] opcodeD,functD);

wire [31:0] InstrD; wire [31:0] SrcAD,SrcAE,SrcBE; wire [31:0] WriteDataD,WriteDataE; wire [31:0] ALUoutE,ALUoutW; wire [4:0] rtE,rdE; wire [4:0] WriteRegE,WriteRegM,WriteRegW; wire [31:0] PcnextbarFD; wire [31:0] PcPlus4F,PcBranchM,PcBranchE; wire [31:0] PcPlus4D,PcPlus4E; wire [31:0] SignExD,SignImmE,SignImmshE; wire [31:0] ResultW,ReaddataW; wire zeroE; wire [31:0] MuxResultD,BranchF;

//Multiplexers mux2 muxPCSrcM (PcPlus4F,PcBranchM,PcSrcM,BranchF); mux4 muxjump (BranchF,{PcPlus4F[31:28],InstrD[25:0],2'b00},{PcPlus4F[31:28],InstrD[25:0],2'b00}, SrcAD,jumpD,PcnextbarFD); (ResultW,ResultW,ResultW,PcPlus4D,jumpD,MuxResultD);

mux4 muxjumpD

mux4 muxALUSrcE (WriteDataE,SignImmE,{InstrD[16:0],16'b00},32'b00,ALUSrcE,SrcBE); mux4 muxRegDstE (rtE,rdE,5'b11111,4'b0000,RegDstE,WriteRegE); mux2 muxMemtoRegW (ALUoutW,ReaddataW,MemtoRegW,ResultW);

//register file (operates in Decode and WriteBack) registerfile rf (clk,RegWriteW,InstrD[25:21],InstrD[20:16],WriteRegW,MuxResultD,SrcAD,WriteDataD);

//Fetch stage Logic flopr PcReg (clk,reset,PcnextbarFD,PcnextFD); adder PcAdd1 (PcnextFD,32'b100,PcPlus4F);

//Decode stage assign opcodeD = InstrD[31:26]; assign functD = InstrD[5:0]; flopr r1D (clk,reset,PcPlus4F,PcPlus4D); flopr r2D (clk,reset,InstrF,InstrD[31:0]); Signext se (InstrD[15:0],SignExD);

//Execute stage flopr flopr flopr flopr flopr flopr r1E (clk, reset, SrcAD,SrcAE); r2E (clk, reset, WriteDataD, WriteDataE); r3E (clk, reset, InstrD[20:16],rtE); r4E (clk, reset, InstrD[15:11],rdE); r5E (clk, reset, SignExD,SignImmE); r6E (clk, reset, PcPlus4D,PcPlus4E);

adder pcadd2 (SignImmshE,PcPlus4E,PcBranchE); Sl2 shift2E (SignImmE,SignImmshE); alu ALU (SrcAE,SrcBE,ALUcontrolE,ALUoutE,zeroE);

// Memory stage flopr r1M (clk,reset,zeroE,zeroM); flopr r2M (clk,reset,ALUoutE,ALUoutM); flopr r3M (clk,reset,WriteDataE,WriteDataM); flopr r4M (clk,reset,WriteRegE,WriteRegM); flopr r5M (clk,reset,PcBranchE,PcBranchM);

//WriteBack stage flopr r1W (clk, reset, ALUoutM, ALUoutW); flopr r2W (clk, reset, ReaddataM,ReaddataW); flopr r3W (clk, reset, WriteRegM, WriteRegW); endmodule

Verilog: ALU
module alu (SrcA, SrcB, ALUcontrol, Result, zero); input [3:0] ALUcontrol; input [31:0] SrcA,SrcB; output zero; output reg [31:0] Result; always@(ALUcontrol,SrcA,SrcB) case(ALUcontrol) 4'b0000: Result <= SrcA&SrcB; //and 4'b0001: Result <= SrcA|SrcB; //or 4'b0010: Result <= SrcA+SrcB; //add 4'b1001: Result <= ~ (SrcA|SrcB); //nor 4'b1010: Result <= SrcA-SrcB; //sub 4'b1011: Result <= SrcA<SrcB ? 1:0; //slt 4'b0100: Result <= (SrcA<<SrcB); //sll 4'b0101: Result <= (SrcA>>SrcB); //srl default: Result <=0; //error endcase endmodule

Testbench: ALU
module alu_TB; // Inputs reg [31:0] SrcA; reg [31:0] SrcB; reg [3:0] ALUcontrol; // Outputs wire [31:0] Result; wire zero; // Instantiate the Unit Under Test (UUT) alu uut ( .SrcA(SrcA), .SrcB(SrcB), .ALUcontrol(ALUcontrol), .Result(Result), .zero(zero)); initial begin // Initialize Inputs SrcA = 10; SrcB = 5; ALUcontrol = 0; // Wait 100 ns for global reset to finish #100; end initial #0 ALUcontrol = 4'b0000; initial #10 ALUcontrol = 4'b0001; initial #20 ALUcontrol = 4'b0010; initial #30 ALUcontrol = 4'b1001; initial #40 ALUcontrol = 4'b1010; initial #50 ALUcontrol = 4'b1011; initial #60 ALUcontrol = 4'b0100; initial #70 ALUcontrol = 4'b0101; endmodule

Verilog: Resettable Flip-Flop
module flopr #(parameter width = 8) (input clk,reset, input [width-1:0] d, output reg [width-1:0] q); //Resettable register

// asynchronous reset always @ (posedge clk, posedge reset) if (reset) q <= 0; else q <= d; endmodule

Testbench: Resettable Flip-Flop
module flopr_TB; // Inputs reg clk; reg reset; reg [7:0] d; // Outputs wire [7:0] q; // Instantiate the Unit Under Test (UUT) flopr uut ( .clk(clk), .reset(reset), .d(d), .q(q)); initial begin // Initialize Inputs clk = 0; reset = 0; d = 0; // Wait 100 ns for global reset to finish #100; // Add stimulus here clk = 1; d = 10; end

Verilog: Multiplexer 2 inputs
module mux2 #(parameter width = 8) (input [width-1:0] d0,d1, input s, output [width-1:0] y); assign y = s ? d1:d0; endmodule initial begin // Initialize Inputs SrcA = 10; SrcB = 5; ALUcontrol = 0; // Wait 100 ns for global reset to finish #100; end initial #0 ALUcontrol = 4'b0000;

Testbench: Multiplexer 2 inputs
module mux2_TB; // Inputs reg [7:0] d0; reg [7:0] d1; reg s; // Outputs wire [7:0] y; // Instantiate the Unit Under Test (UUT) mux2 uut ( .d0(d0), .d1(d1), .s(s), .y(y)); initial begin // Initialize Inputs d0 = 1; d1 = 2; s = 1; end endmodule

Verilog: Multiplexer 4 inputs
module mux4 #(parameter width = 8) (input [width-1:0] d0,d1,d2,d3, input [1:0] s, output [width-1:0] y); assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0); endmodule

Testbench: Multiplexer 4 inputs
module mux4_TB; // Inputs reg [7:0] d0; reg [7:0] d1; reg [7:0] d2; reg [7:0] d3; reg [1:0] s; // Outputs wire [7:0] y; // Instantiate the Unit Under Test (UUT) mux4 uut ( .d0(d0), .d1(d1), .d2(d2), .d3(d3), .s(s), .y(y)); initial begin // Initialize Inputs d0 = 0; d1 = 1; d2 = 0; d3 = 4; s = 3; end endmodule

Verilog: Register File
module registerfile( input clk, input we3, input [4:0] ra1,ra2,wa3, input [31:0] wd3, output [31:0] rd1,rd2); reg [31:0] rf[31:0]; // three port register file // read two ports combinationally // write third port on rising edge of clock // register 0 hardwired to 0 always @ (posedge clk) if (we3) rf[wa3] <= wd3; assign rd1 = (ra1 != 0) ? rf[ra1] : 0; assign rd2 = (ra2 != 0) ? rf[ra2] : 0; endmodule

Verilog: Register File
module registerfile_TB; // Inputs reg clk; reg we3; reg [4:0] ra1; reg [4:0] ra2; reg [4:0] wa3; reg [31:0] wd3; // Outputs wire [31:0] rd1; wire [31:0] rd2; // Instantiate the Unit Under Test (UUT) registerfile uut ( .clk(clk), .we3(we3), .ra1(ra1), .ra2(ra2), .wa3(wa3), .wd3(wd3), .rd1(rd1), .rd2(rd2) ); initial begin // Initialize Inputs clk = 0; we3 = 1; ra1 = 0; ra2 = 17; wa3 = 17; wd3 = 32; // Wait 100 ns for global reset to finish #100; // Add stimulus here end initial forever #10 clk =!clk; endmodule

Verilog: Adder
module adder( input [31:0] a,b, output [31:0] y); assign y = a + b; endmodule

Testbench: Adder
module adder_TB; // Inputs reg [31:0] a; reg [31:0] b; // Outputs wire [31:0] y; // Instantiate the Unit Under Test (UUT) adder uut ( .a(a), .b(b), .y(y)); initial begin // Initialize Inputs a = 50; b = 10; // Wait 50 ns for global reset to finish #50; end endmodule

Verilog: Shift Left 16-bits
module Sl16( input [31:0] a, output [31:0] y); assign y = a << 16;
endmodule

Testbench: Shift Left 16-bits
module Sl16_TB; // Inputs reg [31:0] a; // Outputs wire [31:0] y; // Instantiate the Unit Under Test (UUT) Sl16 uut ( .a(a), .y(y)); initial begin // Initialize Inputs a = 20; // Wait 100 ns for global reset to finish #100; end endmodule

Verilog: Shift Left 2-bits
module Sl2( input [31:0] a, output [31:0] y); assign y = a << 2; endmodule

Testbench: Shift Left 2-bits
module Sl2_TB; // Inputs reg [31:0] a; // Outputs wire [31:0] y; // Instantiate the Unit Under Test (UUT) Sl2 uut ( .a(a), .y(y)); initial begin // Initialize Inputs a = 10; // Wait 100 ns for global reset to finish #100; end endmodule

Verilog: Sign Extended
module Signext( input [15:0] a, output [31:0] y); assign y = {{16{a[15]}},a}; endmodule

Testbench: Sign Extended
module Signext_TB; // Inputs reg [15:0] a; // Outputs wire [31:0] y; // Instantiate the Unit Under Test (UUT) Signext uut ( .a(a), .y(y)); initial begin // Initialize Inputs a = 0; // Wait 100 ns for global reset to finish #100; // Add stimulus here a = 10; end endmodule

Testbench: Top
module testbench_TB; // Inputs reg clk; reg reset; // Outputs wire [31:0] WriteData; wire [31:0] DataAdr; wire MemWrite; // Instantiate the Unit Under Test (UUT) top dut (clk,reset,WriteData,DataAdr,MemWrite); initial begin // Initialize Inputs reset <= 1; #20; reset <= 0; end // Generate clock to sequence test always begin clk <= 1; # 5; clk <= 0; # 5; end endmodule

Sign up to vote on this title
UsefulNot useful