Ver código fonte

OISC WIP

Changed instructions to 13bit [1: is immedate][4: dst addr][8: src addr/immediate]
Implemented ALU, PC, Memory and Stack
Min 6 anos atrás
pai
commit
3ba774083d
3 arquivos alterados com 505 adições e 285 exclusões
  1. 186 0
      src/oisc/blocks.sv
  2. 166 126
      src/oisc/cpu.sv
  3. 153 159
      src/oisc/oisc.sv

+ 186 - 0
src/oisc/blocks.sv

@@ -0,0 +1,186 @@
+
+module pc_block(IBus bus);
+	parameter PROGRAM = "";
+	reg[15:0] pc, pcn; // Program counter
+
+	reg[15:0] pointer;  // Instruction pointer accumulator
+	reg[7:0] comp_acc;  // Compare accumulator
+	reg comp_acc_rst, comp_zero;
+	/* ====================
+	*       ROM BLOCK
+	   ==================== */
+	`ifdef SYNTHESIS
+	m9k_rom#(
+			.PROGRAM({PROGRAM, ".mif"}), 
+			.NAME("rom0"),
+			.WIDTH(16),
+			.NUMWORDS(2048)
+	)
+	`else
+	pseudo_rom#(
+			.PROGRAM({PROGRAM, ".mem"}), 
+			.WIDTH(16),
+			.NUMWORDS(2048)
+	) 
+	`endif
+		rom0(pcn[11:0], bus.clk, bus.instr);
+	
+	assign comp_zero = comp_acc == 0;
+	assign pcn = comp_zero ? pointer : pc + 1;
+	always_ff@(posedge bus.clk) begin
+		if(bus.rst) begin 
+			pc <= 0;
+			comp_acc_rst <= 0;
+		end
+		else begin 
+			pc <= pcn;
+			comp_acc_rst <= comp_zero;
+		end
+	end
+	/* ====================
+	*      BRANCH PART
+	   ==================== */
+		
+	PortInput #(.ADDR(BRPT0)) p_brpt0_0(
+			.bus(bus),
+			.data_from_bus(pointer[7:0])
+	);
+	PortInput #(.ADDR(BRPT1)) p_brpt1_0(
+			.bus(bus),
+			.data_from_bus(pointer[15:8])
+	);	
+	PortInput #(.ADDR(BRZ), .DEFAULT(8'hFF)) p_brz_0(
+			.bus(bus),
+			.data_from_bus(comp_acc),
+			.reset(comp_acc_rst)
+	);
+
+endmodule
+
+module alu_block(IBus bus);
+	reg[7:0] acc0, acc1;
+	logic add_carry, sub_carry;
+	PortComb #(.ADDR(ACC), .ADDRI(ACCI)) p_acc0(
+			.bus(bus),
+			.data_from_bus(acc),
+			.data_to_bus(acc)
+	);
+	/* ====================
+	*     ADD / SUBTRACT
+	   ==================== */
+	reg[7:0] add_input;
+	reg[7:0] add_output;
+	assign {add_carry,add_output} = add_input + acc;
+	PortCombDual #(.ADDR(ADD), .ADDRI(ADDI)) p_add0(
+			.bus(bus),
+			.data_from_bus(add_input),
+			.data_to_bus(add_output),
+			.data_to_bus_i({7'd0, add_carry})
+	);
+	
+	reg[7:0] sub_input;
+	reg[7:0] sub_output;
+	assign {sub_carry,sub_output} = sub_input - acc;
+	PortCombDual #(.ADDR(SUB), .ADDRI(SUBI)) p_sub0(
+			.bus(bus),
+			.data_from_bus(sub_input),
+			.data_to_bus(sub_output),
+			.data_to_bus_i({7'd0, sub_carry})
+	);
+
+	/* ====================
+	*        AND / OR
+	   ==================== */
+
+	reg[7:0] andor_input;
+	reg[7:0] and_output;
+	reg[7:0] or_output;
+	assign and_output = andor_input & acc;
+	assign or_output = andor_input & acc;
+	PortCombDual #(.ADDR(ANDOR), .ADDRI(ANDORI)) p_andor0(
+			.bus(bus),
+			.data_from_bus(andor_input),
+			.data_to_bus(and_output),
+			.data_to_bus_i(or_output)
+	);
+
+	/* ====================
+	*        NOT / XOR
+	   ==================== */
+
+	reg[7:0] nxor_input;
+	reg[7:0] not_output;
+	reg[7:0] xor_output;
+	assign xor_output = nxor_input ^ acc;
+	assign not_output = ~nxor_input;
+	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_nxor0(
+			.bus(bus),
+			.data_from_bus(nxor_input),
+			.data_to_bus(xor_output),
+			.data_to_bus_i(not_output)
+	);
+
+	/* ====================
+	*        SLL / SRL
+	   ==================== */
+
+	reg[7:0] shf_input;
+	reg[7:0] sll_output;
+	reg[7:0] srl_output;
+	assign sll_output = acc << shf_input[2:0];
+	assign srl_output = acc >> shf_input[2:0];
+	PortCombDual #(.ADDR(SHF), .ADDRI(SHFI)) p_shf0(
+			.bus(bus),
+			.data_from_bus(shf_input),
+			.data_to_bus(sll_output),
+			.data_to_bus_i(srl_output)
+	);
+
+	/* ====================
+	*    		MUL
+	   ==================== */
+
+	reg[7:0] mul_input;
+	reg[7:0] mul_output0;
+	reg[7:0] mul_output1;
+	assign {mul_output1, mul_output0} = mul_input * acc;
+	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_mul0(
+			.bus(bus),
+			.data_from_bus(mul_input),
+			.data_to_bus(mul_output0),
+			.data_to_bus_i(mul_output1)
+	);
+
+	/* ====================
+	*    	DIV / MOD
+	   ==================== */
+
+	reg[7:0] div_input;
+	reg[7:0] div_output;
+	reg[7:0] mod_output;
+	assign div_output = acc / div_input;
+	assign mod_output = acc % div_input;
+	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_div0(
+			.bus(bus),
+			.data_from_bus(div_input),
+			.data_to_bus(div_output),
+			.data_to_bus_i(mod_output)
+	);
+
+	/* ====================
+	*   	GT / GE 
+	   ==================== */
+
+	reg[7:0] gtge_input;
+	reg[7:0] gt_output;
+	reg[7:0] ge_output;
+	assign gt_output = acc > gtge_input;
+	assign ge_output = acc >= gtge_input;
+	PortCombDual #(.ADDR(GTGE), .ADDRI(GTGEI)) p_gtge0(
+			.bus(bus),
+			.data_from_bus(gtge_input),
+			.data_to_bus({7'd0, gt_output}),
+			.data_to_bus_i({7'd0, ge_output})
+	);
+endmodule
+	

+ 166 - 126
src/oisc/cpu.sv

@@ -1,10 +1,12 @@
 `include "oisc.sv"
+`include "../const.sv"
 import oisc8_pkg::*;
 
+
 module oisc8_cpu(processor_port port);
 	
-	wire [7:0] data_bus;
-	wire [8*2-1:0] instr_bus;  // FIXME: replace 8 with ASIZE
+	wire [`DWIDTH-1:0] data_bus;
+	wire [`DAWIDTH+`SAWIDTH:0] instr_bus;  
 	
 	IBus bus0(
 			.clk(port.clk),
@@ -14,23 +16,26 @@ module oisc8_cpu(processor_port port);
 	);
 	
 	// NULL block always return 0 and ignores input.
-	Port #() p_null0(
-			.bus(bus0),
-			.data_to_bus(8'd0)
-	);
-
+	//Port #() p_null0(
+	//		.bus(bus0),
+	//		.data_to_bus(8'd0)
+	//);
+	//Port #(.ADDR)
+	PortOutput#() p_null(.bus(bus0),.data_to_bus(`DWIDTH'd0));
 	pc_block#(.PROGRAM("../../memory/oisc8.text")) pc0(bus0);
 	alu_block alu0(bus0);
+	mem_block ram0(bus0, port);
 
 endmodule
 
 module pc_block(IBus bus);
-	parameter PROGRAM = "";
-	reg[15:0] pc, pcn; // Program counter
 
+	parameter PROGRAM = "";
+	reg[15:0] pc, pcn, pcr; // Program counter
 	reg[15:0] pointer;  // Instruction pointer accumulator
 	reg[7:0] comp_acc;  // Compare accumulator
-	reg comp_acc_rst, comp_zero;
+	reg comp_zero;
+
 	/* ====================
 	*       ROM BLOCK
 	   ==================== */
@@ -45,151 +50,186 @@ module pc_block(IBus bus);
 	pseudo_rom#(
 			.PROGRAM({PROGRAM, ".mem"}), 
 			.WIDTH(16),
-			.NUMWORDS(2048)
+	 		.NUMWORDS(2048)
 	) 
 	`endif
-		rom0(pcn[11:0], bus.clk, bus.instr);
+		rom0(pc[12:0], bus.clk, bus.instr[12:0]);
 	
+	`ifndef SYNTHESIS
+	reg [15:0] pcp;  // Current program counter for debugging
+	`endif 
+
 	assign comp_zero = comp_acc == 0;
-	assign pcn = comp_zero ? pointer : pc + 1;
+	//assign pcn = comp_zero|bus.rst ? pointer : pc + 1;
+	assign pcn = pc + 1;
 	always_ff@(posedge bus.clk) begin
 		if(bus.rst) begin 
-			pc <= 0;
-			comp_acc_rst <= 0;
+			pcr <= 0;
 		end
 		else begin 
-			pc <= pcn;
-			comp_acc_rst <= comp_zero;
+			`ifndef SYNTHESIS
+			pcp <= pc;
+			`endif 
+			pcr <= pcn;
 		end
 	end
-	/* ====================
-	*      BRANCH PART
-	   ==================== */
-		
-	PortInput #(.ADDR(BRPT0)) p_brpt0_0(
-			.bus(bus),
-			.data_from_bus(pointer[7:0])
+	assign pc = (comp_zero) ? pointer : pcr; 	
+
+	PortReg#(.ADDR_SRC(BRPT0R), .ADDR_DST(BRPT0)) p_brpt0(
+			.bus(bus),.data_from_bus(pointer[7:0]),.data_to_bus(pointer[7:0]),.wr(),.rd()
 	);
-	PortInput #(.ADDR(BRPT1)) p_brpt1_0(
-			.bus(bus),
-			.data_from_bus(pointer[15:8])
-	);	
-	PortInput #(.ADDR(BRZ), .DEFAULT(8'hFF)) p_brz_0(
-			.bus(bus),
-			.data_from_bus(comp_acc),
-			.reset(comp_acc_rst)
+	PortReg#(.ADDR_SRC(BRPT1R), .ADDR_DST(BRPT1)) p_brpt1(
+			.bus(bus),.data_from_bus(pointer[15:8]),.data_to_bus(pointer[15:8]),.wr(),.rd()
+	);
+	PortInputSeq#(.ADDR(BRZ), .DEFAULT(`DWIDTH'hFF)) p_brz(
+			.bus(bus),.data_from_bus(comp_acc)
 	);
 
 endmodule
 
-module alu_block(IBus bus);
-	reg[7:0] acc;
-	logic add_carry, sub_carry;
-	PortComb #(.ADDR(ACC), .ADDRI(ACCI)) p_acc0(
+module mem_block(IBus bus, processor_port port);
+	reg w0,w1,w2,wd0,wd1;
+	reg [15:0] data, cached;
+	reg [23:0] pointer;
+	always_ff@(posedge bus.clk) begin 
+		if(port.ram_rd_en) cached <= port.ram_rd_data;
+		else if(port.ram_wr_en) cached <= data;
+	end
+
+	PortRegSeq#(.ADDR_SRC(MEMPT0R), .ADDR_DST(MEMPT0)) p_mempt0(
 			.bus(bus),
-			.data_from_bus(acc),
-			.data_to_bus(acc)
+			.data_from_bus(pointer[7:0]),
+			.data_to_bus(pointer[7:0]),
+			.wr(w0)
 	);
-	/* ====================
-	*     ADD / SUBTRACT
-	   ==================== */
-	reg[7:0] add_input;
-	reg[7:0] add_output;
-	assign {add_carry,add_output} = add_input + acc;
-	PortCombDual #(.ADDR(ADD), .ADDRI(ADDI)) p_add0(
+	PortRegSeq#(.ADDR_SRC(MEMPT1R), .ADDR_DST(MEMPT1)) p_mempt1(
 			.bus(bus),
-			.data_from_bus(add_input),
-			.data_to_bus(add_output),
-			.data_to_bus_i({7'd0, add_carry})
+			.data_from_bus(pointer[15:8]),
+			.data_to_bus(pointer[15:8]),
+			.wr(w1)
 	);
-	
-	reg[7:0] sub_input;
-	reg[7:0] sub_output;
-	assign {sub_carry,sub_output} = sub_input - acc;
-	PortCombDual #(.ADDR(SUB), .ADDRI(SUBI)) p_sub0(
+	PortRegSeq#(.ADDR_SRC(MEMPT2R), .ADDR_DST(MEMPT2)) p_mempt2(
 			.bus(bus),
-			.data_from_bus(sub_input),
-			.data_to_bus(sub_output),
-			.data_to_bus_i({7'd0, sub_carry})
+			.data_from_bus(pointer[23:16]),
+			.data_to_bus(pointer[23:16]),
+			.wr(w2)
 	);
-
-	/* ====================
-	*        AND / OR
-	   ==================== */
-
-	reg[7:0] andor_input;
-	reg[7:0] and_output;
-	reg[7:0] or_output;
-	assign and_output = andor_input & acc;
-	assign or_output = andor_input & acc;
-	PortCombDual #(.ADDR(ANDOR), .ADDRI(ANDORI)) p_andor0(
+	
+	PortRegSeq#(.ADDR_SRC(MEMLWLO), .ADDR_DST(MEMSWLO)) p_mem0(
 			.bus(bus),
-			.data_from_bus(andor_input),
-			.data_to_bus(and_output),
-			.data_to_bus_i(or_output)
+			.data_from_bus(data[7:0]),
+			.data_to_bus(cached[7:0]),
+			.wr(wd0)
 	);
-
-	/* ====================
-	*        NOT / XOR
-	   ==================== */
-
-	reg[7:0] nxor_input;
-	reg[7:0] not_output;
-	reg[7:0] xor_output;
-	assign xor_output = nxor_input ^ acc;
-	assign not_output = ~nxor_input;
-	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_nxor0(
+	PortRegSeq#(.ADDR_SRC(MEMLWHI), .ADDR_DST(MEMSWHI)) p_mem1(
 			.bus(bus),
-			.data_from_bus(nxor_input),
-			.data_to_bus(xor_output),
-			.data_to_bus_i(not_output)
+			.data_from_bus(data[15:8]),
+			.data_to_bus(cached[15:8]),
+			.wr(wr1)
 	);
 
-	/* ====================
-	*        SLL / SRL
-	   ==================== */
-
-	reg[7:0] shf_input;
-	reg[7:0] sll_output;
-	reg[7:0] srl_output;
-	assign sll_output = acc << shf_input[2:0];
-	assign srl_output = acc >> shf_input[2:0];
-	PortCombDual #(.ADDR(SHF), .ADDRI(SHFI)) p_shf0(
-			.bus(bus),
-			.data_from_bus(shf_input),
-			.data_to_bus(sll_output),
-			.data_to_bus_i(srl_output)
+	// ========================
+	// 			STACK
+	// ========================
+	reg st_push_en, st_pop_en, st_pop_en0;
+	reg[`DWIDTH-1:0] st_push, st_cache;
+	reg[15:0] stp, stpp, stpp2;  // stack pointer
+	assign stpp = stp + (st_pop_en ? 16'h0001 : 16'hFFFF);
+	assign stpp2 = stp + 16'h0002;
+	always_latch begin
+		if(bus.rst) st_cache <= 16'd0;
+		else if(st_push_en) st_cache <= st_push;
+		else if(st_pop_en0) st_cache <= port.ram_rd_data;
+	end
+	always_ff@(posedge bus.clk) begin
+		if(bus.rst) begin 
+			stp <= 16'd`RAM_SIZE-1;
+		end else begin
+			st_pop_en0 <= st_pop_en; // Delayed by 1
+			if(st_push_en|st_pop_en) stp <= stpp;
+		end
+	end
+	PortInputSeq#(.ADDR(STACK)) p_push(
+		.bus(bus),
+		.data_from_bus(st_push),
+		.wr(st_push_en)
+	);
+	PortOutput#(.ADDR(STACKR)) p_pop(
+		.bus(bus),
+		.data_to_bus(st_cache),
+		.rd(st_pop_en)
 	);
 
-	/* ====================
-	*    		MUL
-	   ==================== */
+	assign port.ram_rd_en = w0|w1|w2|st_pop_en;
+	assign port.ram_wr_en = wd0|st_push_en;
+	assign port.ram_wr_data = st_push_en ? {8'd0,st_push} : data;
+	assign port.ram_addr = 
+		st_push_en ? {8'hFF, stp} :
+		(st_pop_en ? {8'hFF, stpp2} : pointer);
+
+		//if(st_push_en) port.ram_addr = {8'hFF, stp};	 
+		//if(st_pop_en)  port.ram_addr = {8'hFF, stpp};
+		//case({st_push_en,st_pop_en})
+		//	2'b00: port.ram_addr = pointer;
+		//	//2'b10: port.ram_addr = {8'hFF, stp};	
+		//	//2'b?1: port.ram_addr = {8'hFF, stpp};	
+		//endcase
+	//end
+endmodule
 
-	reg[7:0] mul_input;
-	reg[7:0] mul_output0;
-	reg[7:0] mul_output1;
-	assign {mul_output1, mul_output0} = mul_input * acc;
-	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_mul0(
-			.bus(bus),
-			.data_from_bus(mul_input),
-			.data_to_bus(mul_output0),
-			.data_to_bus_i(mul_output1)
-	);
+module alu_block(IBus bus);
+	logic [`DWIDTH-1:0] acc0, acc1;	
+	
+	PortReg#(.ADDR_SRC(ALUACC0R), .ADDR_DST(ALUACC0)) p_aluacc0(
+			.bus(bus),.data_from_bus(acc0),.data_to_bus(acc0),.wr(),.rd());
+	PortReg#(.ADDR_SRC(ALUACC1R), .ADDR_DST(ALUACC1)) p_aluacc1(
+			.bus(bus),.data_from_bus(acc1),.data_to_bus(acc1),.wr(),.rd());
+
+	logic [`DWIDTH:0] reg_add;
+	//carry_lookahead_adder#(.WIDTH(`DWIDTH)) alu_adder0(acc0,acc1,reg_add);
+	assign reg_add = acc0 + acc1;
+	PortOutput#(.ADDR(ADD)) p_add(.bus(bus),.data_to_bus(reg_add[`DWIDTH-1:0]));
+	PortOutput#(.ADDR(ADDC)) p_addc(.bus(bus),.data_to_bus({{`DWIDTH-1{1'b0}},reg_add[`DWIDTH]}));
+
+	logic [`DWIDTH-1:0] reg_sub;
+	logic reg_sub_c;
+	assign {reg_sub_c,reg_sub} = acc0 - acc1;
+	PortOutput#(.ADDR(SUB)) p_sub(.bus(bus),.data_to_bus(reg_sub));
+	PortOutput#(.ADDR(SUBC)) p_subc(.bus(bus),.data_to_bus({{`DWIDTH-1{1'b0}},reg_sub_c}));
+
+	logic [`DWIDTH-1:0] reg_and, reg_or, reg_xor; 
+	assign reg_and = acc0 & acc1;
+	assign reg_or  = acc0 | acc1;
+	assign reg_xor = acc0 ^ acc1;
+	PortOutput#(.ADDR(AND)) p_and(.bus(bus),.data_to_bus(reg_and));
+	PortOutput#(.ADDR(OR)) p_or(.bus(bus),.data_to_bus(reg_or));
+	PortOutput#(.ADDR(XOR)) p_xor(.bus(bus),.data_to_bus(reg_xor));
+
+	logic [`DWIDTH-1:0] reg_sll, reg_srl; 
+	assign reg_sll = acc0 << acc1[$clog2(`DWIDTH)-1:0];
+	assign reg_srl = acc0 >> acc1[$clog2(`DWIDTH)-1:0];
+	PortOutput#(.ADDR(SLL)) p_sll(.bus(bus),.data_to_bus(reg_sll));
+	PortOutput#(.ADDR(SRL)) p_srl(.bus(bus),.data_to_bus(reg_srl));
+	
+	logic reg_eq, reg_gt, reg_ge;
+	assign reg_eq = acc0 == acc1;
+	assign reg_gt = acc0 >  acc1;
+	assign reg_ge = acc0 >= acc1;
+	PortOutput#(.ADDR(EQ)) p_eq(.bus(bus),.data_to_bus({{`DWIDTH-1{1'b0}},reg_eq}));
+	PortOutput#(.ADDR(GT)) p_gt(.bus(bus),.data_to_bus({{`DWIDTH-1{1'b0}},reg_gt}));
+	PortOutput#(.ADDR(GE)) p_ge(.bus(bus),.data_to_bus({{`DWIDTH-1{1'b0}},reg_ge}));
+	
+	logic [`DWIDTH*2-1:0] reg_mul;
+	assign reg_mul = acc0 * acc1;
+	PortOutput#(.ADDR(MULLO)) p_mul0(.bus(bus),.data_to_bus(reg_mul[`DWIDTH-1:0]));
+	PortOutput#(.ADDR(MULHI)) p_mul1(.bus(bus),.data_to_bus(reg_mul[`DWIDTH*2-1:`DWIDTH]));
+	
 
-	/* ====================
-	*    	DIV / MOD
-	   ==================== */
+	logic [`DWIDTH-1:0] reg_div, reg_mod; 
+	assign reg_div = acc0 / acc1;
+	assign reg_mod = acc0 % acc1;
+	PortOutput#(.ADDR(DIV)) p_div(.bus(bus),.data_to_bus(reg_div));
+	PortOutput#(.ADDR(MOD)) p_mod(.bus(bus),.data_to_bus(reg_mod));
 
-	reg[7:0] div_input;
-	reg[7:0] div_output;
-	reg[7:0] mod_output;
-	assign div_output = acc / div_input;
-	assign mod_output = acc % div_input;
-	PortCombDual #(.ADDR(NXOR), .ADDRI(NXORI)) p_div0(
-			.bus(bus),
-			.data_from_bus(div_input),
-			.data_to_bus(div_output),
-			.data_to_bus_i(mod_output)
-	);
 endmodule
-	
+

+ 153 - 159
src/oisc/oisc.sv

@@ -1,193 +1,187 @@
-package oisc8_pkg;
+`define DWIDTH  8 // Data bus width
+`define DAWIDTH 4 // Dest. address width
+`define SAWIDTH 8 // Src. address width
 
-	// Instruction address bus width
-	parameter ASIZE = 8;
+package oisc8_pkg;
 
-	typedef enum logic [ASIZE-1:0] {
-		NONE   =8'd0,
+	typedef enum logic [`DAWIDTH-1:0] {
+		ALUACC0 ='d0,
+		ALUACC1 ='d1,
+		BRPT0   ='d2,
+		BRPT1   ='d3,
+		BRZ     ='d4,
+		STACK   ='d5,
+		MEMPT0  ='d6,
+		MEMPT1  ='d7,
+		MEMPT2  ='d8,
+		MEMSWHI ='d9,
+		MEMSWLO ='d10,
+		COMA    ='d11,
+		COMD    ='d12
+	} e_iaddr_dst;  // destination enum
+
+	typedef enum logic [`SAWIDTH-1:0] {
+		NULL    ='d0,
 		// ALU BLOCK
-		ACC    =8'd1,
-		ACCI   =8'd2,
-		ADD    =8'd3,
-		ADDI   =8'd4,
-		SUB    =8'd5,
-		SUBI   =8'd6,
-		ANDOR  =8'd7,
-		ANDORI =8'd8,
-		NXOR   =8'd9,	
-		NXORI  =8'd10,	
-		SHF    =8'd11,	
-		SHFI   =8'd12,	
-		MUL    =8'd13,	
-		MULI   =8'd14,	
-		DIV    =8'd15,	
-		DIVI   =8'd16,
-		// PC BLOCK
-		BRPT0  =8'd17,
-		BRPT1  =8'd18,
-		BRZ    =8'd19
-		
-	} e_iaddr;  // destination enum
-
-	typedef enum logic [ASIZE-1:0] {
-		NULL_   =8'd0,
-		// ALU BLOCK
-		ACC0_S  =8'd1,
-		ACC1_S  =8'd2,
-		ADD_S   =8'd3,
-		ADDC_S  =8'd4,
-		SUB_S   =8'd5,
-		SUBC_S  =8'd6,
-		AND_S   =8'd7,
-		OR_S    =8'd8,
-		XOR_S   =8'd9,	
-		NOT_S   =8'd10,	
-		SLL_S   =8'd11,	
-		SRL_S   =8'd12,	
-		MULLO_S =8'd13,	
-		MULHI_S =8'd14,	
-		DIV_S   =8'd15,	
-		MOD_S   =8'd16
-		// PC BLOCK
-		
+		ALUACC0R='d1,
+		ALUACC1R='d2,
+		ADD     ='d3,
+		ADDC    ='d4,
+		SUB     ='d5,
+		SUBC    ='d6,
+		AND     ='d7,
+		OR      ='d8,
+		XOR     ='d9,	
+		SLL     ='d11,	
+		SRL     ='d12,	
+		EQ     	='d13,	
+		GT     	='d14,	
+		GE    	='d15,	
+		MULLO   ='d16,	
+		MULHI   ='d17,	
+		DIV     ='d18,	
+		MOD     ='d19,
+		// Program Counter
+		BRPT0R  ='d20,
+		BRPT1R  ='d21,
+		// Memory
+		MEMPT0R ='d22,
+		MEMPT1R ='d23,
+		MEMPT2R ='d24,
+		MEMLWHI ='d25,
+		MEMLWLO ='d26,
+		STACKR	='d27,
+		STPT0R  ='d28,
+		STPT1R  ='d29,
+		// COM
+		COMAR   ='d30,
+		COMDR   ='d31		
 	} e_iaddr_src;  // source enum
 
 endpackage
 
-interface IBus(
-	input logic clk, rst,
-	inout wire[7:0] data,
-	input wire[8*2-1:0] instr  // FIXME, replace 8 with ASIZE
-	);
+interface IBus(clk, rst, data, instr);
 	import oisc8_pkg::*;
+	
+	input logic clk, rst;
+	inout wire[`DWIDTH-1:0] data;
+	input wire[`SAWIDTH+`DAWIDTH:0] instr;
 
-	e_iaddr instr_dst;
+	logic imm;
+	e_iaddr_dst instr_dst;
 	e_iaddr_src instr_src;
-	assign instr_dst = e_iaddr'(instr[15:8]); // FIXME: Use ASIZE
-	assign instr_src = e_iaddr_src'(instr[7:0]);
+	assign imm = instr[`DAWIDTH+`SAWIDTH];
+	assign instr_dst = e_iaddr_dst'(instr[`DAWIDTH+`SAWIDTH-1:`SAWIDTH]);
+	assign instr_src = e_iaddr_src'(instr[`SAWIDTH-1:0]);
 
 endinterface
 
-module Port(
-		IBus bus,
-		output reg[7:0] data_from_bus,
-		input  reg[7:0] data_to_bus
-	);
-	parameter ADDR = 8'd0;
-
-	reg rd, wr;
-	assign rd = bus.instr_dst == ADDR;
-	assign wr = bus.instr_src == ADDR;
-	assign bus.data = wr ? data_to_bus : 'bZ;
-	always_ff@(posedge bus.clk) begin
-		if(bus.rst) 
-			data_from_bus <= 0;
-		else 
-			data_from_bus <= rd ? bus.data : data_from_bus;
-	end
-endmodule
-
-module PortImm(
-		IBus bus,
-		output reg[7:0] data_from_bus,
-		input  reg[7:0] data_to_bus
-);
-	parameter ADDR = 8'd0;
+module PortReg(bus, data_from_bus, data_to_bus, rd, wr);
+	import oisc8_pkg::*;
 
-	reg rd, wr;
-	assign rd = bus.instr_dst == ADDR;
-	assign wr = bus.instr_src == ADDR;
-	
-	assign bus.data = wr ? data_to_bus : 'bZ;
+	IBus bus;
+	output logic[`DWIDTH-1:0] data_from_bus;
+	input  logic[`SAWIDTH-1:0] data_to_bus;
+	output reg rd, wr;
+
+	parameter ADDR_SRC = e_iaddr_src'(0);
+	parameter ADDR_DST = e_iaddr_dst'(0);
+	parameter DEFAULT = `DWIDTH'd0;
+
+	reg [`SAWIDTH-1:0] data;
+	always_comb casez({bus.imm,bus.rst})
+		2'b00: data = bus.data[`SAWIDTH-1:0];
+		2'b10: data = bus.instr_src;
+		2'b?1: data = DEFAULT;
+	endcase
+
+	assign wr = bus.instr_dst == ADDR_DST;
+	assign rd = bus.instr_src == ADDR_SRC;
+	assign bus.data = rd ? data_to_bus : 'bZ;
 	always_ff@(posedge bus.clk) begin
-		if(bus.rst) 
-			data_from_bus <= 0;
-		else 
-			data_from_bus <= rd ? bus.data : bus.instr_src;	
+		if(bus.rst) data_from_bus <= DEFAULT;
+		else if(wr) data_from_bus <= data;
 	end
 endmodule
 
-module PortComb(
-		IBus bus,
-		output reg[7:0] data_from_bus,
-		input  reg[7:0] data_to_bus
-);
-	parameter ADDR = 8'd0;
-	parameter ADDRI = 8'd0;
-	
+module PortRegSeq(bus, data_from_bus, data_to_bus, rd, wr);
+	import oisc8_pkg::*;
 
-	reg rd, wr;
-	assign rd = bus.instr_dst == ADDR;
-	assign rdi = bus.instr_dst == ADDRI;
-	assign wr = bus.instr_src == ADDR;
-	assign wri = bus.instr_src == ADDRI;
-	
-	assign bus.data = (wr|wri) ? data_to_bus : 'bZ;
+	IBus bus;
+	output logic[`DWIDTH-1:0] data_from_bus;
+	input  logic[`SAWIDTH-1:0] data_to_bus;
+	output reg rd, wr;
+
+	parameter ADDR_SRC = e_iaddr_src'(0);
+	parameter ADDR_DST = e_iaddr_dst'(0);
+	parameter DEFAULT = `DWIDTH'd0;
+
+	reg [`SAWIDTH-1:0] data, latch;
+	always_comb casez({bus.imm,bus.rst})
+		2'b00: data = bus.data[`SAWIDTH-1:0];
+		2'b10: data = bus.instr_src;
+		2'b?1: data = DEFAULT;
+	endcase
+
+	assign wr = bus.instr_dst == ADDR_DST;
+	assign rd = bus.instr_src == ADDR_SRC;
+	assign bus.data = rd ? data_to_bus : 'bZ;
+	assign data_from_bus = wr ? data : latch;
 	always_ff@(posedge bus.clk) begin
-		if(bus.rst) 
-			data_from_bus = 0;
-		else begin
-			if(rd) data_from_bus <= bus.data;
-			else if(rdi) data_from_bus <= bus.instr_src;
-			else data_from_bus <= data_from_bus; // keep previous value
-		end
+		if(bus.rst) latch <= DEFAULT;
+		else if(wr) latch <= data;
 	end
 endmodule
 
-module PortCombDual(
-		IBus bus,
-		output reg[7:0] data_from_bus,
-		input  reg[7:0] data_to_bus,   // When ADDR
-		input  reg[7:0] data_to_bus_i  // When ADDRI
-);
-	parameter ADDR = 8'd0;
-	parameter ADDRI = 8'd0;
-	
-	reg rd, wr;
-	assign rd = bus.instr_dst == ADDR;
-	assign rdi = bus.instr_dst == ADDRI;
-	assign wr = bus.instr_src == ADDR;
-	assign wri = bus.instr_src == ADDRI;
-	
-	assign bus.data = wr ? data_to_bus : 'bz;
-	assign bus.data = wri & !wr ? data_to_bus_i : 'bz; // with protection.
+module PortInput(bus, data_from_bus, wr, rst);
+	import oisc8_pkg::*;
 
-	always_ff@(posedge bus.clk) begin
-		if(bus.rst) 
-			data_from_bus <= 0;
-		else begin
-			if(rd) data_from_bus <= bus.data;
-			else if(rdi) data_from_bus <= bus.instr_src;
-			else data_from_bus <= data_from_bus; // keep previous value
-		end
-	end
-endmodule
+	IBus bus;
+	output reg[`DWIDTH-1:0] data_from_bus;
+	output reg wr;
+	input reg rst;
+
+	parameter ADDR = e_iaddr_dst'(0);
+	parameter DEFAULT = `DWIDTH'd0;
 
-module PortInput(
-		IBus bus,
-		output reg[7:0] data_from_bus,
-		input reg reset
-	);
-	parameter ADDR = 8'd0;
-	parameter DEFAULT = 8'd0;
+	reg [`SAWIDTH-1:0] data;
+	assign data = bus.imm ? bus.instr_src : bus.data[`SAWIDTH-1:0];
 
-	reg rd;
-	assign rd = bus.instr_dst == ADDR;
+	assign wr = bus.instr_dst == ADDR;
 	always_ff@(posedge bus.clk) begin
-		if(bus.rst|reset) 
+		if(bus.rst|rst) 
 			data_from_bus <= DEFAULT;
 		else 
-			data_from_bus <= rd ? bus.data : data_from_bus;
+			data_from_bus <= wr ? data : data_from_bus;
 	end
 endmodule
 
-module PortOutput(
-		IBus bus,
-		input  reg[7:0] data_to_bus
-	);
-	parameter ADDR = 8'd0;
+module PortInputSeq(bus, data_from_bus, wr);
+	import oisc8_pkg::*;
+
+	IBus bus;
+	output reg[`DWIDTH-1:0] data_from_bus;
+	output reg wr;
+
+	parameter ADDR = e_iaddr_dst'(0);
+	parameter DEFAULT = `DWIDTH'd0;
+
+	reg [`SAWIDTH-1:0] data;
+	assign data = bus.imm ? bus.instr_src : bus.data[`SAWIDTH-1:0];
+	assign wr = bus.instr_dst == ADDR;
+	assign data_from_bus = wr ? data : DEFAULT;
+endmodule
+
+
+module PortOutput(bus, data_to_bus, rd);
+	import oisc8_pkg::*;
+
+	IBus bus;
+	input  reg[`SAWIDTH-1:0] data_to_bus;
+	output reg rd;
+
+	parameter ADDR = e_iaddr_src'(0);
 
-	reg wr;
-	assign wr = bus.instr_src == ADDR;
-	assign bus.data = wr ? data_to_bus : 'bZ;
+	assign rd = bus.instr_src == ADDR;
+	assign bus.data = rd ? data_to_bus : 'bZ;
 endmodule