Quellcode durchsuchen

Control Block Updates

Created script to convert csv table to verilog casez list. This allowed
to generated control block. Changed risc instruction to correspond to
this new casez list with high impediance values at places where 1 or 2
operrands are at.
Min vor 6 Jahren
Ursprung
Commit
a7515eb5dd
10 geänderte Dateien mit 1071 neuen und 308 gelöschten Zeilen
  1. 2 1
      UCL_project_y3.qsf
  2. 13 12
      src/blocks/alu.sv
  3. 2 2
      src/blocks/instr_mem.sv
  4. 50 0
      src/risc/controller.csv
  5. 504 140
      src/risc/controller.sv
  6. 42 27
      src/risc/cpu.sv
  7. 166 94
      src/risc/datapath.sv
  8. 204 30
      src/risc/general.sv
  9. 1 2
      src/top.sv
  10. 87 0
      tools/gen_sv.py

+ 2 - 1
UCL_project_y3.qsf

@@ -125,6 +125,7 @@ set_location_assignment PIN_R8 -to CLK50
 set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
 set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
 set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+set_global_assignment -name VERILOG_FILE src/blocks/alu.v
 set_global_assignment -name SYSTEMVERILOG_FILE src/project.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/top.sv
 set_global_assignment -name VERILOG_FILE src/blocks/fifo.v
@@ -139,6 +140,6 @@ set_global_assignment -name VERILOG_FILE src/blocks/uart.v
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/instr_mem.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/reg_file.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/memory.sv
-set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/alu.sv
 set_global_assignment -name QIP_FILE quartus/pll_clk.qip
+set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/alu.sv
 set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

+ 13 - 12
src/blocks/alu.sv

@@ -1,6 +1,7 @@
 package alu_pkg;
 
 	typedef enum logic [3:0] {
+		 ALU_NONE= 4'bxxxx, 
 		 ALU_ADD = 4'd0, 
 		 ALU_SUB = 4'd1,
 		 ALU_AND = 4'd2,
@@ -11,8 +12,8 @@ package alu_pkg;
 		 ALU_XNOR= 4'd7,
 		 ALU_SL  = 4'd8,
 		 ALU_SR  = 4'd9,
-		 ALU_ROR = 4'd10,
-		 ALU_ROL = 4'd11,
+		 ALU_RA  = 4'd10,
+		 ALU_RAS = 4'd11,
 		 ALU_MUL = 4'd12,
 		 ALU_DIV = 4'd13,
 		 ALU_MOD = 4'd14
@@ -24,7 +25,7 @@ endpackage
 import alu_pkg::*;
 
 module alu(
-	a, b, r, op, cin, sign, zero, cout, gt, eq, overflow
+	a, b, r, r_high, op, cin, sign, zero, cout, gt, eq, overflow
 );
 	parameter WORD=8;
 	localparam WSIZE=$clog2(WORD);
@@ -34,7 +35,7 @@ module alu(
 	input logic [WORD-1:0] 	a, b;
 	
 	output logic 			zero, cout, gt, eq, overflow;
-	output logic [WORD-1:0] r;
+	output logic [WORD-1:0] r, r_high;
 	
 	logic [WSIZE-1:0] shmt;
 	assign shmt = b[WSIZE-1:0];
@@ -62,8 +63,8 @@ module alu(
 
 	always_comb begin
 	case(op)
-		ALU_ADD: r = a + b + cin;
-		ALU_SUB: r = a - b - cin;
+		ALU_ADD: {r,cout} = a + b + cin;
+		ALU_SUB: {r,cout} = a - b - cin;
 		ALU_AND: r = a & b;
 		ALU_OR : r = a | b;
 		ALU_XOR: r = a ^ b;
@@ -72,10 +73,10 @@ module alu(
 		ALU_XNOR: r = ~(a ^ b);
 		ALU_SL: r = a << shmt;
 		ALU_SR: r = (sign) ? sr : a >> shmt;
-		ALU_ROL: r = {a[0], a[WORD-1:1]};
-		ALU_ROR: r = {a[WORD-2:0], a[WORD-1]};
-		ALU_MUL: r = a * b;
-		ALU_DIV: r = a / b;
+		ALU_RA: r = {a[0], a[WORD-1:1]};
+		ALU_RAS: r = {a[WORD-2:0], a[WORD-1]};
+		ALU_MUL: {r_high, r} = a * b;
+		ALU_DIV: {r, r_high} = {a / b, a % b};
 		ALU_MOD: r = a % b;
 		default: r = 0;
 	endcase
@@ -191,8 +192,8 @@ module alu_tb;
 		test(ALU_SUB, -10, 20, -30, 0, 0);
 		testb(ALU_SUB, -10, 20, -30, 0, 0);
 		
-		testb(ALU_ROR, 8'b1100_0000, 0, 8'b1000_0001, 0, 0);
-		testb(ALU_ROL, 8'b0000_0011, 0, 8'b1000_0001, 0, 0);
+		testb(ALU_RA, 8'b1100_0000, 0, 8'b1000_0001, 0, 0);
+		testb(ALU_RAS, 8'b0000_0011, 0, 8'b1000_0001, 0, 0);
 		test(ALU_MUL, 5, 8, 40, 0, 0);
 		testb(ALU_MUL, -5, 8, -40, 0, 0);
 		test(ALU_DIV, 64, 4, 16, 0, 0);

+ 2 - 2
src/blocks/instr_mem.sv

@@ -11,9 +11,9 @@ module instr_mem(addr, instr, imm);
 	initial $readmemh(IMEM_FILE, rom);
 	initial begin
 		 $display("Instruction ROM dump");
-		 for (int i=0; i < rom_size; i+=16) begin
+		 for (int i=0; i < LENGTH; i+=16) begin
 			$write("%h:", i);
-			for(int j=0; j<16 && j+i < rom_size; j++)
+			for(int j=0; j<16 && j+i < LENGTH; j++)
 		 		$write(" %h", rom[i+j]);
 			$display(" :%h", i);
 		end

+ 50 - 0
src/risc/controller.csv

@@ -0,0 +1,50 @@
+ instr_op, cdi.alu_op, cdi.selb, cdi.rw_en, cdi.selr, mem_rd, mem_wr
+     MOVE,   ALU_NONE,      SB_NONE,         1,     SR_COM,      0,      0
+     CPY0,   ALU_NONE,       SB_IMM,         1,     SR_IMM,      0,      0
+     CPY1,   ALU_NONE,       SB_IMM,         1,     SR_IMM,      0,      0
+     CPY2,   ALU_NONE,       SB_IMM,         1,     SR_IMM,      0,      0
+     CPY3,   ALU_NONE,       SB_IMM,         1,     SR_IMM,      0,      0
+         ,           ,             ,          ,           ,      0,      0
+      ADD,    ALU_ADD,       SB_REG,         1,    SR_ALUL,      0,      0
+      SUB,    ALU_SUB,       SB_REG,         1,    SR_ALUL,      0,      0
+      AND,    ALU_AND,       SB_REG,         1,    SR_ALUL,      0,      0
+       OR,     ALU_OR,       SB_REG,         1,    SR_ALUL,      0,      0
+      XOR,    ALU_XOR,       SB_REG,         1,    SR_ALUL,      0,      0
+      MUL,    ALU_MUL,       SB_REG,         1,    SR_ALUL,      0,      0
+      DIV,    ALU_DIV,       SB_REG,         1,    SR_ALUL,      0,      0
+       BR,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+         ,           ,             ,          ,           ,      0,      0
+      SLL,     ALU_SL,       SB_REG,         1,    SR_ALUL,      0,      0
+      SRL,     ALU_SR,       SB_REG,         1,    SR_ALUL,      0,      0
+      SRA,     ALU_RA,       SB_REG,         1,    SR_ALUL,      0,      0
+     SRAS,    ALU_RAS,       SB_REG,         1,    SR_ALUL,      0,      0
+         ,           ,             ,          ,           ,      0,      0
+     LWHI,   ALU_NONE,      SB_NONE,         1,    SR_MEMH,      0,      1
+     SWHI,   ALU_NONE,      SB_NONE,         0,    SR_NONE,      1,      0
+     LWLO,   ALU_NONE,      SB_NONE,         1,    SR_MEML,      0,      1
+     SWLO,   ALU_NONE,      SB_NONE,         0,    SR_NONE,      1,      0
+         ,           ,             ,          ,           ,      0,      0
+      INC,    ALU_ADD,         SB_1,         1,    SR_ALUL,      0,      0
+      DEC,    ALU_SUB,         SB_1,         1,    SR_ALUL,      0,      0
+    GETAH,   ALU_NONE,      SB_NONE,         1,    SR_ALUH,      0,      0
+    GETIF,   ALU_NONE,      SB_NONE,         1,    SR_INTR,      0,      0
+         ,           ,             ,          ,           ,      0,      0
+     PUSH,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      POP,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      COM,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+         ,           ,             ,          ,           ,      0,      0
+     CALL,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      RET,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     JUMP,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     RETI,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      CLC,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     SETC,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      CLS,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     SETS,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+    SSETS,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+      CLN,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     SETN,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+    SSETN,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+    RJUMP,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+     RBWI,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0
+  default,   ALU_NONE,      SB_NONE,         x,    SR_NONE,      0,      0

+ 504 - 140
src/risc/controller.sv

@@ -1,148 +1,512 @@
-import risc_pkg::*;
+import risc8_pkg::*;
 import alu_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, sp_wr, mem_sp);
-	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;
-	output logic sp_wr, mem_sp;
-
+module controller8(
+		input word instr,
+		risc8_cdi.control cdi,
+		output mem_wr, mem_rd	
+);
 	// Instruction decoding
 	assign instr_op 	= e_instr'(instr[7:4]);
-	assign rd 			= e_reg'(instr[3:2]);
-	assign rs 			= e_reg'(instr[1:0]);
-	
-	e_alu_op alu_subsel;
-	//assign alu_subsel = (instr_op == JEQ) ? ALU_SUB : ALU_CPY;
-	assign alu_subsel = (instr_op == JEQ) ? ALU_SUB: ALU_ADD;
-	assign alu_op = instr_op[3] ? alu_subsel : e_alu_op'(instr_op[2:0]);
-	assign reg_wr = ~instr_op[3] | instr_op == LW | instr_op == POP; 
-	
-	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
+	assign cdi.a1		= e_reg_addr'(instr[3:2]);
+	assign cdi.a2		= e_reg_addr'(instr[1:0]);
+	assign cdi.a3 		= cdi.a1; // Assuming destination always first operand
 
-module controller_tb;
-	word instr;
-	logic zero, mem_wr, reg_wr, alu_src, mem_to_reg, pc_src;
-	e_alu_op alu_op;
+	// generated table
+    always_comb begin
+    casez(instr_op)
+        MOVE   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_COM;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CPY0   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_IMM;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_IMM;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CPY1   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_IMM;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_IMM;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CPY2   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_IMM;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_IMM;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CPY3   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_IMM;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_IMM;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        ADD    : begin
+            cdi.alu_op = ALU_ADD;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SUB    : begin
+            cdi.alu_op = ALU_SUB;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        AND    : begin
+            cdi.alu_op = ALU_AND;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        OR     : begin
+            cdi.alu_op = ALU_OR;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        XOR    : begin
+            cdi.alu_op = ALU_XOR;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        MUL    : begin
+            cdi.alu_op = ALU_MUL;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        DIV    : begin
+            cdi.alu_op = ALU_DIV;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        BR     : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SLL    : begin
+            cdi.alu_op = ALU_SL;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SRL    : begin
+            cdi.alu_op = ALU_SR;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SRA    : begin
+            cdi.alu_op = ALU_RA;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SRAS   : begin
+            cdi.alu_op = ALU_RAS;
+            cdi.selb   = SB_REG;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        LWHI   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_MEMH;
+            mem_rd     = 0;
+            mem_wr     = 1;
+        end
+        SWHI   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 0;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 1;
+            mem_wr     = 0;
+        end
+        LWLO   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_MEML;
+            mem_rd     = 0;
+            mem_wr     = 1;
+        end
+        SWLO   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 0;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 1;
+            mem_wr     = 0;
+        end
+        INC    : begin
+            cdi.alu_op = ALU_ADD;
+            cdi.selb   = SB_1;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        DEC    : begin
+            cdi.alu_op = ALU_SUB;
+            cdi.selb   = SB_1;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUL;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        GETAH  : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_ALUH;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        GETIF  : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1;
+            cdi.selr   = SR_INTR;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        PUSH   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        POP    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        COM    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CALL   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        RET    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        JUMP   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        RETI   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CLC    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SETC   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CLS    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SETS   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SSETS  : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        CLN    : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SETN   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        SSETN  : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        RJUMP  : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        RBWI   : begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+        default: begin
+            cdi.alu_op = ALU_NONE;
+            cdi.selb   = SB_NONE;
+            cdi.rw_en  = 1'bx;
+            cdi.selr   = SR_NONE;
+            mem_rd     = 0;
+            mem_wr     = 0;
+        end
+    endcase
+    end
+	// generated table end
 
-	controller CTR(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_reg);
-
-	initial begin
-		instr = 8'h00;
-		zero = 1;
-		#5ns;
-		//assert(alu_op == ALU_NOP);
-		assert(mem_wr == 0);
-		assert(reg_wr == 0);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h10;
-		#5ns;
-		assert(alu_op == ALU_ADD);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h20;
-		#5ns;
-		assert(alu_op == ALU_ADD);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 1);
-		assert(mem_to_reg == 0);
-		instr = 8'h30;
-		#5ns;
-		assert(alu_op == ALU_SUB);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h40;
-		#5ns;
-		assert(alu_op == ALU_AND);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h50;
-		#5ns;
-		assert(alu_op == ALU_OR);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h60;
-		#5ns;
-		//assert(alu_op == ALU_NOT);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'h70;
-		#5ns;
-		//assert(alu_op == ALU_NOP);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 1);
-		instr = 8'h80;
-		#5ns;
-		//assert(alu_op == ALU_NOP);
-		assert(mem_wr == 1);
-		assert(reg_wr == 0);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'hB0;
-		#5ns;
-		//assert(alu_op == ALU_NOP);
-		assert(mem_wr == 0);
-		assert(reg_wr == 1);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		instr = 8'hC0;
-		#5ns;
-		assert(alu_op == ALU_SUB);
-		assert(mem_wr == 0);
-		assert(reg_wr == 0);
-		assert(pc_src == 1);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-		zero = 0;
-		#5ns;
-		assert(alu_op == ALU_SUB);
-		assert(mem_wr == 0);
-		assert(reg_wr == 0);
-		assert(pc_src == 0);
-		assert(alu_src == 0);
-		assert(mem_to_reg == 0);
-
-		$stop;
-	end
 endmodule
 
+//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;
+//	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;
+//	output logic sp_wr, mem_sp;
+//
+//	// Instruction decoding
+//	assign instr_op 	= e_instr'(instr[7:4]);
+//	assign rd 			= e_reg'(instr[3:2]);
+//	assign rs 			= e_reg'(instr[1:0]);
+//	
+//	e_alu_op alu_subsel;
+//	//assign alu_subsel = (instr_op == JEQ) ? ALU_SUB : ALU_CPY;
+//	assign alu_subsel = (instr_op == JEQ) ? ALU_SUB: ALU_ADD;
+//	assign alu_op = instr_op[3] ? alu_subsel : e_alu_op'(instr_op[2:0]);
+//	assign reg_wr = ~instr_op[3] | instr_op == LW | instr_op == POP; 
+//	
+//	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;
+//	word instr;
+//	logic zero, mem_wr, reg_wr, alu_src, mem_to_reg, pc_src;
+//	e_alu_op alu_op;
+//
+//	controller CTR(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_reg);
+//
+//	initial begin
+//		instr = 8'h00;
+//		zero = 1;
+//		#5ns;
+//		//assert(alu_op == ALU_NOP);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 0);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h10;
+//		#5ns;
+//		assert(alu_op == ALU_ADD);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h20;
+//		#5ns;
+//		assert(alu_op == ALU_ADD);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 1);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h30;
+//		#5ns;
+//		assert(alu_op == ALU_SUB);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h40;
+//		#5ns;
+//		assert(alu_op == ALU_AND);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h50;
+//		#5ns;
+//		assert(alu_op == ALU_OR);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h60;
+//		#5ns;
+//		//assert(alu_op == ALU_NOT);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'h70;
+//		#5ns;
+//		//assert(alu_op == ALU_NOP);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 1);
+//		instr = 8'h80;
+//		#5ns;
+//		//assert(alu_op == ALU_NOP);
+//		assert(mem_wr == 1);
+//		assert(reg_wr == 0);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'hB0;
+//		#5ns;
+//		//assert(alu_op == ALU_NOP);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 1);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		instr = 8'hC0;
+//		#5ns;
+//		assert(alu_op == ALU_SUB);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 0);
+//		assert(pc_src == 1);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//		zero = 0;
+//		#5ns;
+//		assert(alu_op == ALU_SUB);
+//		assert(mem_wr == 0);
+//		assert(reg_wr == 0);
+//		assert(pc_src == 0);
+//		assert(alu_src == 0);
+//		assert(mem_to_reg == 0);
+//
+//		$stop;
+//	end
+//endmodule
+

+ 42 - 27
src/risc/cpu.sv

@@ -1,37 +1,52 @@
 `timescale 1ns / 100ps
-import risc_pkg::*;
+import risc8_pkg::*;
 import alu_pkg::*;
 
-module risc8_cpu(clk, rst, instr, imm, pc, mem_addr, mem_wr_en, mem_wr_data, mem_rd_data);
-	input logic clk, rst;
-	input word instr, imm, mem_rd_data;
-	output logic mem_wr_en;
-	output word pc, mem_addr, mem_wr_data;
+//module risc8_cpu(clk, rst, instr, imm, pc, mem_addr, mem_wr_en, mem_wr_data, mem_rd_data);
+//	input logic clk, rst;
+//	input word instr, imm, mem_rd_data;
+//	output logic mem_wr_en;
+//	output word pc, mem_addr, mem_wr_data;
+//	
+//
+//
+//	//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, sp_wr, mem_sp);	
+//endmodule
 
-	// Controller
-	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, 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, sp_wr, mem_sp);	
-endmodule
-
-module risc8_port(processor_port port);
-	logic clk, rst, mem_wr; 
-	word pc, instr, imm, mem_addr, mem_data, mem_rd_data;
+module risc8_cpu(processor_port port);
+	//logic clk, rst, mem_wr; 
+	//word pc, instr, imm, mem_addr, mem_data, mem_rd_data;
 	
-	assign port.ram_wr_en = mem_wr;
-	assign port.ram_rd_en = ~mem_wr;
+	//assign port.ram_wr_en = mem_wr;
+	//assign port.ram_rd_en = ~mem_wr;
 
-	instr_mem #("/home/min/devel/fpga/ucl_project_y3/memory/test.mem") imem0(pc, instr, imm);
+	//instr_mem #("/home/min/devel/fpga/ucl_project_y3/memory/test.mem") imem0(pc, instr, imm);
+	
+	//risc8_cpu cpu0(port.clk, port.rst, instr, imm, pc,
+	//		port.ram_addr, mem_wr, port.ram_wr_data, port.ram_rd_data);
 	
-	risc8_cpu cpu0(port.clk, port.rst, instr, imm, pc,
-			port.ram_addr, mem_wr, port.ram_wr_data, port.ram_rd_data);
+	word instr, imm0, imm1, imm2;
+	assign imm0 = 8'h00;
+	assign instr = 8'h00;
+
+	risc8_cdi cdi0();
+	controller8 ctrl0(
+			.instr(instr),
+			.cdi(cdi0),
+			.mem_wr(port.ram_wr_en),
+			.mem_rd(port.ram_rd_en)
+	);
+	datapath8 dpath0(
+			.clk(port.clk),
+			.rst(port.rst),
+			.cdi(cdi0),
+			.imm(imm0),
+			.mem_rd(port.ram_rd_data),
+			.mem_wr(port.ram_wr_data)
+	);
 
 endmodule
 

+ 166 - 94
src/risc/datapath.sv

@@ -1,110 +1,182 @@
-import risc_pkg::*;
+import risc8_pkg::*;
 import alu_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, 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;
+
+module datapath8(
+		input logic clk, rst, interrupt,
+		risc8_cdi.datapath cdi,
+		input  word imm, com_rd,
+		output word com_wr, com_addr,
+		input  [15:0] mem_rd,
+		output [15:0] mem_wr
+);
 	
-	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;
-	assign reg_rd_a1 = rd;
-	assign reg_rd_a2 = rs;
-	assign reg_wr_a = rd;
-	assign reg_wr_d = (mem_to_reg) ? mem_data : alu_out;
-	reg_file RFILE(clk, rst, reg_rd_a1, reg_rd_a2, reg_rd_d1, reg_rd_d2, reg_wr_a, reg_wr_d, reg_wr);
+	word r1, r2, reg_wr;
+
+	reg_file reg0(.clk(clk), .rst(rst), 
+			.rd_addr1(cdi.a1),
+			.rd_addr2(cdi.a2),
+			.rd_data1(r1),
+			.rd_data2(r2),
+			.wr_addr(cdi.a3),
+			.wr_data(reg_wr),
+			.wr_en(cdi.rw_en)
+	);
 
-	// Mem output data
-	assign mem_wr_data = reg_rd_d1;
+	word srcA, srcB, alu_rlo, alu_rhi;
+	logic cout, cin, alu_eq, alu_gt, alu_zero;
+	assign cdi.alu_comp = {alu_eq, alu_gt, alu_zero};
 
-	// ALU
-	word alu_srcA, alu_srcB;
-	word alu_result;
-	assign alu_srcA = reg_rd_d1;
-	assign alu_srcB = alu_src ? imm : reg_rd_d2;
-	word sp_sel;
-	assign sp_sel = (mem_sp) ? sp_next : sp;
-	assign alu_out = (sp_wr) ? sp_sel : alu_result;
 	alu#(.WORD(8)) alu0(
 		.a(alu_srcA),
 		.b(alu_srcB),
-		.op(alu_op),
-		.r(alu_result),
-		.zero(alu_zero)
+		.op(e_alu_op'(alu_op)),
+		.r(alu_rlo),
+		.r_high(alu_rhi),
+		.zero(alu_zero),
+		.eq(alu_eq),
+		.gt(alu_gt),
+		.cin(cin), .cout(cout),
+		.sign(cdi.sign)
+		// TODO: missing overflow
 	);
-	//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
-	logic [0:1]pcadd;
-	assign pcadd = (rimm) ? 2 : 1;
-	assign pcj =  pc + pcadd;
-	//assign pcj = pc + 1;
-	assign pcn = (pc_src) ? imm : pcj;
-	always_ff@(posedge clk) begin
-	  	if (rst) pc <= 0;
-		else pc <= pcn;
-	end
 	
+	word interrupt_flag;
 	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;
-	logic clk, rst, reg_wr, pc_src, rimm, mem_to_reg, alu_zero;
-	e_reg rs, rt;
-	e_alu_op alu_op;
-	word imm, mem_data, pc, alu_out;
-	datapath DPATH(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, rimm, mem_to_reg, pc, alu_out, mem_data, alu_zero);
-
-	initial begin
-		clk = 0;
-		forever #5ns clk = ~clk;
+		if(rst) interrupt_flag <= 0;
+		else if(interrupt) interrupt_flag <= com_rd;
 	end
+	
+	assign srcA = r1;
+	always_comb begin
+		case(cdi.selb)
+			SB_REG : srcB = r2;
+			SB_0   : srcB = 8'h00;
+			SB_1   : srcB = 8'h01;
+			SB_IMM : srcB = imm;
+			default: srcB = r2;
+		endcase
 
-	initial begin
-		rst = 1;
-		reg_wr = 0;
-		pc_src = 0;
-		rimm = 0;
-		mem_to_reg = 0;
-		rs = ra;
-		rt = ra;
-		//alu_op = ALU_CPY;
-		imm = 8'h00;
-		mem_data = 8'h00;
-		#10ns;
-		rst = 0;
-		reg_wr = 1;
-		mem_to_reg = 1;
-		mem_data = 8'h7A;
-		#10ns;
-		rs = rb;
-		mem_data = 8'h8A;
-		#10ns;
-		rs = rc;
-		mem_data = 8'h9A;
-		#10ns;
-		rs = re;
-		mem_data = 8'hFD;
-		#10ns;
-		rs = ra;
-		#10ns;
-		$stop;
+		case(cdi.selr)
+			SR_MEML: reg_wr = mem_rd[7:0];
+			SR_MEMH: reg_wr = mem_rd[15:8];
+			SR_ALUL: reg_wr = alu_rlo;
+			SR_ALUH: reg_wr = alu_rhi;
+			SR_IMM : reg_wr = imm;
+			SR_COM : reg_wr = com_rd;
+			SR_INTR: reg_wr = interrupt_flag;
+			default: reg_wr = alu_rlo;
+		endcase
 	end
 
-
 endmodule
+
+//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;
+//	assign reg_rd_a1 = rd;
+//	assign reg_rd_a2 = rs;
+//	assign reg_wr_a = rd;
+//	assign reg_wr_d = (mem_to_reg) ? mem_data : alu_out;
+//	reg_file RFILE(clk, rst, reg_rd_a1, reg_rd_a2, reg_rd_d1, reg_rd_d2, reg_wr_a, reg_wr_d, reg_wr);
+//
+//	// Mem output data
+//	assign mem_wr_data = reg_rd_d1;
+//
+//	// ALU
+//	word alu_srcA, alu_srcB;
+//	word alu_result;
+//	assign alu_srcA = reg_rd_d1;
+//	assign alu_srcB = alu_src ? imm : reg_rd_d2;
+//	word sp_sel;
+//	assign sp_sel = (mem_sp) ? sp_next : sp;
+//	assign alu_out = (sp_wr) ? sp_sel : alu_result;
+//	alu#(.WORD(8)) alu0(
+//		.a(alu_srcA),
+//		.b(alu_srcB),
+//		.op(alu_op),
+//		.r(alu_result),
+//		.zero(alu_zero)
+//	);
+//	
+//	// Program counter
+//	word pcn; 	// PC next
+//	word pcj;   // PC jump, +2 if imm used otherwise +1
+//	logic [0:1]pcadd;
+//	assign pcadd = (rimm) ? 2 : 1;
+//	assign pcj =  pc + pcadd;
+//	//assign pcj = pc + 1;
+//	assign pcn = (pc_src) ? imm : pcj;
+//	always_ff@(posedge clk) begin
+//	  	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;
+//	logic clk, rst, reg_wr, pc_src, rimm, mem_to_reg, alu_zero;
+//	e_reg rs, rt;
+//	e_alu_op alu_op;
+//	word imm, mem_data, pc, alu_out;
+//	datapath DPATH(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, rimm, mem_to_reg, pc, alu_out, mem_data, alu_zero);
+//
+//	initial begin
+//		clk = 0;
+//		forever #5ns clk = ~clk;
+//	end
+//
+//	initial begin
+//		rst = 1;
+//		reg_wr = 0;
+//		pc_src = 0;
+//		rimm = 0;
+//		mem_to_reg = 0;
+//		rs = ra;
+//		rt = ra;
+//		//alu_op = ALU_CPY;
+//		imm = 8'h00;
+//		mem_data = 8'h00;
+//		#10ns;
+//		rst = 0;
+//		reg_wr = 1;
+//		mem_to_reg = 1;
+//		mem_data = 8'h7A;
+//		#10ns;
+//		rs = rb;
+//		mem_data = 8'h8A;
+//		#10ns;
+//		rs = rc;
+//		mem_data = 8'h9A;
+//		#10ns;
+//		rs = re;
+//		mem_data = 8'hFD;
+//		#10ns;
+//		rs = ra;
+//		#10ns;
+//		$stop;
+//	end
+//
+//
+//endmodule

+ 204 - 30
src/risc/general.sv

@@ -1,8 +1,130 @@
-package risc_pkg;
+import alu_pkg::*;
+
+interface risc8_cdi;  // Control Datapath interface
+	
+	// ALU
+	e_alu_op alu_op;
+	logic sign, alu_not;
+	e_selb selb;
+	logic [2:0] alu_comp;
+	
+	// Register
+	reg_addr a1, a2, a3;
+	logic rw_en, mem_h;
+	e_selr selr;
+	
+	modport datapath(
+		input alu_op, selb, sign, alu_not,
+		output alu_comp,
+		input a1, a2, a3, rw_en, selr, mem_h
+	);
+	
+	modport control(
+		output alu_op, selb, sign, alu_not,
+		input alu_comp,
+		output a1, a2, a3, rw_en, selr, mem_h
+	);
+
+endinterface
+
+
+package risc8_pkg;
+
+	localparam word_size = 8;
+	localparam reg_size = 4;
+
+	localparam reg_addr_size = $clog2(reg_size);
+	typedef logic [word_size-1:0] word;
+	typedef logic [reg_addr_size-1:0] reg_addr;
+
+	typedef enum logic [7:0] { 
+		// [ xxxx xx xx ] => [ inst rd rs ]
+		// mp: Memory page
+		// cp: Co-processor, 0x00 = RAM, 0x01 = ROM, 0x02 = FPU, 0x03 = GPIO
+		MOVE =8'b0000_????,  // &rd = &rs
+		CPY0 =8'b0000_0000,  // &rd = imm
+		CPY1 =8'b0000_0101,  // &rd = imm
+		CPY2 =8'b0000_1010,  // &rd = imm
+		CPY3 =8'b0000_1111,  // &rd = imm
+
+		ADD  =8'b0001_????,  // &rd = &rd + &rs
+		SUB  =8'b0010_????,  // &rd = &rd - &rs
+		AND  =8'b0011_????,  // &rd = &rd & &rsgt
+		OR   =8'b0100_????,  // &rd = &rd | &rs
+		XOR  =8'b0101_????,  // &rd = &rd ^ &rs
+		MUL  =8'b0110_????,  // {&ah,  &rd} = &rd * &rs
+		DIV  =8'b0111_????,  // &rd = &rd / &rs, &ah = &rd % &rs 
+		BR   =8'b1000_????,  // Conditional branch
+		
+		SLL  =8'b1001_??00,  // i9-0 shift left logical
+		SRL  =8'b1001_??01,  // i9-1 shift right logical
+		SRA  =8'b1001_??10,  // i9-2 shift right arithmetic
+		SRAS =8'b1001_??11,  // i9-3 shift rigth arithmetic signed
+
+		LWHI =8'b1010_??00,  // i10-0 
+		SWHI =8'b1010_??01,  // i10-1 
+		LWLO =8'b1010_??10,  // i10-2 
+		SWLO =8'b1010_??11,  // i10-3 
+		
+		INC  =8'b1011_??00,  // i11-0 
+		DEC  =8'b1011_??01,  // i11-1 
+		GETAH=8'b1011_??10,  // i11-2 
+		GETIF=8'b1011_??11,  // i11-3 
+		
+		PUSH =8'b1100_??00,  // i12-0
+        POP  =8'b1100_??01,  // i12-1 
+        COM  =8'b1100_??10,  // i12-2 
+		
+		CALL =8'b1111_0000,  // i15-0
+        RET  =8'b1111_0001,  // i15-1
+        JUMP =8'b1111_0010,  // i15-2
+        RETI =8'b1111_0011,  // i15-3
+        CLC  =8'b1111_0100,  // i15-4
+        SETC =8'b1111_0101,  // i15-5
+        CLS  =8'b1111_0110,  // i15-6
+        SETS =8'b1111_0111,  // i15-7
+        SSETS=8'b1111_1000,  // i15-8
+        CLN  =8'b1111_1001,  // i15-9
+        SETN =8'b1111_1010,  // i15-10
+        SSETN=8'b1111_1011,  // i15-11
+        RJUMP=8'b1111_1100,  // i15-12
+        RBWI =8'b1111_1101,  // i15-13 Replace ALU src B with immediate
+        i254 =8'b1111_1110,  // i15-14
+        i255 =8'b1111_1111   // i15-15
+		
+	} e_instr;               
+
+	typedef enum logic [1:0] {
+		SB_NONE= 2'bxx,
+		SB_REG = 2'b00,
+		SB_0   = 2'b01,
+		SB_1   = 2'b10,
+		SB_IMM = 2'b11
+	} e_selb;
+
+	typedef enum logic [2:0] {
+		SR_NONE= 3'bxxx,
+		SR_MEML= 3'b001,
+		SR_MEMH= 3'b010,
+		SR_ALUL= 3'b011,
+		SR_ALUH= 3'b100,
+		SR_IMM = 3'b101,
+		SR_COM = 3'b110,
+		SR_INTR= 3'b111
+	} e_selr;
+
+	typedef enum logic [1:0] {
+		REG0  = 2'b00,
+		REG1  = 2'b01,
+		REG2  = 2'b10,
+		REG3  = 2'b11
+	} e_reg_addr;
+
+endpackage
+
+package risc8x_pkg;
 		
 	localparam word_size = 8;
-	localparam mem_size = 256;
-	localparam rom_size = 256;
 	localparam reg_size = 4;
 
 	localparam reg_addr_size = $clog2(reg_size);
@@ -16,33 +138,85 @@ package risc_pkg;
 		re = 2'b11
 	} e_reg;
 	
-	typedef enum logic [3:0] { 
-		// [ xxxx xx xx ] => [ inst rd rs ]
-		// mp: Memory page
-		// cp: Co-processor, 0x00 = RAM, 0x01 = ROM, 0x02 = FPU, 0x03 = GPIO
-		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 & $rsgt
-		OR  =4'b0100,  // $rd = $rd | $rs
-		XOR =4'b0101,  // $rd = $rd ^ $rs
-		GT  =4'b0110,  // $rd = $rd > $rs
-		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
-		JMP =4'b1011,  // Jump to case rs 00: $rd  01: imm 10: $rd+imm 11: ??
-		SET =4'b1100,  // Set memory page $mp = $rd
-		SCO =4'b1101,  // Set co-processor $cp = $rs
-		PUSH=4'b1110,  // Push $rd to top of stack
-		POP =4'b1111   // Pop stack to $rd
+	typedef enum logic [5:0] { 
+		// [ xxxxxx xx xx xxxxxx ] => [ inst rd rs arg ]
+		// [ xxxxxx xx xxxxxxx 	 ] => [ inst rd imm    ]
+		
+		// Arithmetic
+		ADD  = 6'b0000_00,  // 0
+		ADDI = 6'b0000_01,  // 1
+		ADDU = 6'b0000_10,  // 2
+		ADDUI= 6'b0000_11,  // 3
+		SUB  = 6'b0001_00,  // 4
+		SUBI = 6'b0001_01,  // 5
+		SUBU = 6'b0001_10,  // 6
+		SUBUI= 6'b0001_11,  // 7
+		INC  = 6'b0010_00,  // 8
+		DEC  = 6'b0010_01,  // 9
+		MUL  = 6'b0010_10,  // 10
+		MULI = 6'b0010_11,  // 11
+		DIV  = 6'b0011_00,  // 12
+		DIVI = 6'b0011_01,  // 13
+		MOD  = 6'b0011_10,  // 14
+		MODI = 6'b0011_11,  // 15
+		
+		// Logic
+		AND  = 6'b0100_00,  // 16
+		ANDI = 6'b0100_01,  // 17
+		OR   = 6'b0100_10,  // 18
+		ORI  = 6'b0100_11,  // 19
+		XOR  = 6'b0101_00,  // 20
+		XORI = 6'b0101_01,  // 21
+		SLL  = 6'b0101_10,  // 22
+		_I23 = 6'b0101_11,  // 23
+		SRL  = 6'b0110_00,  // 24
+		_I25 = 6'b0110_01,  // 25
+		SRA  = 6'b0110_10,  // 26
+		_I26 = 6'b0110_11,  // 27
+
+		// Branching
+		BGT  = 6'b0111_00,  // 28
+		BGE  = 6'b0111_01,  // 29
+		BEQ  = 6'b0111_10,  // 30
+		BLT  = 6'b0111_11,  // 31	
+		BLE  = 6'b1000_00,  // 32
+		BNE  = 6'b1000_01,  // 33
+		BGTZ = 6'b1000_10,  // 34
+		BGEZ = 6'b1000_11,  // 35
+		BEQZ = 6'b1001_00,  // 36
+		BLTZ = 6'b1001_01,  // 37
+		BLEZ = 6'b1001_10,  // 38
+		BNEZ = 6'b1001_11,  // 39
+		BGTI = 6'b1010_00,  // 40
+		BGEI = 6'b1010_01,  // 41
+		BEQI = 6'b1010_10,  // 42
+		BLTI = 6'b1010_11,  // 43
+		BLEI = 6'b1011_00,  // 44
+		BNEI = 6'b1011_01,  // 45
+		JMP  = 6'b1011_10,  // 46
+		RJMP = 6'b1011_11,  // 47
+		
+		// Data move
+		SWLO = 6'b1100_00,  // 48
+		SWHI = 6'b1100_01,  // 49
+		LWLO = 6'b1100_10,  // 50
+		LWHI = 6'b1100_11,  // 51
+		PUSH = 6'b1101_00,  // 52
+		POP  = 6'b1101_01,  // 53
+		CALL = 6'b1101_10,  // 54
+		RET  = 6'b1101_11,  // 55
+		
+		RETI = 6'b1110_00,  // 56
+		MOV  = 6'b1110_01,  // 57
+		COM  = 6'b1110_10,  // 58
+		COMI = 6'b1110_11,  // 59	
+		IFLAG= 6'b1111_00,  // 60
+
+		// Special
+		HALT = 6'b1111_01,  // 61
+		_I62 = 6'b1111_10,  // 62
+		_I63 = 6'b1111_11  // 63
+
 	} e_instr;
 
-	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

+ 1 - 2
src/top.sv

@@ -26,7 +26,6 @@ module top(
 	output			DRAM_RAS_N, // Row Address Strobe
 	output			DRAM_CS_N,	// Chip Select
 	output [1:0] 	DRAM_BA		// Bank Address
-
 	);
 	
 	assign rst = ~KEY[0];
@@ -96,7 +95,7 @@ module top(
 		.com_interrupt(com0_interrupt)
 	);
 
-	risc8_port cpu_port0(port0);
+	risc8_cpu cpu_block0(port0);
 
 	//Communication block
 	wire [7:0] com0_addr, com0_wr, com0_rd;

+ 87 - 0
tools/gen_sv.py

@@ -0,0 +1,87 @@
+import csv
+import sys
+from os import path
+
+
+def remove(datal, skipl):
+    for skip in skipl:
+        del datal[skip]
+    return datal
+
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        print(f"Invalid arguments, usage: {sys.argv[0]} [input csv] [output verilog]")
+        sys.exit(1)
+
+    if not path.exists(sys.argv[1]):
+        print(f"Input csv does not exist: {sys.argv[1]}")
+        sys.exit(1)
+
+    if not path.exists(sys.argv[2]):
+        print(f"Output verilog does not exist: {sys.argv[1]}")
+        sys.exit(1)
+
+    header = []
+    casename = ''
+    cases = dict()
+    skip = set()
+
+    with open(sys.argv[1]) as csv_file:
+        csv_reader = csv.reader(csv_file, delimiter=',')
+        line_count = 0
+
+        for row in csv_reader:
+            line_count += 1
+            if line_count == 1:
+                casename = row[0].strip() or 'case_name'
+                header = row[1:]
+                for i, head in enumerate(header):
+                    head = head.strip()
+                    if not head:
+                        skip.add(i)
+                    header[i] = head
+                header = remove(header, skip)
+                continue
+            if row[0].strip():
+                cases[row[0].strip()] = list(map(lambda x: x.strip(), remove(row[1:], skip)))
+
+    for arr in cases.values():
+        for i, v in enumerate(arr):
+            if set(v) == {'x'}:
+                arr[i] = f"{len(v)}'b{'_'.join([v[i:i+4] for i in range(0, len(v), 4)])}"
+
+    max_header = max(map(lambda x: len(x), header))
+    max_case = max(map(lambda x: len(x), cases.keys()))
+
+    sv_data = []
+    start_line = 0
+    end_line = 0
+
+    with open(sys.argv[2], 'r') as v_file:
+        line_no = 0
+        for line in v_file.readlines():
+            sv_data.append(line)
+            line_no += 1
+            if line.strip().lower() == '// generated table':
+                start_line = line_no
+            elif line.strip().lower() == '// generated table end':
+                end_line = line_no
+
+    if start_line == 0 or end_line <= start_line:
+        print(f"Failed to find 'generated table' comment in {sys.argv[2]}")
+        sys.exit(1)
+
+    idata = ['\talways_comb begin', f'\tcasez({casename})']
+    for case, value in cases.items():
+        idata.append(f'\t\t{case.ljust(max_case, " ")}: begin')
+        for i, head in enumerate(header):
+            idata.append(f'\t\t\t{head.ljust(max_header, " ")} = {value[i]};')
+        idata.append('\t\tend')
+    idata.append('\tendcase')
+    idata.append('\tend')
+
+    with open(sys.argv[2], 'w') as v_file:
+        v_file.writelines(sv_data[:start_line])
+        v_file.write("\n".join(idata).replace('\t', '    ')+"\n")
+        v_file.writelines(sv_data[end_line-1:])