Bläddra i källkod

OISC WIP

Inluded most ALU reads/writes: ADD, ADDC, AND, OR, XOR, MUL, DIV, MOD,
SLL, SRL.
Also added branch on zero functionality
Min 6 år sedan
förälder
incheckning
22faf38de4
2 ändrade filer med 291 tillägg och 31 borttagningar
  1. 130 12
      src/oisc/cpu.sv
  2. 161 19
      src/oisc/oisc.sv

+ 130 - 12
src/oisc/cpu.sv

@@ -4,7 +4,7 @@ import oisc8_pkg::*;
 module oisc8_cpu(processor_port port);
 	
 	wire [7:0] data_bus;
-	wire [8*2-1:0] inst_bus;  // FIXME: replace 8 with ASIZE
+	wire [8*2-1:0] instr_bus;  // FIXME: replace 8 with ASIZE
 	
 	IBus bus0(
 			.clk(port.clk),
@@ -12,6 +12,12 @@ module oisc8_cpu(processor_port port);
 			.instr(instr_bus),
 			.data(data_bus)
 	);
+	
+	// NULL block always return 0 and ignores input.
+	Port #() p_null0(
+			.bus(bus0),
+			.data_to_bus(8'd0)
+	);
 
 	pc_block#(.PROGRAM("../../memory/oisc8.text")) pc0(bus0);
 	alu_block alu0(bus0);
@@ -22,6 +28,12 @@ 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"}), 
@@ -37,41 +49,147 @@ module pc_block(IBus bus);
 	) 
 	`endif
 		rom0(pcn[11:0], bus.clk, bus.instr);
-
-	assign pcn = pc + 1;  // Next pc 
+	
+	assign comp_zero = comp_acc == 0;
+	assign pcn = comp_zero ? pointer : pc + 1;
 	always_ff@(posedge bus.clk) begin
-		if(bus.rst) pc <= 0;
-		else pc <= pcn;
+		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] acc;
 	logic add_carry, sub_carry;
-	Port #(.ADDR(ACCI), .IMMIDATE(1)) p_acc0(
+	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;
-	Port #(.ADDR(ADDI), .IMMIDATE(1)) p_add0(
+	PortCombDual #(.ADDR(ADD), .ADDRI(ADDI)) p_add0(
 			.bus(bus),
 			.data_from_bus(add_input),
-			.data_to_bus(add_output)
+			.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;
-	Port #(.ADDR(SUB)) p_sub0(
+	PortCombDual #(.ADDR(SUB), .ADDRI(SUBI)) p_sub0(
 			.bus(bus),
 			.data_from_bus(sub_input),
-			.data_to_bus(sub_output)
-	);	
+			.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)
+	);
 endmodule
 	

+ 161 - 19
src/oisc/oisc.sv

@@ -4,14 +4,53 @@ package oisc8_pkg;
 	parameter ASIZE = 8;
 
 	typedef enum logic [ASIZE-1:0] {
-		NONE=8'd0,
-		ACC =8'd1,
-		ACCI=8'd2,
-		ADD =8'd3,
-		ADDI=8'd4,
-		SUB =8'd5,
-		SUBI=8'd6
-	} e_iaddr;
+		NONE   =8'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
+		
+	} e_iaddr_src;  // source enum
 
 endpackage
 
@@ -20,6 +59,13 @@ interface IBus(
 	inout wire[7:0] data,
 	input wire[8*2-1:0] instr  // FIXME, replace 8 with ASIZE
 	);
+	import oisc8_pkg::*;
+
+	e_iaddr 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]);
+
 endinterface
 
 module Port(
@@ -27,25 +73,121 @@ module Port(
 		output reg[7:0] data_from_bus,
 		input  reg[7:0] data_to_bus
 	);
-	
+	parameter ADDR = 8'd0;
 
-	localparam ASIZE = 8;  // FIXME: take from 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;
+	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;
-	parameter IMMIDATE = 0;
 
 	reg rd, wr;
-	assign rd = bus.instr[ASIZE-1:0] == ADDR;
-	assign wr = bus.instr[ASIZE*2-1:ASIZE] == ADDR;
+	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) begin
+		if(bus.rst) 
+			data_from_bus <= 0;
+		else 
+			data_from_bus <= rd ? bus.data : bus.instr_src;	
+	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;
+	
+
+	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;
+	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
+
+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.
+
+	always_ff@(posedge bus.clk) begin
+		if(bus.rst) 
 			data_from_bus <= 0;
-		end else begin
-			if(IMMIDATE == 0)
-				data_from_bus <= rd ? bus.data : data_from_bus;
-			else 
-				data_from_bus <= rd ? bus.data : bus.instr[ASIZE*2-1:ASIZE];
+		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
 
+module PortInput(
+		IBus bus,
+		output reg[7:0] data_from_bus,
+		input reg reset
+	);
+	parameter ADDR = 8'd0;
+	parameter DEFAULT = 8'd0;
+
+	reg rd;
+	assign rd = bus.instr_dst == ADDR;
+	always_ff@(posedge bus.clk) begin
+		if(bus.rst|reset) 
+			data_from_bus <= DEFAULT;
+		else 
+			data_from_bus <= rd ? bus.data : data_from_bus;
+	end
+endmodule
+
+module PortOutput(
+		IBus bus,
+		input  reg[7:0] data_to_bus
+	);
+	parameter ADDR = 8'd0;
+
+	reg wr;
+	assign wr = bus.instr_src == ADDR;
+	assign bus.data = wr ? data_to_bus : 'bZ;
 endmodule