From 1be7b4b14ee37ea7d6dc117474396e9e0ffa91f8 Mon Sep 17 00:00:00 2001 From: ClF3 Date: Sat, 29 Jun 2024 14:20:54 +0800 Subject: [PATCH] 1 and 2 --- constrs_1/imports/mips/xdc_for_both.xdc | 1 + sources_1/imports/single-cycle/ALU.v | 60 +++++++ sources_1/imports/single-cycle/ALUControl.v | 61 +++++++ sources_1/imports/single-cycle/CPU.v | 154 ++++++++++++++++++ sources_1/imports/single-cycle/Control.v | 68 ++++++++ sources_1/imports/single-cycle/DataMemory.v | 57 +++++++ .../imports/single-cycle/InstructionMemory.v | 39 +++++ sources_1/imports/single-cycle/RegisterFile.v | 32 ++++ sources_1/imports/single-cycle/test_cpu.v | 30 ++++ utils_1/imports/synth_1/test_cpu.dcp | Bin 0 -> 7733 bytes 10 files changed, 502 insertions(+) create mode 100644 constrs_1/imports/mips/xdc_for_both.xdc create mode 100644 sources_1/imports/single-cycle/ALU.v create mode 100644 sources_1/imports/single-cycle/ALUControl.v create mode 100644 sources_1/imports/single-cycle/CPU.v create mode 100644 sources_1/imports/single-cycle/Control.v create mode 100644 sources_1/imports/single-cycle/DataMemory.v create mode 100644 sources_1/imports/single-cycle/InstructionMemory.v create mode 100644 sources_1/imports/single-cycle/RegisterFile.v create mode 100644 sources_1/imports/single-cycle/test_cpu.v create mode 100644 utils_1/imports/synth_1/test_cpu.dcp diff --git a/constrs_1/imports/mips/xdc_for_both.xdc b/constrs_1/imports/mips/xdc_for_both.xdc new file mode 100644 index 0000000..103c2dd --- /dev/null +++ b/constrs_1/imports/mips/xdc_for_both.xdc @@ -0,0 +1 @@ +create_clock -name clk -period 1000.000 [get_ports clk] \ No newline at end of file diff --git a/sources_1/imports/single-cycle/ALU.v b/sources_1/imports/single-cycle/ALU.v new file mode 100644 index 0000000..fddecbd --- /dev/null +++ b/sources_1/imports/single-cycle/ALU.v @@ -0,0 +1,60 @@ + +module ALU( + input [32 -1:0] in1 , + input [32 -1:0] in2 , + input [5 -1:0] ALUCtl , + input Sign , + output reg [32 -1:0] out , + output zero +); + reg signed [7:0] in11,in12,in13,in14,in21,in22,in23,in24; + reg [31:0] MACout; + // zero means whether the output is zero or not + assign zero = (out == 0); + + wire ss; + assign ss = {in1[31], in2[31]}; + + wire lt_31; + assign lt_31 = (in1[30:0] < in2[30:0]); + + // lt_signed means whether (in1 < in2) + wire lt_signed; + assign lt_signed = (in1[31] ^ in2[31])? + ((ss == 2'b01)? 0: 1): lt_31; + + always @(*) + begin + in11=in1[31:24]; + in12=in1[23:16]; + in13=in1[15:8]; + in14=in1[7:0]; + in21=in2[31:24]; + in22=in2[23:16]; + in23=in2[15:8]; + in24=in2[7:0]; + MACout=in11*in21+in12*in22+in13*in23+in14*in24; + end + + // different ALU operations + always @(*) + case (ALUCtl) + 5'b00000: out <= in1 & in2; + 5'b00001: out <= in1 | in2; + 5'b00010: out <= in1 + in2; + 5'b00110: out <= in1 - in2; + 5'b00111: out <= {31'h00000000, Sign? lt_signed: (in1 < in2)}; + 5'b01100: out <= ~(in1 | in2); + 5'b01101: out <= in1 ^ in2; + 5'b10000: out <= (in2 << in1[4:0]); + 5'b11000: out <= (in2 >> in1[4:0]); + 5'b11001: out <= ({{32{in2[31]}}, in2} >> in1[4:0]); + 5'b11010: out <= in1 * in2; // mul + 5'b11011: out <= MACout; + default: out <= 32'h00000000; + endcase + + + + +endmodule \ No newline at end of file diff --git a/sources_1/imports/single-cycle/ALUControl.v b/sources_1/imports/single-cycle/ALUControl.v new file mode 100644 index 0000000..01e8bb2 --- /dev/null +++ b/sources_1/imports/single-cycle/ALUControl.v @@ -0,0 +1,61 @@ + +module ALUControl( + input [4 -1:0] ALUOp , + input [6 -1:0] Funct , + output reg [5 -1:0] ALUCtl , + output Sign +); + + + // funct number for different operation + parameter aluAND = 5'b00000; + parameter aluOR = 5'b00001; + parameter aluADD = 5'b00010; + parameter aluSUB = 5'b00110; + parameter aluSLT = 5'b00111; + parameter aluNOR = 5'b01100; + parameter aluXOR = 5'b01101; + parameter aluSLL = 5'b10000; + parameter aluSRL = 5'b11000; + parameter aluSRA = 5'b11001; + parameter aluMUL = 5'b11010; //mul + parameter aluMAC = 5'b11011; + + // Sign means whether the ALU treats the input as a signed number or an unsigned number + assign Sign = (ALUOp[2:0] == 3'b010)? ~Funct[0]: ~ALUOp[3]; + + // set aluFunct + reg [4:0] aluFunct; + always @(*) + case (Funct) + 6'b00_0000: aluFunct <= aluSLL; + 6'b00_0010: aluFunct <= aluSRL; + 6'b00_0011: aluFunct <= aluSRA; + 6'b10_0000: aluFunct <= aluADD; + 6'b10_0001: aluFunct <= aluADD; + 6'b10_0010: aluFunct <= aluSUB; + 6'b10_0011: aluFunct <= aluSUB; + 6'b10_0100: aluFunct <= aluAND; + 6'b10_0101: aluFunct <= aluOR; + 6'b10_0110: aluFunct <= aluXOR; + 6'b10_0111: aluFunct <= aluNOR; + 6'b10_1010: aluFunct <= aluSLT; + 6'b10_1011: aluFunct <= aluSLT; + 6'b10_1101: aluFunct <= aluMAC; + default: aluFunct <= aluADD; + endcase + + // set ALUCtrl + always @(*) + case (ALUOp[2:0]) + 3'b000: ALUCtl <= aluADD; + 3'b001: ALUCtl <= aluSUB; + 3'b100: ALUCtl <= aluAND; + 3'b101: ALUCtl <= aluSLT; + 3'b010: ALUCtl <= aluFunct; + 3'b110: ALUCtl <= aluMUL; //mul + default: ALUCtl <= aluADD; + endcase + + +endmodule diff --git a/sources_1/imports/single-cycle/CPU.v b/sources_1/imports/single-cycle/CPU.v new file mode 100644 index 0000000..a21c652 --- /dev/null +++ b/sources_1/imports/single-cycle/CPU.v @@ -0,0 +1,154 @@ +module CPU( + input reset , + input clk , + output MemRead , + output MemWrite , + output [32 -1:0] MemBus_Address , + output [32 -1:0] MemBus_Write_Data , + input [32 -1:0] Device_Read_Data +); + + // PC register + reg [31 :0] PC; + wire [31 :0] PC_next; + wire [31 :0] PC_plus_4; + + always @(posedge reset or posedge clk) + if (reset) + PC <= 32'h00000000; + else + PC <= PC_next; + + assign PC_plus_4 = PC + 32'd4; + + // Instruction Memory + wire [31 :0] Instruction; + InstructionMemory instruction_memory1( + .Address (PC ), + .Instruction (Instruction ) + ); + + // Control + wire [2 -1:0] RegDst ; + wire [2 -1:0] PCSrc ; + wire Branch ; + wire MemRead ; + wire MemWrite ; + wire [2 -1:0] MemtoReg ; + wire ALUSrc1 ; + wire ALUSrc2 ; + wire [4 -1:0] ALUOp ; + wire ExtOp ; + wire LuOp ; + wire RegWrite ; + + Control control1( + .OpCode (Instruction[31:26] ), + .Funct (Instruction[5 : 0] ), + .PCSrc (PCSrc ), + .Branch (Branch ), + .RegWrite (RegWrite ), + .RegDst (RegDst ), + .MemRead (MemRead ), + .MemWrite (MemWrite ), + .MemtoReg (MemtoReg ), + .ALUSrc1 (ALUSrc1 ), + .ALUSrc2 (ALUSrc2 ), + .ExtOp (ExtOp ), + .LuOp (LuOp ), + .ALUOp (ALUOp ) + ); + + // Register File + wire [32 -1:0] Databus1; + wire [32 -1:0] Databus2; + wire [32 -1:0] Databus3; + wire [5 -1:0] Write_register; + + assign Write_register = (RegDst == 2'b00)? Instruction[20:16]: (RegDst == 2'b01)? Instruction[15:11]: 5'b11111; + + RegisterFile register_file1( + .reset (reset ), + .clk (clk ), + .RegWrite (RegWrite ), + .Read_register1 (Instruction[25:21] ), + .Read_register2 (Instruction[20:16] ), + .Write_register (Write_register ), + .Write_data (Databus3 ), + .Read_data1 (Databus1 ), + .Read_data2 (Databus2 ) + ); + + // Extend + wire [32 -1:0] Ext_out; + assign Ext_out = { ExtOp? {16{Instruction[15]}}: 16'h0000, Instruction[15:0]}; + + wire [32 -1:0] LU_out; + assign LU_out = LuOp? {Instruction[15:0], 16'h0000}: Ext_out; + + // ALU Control + wire [5 -1:0] ALUCtl; + wire Sign ; + + ALUControl alu_control1( + .ALUOp (ALUOp ), + .Funct (Instruction[5:0] ), + .ALUCtl (ALUCtl ), + .Sign (Sign ) + ); + + // ALU + wire [32 -1:0] ALU_in1; + wire [32 -1:0] ALU_in2; + wire [32 -1:0] ALU_out; + wire Zero ; + + assign ALU_in1 = ALUSrc1? {27'h00000, Instruction[10:6]}: Databus1; + assign ALU_in2 = ALUSrc2? LU_out: Databus2; + + ALU alu1( + .in1 (ALU_in1 ), + .in2 (ALU_in2 ), + .ALUCtl (ALUCtl ), + .Sign (Sign ), + .out (ALU_out ), + .zero (Zero ) + ); + + // Data Memory + wire [32 -1:0] Memory_Read_Data ; + wire Memory_Read ; + wire Memory_Write ; + wire [32 -1:0] MemBus_Read_Data ; + + DataMemory data_memory1( + .reset (reset ), + .clk (clk ), + .Address (MemBus_Address ), + .Write_data (MemBus_Write_Data ), + .Read_data (Memory_Read_Data ), + .MemRead (Memory_Read ), + .MemWrite (Memory_Write ) + ); + + + assign Memory_Read = MemRead ; + assign Memory_Write = MemWrite; + assign MemBus_Address = ALU_out ; + assign MemBus_Write_Data = Databus2; + assign MemBus_Read_Data = Memory_Read_Data; + + + // write back + assign Databus3 = (MemtoReg == 2'b00)? ALU_out: (MemtoReg == 2'b01)? MemBus_Read_Data: PC_plus_4; + + // PC jump and branch + wire [32 -1:0] Jump_target; + assign Jump_target = {PC_plus_4[31:28], Instruction[25:0], 2'b00}; + + wire [32 -1:0] Branch_target; + assign Branch_target = (Branch & Zero)? PC_plus_4 + {LU_out[29:0], 2'b00}: PC_plus_4; + + assign PC_next = (PCSrc == 2'b00)? Branch_target: (PCSrc == 2'b01)? Jump_target: Databus1; + +endmodule diff --git a/sources_1/imports/single-cycle/Control.v b/sources_1/imports/single-cycle/Control.v new file mode 100644 index 0000000..b439f8d --- /dev/null +++ b/sources_1/imports/single-cycle/Control.v @@ -0,0 +1,68 @@ + +module Control( + input [6 -1:0] OpCode , + input [6 -1:0] Funct , + output [2 -1:0] PCSrc , + output Branch , + output RegWrite , + output [2 -1:0] RegDst , + output MemRead , + output MemWrite , + output [2 -1:0] MemtoReg , + output ALUSrc1 , + output ALUSrc2 , + output ExtOp , + output LuOp , + output [4 -1:0] ALUOp +); + + + // Your code below (for question 1) + assign PCSrc = + (OpCode == 6'h00 && Funct == 6'h08)? 2'b10: + (OpCode == 6'h02 || OpCode == 6'h03)? 2'b01: + 2'b00; + assign Branch = (OpCode == 6'h04)? 1'b1: 1'b0; + assign RegWrite = + (OpCode == 6'h2b || OpCode == 6'h04 || OpCode == 6'h02)? 1'b0: + (OpCode == 6'h00 && Funct == 6'h08)? 1'b0: + 1'b1; + assign RegDst = + (OpCode[5:3] == 3'b001)? 2'b00: + (OpCode == 6'h23)? 2'b00: + (OpCode == 6'h03)? 2'b10: + 2'b01; + assign MemRead = (OpCode == 6'h23)? 1'b1: 1'b0; + assign MemWrite = (OpCode == 6'h2b)? 1'b1: 1'b0; + assign MemtoReg = + (OpCode == 6'h23)? 2'b01: + (OpCode == 6'h03)? 2'b10: + 2'b00; + assign ALUSrc1 = (OpCode == 6'h00 && Funct[5:2] == 4'b0000)? 1'b1: 1'b0; + assign ALUSrc2 = + (OpCode[5:3] == 3'b001)? 1'b1: + (OpCode == 6'h23 || OpCode == 6'h2b)? 1'b1: + 1'b0; + assign ExtOp = + (OpCode == 6'h0c)? 1'b0: + 1'b1; + assign LuOp = + (OpCode == 6'h0f)? 1'b1: + 1'b0; + // Your code above (for question 1) + + // set ALUOp + assign ALUOp[2:0] = + (OpCode == 6'h00)? 3'b010: + (OpCode == 6'h04)? 3'b001: + (OpCode == 6'h0c)? 3'b100: + (OpCode == 6'h0a || OpCode == 6'h0b)? 3'b101: + (OpCode == 6'h1c && Funct == 6'h02)? 3'b110: + 3'b000; //mul + + assign ALUOp[3] = OpCode[0]; + + + + +endmodule \ No newline at end of file diff --git a/sources_1/imports/single-cycle/DataMemory.v b/sources_1/imports/single-cycle/DataMemory.v new file mode 100644 index 0000000..f8e28e1 --- /dev/null +++ b/sources_1/imports/single-cycle/DataMemory.v @@ -0,0 +1,57 @@ +module DataMemory( + input reset , + input clk , + input MemRead , + input MemWrite , + input [32 -1:0] Address , + input [32 -1:0] Write_data , + output [32 -1:0] Read_data +); + + // RAM size is 256 words, each word is 32 bits, valid address is 8 bits + parameter RAM_SIZE = 256; + parameter RAM_SIZE_BIT = 8; + + // RAM_data is an array of 256 32-bit registers + reg [31:0] RAM_data [RAM_SIZE - 1: 0]; + + // read data from RAM_data as Read_data + assign Read_data = MemRead? RAM_data[Address[RAM_SIZE_BIT + 1:2]]: 32'h00000000; + + // write Write_data to RAM_data at clock posedge + integer i; + always @(posedge reset or posedge clk)begin + if (reset) begin + // -------- Paste Data Memory Configuration Below (Data-q1.txt) + // Data Input: X = [[X11, X12, X13, X14, X15, X16, X17, X18], [X21, X22, X23, X24, X25, X26, X27, X28]] + // Data Input: Y = [[Y11, Y12], [Y21, Y22], [Y31, Y32], [Y41, Y42], [Y51, Y52], [Y61, Y62], [Y71, Y72], [Y81, Y82]] + + // Data Output: Z = matmul(X,Y) = [[Z11, Z12], [Z21, Z22]] + + // Calculation in cpu: Z11 = X11*Y11 + X12*Y21 + X13*Y31 + X14*Y41 + X15*Y51 + X16*Y61 + X17*Y71 + X18*Y81 + // Calculation in cpu: Z12 = X11*Y12 + X12*Y22 + X13*Y32 + X14*Y42 + X15*Y52 + X16*Y62 + X17*Y72 + X18*Y82 + // Calculation in cpu: Z21 = X21*Y11 + X22*Y21 + X23*Y31 + X24*Y41 + X25*Y51 + X26*Y61 + X27*Y71 + X28*Y81 + // Calculation in cpu: Z22 = X21*Y12 + X22*Y22 + X23*Y32 + X24*Y42 + X25*Y52 + X26*Y62 + X27*Y72 + X28*Y82 + + // paste in DataMemory.v + + RAM_data[0] <= 32'hd328fef9; // X11, X12, X13, X14, to be stored in $t0 + RAM_data[1] <= 32'h0324063a; // X15, X16, X17, X18, to be stored in $t1 + RAM_data[2] <= 32'h12da0c13; // X21, X22, X23, X24, to be stored in $t2 + RAM_data[3] <= 32'hde1015d6; // X25, X26, X27, X28, to be stored in $t3 + + RAM_data[4] <= 32'hdaf20624; // Y11, Y21, Y31, Y41, to be stored in $t4 + RAM_data[5] <= 32'hc31f27c9; // Y51, Y61, Y71, Y81, to be stored in $t5 + RAM_data[6] <= 32'h3ce4c0c6; // Y12, Y22, Y32, Y42, to be stored in $t6 + RAM_data[7] <= 32'h12ea09c2; // Y52, Y62, Y72, Y82, to be stored in $t7 + + for (i = 8; i < RAM_SIZE; i = i + 1) + RAM_data[i] <= 32'h00000000; + // -------- Paste Data Memory Configuration Above + end + else if (MemWrite) begin + RAM_data[Address[RAM_SIZE_BIT + 1:2]] <= Write_data; + end + end + +endmodule diff --git a/sources_1/imports/single-cycle/InstructionMemory.v b/sources_1/imports/single-cycle/InstructionMemory.v new file mode 100644 index 0000000..5ab3594 --- /dev/null +++ b/sources_1/imports/single-cycle/InstructionMemory.v @@ -0,0 +1,39 @@ +module InstructionMemory( + input [32 -1:0] Address, + output reg [32 -1:0] Instruction +); + + always @(*) + case (Address[9:2]) + + // -------- Paste Binary Instruction Below (Inst-q1-1/Inst-q1-2.txt) + 8'd0: Instruction <= 32'h8c080000; + 8'd1: Instruction <= 32'h8c090004; + 8'd2: Instruction <= 32'h8c0a0008; + 8'd3: Instruction <= 32'h8c0b000c; + 8'd4: Instruction <= 32'h8c0c0010; + 8'd5: Instruction <= 32'h8c0d0014; + 8'd6: Instruction <= 32'h8c0e0018; + 8'd7: Instruction <= 32'h8c0f001c; + 8'd8: Instruction <= 32'h010c802d; + 8'd9: Instruction <= 32'h012d202d; + 8'd10: Instruction <= 32'h02048020; + 8'd11: Instruction <= 32'h010e882d; + 8'd12: Instruction <= 32'h012f202d; + 8'd13: Instruction <= 32'h02248820; + 8'd14: Instruction <= 32'h014c902d; + 8'd15: Instruction <= 32'h016d202d; + 8'd16: Instruction <= 32'h02449020; + 8'd17: Instruction <= 32'h014e982d; + 8'd18: Instruction <= 32'h016f202d; + 8'd19: Instruction <= 32'h02649820; + 8'd20: Instruction <= 32'hac100020; + 8'd21: Instruction <= 32'hac110024; + 8'd22: Instruction <= 32'hac120028; + 8'd23: Instruction <= 32'hac13002c; + 8'd24: Instruction <= 32'h08100018; + // -------- Paste Binary Instruction Above + default: Instruction <= 32'h00000000; + endcase + +endmodule diff --git a/sources_1/imports/single-cycle/RegisterFile.v b/sources_1/imports/single-cycle/RegisterFile.v new file mode 100644 index 0000000..39ae3f6 --- /dev/null +++ b/sources_1/imports/single-cycle/RegisterFile.v @@ -0,0 +1,32 @@ + +module RegisterFile( + input reset , + input clk , + input RegWrite , + input [5 -1:0] Read_register1 , + input [5 -1:0] Read_register2 , + input [5 -1:0] Write_register , + input [32 -1:0] Write_data , + output [32 -1:0] Read_data1 , + output [32 -1:0] Read_data2 +); + + // RF_data is an array of 32 32-bit registers + // here RF_data[0] is not defined because RF_data[0] identically equal to 0 + reg [31:0] RF_data[31:1]; + + // read data from RF_data as Read_data1 and Read_data2 + assign Read_data1 = (Read_register1 == 5'b00000)? 32'h00000000: RF_data[Read_register1]; + assign Read_data2 = (Read_register2 == 5'b00000)? 32'h00000000: RF_data[Read_register2]; + + integer i; + // write Wrtie_data to RF_data at clock posedge + always @(posedge reset or posedge clk) + if (reset) + for (i = 1; i < 32; i = i + 1) + RF_data[i] <= 32'h00000000; + else if (RegWrite && (Write_register != 5'b00000)) + RF_data[Write_register] <= Write_data; + +endmodule + \ No newline at end of file diff --git a/sources_1/imports/single-cycle/test_cpu.v b/sources_1/imports/single-cycle/test_cpu.v new file mode 100644 index 0000000..d805dfd --- /dev/null +++ b/sources_1/imports/single-cycle/test_cpu.v @@ -0,0 +1,30 @@ +module test_cpu(); + + reg reset ; + reg clk ; + + wire MemRead ; + wire MemWrite ; + wire [31:0] MemBus_Address ; + wire [31:0] MemBus_Write_Data ; + wire [31:0] Device_Read_Data ; + + CPU cpu1( + .reset (reset ), + .clk (clk ), + .MemBus_Address (MemBus_Address ), + .Device_Read_Data (Device_Read_Data ), + .MemBus_Write_Data (MemBus_Write_Data ), + .MemRead (MemRead ), + .MemWrite (MemWrite ) + ); + + initial begin + reset = 1; + clk = 1; + #100 reset = 0; + end + + always #50 clk = ~clk; + +endmodule diff --git a/utils_1/imports/synth_1/test_cpu.dcp b/utils_1/imports/synth_1/test_cpu.dcp new file mode 100644 index 0000000000000000000000000000000000000000..50aad7bcc3d60db5638db70b87f0aba51e81b075 GIT binary patch literal 7733 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 literal 0 HcmV?d00001