diff --git a/saturn_bus.v b/saturn_bus.v index ad575ba..bb491d7 100644 --- a/saturn_bus.v +++ b/saturn_bus.v @@ -237,7 +237,7 @@ always @(posedge i_clk) begin end `ifdef SIM - if (cycle_ctr == 265) begin + if (cycle_ctr == 285) begin bus_halt <= 1'b1; $display("BUS %0d: [%d] enough cycles for now", phase, cycle_ctr); end diff --git a/saturn_control_unit.v b/saturn_control_unit.v index 4e043fc..87a3235 100644 --- a/saturn_control_unit.v +++ b/saturn_control_unit.v @@ -724,6 +724,9 @@ always @(posedge i_clk) begin endcase /* need to prepare the carry here */ + case (alu_opcode) + `ALU_OP_ADD: alu_prep_carry <= (alu_prep_pos == alu_ptr_begin) ? 1'b0 : alu_prep_carry; + endcase if (alu_prep_pos == alu_ptr_end) begin alu_prep_done <= 1'b1; @@ -753,6 +756,16 @@ always @(posedge i_clk) begin alu_calc_res_1_val <= alu_prep_src_2_val; alu_calc_res_2_val <= alu_prep_src_1_val; end + `ALU_OP_2CMPL: alu_calc_res_1_val <= ~alu_prep_src_1_val + 4'h1; + `ALU_OP_ADD: + begin + $display("ALU_CALC %0d: [%d] add | s1 %b | s2 %b | c %b | res %b | nc %b", i_phase, i_cycle_ctr, + alu_prep_src_1_val, alu_prep_src_2_val, {3'b0, alu_prep_carry}, + alu_prep_src_1_val + alu_prep_src_2_val + {3'b0, alu_prep_carry}, + alu_prep_src_1_val[3] && alu_prep_src_2_val[3] ); + alu_calc_res_1_val <= alu_prep_src_1_val + alu_prep_src_2_val + {3'b0, alu_prep_carry}; + alu_calc_carry <= alu_prep_src_1_val[3] && alu_prep_src_2_val[3]; + end default: $display("ALU_CALC %0d: [%d] unhandled opcode %0d", i_phase, i_cycle_ctr, alu_opcode); endcase @@ -799,6 +812,14 @@ always @(posedge i_clk) begin default: $display("ALU_SAVE %0d: [%d] exch: src_2 register %0d not supported", i_phase, i_cycle_ctr, alu_reg_src_2); endcase + alu_prep_carry <= alu_calc_carry; + case (alu_opcode) + // this may not be correct, need to check on the HP 49G + `ALU_OP_2CMPL: reg_CARRY <= reg_CARRY || ( | alu_calc_res_1_val); + `ALU_OP_ADD : reg_CARRY <= alu_calc_carry; + default: begin end + endcase + if (alu_save_pos == alu_ptr_end) begin alu_save_done <= 1'b1; alu_save_run <= 1'b0; diff --git a/saturn_inst_decoder.v b/saturn_inst_decoder.v index da84155..90de784 100644 --- a/saturn_inst_decoder.v +++ b/saturn_inst_decoder.v @@ -147,7 +147,9 @@ reg [0:0] block_84x_85x; reg [0:0] block_Ax; reg [0:0] block_Aax; reg [0:0] block_Abx; +reg [0:0] block_Cx; reg [0:0] block_Dx; +reg [0:0] block_Fx; reg [0:0] block_JUMP; reg [0:0] block_LOAD; @@ -200,7 +202,9 @@ initial begin block_Ax = 1'b0; block_Aax = 1'b0; block_Abx = 1'b0; + block_Cx = 1'b0; block_Dx = 1'b0; + block_Fx = 1'b0; block_JUMP = 1'b0; block_LOAD = 1'b0; @@ -280,7 +284,9 @@ always @(posedge i_clk) begin block_FIELDS <= 1'b1; fields_table <= `FT_A_B; end + 4'hC: block_Cx <= 1'b1; 4'hD: block_Dx <= 1'b1; + 4'hF: block_Fx <= 1'b1; default: begin $display("invalid instruction"); @@ -524,6 +530,27 @@ always @(posedge i_clk) begin block_Abx <= 1'b0; end + if (block_Cx) begin + $display("DECODER %0d: [%d] block_Cx %h", i_phase, i_cycle_ctr, i_nibble); + o_instr_type <= `INSTR_TYPE_ALU; + o_alu_field <= `FT_FIELD_A; + o_alu_ptr_begin <= 4'h0; + o_alu_ptr_end <= 4'h4; + o_alu_opcode <= (i_nibble[3] && i_nibble[2]) ? `ALU_OP_DEC : `ALU_OP_ADD; + o_alu_reg_dest <= (i_nibble[3] && !i_nibble[2]) ? regs_BCAC : regs_ABCD; + o_alu_reg_src_1 <= (i_nibble[3] && !i_nibble[2]) ? regs_BCAC : regs_ABCD; + case ({i_nibble[3], i_nibble[2]}) + 2'b00: o_alu_reg_src_2 <= regs_BCAC; + 2'b01, + 2'b10: o_alu_reg_src_2 <= regs_ABCD; + 2'b11: o_alu_reg_src_2 <= `ALU_REG_NONE; + endcase + o_instr_decoded <= 1'b1; + o_instr_execute <= 1'b1; + decode_started <= 1'b0; + block_Cx <= 1'b0; + end + if (block_Dx) begin $display("DECODER %0d: [%d] block_Dx %h", i_phase, i_cycle_ctr, i_nibble); o_instr_type <= `INSTR_TYPE_ALU; @@ -564,6 +591,27 @@ always @(posedge i_clk) begin block_Dx <= 1'b0; end + if (block_Fx) begin + $display("DECODER %0d: [%d] block_Fx %h", i_phase, i_cycle_ctr, i_nibble); + o_instr_type <= `INSTR_TYPE_ALU; + o_alu_field <= `FT_FIELD_A; + o_alu_ptr_begin <= 4'h0; + o_alu_ptr_end <= 4'h4; + o_alu_reg_dest <= regs_ABCD; + o_alu_reg_src_1 <= regs_ABCD; + o_alu_reg_src_2 <= `ALU_REG_NONE; + case ({i_nibble[3], i_nibble[2]}) + 2'b00: o_alu_opcode <= `ALU_OP_SHL; + 2'b01: o_alu_opcode <= `ALU_OP_SHR; + 2'b10: o_alu_opcode <= `ALU_OP_2CMPL; + 2'b11: o_alu_opcode <= `ALU_OP_1CMPL; + endcase + o_instr_decoded <= 1'b1; + o_instr_execute <= 1'b1; + decode_started <= 1'b0; + block_Fx <= 1'b0; + end + /* special cases */ if (block_JUMP) begin @@ -717,7 +765,9 @@ always @(posedge i_clk) begin block_Ax <= 1'b0; block_Aax <= 1'b0; block_Abx <= 1'b0; + block_Cx <= 1'b0; block_Dx <= 1'b0; + block_Fx <= 1'b0; block_JUMP <= 1'b0; block_LOAD <= 1'b0;