make it so that execution of bus programs happen

in the same cycle as the instruction
modify the way jump and rtn are handled
add some registers to the debugger
This commit is contained in:
Raphael Jacquot 2019-03-14 16:37:51 +01:00
parent e97ec2243f
commit c62d562008
5 changed files with 186 additions and 47 deletions

View file

@ -89,6 +89,7 @@ saturn_control_unit control_unit (
.o_error (ctrl_unit_error), .o_error (ctrl_unit_error),
.o_alu_busy (alu_busy), .o_alu_busy (alu_busy),
.o_exec_unit_busy (exec_unit_busy),
/* debugger interface */ /* debugger interface */
.o_current_pc (ctrl_current_pc), .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] ctrl_unit_no_read;
wire [0:0] alu_busy; wire [0:0] alu_busy;
wire [0:0] exec_unit_busy;
/* debugger insterface */ /* debugger insterface */
wire [19:0] ctrl_current_pc; wire [19:0] ctrl_current_pc;
@ -161,6 +163,7 @@ saturn_debugger debugger (
.o_debug_cycle (dbg_debug_cycle), .o_debug_cycle (dbg_debug_cycle),
.i_alu_busy (alu_busy), .i_alu_busy (alu_busy),
.i_exec_unit_busy (exec_unit_busy),
/* debugger interface */ /* debugger interface */
.i_current_pc (ctrl_current_pc), .i_current_pc (ctrl_current_pc),

View file

@ -44,6 +44,7 @@ module saturn_control_unit (
/* alu is busy doing something */ /* alu is busy doing something */
o_alu_busy, o_alu_busy,
o_exec_unit_busy,
/* debugger interface */ /* debugger interface */
@ -92,7 +93,14 @@ output wire [0:0] o_error;
assign o_error = control_unit_error || dec_error; assign o_error = control_unit_error || dec_error;
output wire [0:0] o_alu_busy; 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 */ /* debugger interface */
@ -153,6 +161,7 @@ saturn_inst_decoder instruction_decoder(
.i_bus_busy (i_bus_busy), .i_bus_busy (i_bus_busy),
.i_alu_busy (o_alu_busy), .i_alu_busy (o_alu_busy),
.i_exec_unit_busy (o_exec_unit_busy),
.i_nibble (i_nibble), .i_nibble (i_nibble),
.i_reg_p (reg_P), .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_alu = (dec_instr_type == `INSTR_TYPE_ALU);
wire [0:0] inst_jump = (dec_instr_type == `INSTR_TYPE_JUMP); 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_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_c = (dec_alu_reg_dest == `ALU_REG_C);
wire [0:0] reg_dest_hst = (dec_alu_reg_dest == `ALU_REG_HST); 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 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 * PC and RSTK module
@ -244,6 +261,7 @@ saturn_regs_pc_rstk regs_pc_rstk (
.i_bus_busy (i_bus_busy), .i_bus_busy (i_bus_busy),
.i_alu_busy (o_alu_busy), .i_alu_busy (o_alu_busy),
.i_exec_unit_busy (o_exec_unit_busy),
.i_nibble (i_nibble), .i_nibble (i_nibble),
.i_jump_instr (inst_jump), .i_jump_instr (inst_jump),
@ -379,6 +397,8 @@ reg [4:0] bus_program[0:31];
reg [4:0] bus_prog_addr; reg [4:0] bus_prog_addr;
reg [2:0] addr_nibble_ptr; reg [2:0] addr_nibble_ptr;
reg [0:0] load_pc_loop; reg [0:0] load_pc_loop;
reg [0:0] send_reg_PC;
reg [0:0] send_reg_C_A; reg [0:0] send_reg_C_A;
reg [0:0] send_pc_read; reg [0:0] send_pc_read;
@ -398,6 +418,8 @@ initial begin
bus_prog_addr = 5'd0; bus_prog_addr = 5'd0;
addr_nibble_ptr = 3'd0; addr_nibble_ptr = 3'd0;
load_pc_loop = 1'b0; load_pc_loop = 1'b0;
send_reg_PC = 1'b0;
send_reg_C_A = 1'b0; send_reg_C_A = 1'b0;
send_pc_read = 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 */ /* this happend right after reset */
if (just_reset) begin
`ifdef SIM `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 `endif
just_reset <= 1'b0; just_reset <= 1'b0;
end else begin
`ifdef SIM
$display("CTRL %0d: [%d] reloading PC", i_phase, i_cycle_ctr);
`endif
end
/* this loads the PC to the modules */ /* this loads the PC to the modules */
bus_program[bus_prog_addr] <= {1'b1, `BUSCMD_LOAD_PC }; bus_program[bus_prog_addr] <= {1'b1, `BUSCMD_LOAD_PC };
`ifdef SIM `ifdef SIM
@ -576,23 +592,38 @@ always @(posedge i_clk) begin
`endif `endif
reg_alu_mode <= dec_alu_imm_value[0]; reg_alu_mode <= dec_alu_imm_value[0];
end end
`INSTR_TYPE_JUMP: begin end `INSTR_TYPE_JUMP,
`INSTR_TYPE_RTN: `INSTR_TYPE_RTN:
begin begin
case (dec_alu_opcode) if (inst_jump) begin
`ALU_OP_SET_CRY: reg_CARRY <= o_alu_imm_value[0]; $display("CTRL %0d: [%d] JUMP", i_phase, i_cycle_ctr);
default: end
begin if (inst_rtn) begin
$display("CTRL %0d: [%d] alu_opcode for RTN %0d", i_phase, i_cycle_ctr, dec_alu_opcode); $display("CTRL %0d: [%d] RTN", i_phase, i_cycle_ctr);
control_unit_error <= 1'b1; case (dec_alu_opcode)
end `ALU_OP_SET_CRY: reg_CARRY <= o_alu_imm_value[0];
endcase 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 end
`INSTR_TYPE_LOAD: `INSTR_TYPE_LOAD:
begin begin
case (dec_alu_reg_dest) case (dec_alu_reg_dest)
`ALU_REG_C: reg_C[dec_alu_ptr_begin] <= dec_alu_imm_value; `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: default:
begin begin
$display("CTRL %0d: [%d] unsupported register for load %0d", i_phase, i_cycle_ctr, dec_alu_reg_dest); $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 endcase
end 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) * send C(A)
* used for CONFIG and UNCNFG * used for CONFIG and UNCNFG
@ -650,11 +702,16 @@ always @(posedge i_clk) begin
end end
/****************************************************************************************** end
*
* ALU control
* /******************************************************************************************
*****************************************************************************************/ *
* ALU control
*
*****************************************************************************************/
if (i_clk_en && control_unit_ready) begin
if (alu_start && alu_prep_run && !alu_prep_done) 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); $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; bus_prog_addr <= 5'd0;
addr_nibble_ptr <= 3'd0; addr_nibble_ptr <= 3'd0;
load_pc_loop <= 1'b0; load_pc_loop <= 1'b0;
send_reg_PC <= 1'b0;
send_reg_C_A <= 1'b0; send_reg_C_A <= 1'b0;
send_pc_read <= 1'b0; send_pc_read <= 1'b0;

View file

@ -33,6 +33,7 @@ module saturn_debugger (
o_debug_cycle, o_debug_cycle,
i_alu_busy, i_alu_busy,
i_exec_unit_busy,
/* interface from the control unit */ /* interface from the control unit */
i_current_pc, i_current_pc,
@ -81,6 +82,7 @@ input wire [31:0] i_cycle_ctr;
output reg [0:0] o_debug_cycle; output reg [0:0] o_debug_cycle;
input wire [0:0] i_alu_busy; input wire [0:0] i_alu_busy;
input wire [0:0] i_exec_unit_busy;
/* inteface from the control unit */ /* inteface from the control unit */
input wire [19:0] i_current_pc; input wire [19:0] i_current_pc;
@ -187,7 +189,7 @@ end
always @(posedge i_clk) begin 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); $display("DEBUGGER %0d: [%d] start debugger cycle (alu_busy %b)", i_phase, i_cycle_ctr, i_alu_busy);
o_debug_cycle <= 1'b1; o_debug_cycle <= 1'b1;
registers_ctr <= 9'd0; registers_ctr <= 9'd0;
@ -586,6 +588,65 @@ always @(posedge i_clk) begin
if (registers_reg_ptr == 6'd0) begin if (registers_reg_ptr == 6'd0) begin
registers_reg_ptr <= 6'd0; registers_reg_ptr <= 6'd0;
o_dbg_register <= `ALU_REG_NONE; 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; registers_state <= `DBG_REG_SPACES_7;
end end
end end

View file

@ -32,6 +32,7 @@ module saturn_inst_decoder (
i_bus_busy, i_bus_busy,
i_alu_busy, i_alu_busy,
i_exec_unit_busy,
i_nibble, i_nibble,
i_reg_p, 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_bus_busy;
input wire [0:0] i_alu_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_nibble;
input wire [3:0] i_reg_p; input wire [3:0] i_reg_p;
@ -235,7 +237,7 @@ always @(posedge i_clk) begin
o_instr_decoded <= 1'b1; o_instr_decoded <= 1'b1;
end 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 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); // $display("DECODER %0d: [%d] store current PC as instruction start %5h", i_phase, i_cycle_ctr, i_current_pc);

View file

@ -30,6 +30,7 @@ module saturn_regs_pc_rstk (
i_bus_busy, i_bus_busy,
i_alu_busy, i_alu_busy,
i_exec_unit_busy,
i_nibble, i_nibble,
i_jump_instr, 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_bus_busy;
input wire [0:0] i_alu_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_nibble;
input wire [0:0] i_jump_instr; input wire [0:0] i_jump_instr;
@ -152,7 +154,7 @@ always @(posedge i_clk) begin
// if (!i_debug_cycle) // if (!i_debug_cycle)
// $display("PC_RSTK %0d: [%d] !i_bus_busy %b", i_phase, i_cycle_ctr, !i_bus_busy); // $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 if (i_phases[3] && just_reset) begin
$display("PC_RSTK %0d: [%d] exit from reset mode", i_phase, i_cycle_ctr); $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 * jump instruction calculations
*/ */
/* start the jump instruction */ /* start the jump instruction
if (i_phases[3] && do_jump_instr && !jump_decode && !jump_exec) begin * 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); $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_counter <= 3'd0;
jump_base <= reg_PC; jump_base <= reg_PC;
@ -182,25 +188,33 @@ always @(posedge i_clk) begin
jump_offset <= jump_next_offset; jump_offset <= jump_next_offset;
jump_counter <= jump_counter + 3'd1; jump_counter <= jump_counter + 3'd1;
if (jump_counter == i_jump_length) begin 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_decode <= 1'b0;
jump_exec <= 1'b1; // jump_exec <= 1'b1;
o_reload_pc <= 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
end end
/* all done, apply to PC and RSTK */ // /* all done, apply to PC and RSTK */
if (i_phases[3] && do_jump_instr && jump_exec) begin // 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); // $write("PC_RSTK %0d: [%d] execute jump %0d", i_phase, i_cycle_ctr, i_jump_length);
if (i_push_pc) begin // if (i_push_pc) begin
$write(" ( push %5h => RSTK[%0d])", reg_PC, reg_rstk_ptr + 3'd1); // $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[(reg_rstk_ptr + 3'o1)&3'o7] <= reg_PC;
reg_rstk_ptr <= reg_rstk_ptr + 3'd1; // reg_rstk_ptr <= reg_rstk_ptr + 3'd1;
end // end
$display(""); // $display("");
reg_PC <= jump_relative ? jump_offset + jump_base : jump_offset; // reg_PC <= jump_relative ? jump_offset + jump_base : jump_offset;
jump_exec <= 1'b0; // jump_exec <= 1'b0;
o_reload_pc <= 1'b0; // o_reload_pc <= 1'b0;
end // end
/* /*
* RTN instruction * RTN instruction
@ -216,7 +230,7 @@ always @(posedge i_clk) begin
4'h3: $display("CC"); 4'h3: $display("CC");
default: begin end default: begin end
endcase endcase
o_reload_pc <= 1'b1; // o_reload_pc <= 1'b1;
end end
if (i_phases[3] && i_rtn_instr) begin 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[reg_rstk_ptr] <= 20'h00000;
reg_rstk_ptr <= (reg_rstk_ptr - 3'd1) & 3'd7; reg_rstk_ptr <= (reg_rstk_ptr - 3'd1) & 3'd7;
/* o_reload_pc was set in advance above */ /* o_reload_pc was set in advance above */
o_reload_pc <= 1'b0; // o_reload_pc <= 1'b0;
end end
end end