diff --git a/saturn_bus_controller.v b/saturn_bus_controller.v index 3c6ab75..6d41c7f 100644 --- a/saturn_bus_controller.v +++ b/saturn_bus_controller.v @@ -89,6 +89,7 @@ saturn_control_unit control_unit ( .o_error (ctrl_unit_error), .o_alu_busy (alu_busy), + .o_exec_unit_busy (exec_unit_busy), /* debugger interface */ .o_current_pc (ctrl_current_pc), @@ -122,6 +123,7 @@ wire [4:0] ctrl_unit_prog_data; wire [0:0] ctrl_unit_no_read; wire [0:0] alu_busy; +wire [0:0] exec_unit_busy; /* debugger insterface */ wire [19:0] ctrl_current_pc; @@ -161,6 +163,7 @@ saturn_debugger debugger ( .o_debug_cycle (dbg_debug_cycle), .i_alu_busy (alu_busy), + .i_exec_unit_busy (exec_unit_busy), /* debugger interface */ .i_current_pc (ctrl_current_pc), diff --git a/saturn_control_unit.v b/saturn_control_unit.v index 1707855..de9d341 100644 --- a/saturn_control_unit.v +++ b/saturn_control_unit.v @@ -44,6 +44,7 @@ module saturn_control_unit ( /* alu is busy doing something */ o_alu_busy, + o_exec_unit_busy, /* debugger interface */ @@ -92,7 +93,14 @@ output wire [0:0] o_error; assign o_error = control_unit_error || dec_error; output wire [0:0] o_alu_busy; -assign o_alu_busy = inst_alu_other || alu_start; +output wire [0:0] o_exec_unit_busy; +assign o_alu_busy = inst_alu_other || alu_start; +assign o_exec_unit_busy = i_bus_busy || + alu_busy || + jump_busy || + rtn_busy || + reset_busy || + config_busy; /* debugger interface */ @@ -153,6 +161,7 @@ saturn_inst_decoder instruction_decoder( .i_bus_busy (i_bus_busy), .i_alu_busy (o_alu_busy), + .i_exec_unit_busy (o_exec_unit_busy), .i_nibble (i_nibble), .i_reg_p (reg_P), @@ -203,6 +212,8 @@ wire [0:0] dec_error; wire [0:0] inst_alu = (dec_instr_type == `INSTR_TYPE_ALU); wire [0:0] inst_jump = (dec_instr_type == `INSTR_TYPE_JUMP); wire [0:0] inst_rtn = (dec_instr_type == `INSTR_TYPE_RTN); +wire [0:0] inst_reset = (dec_instr_type == `INSTR_TYPE_RESET); +wire [0:0] inst_config = (dec_instr_type == `INSTR_TYPE_CONFIG); wire [0:0] reg_dest_c = (dec_alu_reg_dest == `ALU_REG_C); wire [0:0] reg_dest_hst = (dec_alu_reg_dest == `ALU_REG_HST); @@ -228,6 +239,12 @@ wire [0:0] inst_alu_other = inst_alu && inst_alu_st_eq_01_n ); +wire [0:0] alu_busy = inst_alu_other || alu_start; +wire [0:0] jump_busy = (inst_jump && dec_instr_decoded) || send_reg_PC; +wire [0:0] rtn_busy = (inst_rtn && dec_instr_decoded) || send_reg_PC; +wire [0:0] reset_busy = inst_reset; +wire [0:0] config_busy = inst_config; + /************************************************************************************************** * * PC and RSTK module @@ -244,6 +261,7 @@ saturn_regs_pc_rstk regs_pc_rstk ( .i_bus_busy (i_bus_busy), .i_alu_busy (o_alu_busy), + .i_exec_unit_busy (o_exec_unit_busy), .i_nibble (i_nibble), .i_jump_instr (inst_jump), @@ -379,6 +397,8 @@ reg [4:0] bus_program[0:31]; reg [4:0] bus_prog_addr; reg [2:0] addr_nibble_ptr; reg [0:0] load_pc_loop; + +reg [0:0] send_reg_PC; reg [0:0] send_reg_C_A; reg [0:0] send_pc_read; @@ -398,6 +418,8 @@ initial begin bus_prog_addr = 5'd0; addr_nibble_ptr = 3'd0; load_pc_loop = 1'b0; + + send_reg_PC = 1'b0; send_reg_C_A = 1'b0; send_pc_read = 1'b0; @@ -432,18 +454,12 @@ always @(posedge i_clk) begin * */ - if (i_clk_en && (just_reset || reload_PC) && i_phases[3]) begin + if (i_clk_en && just_reset && i_phases[3]) begin /* this happend right after reset */ - if (just_reset) begin `ifdef SIM - $display("CTRL %0d: [%d] we were just reset, loading PC", i_phase, i_cycle_ctr); + $display("CTRL %0d: [%d] we were just reset, loading PC", i_phase, i_cycle_ctr); `endif - just_reset <= 1'b0; - end else begin -`ifdef SIM - $display("CTRL %0d: [%d] reloading PC", i_phase, i_cycle_ctr); -`endif - end + just_reset <= 1'b0; /* this loads the PC to the modules */ bus_program[bus_prog_addr] <= {1'b1, `BUSCMD_LOAD_PC }; `ifdef SIM @@ -576,23 +592,38 @@ always @(posedge i_clk) begin `endif reg_alu_mode <= dec_alu_imm_value[0]; end - `INSTR_TYPE_JUMP: begin end + `INSTR_TYPE_JUMP, `INSTR_TYPE_RTN: begin - case (dec_alu_opcode) - `ALU_OP_SET_CRY: reg_CARRY <= o_alu_imm_value[0]; - default: - begin - $display("CTRL %0d: [%d] alu_opcode for RTN %0d", i_phase, i_cycle_ctr, dec_alu_opcode); - control_unit_error <= 1'b1; - end - endcase + if (inst_jump) begin + $display("CTRL %0d: [%d] JUMP", i_phase, i_cycle_ctr); + end + if (inst_rtn) begin + $display("CTRL %0d: [%d] RTN", i_phase, i_cycle_ctr); + case (dec_alu_opcode) + `ALU_OP_SET_CRY: reg_CARRY <= o_alu_imm_value[0]; + default: + begin + $display("CTRL %0d: [%d] alu_opcode for RTN %0d", i_phase, i_cycle_ctr, dec_alu_opcode); + control_unit_error <= 1'b1; + end + endcase + end + + if (dec_instr_decoded) begin + $display("CTRL %0d: [%d] exec : JUMP/RTN reload pc to %5h", i_phase, i_cycle_ctr, reg_PC); + bus_program[bus_prog_addr] <= {1'b1, `BUSCMD_LOAD_PC }; + bus_prog_addr <= bus_prog_addr + 5'd1; + addr_nibble_ptr <= 3'b0; + send_reg_PC <= 1'b1; + end + end `INSTR_TYPE_LOAD: begin case (dec_alu_reg_dest) `ALU_REG_C: reg_C[dec_alu_ptr_begin] <= dec_alu_imm_value; - `ALU_REG_D0: reg_D0[dec_alu_ptr_begin] <= dec_alu_imm_value; + `ALU_REG_D0: reg_D0[dec_alu_ptr_begin[2:0]] <= dec_alu_imm_value; default: begin $display("CTRL %0d: [%d] unsupported register for load %0d", i_phase, i_cycle_ctr, dec_alu_reg_dest); @@ -624,6 +655,27 @@ always @(posedge i_clk) begin endcase end + end + + /********************************************************************************************** + * + * sending bus programs + * + *********************************************************************************************/ + + if (i_clk_en && control_unit_ready) begin + + if (send_reg_PC) begin + $display("CTRL %0d: [%d] exec: send_reg_PC[%0d] %h", i_phase, i_cycle_ctr, addr_nibble_ptr, reg_PC[addr_nibble_ptr*4+:4] ); + bus_program[bus_prog_addr] <= { 1'b0, reg_PC[addr_nibble_ptr*4+:4] }; + addr_nibble_ptr <= addr_nibble_ptr + 3'd1; + bus_prog_addr <= bus_prog_addr + 5'd1; + if (addr_nibble_ptr == 3'd4) begin + addr_nibble_ptr <= 3'd0; + send_reg_PC <= 1'b0; + end + end + /* * send C(A) * used for CONFIG and UNCNFG @@ -650,11 +702,16 @@ always @(posedge i_clk) begin end - /****************************************************************************************** - * - * ALU control - * - *****************************************************************************************/ + end + + + /****************************************************************************************** + * + * ALU control + * + *****************************************************************************************/ + + if (i_clk_en && control_unit_ready) begin if (alu_start && alu_prep_run && !alu_prep_done) begin $display("ALU_PREP %0d: [%d] b %h | p %h | e %h", i_phase, i_cycle_ctr, alu_ptr_begin, alu_prep_pos, alu_ptr_end); @@ -714,6 +771,8 @@ always @(posedge i_clk) begin bus_prog_addr <= 5'd0; addr_nibble_ptr <= 3'd0; load_pc_loop <= 1'b0; + + send_reg_PC <= 1'b0; send_reg_C_A <= 1'b0; send_pc_read <= 1'b0; diff --git a/saturn_debugger.v b/saturn_debugger.v index b53c970..c74b1c2 100644 --- a/saturn_debugger.v +++ b/saturn_debugger.v @@ -33,6 +33,7 @@ module saturn_debugger ( o_debug_cycle, i_alu_busy, + i_exec_unit_busy, /* interface from the control unit */ i_current_pc, @@ -81,6 +82,7 @@ input wire [31:0] i_cycle_ctr; output reg [0:0] o_debug_cycle; input wire [0:0] i_alu_busy; +input wire [0:0] i_exec_unit_busy; /* inteface from the control unit */ input wire [19:0] i_current_pc; @@ -187,7 +189,7 @@ end always @(posedge i_clk) begin - if (i_clk_en && i_phases[3] && i_instr_decoded && !debug_done && !i_alu_busy) begin + if (i_clk_en && i_phases[3] && i_instr_decoded && !debug_done && !i_exec_unit_busy) begin $display("DEBUGGER %0d: [%d] start debugger cycle (alu_busy %b)", i_phase, i_cycle_ctr, i_alu_busy); o_debug_cycle <= 1'b1; registers_ctr <= 9'd0; @@ -586,6 +588,65 @@ always @(posedge i_clk) begin if (registers_reg_ptr == 6'd0) begin registers_reg_ptr <= 6'd0; o_dbg_register <= `ALU_REG_NONE; + registers_state <= `DBG_REG_R4_STR; + end + end + `DBG_REG_R4_STR: + begin + case (registers_reg_ptr) + 6'd0: registers_str[registers_ctr] <= " "; + 6'd1: registers_str[registers_ctr] <= " "; + 6'd2: registers_str[registers_ctr] <= "R"; + 6'd3: registers_str[registers_ctr] <= "4"; + 6'd4: registers_str[registers_ctr] <= ":"; + 6'd5: registers_str[registers_ctr] <= " "; + 6'd6: registers_str[registers_ctr] <= " "; + default: begin end + endcase + registers_reg_ptr <= registers_reg_ptr + 6'd1; + if (registers_reg_ptr == 6'd6) begin + registers_reg_ptr <= 6'd15; + o_dbg_register <= `ALU_REG_R4; + registers_state <= `DBG_REG_R4_VALUE; + end + end + `DBG_REG_R4_VALUE: + begin + registers_str[registers_ctr] <= hex[i_dbg_reg_nibble]; + registers_reg_ptr <= registers_reg_ptr - 6'd1; + if (registers_reg_ptr == 6'd0) begin + registers_reg_ptr <= 6'd0; + o_dbg_register <= `ALU_REG_NONE; + registers_state <= `DBG_REG_RSTK1_STR; + end + end + `DBG_REG_RSTK1_STR: + begin + case (registers_reg_ptr) + 6'd0: registers_str[registers_ctr] <= " "; + 6'd1: registers_str[registers_ctr] <= " "; + 6'd2: registers_str[registers_ctr] <= "R"; + 6'd3: registers_str[registers_ctr] <= "S"; + 6'd4: registers_str[registers_ctr] <= "T"; + 6'd5: registers_str[registers_ctr] <= "K"; + 6'd6: registers_str[registers_ctr] <= "1"; + 6'd7: registers_str[registers_ctr] <= ":"; + 6'd8: registers_str[registers_ctr] <= " "; + default: begin end + endcase + registers_reg_ptr <= registers_reg_ptr + 6'd1; + if (registers_reg_ptr == 6'd8) begin + registers_reg_ptr <= 6'd4; + o_dbg_rstk_ptr <= 3'd1; + registers_state <= `DBG_REG_RSTK1_VALUE; + end + end + `DBG_REG_RSTK1_VALUE: + begin + registers_str[registers_ctr] <= hex[i_dbg_rstk_val[(registers_reg_ptr)*4+:4]]; + registers_reg_ptr <= registers_reg_ptr - 6'd1; + if (registers_reg_ptr == 6'd0) begin + registers_reg_ptr <= 6'd0; registers_state <= `DBG_REG_SPACES_7; end end diff --git a/saturn_inst_decoder.v b/saturn_inst_decoder.v index e8ad29e..a9ad894 100644 --- a/saturn_inst_decoder.v +++ b/saturn_inst_decoder.v @@ -32,6 +32,7 @@ module saturn_inst_decoder ( i_bus_busy, i_alu_busy, + i_exec_unit_busy, i_nibble, i_reg_p, @@ -70,6 +71,7 @@ input wire [31:0] i_cycle_ctr; input wire [0:0] i_bus_busy; input wire [0:0] i_alu_busy; +input wire [0:0] i_exec_unit_busy; input wire [3:0] i_nibble; input wire [3:0] i_reg_p; @@ -235,7 +237,7 @@ always @(posedge i_clk) begin o_instr_decoded <= 1'b1; end - if (i_clk_en && !i_bus_busy && !i_alu_busy) begin + if (i_clk_en && !i_bus_busy && !i_exec_unit_busy) begin if (i_phases[1] && !decode_started) begin // $display("DECODER %0d: [%d] store current PC as instruction start %5h", i_phase, i_cycle_ctr, i_current_pc); diff --git a/saturn_regs_pc_rstk.v b/saturn_regs_pc_rstk.v index d484ed2..bb33907 100644 --- a/saturn_regs_pc_rstk.v +++ b/saturn_regs_pc_rstk.v @@ -30,6 +30,7 @@ module saturn_regs_pc_rstk ( i_bus_busy, i_alu_busy, + i_exec_unit_busy, i_nibble, i_jump_instr, @@ -56,6 +57,7 @@ input wire [31:0] i_cycle_ctr; input wire [0:0] i_bus_busy; input wire [0:0] i_alu_busy; +input wire [0:0] i_exec_unit_busy; input wire [3:0] i_nibble; input wire [0:0] i_jump_instr; @@ -152,7 +154,7 @@ always @(posedge i_clk) begin // if (!i_debug_cycle) // $display("PC_RSTK %0d: [%d] !i_bus_busy %b", i_phase, i_cycle_ctr, !i_bus_busy); - if (i_clk_en && !i_bus_busy && !i_alu_busy) begin + if (i_clk_en && !i_bus_busy && !i_exec_unit_busy) begin if (i_phases[3] && just_reset) begin $display("PC_RSTK %0d: [%d] exit from reset mode", i_phase, i_cycle_ctr); @@ -168,8 +170,12 @@ always @(posedge i_clk) begin * jump instruction calculations */ - /* start the jump instruction */ - if (i_phases[3] && do_jump_instr && !jump_decode && !jump_exec) begin + /* start the jump instruction + * the jump base is: + * address of first nibble of the offset when goto + * address of nibble after the offset when gosub + */ + if (i_phases[3] && do_jump_instr && !jump_decode) begin $display("PC_RSTK %0d: [%d] start decode jump %0d | jump_base %5h", i_phase, i_cycle_ctr, i_jump_length, reg_PC); jump_counter <= 3'd0; jump_base <= reg_PC; @@ -182,25 +188,33 @@ always @(posedge i_clk) begin jump_offset <= jump_next_offset; jump_counter <= jump_counter + 3'd1; if (jump_counter == i_jump_length) begin + $write("PC_RSTK %0d: [%d] execute jump(%0d) jump_base %h jump_next_offset %h", i_phase, i_cycle_ctr, i_jump_length, jump_base, jump_next_offset); jump_decode <= 1'b0; - jump_exec <= 1'b1; - o_reload_pc <= 1'b1; + // jump_exec <= 1'b1; + // o_reload_pc <= 1'b1; + reg_PC <= jump_relative ? jump_next_offset + jump_base : jump_next_offset; + if (i_push_pc) begin + $write(" ( push %5h => RSTK[%0d] )", reg_PC, reg_rstk_ptr + 3'd1); + reg_RSTK[(reg_rstk_ptr + 3'o1)&3'o7] <= reg_PC; + reg_rstk_ptr <= reg_rstk_ptr + 3'd1; + end + $write("\n"); end end - /* all done, apply to PC and RSTK */ - if (i_phases[3] && do_jump_instr && jump_exec) begin - $write("PC_RSTK %0d: [%d] execute jump %0d", i_phase, i_cycle_ctr, i_jump_length); - if (i_push_pc) begin - $write(" ( push %5h => RSTK[%0d])", reg_PC, reg_rstk_ptr + 3'd1); - reg_RSTK[(reg_rstk_ptr + 3'o1)&3'o7] <= reg_PC; - reg_rstk_ptr <= reg_rstk_ptr + 3'd1; - end - $display(""); - reg_PC <= jump_relative ? jump_offset + jump_base : jump_offset; - jump_exec <= 1'b0; - o_reload_pc <= 1'b0; - end + // /* all done, apply to PC and RSTK */ + // if (i_phases[3] && do_jump_instr && jump_exec) begin + // $write("PC_RSTK %0d: [%d] execute jump %0d", i_phase, i_cycle_ctr, i_jump_length); + // if (i_push_pc) begin + // $write(" ( push %5h => RSTK[%0d])", reg_PC, reg_rstk_ptr + 3'd1); + // reg_RSTK[(reg_rstk_ptr + 3'o1)&3'o7] <= reg_PC; + // reg_rstk_ptr <= reg_rstk_ptr + 3'd1; + // end + // $display(""); + // reg_PC <= jump_relative ? jump_offset + jump_base : jump_offset; + // jump_exec <= 1'b0; + // o_reload_pc <= 1'b0; + // end /* * RTN instruction @@ -216,7 +230,7 @@ always @(posedge i_clk) begin 4'h3: $display("CC"); default: begin end endcase - o_reload_pc <= 1'b1; + // o_reload_pc <= 1'b1; end if (i_phases[3] && i_rtn_instr) begin @@ -225,7 +239,7 @@ always @(posedge i_clk) begin reg_RSTK[reg_rstk_ptr] <= 20'h00000; reg_rstk_ptr <= (reg_rstk_ptr - 3'd1) & 3'd7; /* o_reload_pc was set in advance above */ - o_reload_pc <= 1'b0; + // o_reload_pc <= 1'b0; end end