`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 `define DIRECTION_N 3'd0 `define DIRECTION_NE 3'd1 `define DIRECTION_E 3'd2 `define DIRECTION_SE 3'd3 `define DIRECTION_S 3'd4 `define DIRECTION_SW 3'd5 `define DIRECTION_W 3'd6 `define DIRECTION_NW 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 [3:0] flagr = I[3:0]; wire bsel = I[4]; wire [0:7] aluc = I[12:5]; // OP_LOADB wire [3:0] cond = I[3:0]; wire inv = I[4]; wire [0:7] alus = I[12:5]; // OP_STORE wire [3:0] flagw = I[3: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 = 0; reg [15:0] B = 0; reg [15:0] C = 0; reg [15:0] F = 0; reg [15:0] Cond = 0; reg [15:0] R = 0; reg [7:0] alu_sum = 0; reg [7:0] alu_carry = 0; reg [15:0] cube_in; reg io; // these are not really regs reg [15:0] alu_sum_out; reg [15:0] alu_carry_out; reg [2:0] alu_index [15:0]; reg [15:0] idx; always @* begin for(idx = 0; idx < 16; idx=idx+1) begin alu_index[idx] = (A[idx] << 2) + (B[idx] << 1) + F[idx]; alu_sum_out[idx] <= alu_sum[alu_index[idx]]; alu_carry_out[idx] <= alu_carry[alu_index[idx]]; end end reg [3:0] newstable[0:15][0:7]; initial begin newstable[0][0] = 12; newstable[0][1] = 13; newstable[0][2] = 1; newstable[0][3] = 5; newstable[0][4] = 4; newstable[0][5] = 7; newstable[0][6] = 3; newstable[0][7] = 15; newstable[1][0] = 13; newstable[1][1] = 14; newstable[1][2] = 2; newstable[1][3] = 6; newstable[1][4] = 5; newstable[1][5] = 4; newstable[1][6] = 0; newstable[1][7] = 12; newstable[2][0] = 14; newstable[2][1] = 15; newstable[2][2] = 3; newstable[2][3] = 7; newstable[2][4] = 6; newstable[2][5] = 5; newstable[2][6] = 1; newstable[2][7] = 13; newstable[3][0] = 15; newstable[3][1] = 12; newstable[3][2] = 0; newstable[3][3] = 4; newstable[3][4] = 7; newstable[3][5] = 6; newstable[3][6] = 2; newstable[3][7] = 14; newstable[4][0] = 0; newstable[4][1] = 1; newstable[4][2] = 5; newstable[4][3] = 9; newstable[4][4] = 8; newstable[4][5] = 11; newstable[4][6] = 7; newstable[4][7] = 3; newstable[5][0] = 1; newstable[5][1] = 2; newstable[5][2] = 6; newstable[5][3] = 10; newstable[5][4] = 9; newstable[5][5] = 8; newstable[5][6] = 4; newstable[5][7] = 0; newstable[6][0] = 2; newstable[6][1] = 3; newstable[6][2] = 7; newstable[6][3] = 11; newstable[6][4] = 10; newstable[6][5] = 9; newstable[6][6] = 5; newstable[6][7] = 1; newstable[7][0] = 3; newstable[7][1] = 0; newstable[7][2] = 4; newstable[7][3] = 8; newstable[7][4] = 11; newstable[7][5] = 10; newstable[7][6] = 6; newstable[7][7] = 2; newstable[8][0] = 4; newstable[8][1] = 5; newstable[8][2] = 9; newstable[8][3] = 13; newstable[8][4] = 12; newstable[8][5] = 15; newstable[8][6] = 11; newstable[8][7] = 7; newstable[9][0] = 5; newstable[9][1] = 6; newstable[9][2] = 10; newstable[9][3] = 14; newstable[9][4] = 13; newstable[9][5] = 12; newstable[9][6] = 8; newstable[9][7] = 4; newstable[10][0] = 6; newstable[10][1] = 7; newstable[10][2] = 11; newstable[10][3] = 15; newstable[10][4] = 14; newstable[10][5] = 13; newstable[10][6] = 9; newstable[10][7] = 5; newstable[11][0] = 7; newstable[11][1] = 4; newstable[11][2] = 8; newstable[11][3] = 12; newstable[11][4] = 15; newstable[11][5] = 14; newstable[11][6] = 10; newstable[11][7] = 6; newstable[12][0] = 8; newstable[12][1] = 9; newstable[12][2] = 13; newstable[12][3] = 1; newstable[12][4] = 0; newstable[12][5] = 3; newstable[12][6] = 15; newstable[12][7] = 11; newstable[13][0] = 9; newstable[13][1] = 10; newstable[13][2] = 14; newstable[13][3] = 2; newstable[13][4] = 1; newstable[13][5] = 0; newstable[13][6] = 12; newstable[13][7] = 8; newstable[14][0] = 10; newstable[14][1] = 11; newstable[14][2] = 15; newstable[14][3] = 3; newstable[14][4] = 2; newstable[14][5] = 1; newstable[14][6] = 13; newstable[14][7] = 9; newstable[15][0] = 11; newstable[15][1] = 8; newstable[15][2] = 12; newstable[15][3] = 0; newstable[15][4] = 3; newstable[15][5] = 2; newstable[15][6] = 14; newstable[15][7] = 10; end // initial begin reg [3:0] flags_addr_latch; reg [3:0] flags_addr; always @* begin if(flags_addr_latch) flags_addr <= flags_addr_latch; else case(op) `OP_LOADA: flags_addr <= flagr; `OP_LOADB: flags_addr <= cond; `OP_STORE: flags_addr <= flagw; default: flags_addr <= 0; endcase end // always @ * reg [15:0] flags_in; wire [15:0] flags_out; reg flags_write; reg [15:0] latest_news; RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr[2:0]), .in(flags_in), .out(flags_out)); reg [15:0] flag_or_news; reg [15:0] newsidx; always @* begin if(flags_addr[3]) begin // read from news for(idx = 0; idx < 16; idx++) begin newsidx = newstable[idx][flags_addr[2:0]]; flag_or_news[idx] = latest_news[newsidx]; end end else begin flag_or_news = flags_out; end end always @ (posedge clk) begin if(mem_write) mem_write <= 0; if(flags_write) begin flags_write <= 0; flags_addr_latch <= 0; end case (op) `OP_NOP: begin end `OP_LOADA: begin alu_carry <= aluc; F <= flag_or_news; A <= mem_out; C <= mem_out; io <= io_pin; if (bsel) B <= cube_in; end `OP_LOADB: begin alu_sum <= alus; Cond <= inv ? ~flag_or_news : flag_or_news; B <= mem_out; R <= mem_out; end `OP_STORE: begin for(idx = 0; idx < 16; idx++) begin flags_in[idx] = Cond[idx] ? alu_carry_out[idx] : flags_out[idx]; latest_news[idx] <= flags_in[idx]; end if(flags_addr) begin // we do not write to flag 0 flags_write <= 1; flags_addr_latch <= flags_addr; end mem_in <= alu_sum_out; mem_write <= 1; 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