`define OP_NOP 3'd0 `define OP_LOADA 3'd1 `define OP_LOADB 3'd2 `define OP_STORE 3'd3 `define OP_READ 3'd4 `define OP_LOADI 3'd5 `define OP_ROUTE 3'd6 `define OP_RUG 3'd7 module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, output reg [15:0] mem_in, input [15:0] mem_out, output reg mem_write); // parity is unimplemented // OP_LOADA wire [2:0] flagr = I[2:0]; wire bsel = I[3]; wire [7:0] aluc = I[11:4]; // OP_LOADB wire [2:0] cond = I[2:0]; wire inv = I[3]; wire [7:0] alus = I[11:4]; // OP_STORE wire [2:0] flagw = I[2:0]; wire edge_ = I[7]; wire [3:0] cube = I[11:8]; // OP_ROUTE wire [5:0] cycle = I[5:0]; wire [1:0] check = I[7:6]; wire [3:0] xor_ = I[11:8]; wire [2:0] snarf = I[14:12]; wire odd = I[15]; // OP_RUG wire rw = I[0]; wire ac = I[1]; wire news = I[2]; wire [4:0] reg_ = I[8:4]; reg [15:0] A; reg [15:0] B; reg [15:0] C; reg [15:0] F; reg [15:0] Cond; reg [15:0] R; reg [7:0] alu_sum; reg [7:0] alu_carry; reg [15:0] cube_in; reg io; // these are not really regs wire [15:0] alu_sum_out; wire [15:0] alu_carry_out; wire [2:0] alu_index [15:0]; assign alu_index[0] = (A[0] << 2) + (B[0] << 1) + F[0]; assign alu_sum_out[0] = alu_sum[alu_index[0]]; assign alu_carry_out[0] = alu_carry[alu_index[0]]; assign alu_index[1] = (A[1] << 2) + (B[1] << 1) + F[1]; assign alu_sum_out[1] = alu_sum[alu_index[1]]; assign alu_carry_out[1] = alu_carry[alu_index[1]]; assign alu_index[2] = (A[2] << 2) + (B[2] << 1) + F[2]; assign alu_sum_out[2] = alu_sum[alu_index[2]]; assign alu_carry_out[2] = alu_carry[alu_index[2]]; assign alu_index[3] = (A[3] << 2) + (B[3] << 1) + F[3]; assign alu_sum_out[3] = alu_sum[alu_index[3]]; assign alu_carry_out[3] = alu_carry[alu_index[3]]; assign alu_index[4] = (A[4] << 2) + (B[4] << 1) + F[4]; assign alu_sum_out[4] = alu_sum[alu_index[4]]; assign alu_carry_out[4] = alu_carry[alu_index[4]]; assign alu_index[5] = (A[5] << 2) + (B[5] << 1) + F[5]; assign alu_sum_out[5] = alu_sum[alu_index[5]]; assign alu_carry_out[5] = alu_carry[alu_index[5]]; assign alu_index[6] = (A[6] << 2) + (B[6] << 1) + F[6]; assign alu_sum_out[6] = alu_sum[alu_index[6]]; assign alu_carry_out[6] = alu_carry[alu_index[6]]; assign alu_index[7] = (A[7] << 2) + (B[7] << 1) + F[7]; assign alu_sum_out[7] = alu_sum[alu_index[7]]; assign alu_carry_out[7] = alu_carry[alu_index[7]]; assign alu_index[8] = (A[8] << 2) + (B[8] << 1) + F[8]; assign alu_sum_out[8] = alu_sum[alu_index[8]]; assign alu_carry_out[8] = alu_carry[alu_index[8]]; assign alu_index[9] = (A[9] << 2) + (B[9] << 1) + F[9]; assign alu_sum_out[9] = alu_sum[alu_index[9]]; assign alu_carry_out[9] = alu_carry[alu_index[9]]; assign alu_index[10] = (A[10] << 2) + (B[10] << 1) + F[10]; assign alu_sum_out[10] = alu_sum[alu_index[10]]; assign alu_carry_out[10] = alu_carry[alu_index[10]]; assign alu_index[11] = (A[11] << 2) + (B[11] << 1) + F[11]; assign alu_sum_out[11] = alu_sum[alu_index[11]]; assign alu_carry_out[11] = alu_carry[alu_index[11]]; assign alu_index[12] = (A[12] << 2) + (B[12] << 1) + F[12]; assign alu_sum_out[12] = alu_sum[alu_index[12]]; assign alu_carry_out[12] = alu_carry[alu_index[12]]; assign alu_index[13] = (A[13] << 2) + (B[13] << 1) + F[13]; assign alu_sum_out[13] = alu_sum[alu_index[13]]; assign alu_carry_out[13] = alu_carry[alu_index[13]]; assign alu_index[14] = (A[14] << 2) + (B[14] << 1) + F[14]; assign alu_sum_out[14] = alu_sum[alu_index[14]]; assign alu_carry_out[14] = alu_carry[alu_index[14]]; assign alu_index[15] = (A[15] << 2) + (B[15] << 1) + F[15]; assign alu_sum_out[15] = alu_sum[alu_index[15]]; assign alu_carry_out[15] = alu_carry[alu_index[15]]; reg [2:0] flags_addr; always @* begin case(op) `OP_LOADA: flags_addr <= flagr; `OP_LOADB: flags_addr <= cond; `OP_STORE: flags_addr <= flagw; default: flags_addr <= 0; endcase end wire [15:0] flags_in; reg [15:0] flags_out; reg flags_write; RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr), .in(flags_in), .out(flags_out)); reg [15:0] idx; always @ (posedge clk) begin if(mem_write) mem_write <= 0; if(flags_write) flags_write <= 0; case (op) `OP_NOP: begin end `OP_LOADA: begin alu_carry <= aluc; F <= flags_out; A <= mem_out; C <= mem_out; io <= io_pin; if (bsel) B <= cube_in; end `OP_LOADB: begin alu_sum <= alus; Cond <= inv ? ~flags_out : flags_out; B <= mem_out; R <= mem_out; end `OP_STORE: begin for(idx=0; idx < 16; idx++) flags_in[idx] <= Cond[idx] ? alu_carry_out[idx] : flags_out[idx]; flags_write <= 1; mem_in <= alu_sum_out; mem_write <= 1; // lots other stuff end `OP_READ: begin if (CS) mem_in <= mem_out; end `OP_LOADI: begin C <= mem_out; A <= I; alu_sum <= 8'b11110000; // out of A, B, F, select exactly A end /* `OP_RUG: begin if(!rw && ac && !news) begin rug[reg_] <= A; C <= mem_out; end if(!rw && !ac && !news) begin rug[reg_] <= C; A <= mem_out; end if(rw && ac && !news) begin A <= rug[reg_]; mem_in <= C; end if(rw && !ac && !news) begin C <= rug[reg_]; mem_in <= A; end if(rw && !ac && news) begin R <= mem_out; cube_in <= mem_out; end if(rw && ac && news) begin cube_in <= mem_out; end end */ endcase end endmodule