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_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),

View file

@ -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;
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);
`endif
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 */
bus_program[bus_prog_addr] <= {1'b1, `BUSCMD_LOAD_PC };
`ifdef SIM
@ -576,9 +592,14 @@ 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
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:
@ -588,11 +609,21 @@ always @(posedge i_clk) begin
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,12 +702,17 @@ always @(posedge i_clk) begin
end
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;

View file

@ -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

View file

@ -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);

View file

@ -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;
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);
// 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);
$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;
$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
/*
* 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