Quellcode durchsuchen

Implemented alu extened instructions

Min vor 6 Jahren
Ursprung
Commit
31ee682781
6 geänderte Dateien mit 42 neuen und 21 gelöschten Zeilen
  1. 6 10
      src/blocks/alu.sv
  2. 3 2
      src/controller.sv
  3. 4 3
      src/cpu.sv
  4. 3 2
      src/datapath.sv
  5. 10 4
      src/general.sv
  6. 16 0
      tools/asm_compiler.py

+ 6 - 10
src/blocks/alu.sv

@@ -1,19 +1,15 @@
 import project_pkg::*;
 
-module alu(op, srcA, srcB, result, zero);	
+module alu(op, exop, srcA, srcB, result, zero);
 	
 	input  e_alu_op 	op;
 	input  word			srcA;
 	input  word			srcB;
+	input  e_alu_ext_op exop; 
 	output word			result;
 	output logic		zero;
 	
-	logic [2:0]xop;
-	logic [2:0]shamt;
-	
 	always_comb begin
-	xop = srcB[7:5];
-	shamt = srcB[2:0];
 	case(op)
 		ALU_CPY: result = srcB;
 		ALU_ADD: result = srcA + srcB;
@@ -23,10 +19,10 @@ module alu(op, srcA, srcB, result, zero);
 		ALU_XOR: result = srcA ^ srcB;
 		ALU_GT : result = srcA > srcB;
 		ALU_EXT: begin
-				case(xop)
-						3'b000: result = srcA << shamt;
-						3'b001: result = srcA >> shamt;
-						3'b010: result = srcA >>> shamt;
+				case(exop)
+						AEX_SHFL: result = srcA << 1;
+						AEX_SHFR: result = srcA >> 1;
+						AEX_ROTR: result = {srcA[0], srcA[7:1]};
 						default: result = srcA;
 				endcase
 		end

+ 3 - 2
src/controller.sv

@@ -1,9 +1,10 @@
 import project_pkg::*;
 
-module controller(instr, zero, alu_op, mem_wr, reg_wr, pc_src, rimm, alu_src, mem_to_reg, instr_op, rd, rs);
+module controller(instr, zero, alu_op, alu_ex, mem_wr, reg_wr, pc_src, rimm, alu_src, mem_to_reg, instr_op, rd, rs);
 	input word instr;
 	input logic zero; // That's from ALU for J instructions
 	output e_alu_op alu_op;
+	output e_alu_ext_op alu_ex;
 	output logic mem_wr, reg_wr, rimm, mem_to_reg, pc_src, alu_src;
 	output e_instr instr_op;
 	output e_reg rs, rd;
@@ -23,7 +24,7 @@ module controller(instr, zero, alu_op, mem_wr, reg_wr, pc_src, rimm, alu_src, me
 	
 	assign alu_src = (instr_op == CPY & rd == rs);	
 	assign rimm = (alu_src) | instr_op == JEQ;	
-
+	assign alu_ex = e_alu_ext_op'(rs);
 endmodule
 
 module controller_tb;

+ 4 - 3
src/cpu.sv

@@ -11,11 +11,12 @@ module cpu(clk, rst, instr, imm, pc, mem_addr, mem_wr_en, mem_wr_data, mem_rd_da
 	e_instr instr_op;
 	e_reg rd, rs;
 	e_alu_op alu_op;
-	
-	controller CTRL(instr, alu_zero, alu_op, mem_wr_en, reg_wr, pc_src, rimm, alu_src, mem_to_reg, instr_op, rd, rs);
+	e_alu_ext_op alu_ex;
+
+	controller CTRL(instr, alu_zero, alu_op, alu_ex, mem_wr_en, reg_wr, pc_src, rimm, alu_src, mem_to_reg, instr_op, rd, rs);
 
 	// Datapath
-	datapath DPATH(clk, rst, rd, rs, imm, alu_op, reg_wr, pc_src, rimm, alu_src, mem_to_reg, pc, mem_addr, mem_rd_data, alu_zero, mem_wr_data);	
+	datapath DPATH(clk, rst, rd, rs, imm, alu_op, alu_ex, reg_wr, pc_src, rimm, alu_src, mem_to_reg, pc, mem_addr, mem_rd_data, alu_zero, mem_wr_data);	
 endmodule
 
 module cpu_tb;

+ 3 - 2
src/datapath.sv

@@ -1,9 +1,10 @@
 import project_pkg::*;
 
-module datapath(clk, rst, rd, rs, imm, alu_op, reg_wr, pc_src, rimm, alu_src, mem_to_reg, pc, alu_out, mem_data, alu_zero, mem_wr_data);
+module datapath(clk, rst, rd, rs, imm, alu_op, alu_ex, reg_wr, pc_src, rimm, alu_src, mem_to_reg, pc, alu_out, mem_data, alu_zero, mem_wr_data);
 	input logic clk, rst, reg_wr, pc_src, rimm, mem_to_reg, alu_src;
 	input e_reg rd, rs;
 	input e_alu_op alu_op;
+	input e_alu_ext_op alu_ex;
 	input word imm, mem_data;
 	output word pc, alu_out, mem_wr_data;
 	output logic alu_zero;
@@ -24,7 +25,7 @@ module datapath(clk, rst, rd, rs, imm, alu_op, reg_wr, pc_src, rimm, alu_src, me
 	word alu_srcA, alu_srcB;
 	assign alu_srcA = reg_rd_d1;
 	assign alu_srcB = alu_src ? imm : reg_rd_d2;
-	alu ALU(alu_op, alu_srcA, alu_srcB, alu_out, alu_zero);
+	alu ALU(alu_op, alu_ex, alu_srcA, alu_srcB, alu_out, alu_zero);
 	
 	// Program counter
 	word pcn; 	// PC next

+ 10 - 4
src/general.sv

@@ -23,11 +23,11 @@ package project_pkg;
 		CPY =4'b0000,  // $rd = imm if rd == rs else $rd = $rs
 		ADD =4'b0001,  // $rd = $rd + $rs
 		SUB =4'b0010,  // $rd = $rd - $rs
-		AND =4'b0011,  // $rd = $rd & $rs
+		AND =4'b0011,  // $rd = $rd & $rsgt
 		OR  =4'b0100,  // $rd = $rd | $rs
 		XOR =4'b0101,  // $rd = $rd ^ $rs
 		GT  =4'b0110,  // $rd = $rd > $rs
-		EXT =4'b0111,  // $rd binary [ xxxxx xxx ], first 5 bits means shift operation, last 3 means shift amount
+		EXT =4'b0111,  // rs 00: shift left; 01: shift right; 10: rotate right; 
 		LW  =4'b1000,  // $rd = mem[$mp + $rs]
 		SW  =4'b1001,  // mem[$mp + $rs] = $rd
 		JEQ =4'b1010,  // Jump to imm if $rd == $rs
@@ -39,7 +39,7 @@ package project_pkg;
 	} e_instr;
 
 	typedef enum logic [2:0] {
-		ALU_CPY = 3'b000,
+		ALU_CPY = 3'b000, // TODO: Could be replaced by AEX_3
 		ALU_ADD = 3'b001,
 		ALU_SUB = 3'b010,
 		ALU_AND = 3'b011,
@@ -48,6 +48,12 @@ package project_pkg;
 		ALU_GT  = 3'b110,
 		ALU_EXT = 3'b111
 	} e_alu_op;
-	
+
+	typedef enum logic [1:0] {
+		AEX_SHFL = 2'b00,
+		AEX_SHFR = 2'b01,
+		AEX_ROTR = 2'b10,
+		AEX_3	 = 2'b11
+	} e_alu_ext_op;
 	
 endpackage

+ 16 - 0
tools/asm_compiler.py

@@ -39,6 +39,10 @@ def is_reg(r):
 
 
 def decode_reg(r):
+    if isinstance(r, int):
+        if 0 <= r <= 3:
+            return r
+        raise ValueError(f"Invalid register value {r}")
     rl = r.lower()
     if rl.startswith('$'):
         rl = rl[1:]
@@ -106,6 +110,18 @@ def assemble(file):
         elif instr == 'EX' or instr == 'EXT':
             iname = 'EXT'
             inibb = 7
+        elif instr == 'SHFL':
+            iname = 'SHTL'
+            inibb = 7
+            ops.append(0)
+        elif instr == 'SHFR':
+            iname = 'SHTR'
+            inibb = 7
+            ops.append(1)
+        elif instr == 'ROTR':
+            iname = 'ROTR'
+            inibb = 7
+            ops.append(2)
         elif instr == 'LW':
             iname = 'LW'
             inibb = 8