add more jump code (hairy)

This commit is contained in:
Raphael Jacquot 2019-09-02 13:20:50 +02:00
parent 6fcf04a5c0
commit bb0654126a
6 changed files with 250 additions and 67 deletions

View file

@ -237,7 +237,7 @@ always @(posedge i_clk) begin
end
`ifdef SIM
if (cycle_ctr == 370) begin
if (cycle_ctr == 379) begin
bus_halt <= 1'b1;
$display("BUS %0d: [%d] enough cycles for now", phase, cycle_ctr);
end

View file

@ -101,6 +101,7 @@ assign o_exec_unit_busy = i_bus_busy ||
alu_busy ||
jump_busy ||
rtn_busy ||
test_jump_busy ||
mem_read_busy ||
mem_write_busy ||
reset_busy ||
@ -219,6 +220,7 @@ 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_test_jump = (dec_instr_type == `INSTR_TYPE_TEST_JUMP);
wire [0:0] inst_mem_read = (dec_instr_type == `INSTR_TYPE_MEM_READ);
wire [0:0] inst_mem_write = (dec_instr_type == `INSTR_TYPE_MEM_WRITE);
wire [0:0] inst_reset = (dec_instr_type == `INSTR_TYPE_RESET);
@ -231,28 +233,35 @@ wire [0:0] reg_dest_p = (dec_alu_reg_dest == `ALU_REG_P);
wire [0:0] reg_src_1_a = (dec_alu_reg_src_1 == `ALU_REG_A);
wire [0:0] reg_src_1_c = (dec_alu_reg_src_1 == `ALU_REG_C);
wire [0:0] reg_src_1_st = (dec_alu_reg_src_1 == `ALU_REG_ST);
wire [0:0] reg_src_1_p = (dec_alu_reg_src_1 == `ALU_REG_P);
wire [0:0] reg_src_1_imm = (dec_alu_reg_src_1 == `ALU_REG_IMM);
wire [0:0] reg_src_2_imm = (dec_alu_reg_src_2 == `ALU_REG_IMM);
wire [0:0] aluop_zero = inst_alu && (dec_alu_opcode == `ALU_OP_ZERO);
wire [0:0] aluop_copy = inst_alu && (dec_alu_opcode == `ALU_OP_COPY);
wire [0:0] aluop_clr_mask = inst_alu && (dec_alu_opcode == `ALU_OP_CLR_MASK);
wire [0:0] aluop_test_bit = inst_alu && (dec_alu_opcode == `ALU_OP_TEST_BIT);
wire [0:0] inst_alu_p_eq_n = aluop_copy && reg_dest_p && reg_src_1_imm;
wire [0:0] inst_alu_c_eq_p_n = aluop_copy && reg_dest_c && reg_src_1_p;
wire [0:0] inst_alu_clrhst_n = aluop_clr_mask && reg_dest_hst && reg_src_1_imm;
wire [0:0] inst_alu_st_eq_01_n = aluop_copy && reg_dest_st && reg_src_1_imm;
wire [0:0] inst_alu_st_test_bit = aluop_test_bit && reg_src_1_st && reg_src_2_imm;
wire [0:0] inst_alu_other = inst_alu &&
!(inst_alu_p_eq_n ||
inst_alu_c_eq_p_n ||
inst_alu_clrhst_n ||
inst_alu_st_eq_01_n
inst_alu_st_eq_01_n ||
inst_alu_st_test_bit
);
wire [0:0] alu_busy = inst_alu_other || alu_start;
wire [0:0] jump_busy = (inst_jump && dec_instr_decoded) || send_reg_PC || just_reset;
wire [0:0] rtn_busy = (inst_rtn && dec_instr_decoded) || send_reg_PC;
wire [0:0] test_jump_busy = (inst_test_jump && dec_instr_decoded) || send_reg_PC;
wire [0:0] mem_read_busy = inst_mem_read || exec_mem_read;
wire [0:0] mem_write_busy = inst_mem_write || exec_mem_write;
wire [0:0] reset_busy = inst_reset;
@ -280,6 +289,7 @@ saturn_regs_pc_rstk regs_pc_rstk (
.i_jump_length (dec_jump_length),
.i_block_0x (dec_block_0x),
.i_push_pc (dec_push_pc),
.i_test_jump (inst_test_jump),
.o_current_pc (reg_PC),
@ -356,9 +366,40 @@ reg [3:0] alu_imm_value;
wire [0:0] alu_run = alu_calc_run || alu_save_run;
wire [0:0] alu_done = alu_calc_done || alu_save_done;
/*
* should we reload the PC after it has been changed
*/
/**************************************************************************************************
*
* wires to pre-calculate ALU operation values
*
*************************************************************************************************/
/* alu operation tests */
`ifdef SIM
wire [0:0] aluop_test_eq = alu_opcode == `ALU_OP_TEST_EQ;
wire [0:0] aluop_test_neq = alu_opcode == `ALU_OP_TEST_NEQ;
wire [0:0] aluop_test = aluop_test_eq || aluop_test_neq;
`endif
/* addition */
wire [0:0] op_bin_add_carry = (alu_calc_pos == alu_ptr_begin) ? 1'b0 : alu_calc_carry;
wire [4:0] op_bin_add_res = alu_prep_src_1_val + alu_prep_src_2_val + {3'b000, op_bin_add_carry };
wire [3:0] op_bin_add_res_value = op_bin_add_res[3:0];
wire [0:0] op_bin_add_next_carry = op_bin_add_res[4];
wire [0:0] op_dec_add_sup_9 = op_bin_add_res_value[3] & ( | op_bin_add_res_value[2:1] );
wire [4:0] op_dec_add_res = op_bin_add_res_value + op_dec_add_sup_9 ? 4'h6 : 4'h0;
wire [3:0] op_dec_add_res_value = op_dec_add_res[3:0];
wire [0:0] op_dec_add_next_carry = op_bin_add_next_carry | op_dec_add_res[4];
/* test not equal */
wire [0:0] op_test_neq_carry = (alu_calc_pos == alu_ptr_begin) ? 1'b0 : alu_calc_carry;
wire [0:0] op_test_neq_next_carry = | (alu_prep_src_1_val ^ alu_prep_src_2_val) || op_test_neq_carry;
/**************************************************************************************************
*
* read register nibble values for the debugger
*
*************************************************************************************************/
always @(i_dbg_register, i_dbg_reg_ptr) begin
case (i_dbg_register)
@ -482,6 +523,7 @@ always @(posedge i_clk) begin
if (i_clk_en && control_unit_ready) begin
if (i_phases[3] && !i_bus_busy && dec_instr_execute) begin
$display("CTRL %0d: [%d] instr %0d", i_phase, i_cycle_ctr, dec_instr_type);
case (dec_instr_type)
`INSTR_TYPE_NOP: begin
$display("CTRL %0d: [%d] NOP instruction", i_phase, i_cycle_ctr);
@ -524,6 +566,12 @@ always @(posedge i_clk) begin
reg_ST[dec_alu_ptr_begin] <= dec_alu_imm_value[0];
end
/* 8[67]x ?ST=[01] n */
if (inst_alu_st_test_bit) begin
$display("CTRL %0d: [%d] exec : ?ST=%b %h", i_phase, i_cycle_ctr, dec_alu_imm_value[0], dec_alu_ptr_begin);
reg_CARRY <= !(reg_ST[dec_alu_ptr_begin] == dec_alu_imm_value[0]);
end
/*
* the general case
*/
@ -566,7 +614,8 @@ always @(posedge i_clk) begin
reg_alu_mode <= dec_alu_imm_value[0];
end
`INSTR_TYPE_JUMP,
`INSTR_TYPE_RTN:
`INSTR_TYPE_RTN,
`INSTR_TYPE_TEST_JUMP:
begin
if (inst_jump) begin
$display("CTRL %0d: [%d] JUMP", i_phase, i_cycle_ctr);
@ -575,7 +624,7 @@ always @(posedge i_clk) begin
$display("CTRL %0d: [%d] RTN", i_phase, i_cycle_ctr);
case (dec_alu_opcode)
`ALU_OP_NOP: begin end
`ALU_OP_SET_CRY: reg_CARRY <= o_alu_imm_value[0];
`ALU_OP_SET_CRY: reg_CARRY <= dec_alu_imm_value[0];
default:
begin
$display("CTRL %0d: [%d] alu_opcode for RTN %0d", i_phase, i_cycle_ctr, dec_alu_opcode);
@ -583,8 +632,13 @@ always @(posedge i_clk) begin
end
endcase
end
if (dec_instr_decoded && inst_test_jump) begin
$write("CTRL %0d: [%d] TEST-JUMP (c %b | imm %b) ", i_phase, i_cycle_ctr, reg_CARRY, dec_alu_imm_value[0]);
if (reg_CARRY ^ dec_alu_imm_value[0]) $write("NO-");
$write("exec\n");
end
if (dec_instr_decoded) begin
if (dec_instr_decoded && (!inst_test_jump || (inst_test_jump && !(reg_CARRY ^ dec_alu_imm_value[0])))) begin
$display("CTRL %0d: [%d] exec : JUMP/RTN reload pc to %5h", i_phase, i_cycle_ctr, reg_PC);
bus_program[bus_prog_addr] <= {2'b01, `BUSCMD_LOAD_PC };
bus_prog_addr <= bus_prog_addr + 5'd1;
@ -712,6 +766,8 @@ always @(posedge i_clk) begin
`ALU_REG_B: alu_prep_src_1_val <= reg_B[alu_prep_pos];
`ALU_REG_C: alu_prep_src_1_val <= reg_C[alu_prep_pos];
`ALU_REG_D: alu_prep_src_1_val <= reg_D[alu_prep_pos];
`ALU_REG_D0: alu_prep_src_1_val <= reg_D0[alu_prep_pos[2:0]];
`ALU_REG_D1: alu_prep_src_1_val <= reg_D1[alu_prep_pos[2:0]];
default: $display("ALU_PREP %0d: [%d] unhandled src1 register %0d", i_phase, i_cycle_ctr, dec_alu_reg_src_1);
endcase
@ -720,6 +776,9 @@ always @(posedge i_clk) begin
`ALU_REG_B: alu_prep_src_2_val <= reg_B[alu_prep_pos];
`ALU_REG_C: alu_prep_src_2_val <= reg_C[alu_prep_pos];
`ALU_REG_D: alu_prep_src_2_val <= reg_D[alu_prep_pos];
`ALU_REG_D0: alu_prep_src_1_val <= reg_D0[alu_prep_pos[2:0]];
`ALU_REG_D1: alu_prep_src_1_val <= reg_D1[alu_prep_pos[2:0]];
`ALU_REG_IMM: alu_prep_src_1_val <= alu_imm_value;
`ALU_REG_NONE: begin end
default: $display("ALU_PREP %0d: [%d] unhandled src2 register %0d", i_phase, i_cycle_ctr, dec_alu_reg_src_2);
endcase
@ -761,11 +820,15 @@ always @(posedge i_clk) begin
`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];
alu_prep_src_1_val, alu_prep_src_2_val, op_bin_add_carry, op_bin_add_res, op_bin_add_next_carry);
alu_calc_res_1_val <= op_bin_add_res_value;
alu_calc_carry <= op_bin_add_next_carry;
end
`ALU_OP_TEST_NEQ:
begin
$display("ALU_CALC %0d: [%d] test_neq | s1 %b | s2 %b | c %b | nc %b", i_phase, i_cycle_ctr,
alu_prep_src_1_val, alu_prep_src_2_val, op_test_neq_carry, op_test_neq_next_carry);
alu_calc_carry <= op_test_neq_next_carry;
end
default: $display("ALU_CALC %0d: [%d] unhandled opcode %0d", i_phase, i_cycle_ctr, alu_opcode);
endcase
@ -799,6 +862,12 @@ always @(posedge i_clk) begin
`ALU_REG_D: reg_D[alu_save_pos] <= alu_calc_res_1_val;
`ALU_REG_D0: reg_D0[alu_save_pos[2:0]] <= alu_calc_res_1_val;
`ALU_REG_D1: reg_D1[alu_save_pos[2:0]] <= alu_calc_res_1_val;
`ALU_REG_NONE:
begin
`ifdef SIM
if (!aluop_test) $display("ALU_SAVE %0d: [%d] dest register %0d not supported for op %0d", i_phase, i_cycle_ctr, alu_reg_dest, alu_opcode);
`endif
end
default: $display("ALU_SAVE %0d: [%d] dest register %0d not supported", i_phase, i_cycle_ctr, alu_reg_dest);
endcase
@ -818,6 +887,7 @@ always @(posedge i_clk) begin
// 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;
`ALU_OP_TEST_NEQ : reg_CARRY <= alu_calc_carry;
default: begin end
endcase

View file

@ -56,12 +56,13 @@
// tests
`define ALU_OP_TEST_EQ 15
`define ALU_OP_TEST_NEQ 16
`define ALU_OP_TEST_BIT 17
// relative jump
`define ALU_OP_JMP_REL2 17
`define ALU_OP_JMP_REL3 18
`define ALU_OP_JMP_REL4 19
`define ALU_OP_JMP_ABS5 20
`define ALU_OP_CLR_MASK 21
`define ALU_OP_JMP_REL2 18
`define ALU_OP_JMP_REL3 19
`define ALU_OP_JMP_REL4 20
`define ALU_OP_JMP_ABS5 21
`define ALU_OP_CLR_MASK 22
`define ALU_OP_SET_CRY 28
`define ALU_OP_TEST_GO 30
@ -119,12 +120,13 @@
`define INSTR_TYPE_SET_MODE 2
`define INSTR_TYPE_JUMP 3
`define INSTR_TYPE_RTN 4
`define INSTR_TYPE_LOAD_LENGTH 5
`define INSTR_TYPE_LOAD 6
`define INSTR_TYPE_MEM_READ 7
`define INSTR_TYPE_MEM_WRITE 8
`define INSTR_TYPE_CONFIG 9
`define INSTR_TYPE_RESET 10
`define INSTR_TYPE_TEST_JUMP 5
`define INSTR_TYPE_LOAD_LENGTH 6
`define INSTR_TYPE_LOAD 7
`define INSTR_TYPE_MEM_READ 8
`define INSTR_TYPE_MEM_WRITE 9
`define INSTR_TYPE_CONFIG 10
`define INSTR_TYPE_RESET 11
`define INSTR_TYPE_NONE 15

View file

@ -148,6 +148,8 @@ reg [0:0] block_80x;
reg [0:0] block_80Cx;
reg [0:0] block_82x;
reg [0:0] block_84x_85x;
reg [0:0] block_86x_87x;
reg [0:0] block_8Ax;
reg [0:0] block_Ax;
reg [0:0] block_Aax;
reg [0:0] block_Abx;
@ -167,6 +169,7 @@ reg [3:0] load_counter;
reg [3:0] load_count;
reg [1:0] fields_table;
reg [0:0] read_write;
reg [0:0] instr_test;
/*
* initialization
@ -182,7 +185,7 @@ initial begin
o_alu_imm_value = 4'b0;
o_alu_opcode = `ALU_OP_NOP;
o_instr_type = 4'd15;
o_instr_type = `INSTR_TYPE_NONE;
o_push_pc = 1'd0;
o_instr_decoded = 1'b0;
o_instr_execute = 1'b0;
@ -208,6 +211,8 @@ initial begin
block_80Cx = 1'b0;
block_82x = 1'b0;
block_84x_85x = 1'b0;
block_86x_87x = 1'b0;
block_8Ax = 1'b0;
block_Ax = 1'b0;
block_Aax = 1'b0;
block_Abx = 1'b0;
@ -224,6 +229,7 @@ initial begin
load_counter = 4'd0;
load_count = 4'd0;
fields_table = `FT_NONE;
instr_test = 1'b0;
/* last line of defense */
o_decoder_error = 1'b0;
@ -240,6 +246,23 @@ wire [4:0] regs_BCAC = { 3'b000, i_nibble[0], !(i_nibble[1] | i_nibble[0]) };
wire [4:0] regs_ABAC = { 3'b000, i_nibble[1] & i_nibble[0], !i_nibble[1] & i_nibble[0] };
wire [4:0] regs_BCCD = { 3'b000, i_nibble[1] | i_nibble[0], !i_nibble[1] ^ i_nibble[0] };
/****************************
*
* wires for test instructions
*
*/
wire [0:0] is_instr_alu = (o_instr_type == `INSTR_TYPE_ALU);
wire [0:0] is_aluop_test_eq = (o_alu_opcode == `ALU_OP_TEST_EQ);
wire [0:0] is_aluop_test_neq = (o_alu_opcode == `ALU_OP_TEST_NEQ);
wire [0:0] is_aluop_test_bit = (o_alu_opcode == `ALU_OP_TEST_BIT);
wire [0:0] is_instr_test_eq = is_instr_alu && is_aluop_test_eq;
wire [0:0] is_instr_test_neq = is_instr_alu && is_aluop_test_neq;
wire [0:0] is_instr_test_bit = is_instr_alu && is_aluop_test_bit;
wire [0:0] is_instr_test = is_instr_test_eq || is_instr_test_neq || is_instr_test_bit;
/****************************
*
* main process
@ -266,6 +289,8 @@ always @(posedge i_clk) begin
o_instr_pc <= i_current_pc;
/* set the instruction to NOP, to avoid any stray processes */
o_instr_type <= `INSTR_TYPE_NOP;
/* now, if we had a test instruction previously, we are in rel2 mode now */
end
if (i_phases[2] && !decode_started) begin
@ -491,6 +516,16 @@ always @(posedge i_clk) begin
o_instr_type <= `INSTR_TYPE_ALU;
block_84x_85x <= 1'b1;
end
4'h6, 4'h7:
begin
o_alu_opcode <= `ALU_OP_TEST_BIT;
o_alu_reg_dest <= `ALU_REG_NONE;
o_alu_reg_src_1 <= `ALU_REG_ST;
o_alu_reg_src_2 <= `ALU_REG_IMM;
o_alu_imm_value <= {3'b0, i_nibble[0]};
block_86x_87x <= 1'b1;
end
4'hA: block_8Ax <= 1'b1;
4'hD, 4'hF: /* GOVLNG or GOSBVL */
begin
o_instr_type <= `INSTR_TYPE_JUMP;
@ -583,6 +618,35 @@ always @(posedge i_clk) begin
block_84x_85x <= 1'b0;
end
if (block_86x_87x) begin
$display("DECODER %0d: [%d] block_86x_87x test_bit %h", i_phase, i_cycle_ctr, i_nibble);
o_instr_type <= `INSTR_TYPE_ALU;
o_alu_ptr_begin <= i_nibble;
o_alu_ptr_end <= i_nibble;
o_instr_decoded <= 1'b1;
o_instr_execute <= 1'b1;
/* execution is immediate, set this bit */
instr_test <= 1'b1;
decode_started <= 1'b0;
block_86x_87x <= 1'b0;
end
if (block_8Ax) begin
o_instr_type <= `INSTR_TYPE_ALU;
o_alu_opcode <= i_nibble[2] ? `ALU_OP_TEST_NEQ : `ALU_OP_TEST_EQ;
o_alu_reg_dest <= `ALU_REG_NONE;
o_alu_reg_src_1 <= i_nibble[3] ? regs_ABCD : regs_BCAC;
o_alu_reg_src_2 <= i_nibble[3] ? `ALU_REG_IMM : regs_ABCD;
o_alu_imm_value <= 4'h0;
o_alu_field <= `FT_FIELD_A;
o_alu_ptr_begin <= 4'h0;
o_alu_ptr_end <= 4'h4;
o_instr_decoded <= 1'b1;
o_instr_execute <= 1'b1;
decode_started <= 1'b0;
block_8Ax <= 1'b0;
end
if (block_Ax) begin
$display("DECODER %0d: [%d] block_Ax %h", i_phase, i_cycle_ctr, i_nibble);
/* work here is done by the block_FIELDS */
@ -795,22 +859,51 @@ always @(posedge i_clk) begin
end
/* o_instr_decoded goes away only when the ALU is not busy anymore */
if (i_phases[3] && o_instr_decoded) begin
$display("DECODER %0d: [%d] decoder cleanup 1", i_phase, i_cycle_ctr);
o_instr_decoded <= 1'b0;
end
// if (i_phases[3] && o_instr_decoded) begin
// $display("DECODER %0d: [%d] decoder cleanup 2 (test %b)", i_phase, i_cycle_ctr, instr_test);
// o_instr_decoded <= 1'b0;
// if (instr_test) begin
// $display("DECODER %0d: [%d] jump after test", i_phase, i_cycle_ctr);
// instr_test <= 1'b0;
// o_instr_type <= `INSTR_TYPE_TEST_JUMP;
// o_jump_length <= 3'd1;
// jump_counter <= 3'd0;
// o_alu_imm_value <= 4'h1;
// decode_started <= 1'b1;
// o_instr_execute <= 1'b1;
// block_JUMP <= 1'b1;
// end
// end
end
if (i_clk_en && !i_bus_busy) begin
/* decoder cleanup only after the instruction is completely decoded and execution has started */
if (i_phases[3] && o_instr_decoded) begin
$display("DECODER %0d: [%d] decoder cleanup 2", i_phase, i_cycle_ctr);
if (i_phases[3] && o_instr_decoded && !(& o_instr_type)) begin
$display("DECODER %0d: [%d] decoder cleanup 1 (instr %0d, exec %b, is_test %b)", i_phase, i_cycle_ctr, o_instr_type, o_instr_execute, is_instr_test);
fields_table <= `FT_NONE;
o_alu_field <= `FT_FIELD_NONE;
o_instr_execute <= 1'b0;
o_instr_type <= `INSTR_TYPE_NONE;
o_push_pc <= 1'b0;
instr_test <= is_instr_test;
end
if (i_phases[3] && !i_exec_unit_busy && o_instr_decoded) begin
$display("DECODER %0d: [%d] decoder cleanup 2 (test %b)", i_phase, i_cycle_ctr, instr_test);
o_instr_decoded <= 1'b0;
if (instr_test) begin
$display("DECODER %0d: [%d] jump after test", i_phase, i_cycle_ctr);
instr_test <= 1'b0;
o_instr_type <= `INSTR_TYPE_TEST_JUMP;
o_jump_length <= 3'd1;
jump_counter <= 3'd0;
o_alu_imm_value <= 4'h1;
decode_started <= 1'b1;
o_instr_execute <= 1'b1;
block_JUMP <= 1'b1;
end
end
end
@ -826,7 +919,7 @@ always @(posedge i_clk) begin
o_alu_imm_value <= 4'b0;
o_alu_opcode <= `ALU_OP_NOP;
o_instr_type <= 4'd15;
o_instr_type <= `INSTR_TYPE_NONE;
o_push_pc <= 1'b0;
o_instr_decoded <= 1'b0;
o_instr_execute <= 1'b0;
@ -852,6 +945,8 @@ always @(posedge i_clk) begin
block_80Cx <= 1'b0;
block_82x <= 1'b0;
block_84x_85x <= 1'b0;
block_86x_87x <= 1'b0;
block_8Ax <= 1'b0;
block_Ax <= 1'b0;
block_Aax <= 1'b0;
block_Abx <= 1'b0;
@ -868,6 +963,7 @@ always @(posedge i_clk) begin
load_counter <= 4'd0;
load_count <= 4'd0;
fields_table <= `FT_NONE;
instr_test <= 1'b0;
/* invalid instruction */
o_decoder_error <= 1'b0;

View file

@ -36,6 +36,7 @@ module saturn_regs_pc_rstk (
i_jump_length,
i_block_0x,
i_push_pc,
i_test_jump,
o_current_pc,
o_reload_pc,
@ -66,6 +67,7 @@ input wire [0:0] i_jump_instr;
input wire [2:0] i_jump_length;
input wire [0:0] i_block_0x;
input wire [0:0] i_push_pc;
input wire [0:0] i_test_jump;
output wire [19:0] o_current_pc;
output reg [0:0] o_reload_pc;
@ -83,7 +85,7 @@ assign o_reg_rstk_ptr = reg_rstk_ptr;
*
*************************************************************************************************/
wire [0:0] do_jump_instr = !just_reset && i_jump_instr;
wire [0:0] do_jump_instr = !just_reset && (i_jump_instr || i_test_jump) ;
/*
* local variables
@ -103,7 +105,10 @@ wire [0:0] jump_rel4 = i_jump_instr && (i_jump_length == 3'd3);
wire [0:0] jump_relative = jump_rel2 || jump_rel3 || jump_rel4;
/* this appears to be SLOW */
wire [0:0] is_rtn = i_phases[2] && i_block_0x && !i_nibble[3] && !i_nibble[2];
wire [0:0] is_inst_rtn = !i_test_jump && i_block_0x && !i_nibble[3] && !i_nibble[2];
wire [0:0] is_rtnyes = i_test_jump && !(| jump_next_offset[7:0]);
wire [0:0] do_rtn = i_phases[2] && is_inst_rtn;
wire [0:0] do_rtnyes = i_phases[2] && is_rtnyes;
reg [19:0] jump_next_offset;
@ -123,6 +128,7 @@ reg [19:0] reg_PC;
reg [2:0] reg_rstk_ptr;
reg [19:0] reg_RSTK[0:7];
reg [19:0] prev_PC;
reg [2:0] rstk_ptr_to_push_at;
reg [19:0] addr_to_return_to;
reg [2:0] rstk_ptr_after_pop;
@ -141,6 +147,11 @@ initial begin
addr_to_return_to = 20'b0;
rstk_ptr_after_pop = 3'd0;
rstk_ptr_to_push_at = 3'd0;
$monitor ("PC_RSTK %0d: [%d] bus_busy %b | exec_unit_busy %b | j_cnt %h | i_jump %b | do_jmp %b | is_rtnyes %b | block_0x %b | nibble %h | test_jmp %b | offset[7:0] %h",
i_phase, i_cycle_ctr, i_bus_busy, i_exec_unit_busy,
jump_counter, i_jump_instr, do_jump_instr, is_rtnyes,
i_block_0x, i_nibble, i_test_jump, jump_next_offset[7:0]);
end
/*
@ -181,6 +192,7 @@ always @(posedge i_clk) begin
if (i_phases[1] && !just_reset) begin
$display("PC_RSTK %0d: [%d] inc_pc %5h => %5h", i_phase, i_cycle_ctr, reg_PC, reg_PC + 20'h00001);
prev_PC <= reg_PC;
reg_PC <= reg_PC + 20'h00001;
end
@ -195,11 +207,12 @@ always @(posedge i_clk) begin
*/
if (i_phases[3] && do_jump_instr && !jump_decode) begin
`ifdef SIM
$display("PC_RSTK %0d: [%d] start decode jump %0d | jump_base %5h", i_phase, i_cycle_ctr,
i_jump_length, i_push_pc? reg_PC + {{17{1'b0}},(i_jump_length + 3'd1)} : reg_PC);
$display("PC_RSTK %0d: [%d] start decode jump %0d | jump_base %5h (i_test_jump %b)", i_phase, i_cycle_ctr,
i_jump_length, i_push_pc? reg_PC + {{17{1'b0}},(i_jump_length + 3'd1)} : (i_test_jump ? prev_PC : reg_PC), i_test_jump);
`endif
jump_counter <= 3'd0;
jump_base <= i_push_pc? reg_PC + {{17{1'b0}},(i_jump_length + 3'd1)} : reg_PC;
/* may not be correct for test_jump */
jump_base <= i_push_pc? reg_PC + {{17{1'b0}},(i_jump_length + 3'd1)} : (i_test_jump ? prev_PC : reg_PC);
jump_decode <= 1'b1;
rstk_ptr_to_push_at <= (reg_rstk_ptr + 3'o1) & 3'o7;
end
@ -235,7 +248,7 @@ always @(posedge i_clk) begin
rstk_ptr_after_pop <= (reg_rstk_ptr - 3'o1) & 3'o7;
end
if (is_rtn) begin
if (do_rtn || do_rtnyes) begin
/* this is an RTN */
reg_PC <= addr_to_return_to;
reg_RSTK[reg_rstk_ptr] <= 20'h00000;
@ -243,7 +256,9 @@ always @(posedge i_clk) begin
`ifdef SIM
$write("PC_RSTK %0d: [%d] RTN", i_phase, i_cycle_ctr);
case (i_nibble)
4'h0: $display("SXM");
4'h0:
if (i_test_jump) $display("YES");
else $display("SXM");
4'h1: $write("\n");
4'h2: $display("SC");
4'h3: $display("CC");

2
view
View file

@ -4,4 +4,4 @@
#
nextpnr-ecp5 --gui --85k --speed 6 --freq 5 --lpf ulx3s_v20.lpf --json z_saturn_test.json
nextpnr-ecp5 --gui --85k --speed 6 --freq 5 --package CABGA381 --lpf ulx3s_v20.lpf --json z_saturn_test.json