Bläddra i källkod

Implemented PUSH/POP instructions

Added push/pop to LIFO stack. Stack pointer (SP) is implemented as a
hidden register within datapath
Min 6 år sedan
förälder
incheckning
067445f9da
4 ändrade filer med 43 tillägg och 10 borttagningar
  1. 11 4
      src/controller.sv
  2. 3 3
      src/cpu.sv
  3. 17 3
      src/datapath.sv
  4. 12 0
      tools/asm_compiler.py

+ 11 - 4
src/controller.sv

@@ -1,6 +1,7 @@
 import project_pkg::*;
 
-module controller(instr, zero, alu_op, alu_ex, 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, sp_wr, mem_sp);
 	input word instr;
 	input logic zero; // That's from ALU for J instructions
 	output e_alu_op alu_op;
@@ -8,6 +9,8 @@ module controller(instr, zero, alu_op, alu_ex, mem_wr, reg_wr, pc_src, rimm, alu
 	output logic mem_wr, reg_wr, rimm, mem_to_reg, pc_src, alu_src;
 	output e_instr instr_op;
 	output e_reg rs, rd;
+	output logic sp_wr, mem_sp;
+
 	// Instruction decoding
 	assign instr_op 	= e_instr'(instr[7:4]);
 	assign rd 			= e_reg'(instr[3:2]);
@@ -16,15 +19,19 @@ module controller(instr, zero, alu_op, alu_ex, mem_wr, reg_wr, pc_src, rimm, alu
 	e_alu_op alu_subsel;
 	assign alu_subsel = (instr_op == JEQ) ? ALU_SUB : ALU_CPY;
 	assign alu_op = instr_op[3] ? alu_subsel : e_alu_op'(instr_op[2:0]);
-	assign reg_wr = ~instr_op[3] | instr_op == LW; 
+	assign reg_wr = ~instr_op[3] | instr_op == LW | instr_op == POP; 
 	
-	assign mem_wr = instr_op == SW;
-	assign mem_to_reg = instr_op == LW;
+	assign mem_wr = instr_op == SW | instr_op == PUSH;
+	assign mem_to_reg = instr_op == LW | instr_op == POP;
 	assign pc_src = (zero && instr_op == JEQ) | instr_op == JMP;
 	
 	assign alu_src = (instr_op == CPY & rd == rs);	
 	assign rimm = (alu_src) | instr_op == JEQ;	
 	assign alu_ex = e_alu_ext_op'(rs);
+
+	// Stack instructions
+	assign mem_sp = instr_op[0];
+	assign sp_wr = instr_op == PUSH | instr_op == POP;
 endmodule
 
 module controller_tb;

+ 3 - 3
src/cpu.sv

@@ -7,16 +7,16 @@ module cpu(clk, rst, instr, imm, pc, mem_addr, mem_wr_en, mem_wr_data, mem_rd_da
 	output word pc, mem_addr, mem_wr_data;
 
 	// Controller
-	logic alu_zero, pc_src, reg_wr, rimm, alu_src, mem_to_reg;
+	logic alu_zero, pc_src, reg_wr, rimm, alu_src, mem_to_reg, sp_wr, mem_sp;
 	e_instr instr_op;
 	e_reg rd, rs;
 	e_alu_op alu_op;
 	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);
+	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, sp_wr, mem_sp);
 
 	// Datapath
-	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);	
+	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, sp_wr, mem_sp);	
 endmodule
 
 module cpu_tb;

+ 17 - 3
src/datapath.sv

@@ -1,14 +1,18 @@
 import project_pkg::*;
 
-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);
+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, sp_wr, mem_sp);
 	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;
+	input logic sp_wr, mem_sp;
 	output word pc, alu_out, mem_wr_data;
 	output logic alu_zero;
 	
+	word sp, sp_next;
 	// Reg File
 	word reg_rd_d1, reg_rd_d2, reg_wr_d;
 	e_reg reg_rd_a1, reg_rd_a2, reg_wr_a;
@@ -23,10 +27,13 @@ module datapath(clk, rst, rd, rs, imm, alu_op, alu_ex, reg_wr, pc_src, rimm, alu
 
 	// ALU
 	word alu_srcA, alu_srcB;
+	word alu_result;
 	assign alu_srcA = reg_rd_d1;
 	assign alu_srcB = alu_src ? imm : reg_rd_d2;
-	alu ALU(alu_op, alu_ex, alu_srcA, alu_srcB, alu_out, alu_zero);
-	
+	word sp_sel;
+	assign sp_sel = (mem_sp) ? sp_next : sp;
+	assign alu_out = (sp_wr) ? sp_sel : alu_result;
+	alu ALU(alu_op, alu_ex, alu_srcA, alu_srcB, alu_result, alu_zero);	
 	// Program counter
 	word pcn; 	// PC next
 	word pcj;   // PC jump, +2 if imm used otherwise +1
@@ -39,6 +46,13 @@ module datapath(clk, rst, rd, rs, imm, alu_op, alu_ex, reg_wr, pc_src, rimm, alu
 	  	if (rst) pc <= 0;
 		else pc <= pcn;
 	end
+	
+	always_ff@(posedge clk) begin
+		if (rst) sp <= 8'hff;
+		if (sp_wr) sp <= sp_next;
+	end
+	// Optimise this
+	assign sp_next = (mem_sp) ? sp + 1 : sp - 1;
 endmodule
 
 module datapath_tb;

+ 12 - 0
tools/asm_compiler.py

@@ -136,6 +136,14 @@ def assemble(file):
             iname = 'JUMP'
             rops = 2
             inibb = 11
+        elif instr == 'PUSH':
+            iname = 'PUSH'
+            rops = 2
+            inibb = 14
+        elif instr == 'POP':
+            iname = 'POP'
+            rops = 2
+            inibb = 15
         else:
             if len(ops) == 1:
                 try:
@@ -174,6 +182,10 @@ def assemble(file):
                 odata.append(int(imm))
                 continue
 
+            if iname == 'PUSH' or iname == 'POP':
+                odata.append((inibb << 4) | (rd << 2) | rd)
+                continue
+
             rs = decode_reg(ops[2])
             if iname == 'COPY' and rd == rs:
                 print(f"{file}:{lnum}: {iname} cannot copy register to itself")