diff --git a/fields.v b/fields.v index 39599de..0a11ae1 100644 --- a/fields.v +++ b/fields.v @@ -36,12 +36,17 @@ `define ALU_OP_EXCH 2 `define ALU_OP_SHL 3 `define ALU_OP_SHR 4 +`define ALU_OP_2CMPL 5 +`define ALU_OP_1CMPL 6 `define ALU_OP_INC 8 +`define ALU_OP_TEST_EQ 12 +`define ALU_OP_TEST_NEQ 13 `define ALU_REG_A 0 `define ALU_REG_B 1 `define ALU_REG_C 2 `define ALU_REG_D 3 +`define ALU_REG_0 15 `endif \ No newline at end of file diff --git a/opcodes/8Ax_test_[n]eq_A.v b/opcodes/8Ax_test_[n]eq_A.v index 99bf5a5..b049166 100644 --- a/opcodes/8Ax_test_[n]eq_A.v +++ b/opcodes/8Ax_test_[n]eq_A.v @@ -8,15 +8,44 @@ `include "decstates.v" `DEC_8AX: begin - case (nb_in) - 4'h6: begin - Carry = !(A[19:0] == C[19:0]); - $display("%5h ?A#C\tA", inst_start_PC); + // prepare ALU for register A + field <= `T_FIELD_A; + alu_first <= 0; + alu_last <= 4; + alu_op <= nb_in[2]?`ALU_OP_TEST_NEQ:`ALU_OP_TEST_EQ; + if (!nb_in[3]) begin + alu_reg_src1 <= {2'b00, nb_in[0], !(nb_in[1] | nb_in[0])}; + alu_reg_src2 <= {2'b00, nb_in[1:0]}; end - default: begin - $display("ERROR : DEC_8AX"); - decode_error <= 1; + else begin + alu_reg_src1 <= {2'b00, nb_in[1:0]}; + alu_reg_src2 <= `ALU_REG_0; end + alu_debug <= 1; + next_cycle <= `BUSCMD_NOP; + decstate <= `DEC_ALU_INIT; + alu_return <= `DEC_TEST_GO; + +`ifdef SIM + $write("%5h ?", inst_start_PC); + + case ({2'b00, (nb_in[3]?nb_in[1:0]:{nb_in[0], !(nb_in[1] | nb_in[0])})}) + `ALU_REG_A: $write("A"); + `ALU_REG_B: $write("B"); + `ALU_REG_C: $write("C"); + `ALU_REG_D: $write("D"); endcase - decstate <= `DEC_TEST_GO; + + $write("%s", nb_in[2]?"#":"="); + + case (nb_in[3]?`ALU_REG_0:{2'b00, nb_in[1:0]}) + `ALU_REG_A: $write("A"); + `ALU_REG_B: $write("B"); + `ALU_REG_C: $write("C"); + `ALU_REG_D: $write("D"); + `ALU_REG_0: $write("0"); + endcase + + $display("\tA"); +`endif end diff --git a/opcodes/A[ab]x.v b/opcodes/A[ab]x.v index eacfccc..590dc9a 100644 --- a/opcodes/A[ab]x.v +++ b/opcodes/A[ab]x.v @@ -20,7 +20,7 @@ if (!nb_in[2]) alu_op <= `ALU_OP_ZERO; else begin alu_op <= `ALU_OP_COPY; - alu_reg_src1 <= {nb_in[0], (!(nb_in[0] | nb_in[1])) & nb_in[2]}; + alu_reg_src1 <= {2'b00, nb_in[0], (!(nb_in[0] | nb_in[1])) & nb_in[2]}; end; end else begin $display("DEC_Axx_EXEC %h", nb_in); @@ -30,6 +30,7 @@ alu_debug <= 1; next_cycle <= `BUSCMD_NOP; decstate <= `DEC_ALU_INIT; + alu_return <= `DEC_START; `ifdef SIM $write("%5h ", inst_start_PC); if (!nb_in[3]) diff --git a/opcodes/B[ab]x.v b/opcodes/B[ab]x.v index 281e407..b2e92e5 100644 --- a/opcodes/B[ab]x.v +++ b/opcodes/B[ab]x.v @@ -29,4 +29,5 @@ alu_debug <= 1; next_cycle <= `BUSCMD_NOP; decstate <= `DEC_ALU_INIT; + alu_return <= `DEC_START; end \ No newline at end of file diff --git a/opcodes/Fx.v b/opcodes/Fx.v index afb0f82..544f27d 100644 --- a/opcodes/Fx.v +++ b/opcodes/Fx.v @@ -8,54 +8,45 @@ `include "decstates.v" `DEC_FX: begin - case (nb_in) - 4'h8, 4'h9, 4'hA, 4'hB: begin - if (!hex_dec) begin - case (nb_in) - 4'h8: {Carry, A[19:0]} <= - A[19:0]; - 4'h9: {Carry, B[19:0]} <= - B[19:0]; - 4'hA: {Carry, C[19:0]} <= - C[19:0]; - 4'hB: {Carry, D[19:0]} <= - D[19:0]; - endcase - decstate <= `DEC_START; - end + field <= `T_FIELD_A; + alu_first <= 0; + alu_last <= 4; + alu_reg_dest <= {2'b00, nb_in[1:0]}; + + if (!nb_in[3]) begin + $display("F%h shifts not implemented"); + decode_error <= 1; + end else begin + alu_reg_src1 <= {2'b00, nb_in[1:0]}; + alu_op <= nb_in[2]?`ALU_OP_1CMPL:`ALU_OP_2CMPL; + end + alu_debug <= 1; + next_cycle <= `BUSCMD_NOP; + decstate <= `DEC_ALU_INIT; + alu_return <= `DEC_START; + `ifdef SIM - $write("%5h ", inst_start_PC); - case (nb_in) - 4'h8: $write("A=-A"); - 4'h8: $write("B=-B"); - 4'h8: $write("C=-C"); - 4'h8: $write("D=-D"); - endcase - if (!hex_dec) $display("\tA"); - else $display("\tA\t\t\t <=== DEC MODE NOT IMPLEMENTED"); -`endif - end - 4'hC, 4'hD, 4'hE, 4'hF: begin - if (!hex_dec) begin - case (nb_in) - 4'hC: {Carry, A[19:0]} <= - A[19:0] - 1; - 4'hD: {Carry, B[19:0]} <= - B[19:0] - 1; - 4'hE: {Carry, C[19:0]} <= - C[19:0] - 1; - 4'hF: {Carry, D[19:0]} <= - D[19:0] - 1; - endcase - decstate <= `DEC_START; - end -`ifdef SIM - $write("%5h ", inst_start_PC); - case (nb_in) - 4'h8: $write("A=-A-1"); - 4'h8: $write("B=-B-1"); - 4'h8: $write("C=-C-1"); - 4'h8: $write("D=-D-1"); - endcase - if (!hex_dec) $display("\tA"); - else $display("\tA\t\t\t <=== DEC MODE NOT IMPLEMENTED"); -`endif - end - default: begin - $display("ERROR : DEC_FX"); - decode_error <= 1; - end + $write("%5h ", inst_start_PC); + case ({2'b00, nb_in[1:0]}) + `ALU_REG_A: $write("A"); + `ALU_REG_B: $write("B"); + `ALU_REG_C: $write("C"); + `ALU_REG_D: $write("D"); endcase + if (!nb_in[3]) begin + $write("S"); + if (!nb_in[2]) $write("L"); + else $write("R"); + end else begin + $write("=-"); + case ({2'b00, nb_in[1:0]}) + `ALU_REG_A: $write("A"); + `ALU_REG_B: $write("B"); + `ALU_REG_C: $write("C"); + `ALU_REG_D: $write("D"); + endcase + if (nb_in[2]) $write("-1"); + end + $display("\tA"); +`endif end diff --git a/opcodes/z_alu_phase_2.v b/opcodes/z_alu_phase_2.v index b507082..38e3594 100644 --- a/opcodes/z_alu_phase_2.v +++ b/opcodes/z_alu_phase_2.v @@ -3,8 +3,21 @@ case (decstate) `ifdef SIM if (alu_debug) begin $display("------------------------------- z_alu_phase_2 ---------------------------------"); - $display("ALU OP %h | FRST %h | LAST %h | SRC1 %h | SRC2 %h | DEST %h", - alu_op, alu_first, alu_last, alu_reg_src1, alu_reg_src2,alu_reg_dest); + $write("ALU OP "); + case (alu_op) + `ALU_OP_ZERO: $write("ZERO "); + `ALU_OP_COPY: $write("COPY "); + `ALU_OP_EXCH: $write("EXCH "); + `ALU_OP_SHL: $write("SHL "); + `ALU_OP_SHR: $write("SHR "); + `ALU_OP_2CMPL: $write("2CMPL "); + `ALU_OP_1CMPL: $write("1CMPL "); + `ALU_OP_INC: $write("INC "); + `ALU_OP_TEST_EQ: $write("TEST_EQ "); + `ALU_OP_TEST_NEQ: $write("TEST_NEQ"); + endcase + $display(" | FRST %h | LAST %h | SRC1 %h | SRC2 %h | DEST %h", + alu_first, alu_last, alu_reg_src1, alu_reg_src2,alu_reg_dest); $display("CARRY %b | STICKY-BIT %b", Carry, HST[1]); case (alu_reg_dest) `ALU_REG_A: $display("A: %h", A); @@ -24,21 +37,88 @@ case (decstate) $display(""); end `endif + +/* + * + * Setting up SRC1 register for operations + * + */ + +`ifdef SIM + $display("setting up source 1 registers"); +`endif case (alu_op) - `ALU_OP_INC: begin + `ALU_OP_2CMPL, + `ALU_OP_1CMPL, + `ALU_OP_INC, + `ALU_OP_TEST_EQ, + `ALU_OP_TEST_NEQ: begin case (alu_reg_src1) `ALU_REG_A: alu_src1 <= A[alu_first*4+:4]; `ALU_REG_B: alu_src1 <= B[alu_first*4+:4]; `ALU_REG_C: alu_src1 <= C[alu_first*4+:4]; `ALU_REG_D: alu_src1 <= D[alu_first*4+:4]; endcase - alu_carry <= (decstate == `DEC_ALU_INIT)?1:Carry; end default: begin `ifdef SIM - $display("nothing to do I suppose"); + $display("no source 1 required"); `endif end endcase + +/* + * + * Setting up SRC2 register for operations + * + */ + + case (alu_op) + `ALU_OP_TEST_EQ, + `ALU_OP_TEST_NEQ: begin + case (alu_reg_src2) + `ALU_REG_A: alu_src2 <= A[alu_first*4+:4]; + `ALU_REG_B: alu_src2 <= B[alu_first*4+:4]; + `ALU_REG_C: alu_src2 <= C[alu_first*4+:4]; + `ALU_REG_D: alu_src2 <= D[alu_first*4+:4]; + `ALU_REG_0: alu_src2 <= 0; + endcase + end + default: begin +`ifdef SIM + $display("no source 2 required"); +`endif + end + endcase + +/* + * + * update internal carry + * + */ + + case (alu_op) + /* + * option 1: carry starts at 0 (not used yet) + */ +// alu_carry <= (decstate == `DEC_ALU_INIT)?0:Carry; + /* + * option 2: carry starts at 1 + */ + `ALU_OP_2CMPL, + `ALU_OP_1CMPL, + `ALU_OP_INC, + `ALU_OP_TEST_EQ, + `ALU_OP_TEST_NEQ: + alu_carry <= (decstate == `DEC_ALU_INIT)?1:Carry; + /* + * option 3: carry is always cleared + */ + `ALU_OP_1CMPL: + Carry <= 0; + endcase + + if (alu_last == alu_first) alu_next_cycle <= `BUSCMD_PC_READ; + else alu_next_cycle <= `BUSCMD_NOP; end endcase diff --git a/opcodes/z_alu_phase_3.v b/opcodes/z_alu_phase_3.v index b83fece..1f0a1fa 100644 --- a/opcodes/z_alu_phase_3.v +++ b/opcodes/z_alu_phase_3.v @@ -26,20 +26,39 @@ endcase alu_first <= (alu_first + 1) & 4'hF; end - `ALU_OP_SHR: begin - + `ALU_OP_2CMPL: begin + case (alu_reg_dest) + `ALU_REG_A: {Carry, A[alu_first*4+:4]} <= !alu_src1 + alu_carry; + default: $display("ALU_OP_2CMPL register not handled"); + endcase + alu_first <= (alu_first + 1) & 4'hF; + end + `ALU_OP_1CMPL: begin + case (alu_reg_dest) + `ALU_REG_A: A[alu_first*4+:4] <= ~alu_src1; + default: $display("ALU_OP_1CMPL register not handled"); + endcase + alu_first <= (alu_first + 1) & 4'hF; end `ALU_OP_INC: begin - $display("ALU_OP_INC"); case (alu_reg_dest) `ALU_REG_D: {Carry, D[alu_first*4+:4]} <= alu_src1 + alu_carry; default: $display("ALU_OP_INC register not handled"); endcase alu_first <= (alu_first + 1) & 4'hF; end + `ALU_OP_TEST_EQ: begin + Carry <= (alu_src1 == alu_src2) & alu_carry; + alu_first <= (alu_first + 1) & 4'hF; + end + `ALU_OP_TEST_NEQ: begin + Carry <= (alu_src1 != alu_src2) & alu_carry; + alu_first <= (alu_first + 1) & 4'hF; + end default: begin `ifdef SIM - + $display("ALU: operation not implemented"); + decode_error <= 1; `endif end endcase @@ -47,7 +66,8 @@ if (alu_last == alu_first) begin // the alu is done - decstate <= `DEC_START; + next_cycle <= alu_next_cycle; + decstate <= alu_return; alu_requested_halt <= alu_halt; end else decstate <= `DEC_ALU_CONT; diff --git a/saturn_core.v b/saturn_core.v index 39b9a5e..0176cd4 100644 --- a/saturn_core.v +++ b/saturn_core.v @@ -142,6 +142,8 @@ reg alu_carry; reg alu_debug; reg alu_halt; reg alu_requested_halt; +reg [11:0] alu_return; +reg [3:0] alu_next_cycle; // processor registers reg [19:0] PC; @@ -358,7 +360,7 @@ always @(posedge ph2) begin end always @(posedge ph3) begin - if (cycle_ctr == 630) + if (cycle_ctr == 260) debug_stop <= 1; end @@ -375,7 +377,8 @@ always @(posedge dec_strobe) begin if ((next_cycle == `BUSCMD_LOAD_PC)| (next_cycle == `BUSCMD_CONFIGURE)| (next_cycle == `BUSCMD_RESET)| - ((next_cycle == `BUSCMD_NOP)&(decstate == `DEC_START))) begin + ((next_cycle == `BUSCMD_NOP)& + (decstate == `DEC_START))) begin $display("SETTING next_cycle to BUSCMD_PC_READ"); next_cycle <= `BUSCMD_PC_READ; end else begin @@ -392,8 +395,8 @@ always @(posedge dec_strobe) begin $display(" RSTK0: %5h", RSTK[0]); end `endif - $display("CYCLE %d | INSTR %d | PC %h | DECSTATE %3h | NIBBLE %h", - cycle_ctr, + $display("CYCLE %d | NEXTC %h | INSTR %d | PC %h | DECSTATE %3h | NIBBLE %h", + cycle_ctr, next_cycle, (decstate == `DEC_START)?instr_ctr+1:instr_ctr, PC, decstate, nb_in); case (decstate)