/* CS 354 - Digital Design 4-bit CPU (behavioral implementation) */ module cpu (Instruction, WriteData, CLK); input [8:0] Instruction; input CLK; output [3:0] WriteData; wire [8:0] IR; wire [3:0] A,B,Result; wire [2:0] ALUctl; instr_reg instr(Instruction,IR,CLK); control ctl (IR[8:6],Sel,ALUctl); quad2x1mux mux(IR[5:2],Result,Sel,WriteData); regfile regs(IR[5:4],IR[3:2],IR[1:0],WriteData,A,B,CLK); ALU alu (ALUctl, A, B, Result); endmodule module instr_reg (Instruction,IR,CLK); input [8:0] Instruction; input CLK; // Replace the following with 9 instances of D flip-flops output reg [8:0] IR; always @(negedge CLK) IR = Instruction; endmodule module control (OP,Sel,ALUctl); input [2:0] OP; // Replace the following with gate-level code output reg Sel; output reg [2:0] ALUctl; always @(OP) case (OP) 3'b000: {Sel,ALUctl} = 4'b1010; // ADD 3'b001: {Sel,ALUctl} = 4'b1110; // SUB 3'b010: {Sel,ALUctl} = 4'b1000; // AND 3'b011: {Sel,ALUctl} = 4'b1001; // OR 3'b100: {Sel,ALUctl} = 4'b1111; // SLT 3'b101: {Sel,ALUctl} = 4'b0000; // LI endcase endmodule module quad2x1mux (I0,I1,Sel,Out); input [3:0] I0,I1; input Sel; output [3:0] Out; // Replace the following with gate-level code assign Out = (Sel)? I1: I0; endmodule module regfile (ReadReg1,ReadReg2,WriteReg,WriteData,ReadData1,ReadData2,CLK); input [1:0] ReadReg1,ReadReg2,WriteReg; input [3:0] WriteData; input CLK; output [3:0] ReadData1,ReadData2; reg [3:0] Regs[0:3]; assign ReadData1 = Regs[ReadReg1]; assign ReadData2 = Regs[ReadReg2]; initial Regs[0] = 0; always @(negedge CLK) Regs[WriteReg] = WriteData; endmodule module ALU (ALUctl, A, B, ALUOut); input [2:0] ALUctl; input [3:0] A,B; output reg [3:0] ALUOut; output Zero,Overflow; always @(ALUctl, A, B) //re-evaluate if these change case (ALUctl) 3'b000: ALUOut <= A & B; 3'b001: ALUOut <= A | B; 3'b010: ALUOut <= A + B; 3'b110: ALUOut <= A - B; 3'b111: ALUOut <= A < B ? 1:0; endcase endmodule module test_cpu; reg [8:0] Instruction; reg CLK; wire [3:0] WriteData; cpu cpu1 (Instruction, WriteData, CLK); initial begin $display("\nCLK Instruction WriteData\n-------------------------"); $monitor("%b %b %d (%b)", CLK,Instruction,WriteData,WriteData); #1 Instruction = 9'b101_0111_01; // li $1, 7 # $1 = 7 CLK=1; #1 CLK=0; // Negative edge - execute instruction #1 Instruction = 9'b101_0101_10; // li $2, 5 # $2 = 5 CLK=1; #1 CLK=0; // Negative edge - execute instruction #1 Instruction = 9'b001_01_10_11; // sub $3, $1, $2 # $3 = 2 CLK=1; #1 CLK=0; // Negative edge - execute instruction // Add more instructions // ... end endmodule