start implementing jump instructions

This commit is contained in:
Raphaël Jacquot 2019-03-03 20:48:56 +01:00
parent d17a4eb533
commit 631b7f9153
4 changed files with 108 additions and 7 deletions

View file

@ -125,6 +125,8 @@ saturn_inst_decoder instruction_decoder(
.o_alu_imm_value (dec_alu_imm_value),
.o_alu_opcode (dec_alu_opcode),
.o_jump_length (dec_jump_length),
.o_instr_type (dec_instr_type),
.o_instr_decoded (dec_instr_decoded),
.o_instr_execute (dec_instr_execute)
@ -136,6 +138,8 @@ wire [4:0] dec_alu_reg_src_2;
wire [3:0] dec_alu_imm_value;
wire [4:0] dec_alu_opcode;
wire [2:0] dec_jump_length;
wire [3:0] dec_instr_type;
wire [0:0] dec_instr_decoded;
wire [0:0] dec_instr_execute;
@ -151,6 +155,8 @@ wire [0:0] aluop_copy = (dec_alu_opcode == `ALU_OP_COPY);
wire [0:0] inst_alu_p_eq_n = aluop_copy && reg_dest_p && reg_src_1_imm;
wire [0:0] inst_alu_other = !(inst_alu_p_eq_n);
wire [0:0] inst_jump = (dec_instr_type == `INSTR_TYPE_JUMP);
/**************************************************************************************************
*
* registers module (contains A, B, C, D, R0, R1, R2, R3, R4)
@ -174,7 +180,9 @@ saturn_regs_pc_rstk regs_pc_rstk (
.i_bus_busy (i_bus_busy),
.i_nibble (i_nibble),
.i_jump_instr (inst_jump),
.i_jump_length (dec_jump_length),
.o_current_pc (reg_PC)
);
@ -200,6 +208,8 @@ reg [4:0] bus_program[0:31];
reg [4:0] bus_prog_addr;
reg [2:0] addr_nibble_ptr;
reg [2:0] jump_counter;
wire [3:0] reg_PC_nibble = reg_PC[addr_nibble_ptr*4+:4];
assign o_program_data = bus_program[i_program_address];
@ -213,6 +223,8 @@ initial begin
control_unit_ready = 1'b0;
bus_prog_addr = 5'd0;
addr_nibble_ptr = 3'd0;
jump_counter = 3'd0;
/* registers */
reg_P = 4'b0;
@ -278,7 +290,7 @@ always @(posedge i_clk) begin
// `ifdef SIM
// $display("CTRL %0d: [%d] starting to do things", i_phase, i_cycle_ctr);
// `endif
if (i_cycle_ctr == 10) begin
if (i_cycle_ctr == 15) begin
control_unit_error <= 1'b1;
$display("CTRL %0d: [%d] enough cycles for now", i_phase, i_cycle_ctr);
end
@ -307,11 +319,22 @@ always @(posedge i_clk) begin
* the general case
*/
end
`INSTR_TYPE_JUMP: begin
$display("CTRL %0d: [%d] JUMP instruction", i_phase, i_cycle_ctr);
jump_counter <= 1'b0;
end
default: begin
$display("CTRL %0d: [%d] unsupported instruction", i_phase, i_cycle_ctr);
end
endcase
end
if (i_phases[2] && ! dec_instr_execute) begin
if (inst_jump) begin
// $display("CTRL %0d: [%d] JUMP nibble %0d : %h", i_phase, i_cycle_ctr, jump_counter, i_nibble);
jump_counter <= jump_counter + 3'd1;
end
end
end
if (i_reset) begin
@ -323,6 +346,8 @@ always @(posedge i_clk) begin
bus_prog_addr <= 5'd0;
addr_nibble_ptr <= 3'd0;
jump_counter <= 3'd0;
/* registers */
reg_P <= 4'b0;
end

View file

@ -98,6 +98,7 @@
`define INSTR_TYPE_NOP 0
`define INSTR_TYPE_ALU 1
`define INSTR_TYPE_JUMP 2
`define INSTR_TYPE_NONE 15

View file

@ -44,6 +44,8 @@ module saturn_inst_decoder (
o_alu_imm_value,
o_alu_opcode,
o_jump_length,
o_instr_type,
o_instr_decoded,
o_instr_execute,
@ -73,6 +75,8 @@ output reg [4:0] o_alu_reg_src_2;
output reg [3:0] o_alu_imm_value;
output reg [4:0] o_alu_opcode;
output reg [2:0] o_jump_length;
output reg [3:0] o_instr_type;
/* instruction is fully decoded */
output reg [0:0] o_instr_decoded;
@ -112,6 +116,12 @@ reg [0:0] decode_started;
*/
reg [0:0] block_2x;
reg [0:0] block_6x;
/*
* temporary variables
*/
reg [2:0] jump_counter;
/*
* initialization
@ -136,6 +146,10 @@ initial begin
decode_started = 1'b0;
block_2x = 1'b0;
block_6x = 1'b0;
/* local variables */
jump_counter = 3'd0;
end
/****************************
@ -161,7 +175,9 @@ always @(posedge i_clk) 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);
o_instr_pc <= i_current_pc;
o_instr_pc <= i_current_pc;
/* set the instruction to NOP, to avoid any stray processes */
o_instr_type <= `INSTR_TYPE_NOP;
end
if (i_phases[2] && !decode_started) begin
@ -170,6 +186,15 @@ always @(posedge i_clk) begin
decode_started <= 1'b1;
case (i_nibble)
4'h2: block_2x <= 1'b1;
4'h6:
begin
o_instr_type <= `INSTR_TYPE_JUMP;
o_jump_length <= 3'd2;
jump_counter <= 3'd0;
o_instr_execute <= 1'b1;
block_6x <= 1'b1;
end
default: o_instr_type <= `INSTR_TYPE_NOP;
endcase
end
@ -190,6 +215,16 @@ always @(posedge i_clk) begin
decode_started <= 1'b0;
end
if (block_6x) begin
// $display("DECODER %0d: [%d] GOTO %h", i_phase, i_cycle_ctr, i_nibble);
jump_counter <= jump_counter + 3'd1;
if (jump_counter == o_jump_length) begin
block_6x <= 1'b0;
o_instr_decoded <= 1'b1;
decode_started <= 1'b0;
end
end
end
if (i_phases[3]) begin
@ -221,6 +256,10 @@ always @(posedge i_clk) begin
decode_started <= 1'b0;
block_2x <= 1'b0;
block_6x <= 1'b0;
/* local variables */
jump_counter = 3'd0;
end
end

View file

@ -31,6 +31,8 @@ module saturn_regs_pc_rstk (
i_bus_busy,
i_nibble,
i_jump_instr,
i_jump_length,
o_current_pc
@ -46,6 +48,8 @@ input wire [31:0] i_cycle_ctr;
input wire [0:0] i_bus_busy;
input wire [3:0] i_nibble;
input wire [0:0] i_jump_instr;
input wire [2:0] i_jump_length;
output wire [19:0] o_current_pc;
@ -55,19 +59,27 @@ output wire [19:0] o_current_pc;
*
*************************************************************************************************/
wire [0:0] do_jump_instr = !just_reset && i_jump_instr;
/*
* local variables
*/
reg [0:0] just_reset;
reg [0:0] jump_decode;
reg [0:0] jump_exec;
reg [2:0] jump_counter;
reg [19:0] PC;
assign o_current_pc = PC;
initial begin
just_reset = 1'b1;
PC = 20'h00000;
just_reset = 1'b1;
jump_decode = 1'b0;
jump_exec = 1'b0;
jump_counter = 3'd0;
PC = 20'h00000;
end
/*
@ -95,11 +107,35 @@ always @(posedge i_clk) begin
$display("PC_RSTK %0d: [%d] inc_pc %5h => %5h", i_phase, i_cycle_ctr, PC, PC + 20'h00001);
PC <= PC + 20'h00001;
end
if (i_phases[2] && do_jump_instr && jump_decode) begin
$display("PC_RSTK %0d: [%d] decode jump %0d - %0d %h", i_phase, i_cycle_ctr, i_jump_length, jump_counter, i_nibble);
jump_counter <= jump_counter + 3'd1;
if (jump_counter == i_jump_length) begin
jump_decode <= 1'b0;
jump_exec <= 1'b1;
end
end
if (i_phases[3] && do_jump_instr && !jump_decode && !jump_exec) begin
$display("PC_RSTK %0d: [%d] start decode jump %0d ", i_phase, i_cycle_ctr, i_jump_length);
jump_counter <= 3'd0;
jump_decode <= 1'b1;
end
if (i_phases[3] && do_jump_instr && jump_exec) begin
$display("PC_RSTK %0d: [%d] execute jump %0d ", i_phase, i_cycle_ctr, i_jump_length);
jump_exec <= 1'b0;
end
end
if (i_reset) begin
just_reset <= 1'b1;
PC <= 20'h00000;
just_reset <= 1'b1;
jump_decode <= 1'b0;
jump_exec <= 1'b0;
jump_counter <= 3'd0;
PC <= 20'h00000;
end
end