initialize all registers, implement jmp_rel2

cleanup the controller some more
prepare the core to be rewired
add support for block Bx
This commit is contained in:
Raphael Jacquot 2019-02-18 17:38:25 +01:00
parent 4418ed5824
commit 4cce55e4ba
9 changed files with 538 additions and 254 deletions

View file

@ -61,6 +61,7 @@ module saturn_alu (
i_mode_dec, i_mode_dec,
i_set_xm, i_set_xm,
i_set_carry, i_set_carry,
i_test_carry,
i_carry_val, i_carry_val,
o_reg_p, o_reg_p,
@ -123,6 +124,7 @@ input wire [0:0] i_ins_unconfig;
input wire [0:0] i_mode_dec; input wire [0:0] i_mode_dec;
input wire [0:0] i_set_xm; input wire [0:0] i_set_xm;
input wire [0:0] i_set_carry; input wire [0:0] i_set_carry;
input wire [0:0] i_test_carry;
input wire [0:0] i_carry_val; input wire [0:0] i_carry_val;
output wire [3:0] o_reg_p; output wire [3:0] o_reg_p;
@ -197,58 +199,6 @@ reg [19:0] RSTK[0:7];
initial begin initial begin
// alu internal control bits
alu_op = 0;
reg_dest = 0;
reg_src1 = 0;
reg_src2 = 0;
f_first = 0;
f_cur = 0;
f_last = 0;
alu_run = 0;
alu_done = 0;
p_src1 = 0;
p_src2 = 0;
p_carry = 0;
c_res1 = 0;
c_res2 = 0;
c_carry = 0;
is_zero = 0;
// o_alu_stall_dec = 0;
// processor registers
PC = 0;
// D0 = 0;
// D1 = 0;
// A = 0;
// B = 0;
// C = 0;
// D = 0;
// R0 = 0;
// R1 = 0;
// R2 = 0;
// R3 = 0;
// R4 = 0;
// CARRY = 0;
// DEC = 0;
// P = 0;
// HST = 0;
// ST = 0;
rstk_ptr = 0;
// RSTK[0] = 0;
// RSTK[1] = 0;
// RSTK[2] = 0;
// RSTK[3] = 0;
// RSTK[4] = 0;
// RSTK[5] = 0;
// RSTK[6] = 0;
// RSTK[7] = 0;
end end
/* /*
@ -313,7 +263,7 @@ end
// the decoder may request the ALU to not stall it // the decoder may request the ALU to not stall it
assign o_alu_stall_dec = (!no_extra_cycles) || assign o_alu_stall_dec = !no_extra_cycles || alu_initializing ||
(alu_run && (alu_run &&
(!i_alu_no_stall || alu_finish || alu_go_test || o_bus_dp_read)); (!i_alu_no_stall || alu_finish || alu_go_test || o_bus_dp_read));
@ -329,11 +279,11 @@ assign f_next = (f_cur + 1) & 4'hF;
* test things on alu_op * test things on alu_op
*/ */
wire is_alu_op_jump; wire is_alu_op_unc_jump;
assign is_alu_op_jump = ((alu_op == `ALU_OP_JMP_REL3) || assign is_alu_op_unc_jump = ((alu_op == `ALU_OP_JMP_REL3) ||
(alu_op == `ALU_OP_JMP_REL4) || (alu_op == `ALU_OP_JMP_REL4) ||
(alu_op == `ALU_OP_JMP_ABS5) || (alu_op == `ALU_OP_JMP_ABS5) ||
i_ins_rtn); i_ins_rtn);
wire is_alu_op_test; wire is_alu_op_test;
assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) || assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) ||
(alu_op == `ALU_OP_TEST_NEQ)); (alu_op == `ALU_OP_TEST_NEQ));
@ -432,6 +382,15 @@ assign is_mem_xfer = is_mem_read || is_mem_write;
assign mem_reg = is_mem_read?i_reg_src1:i_reg_dest; assign mem_reg = is_mem_read?i_reg_src1:i_reg_dest;
always @(posedge i_clk) begin always @(posedge i_clk) begin
if (i_reset) begin
alu_op <= 0;
reg_dest <= 0;
reg_src1 <= 0;
reg_src2 <= 0;
f_last <= 0;
end
// this happens in phase 3, right after the instruction decoder (in phase 2) is finished // this happens in phase 3, right after the instruction decoder (in phase 2) is finished
if (do_alu_init) begin if (do_alu_init) begin
@ -458,6 +417,16 @@ end
always @(posedge i_clk) begin always @(posedge i_clk) begin
if (i_reset) begin
alu_run <= 0;
alu_done <= 0;
f_first <= 0;
f_cur <= 0;
end
if (alu_initializing)
f_cur <= f_cur + 1;
if (do_alu_init) begin if (do_alu_init) begin
// $display("------------------------------------------------- DO_ALU_INIT"); // $display("------------------------------------------------- DO_ALU_INIT");
alu_run <= 1; alu_run <= 1;
@ -493,6 +462,14 @@ end
always @(posedge i_clk) begin always @(posedge i_clk) begin
if (i_reset) begin
p_src1 <= 0;
p_src2 <= 0;
p_carry <= 0;
jump_bse <= 0;
end
if (do_alu_prep) begin if (do_alu_prep) begin
if (alu_debug) begin if (alu_debug) begin
`ifdef SIM `ifdef SIM
@ -511,9 +488,11 @@ always @(posedge i_clk) begin
`ALU_OP_RST_BIT, `ALU_OP_RST_BIT,
`ALU_OP_SET_BIT, `ALU_OP_SET_BIT,
`ALU_OP_2CMPL, `ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_ADD, `ALU_OP_ADD,
`ALU_OP_TEST_EQ, `ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ, `ALU_OP_TEST_NEQ,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3, `ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4, `ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5, `ALU_OP_JMP_ABS5,
@ -551,6 +530,8 @@ always @(posedge i_clk) begin
`ALU_OP_RST_BIT, `ALU_OP_RST_BIT,
`ALU_OP_SET_BIT, `ALU_OP_SET_BIT,
`ALU_OP_2CMPL, `ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3, `ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4, `ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5: begin end // no need for a 2nd operand `ALU_OP_JMP_ABS5: begin end // no need for a 2nd operand
@ -584,13 +565,15 @@ always @(posedge i_clk) begin
// setup p_carry // setup p_carry
// $display("fs %h | fs=0 %b | cc %b | npc %b", f_start, (f_start == 0), c_carry, (f_start == 0)?1'b1:c_carry); // $display("fs %h | fs=0 %b | cc %b | npc %b", f_start, (f_start == 0), c_carry, (f_start == 0)?1'b1:c_carry);
case (alu_op) case (alu_op)
`ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry; `ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry;
`ALU_OP_ADD: p_carry <= alu_start?0:c_carry; `ALU_OP_DEC: p_carry <= alu_start?1'b0:c_carry;
`ALU_OP_TEST_NEQ: p_carry <= alu_start?0:c_carry; `ALU_OP_ADD: p_carry <= alu_start?1'b0:c_carry;
`ALU_OP_TEST_NEQ: p_carry <= alu_start?1'b0:c_carry;
endcase endcase
// prepare jump base // prepare jump base
case (alu_op) case (alu_op)
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3, `ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4: `ALU_OP_JMP_REL4:
begin begin
@ -609,7 +592,11 @@ end
always @(posedge i_clk) begin always @(posedge i_clk) begin
if (i_reset) begin if (i_reset) begin
c_carry <= 0; c_res1 <= 0;
c_res2 <= 0;
c_carry <= 0;
is_zero <= 0;
jump_off <= 0;
end end
if (do_alu_calc) begin if (do_alu_calc) begin
@ -622,13 +609,13 @@ always @(posedge i_clk) begin
alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, jump_bse, jump_off, jump_pc, alu_finish); alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, jump_bse, jump_off, jump_pc, alu_finish);
`endif `endif
case (alu_op) if(alu_start)
`ALU_OP_JMP_REL3, case (alu_op)
`ALU_OP_JMP_REL4, `ALU_OP_JMP_REL2,
`ALU_OP_JMP_ABS5: `ALU_OP_JMP_REL3,
if (alu_start) `ALU_OP_JMP_REL4,
jump_off <= { 16'b0, p_src1 }; `ALU_OP_JMP_ABS5: jump_off <= { 16'b0, p_src1 };
endcase endcase
// main case // main case
case (alu_op) case (alu_op)
@ -641,16 +628,18 @@ always @(posedge i_clk) begin
`ALU_OP_COPY, `ALU_OP_COPY,
`ALU_OP_RST_BIT, `ALU_OP_RST_BIT,
`ALU_OP_SET_BIT: c_res1 <= p_src1; `ALU_OP_SET_BIT: c_res1 <= p_src1;
`ALU_OP_2CMPL: `ALU_OP_2CMPL: begin
begin
c_carry <= (~p_src1 == 4'hf) && p_carry ; c_carry <= (~p_src1 == 4'hf) && p_carry ;
c_res1 <= ~p_src1 + {3'b000, p_carry}; c_res1 <= ~p_src1 + {3'b000, p_carry};
is_zero <= ((~p_src1 + {3'b000, p_carry}) == 0) && alu_start?1:is_zero; is_zero <= ((~p_src1 + {3'b000, p_carry}) == 0) && alu_start?1:is_zero;
end end
`ALU_OP_DEC:
{c_carry, c_res1} <= p_src1 + 4'b1111 + {4'b0000, p_carry};
`ALU_OP_ADD: `ALU_OP_ADD:
{c_carry, c_res1} <= p_src1 + p_src2 + {4'b0000, p_carry}; {c_carry, c_res1} <= p_src1 + p_src2 + {4'b0000, p_carry};
`ALU_OP_TEST_NEQ: `ALU_OP_TEST_NEQ:
c_carry <= !(p_src1 == p_src2) || p_carry; c_carry <= !(p_src1 == p_src2) || p_carry;
`ALU_OP_JMP_REL2: begin end // there is no middle part
`ALU_OP_JMP_REL3, `ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4, `ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5: jump_off[f_cur*4+:4] <= p_src1; `ALU_OP_JMP_ABS5: jump_off[f_cur*4+:4] <= p_src1;
@ -658,12 +647,12 @@ always @(posedge i_clk) begin
default: $display("#### CALC 2 UNHANDLED OPERATION %0d", alu_op); default: $display("#### CALC 2 UNHANDLED OPERATION %0d", alu_op);
endcase endcase
case (alu_op) if (alu_finish)
`ALU_OP_JMP_REL3: if (alu_finish) case (alu_op)
jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] }; `ALU_OP_JMP_REL2: jump_off <= { {12{p_src1[3]}}, p_src1, jump_off[3:0] };
`ALU_OP_JMP_REL4: if (alu_finish) `ALU_OP_JMP_REL3: jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] };
jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] }; `ALU_OP_JMP_REL4: jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] };
endcase endcase
// $display("-------C- SRC1 %b %h | ~SRC1 %b %h | PC %b | RES1 %b %h | CC %b", // $display("-------C- SRC1 %b %h | ~SRC1 %b %h | PC %b | RES1 %b %h | CC %b",
// p_src1, p_src1, ~p_src1, ~p_src1, p_carry, // p_src1, p_src1, ~p_src1, ~p_src1, p_carry,
@ -672,13 +661,62 @@ always @(posedge i_clk) begin
end end
if (do_go_init) begin if (do_go_init) begin
// $display("GO_INIT 3: imm %h", i_imm_value); $display("GO_INIT 3: imm %h", i_imm_value);
jump_off <= { {16{1'b0}}, i_imm_value}; jump_off <= { {16{1'b0}}, i_imm_value};
end end
end end
/******************************************************************************
* save alu registers after calculations
*
* this is the only place the registers can be updated !
*
*
*
*
*
*
*****************************************************************************/
reg [0:0] alu_initializing;
always @(posedge i_clk) begin always @(posedge i_clk) begin
/*
* Initialization of all registers
* This happens at the same time the first LOAD_PC command goes out
*
*/
if (i_reset) begin
alu_initializing <= 1;
CARRY <= 0;
P <= 0;
D0 <= 0;
D1 <= 0;
end
if (alu_initializing) begin
A[f_cur] <= 0;
B[f_cur] <= 0;
C[f_cur] <= 0;
D[f_cur] <= 0;
R0[f_cur] <= 0;
R1[f_cur] <= 0;
R2[f_cur] <= 0;
R3[f_cur] <= 0;
R4[f_cur] <= 0;
ST[f_cur] <= 0;
HST[f_cur[1:0]] <= 0;
alu_initializing <= (f_cur != 15);
end
/*
*
* Debug for some JUMP condition testing
*
*/
if (do_alu_save || do_go_prep) begin if (do_alu_save || do_go_prep) begin
if (alu_debug_jump) begin if (alu_debug_jump) begin
`ifdef SIM `ifdef SIM
@ -714,10 +752,6 @@ always @(posedge i_clk) begin
alu_run, alu_done, o_alu_stall_dec, alu_op, alu_run, alu_done, o_alu_stall_dec, alu_op,
f_first, f_cur, f_last, reg_dest, c_res1, c_res2, p_src1, p_src2, c_carry); f_first, f_cur, f_last, reg_dest, c_res1, c_res2, p_src1, p_src2, c_carry);
// $display("-------S- SRC1 %b %h | ~SRC1 %b %h | PC %b | RES1 %b %h | CC %b",
// p_src1, p_src1, ~p_src1, ~p_src1, p_carry,
// (~p_src1) + p_carry, (~p_src1) + p_carry,
// (~p_src1) == 4'hf );
end end
`endif `endif
@ -726,6 +760,7 @@ always @(posedge i_clk) begin
`ALU_OP_COPY, `ALU_OP_COPY,
`ALU_OP_EXCH, // does the first assign `ALU_OP_EXCH, // does the first assign
`ALU_OP_2CMPL, `ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_ADD, `ALU_OP_ADD,
`ALU_OP_CLR_MASK: `ALU_OP_CLR_MASK:
case (reg_dest) case (reg_dest)
@ -756,6 +791,7 @@ always @(posedge i_clk) begin
endcase endcase
`ALU_OP_TEST_EQ, `ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ, `ALU_OP_TEST_NEQ,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3, `ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4, `ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5: begin end // nothing to save, handled by PC management below `ALU_OP_JMP_ABS5: begin end // nothing to save, handled by PC management below
@ -772,13 +808,13 @@ always @(posedge i_clk) begin
`ALU_REG_B: B[f_cur] <= c_res2; `ALU_REG_B: B[f_cur] <= c_res2;
`ALU_REG_C: C[f_cur] <= c_res2; `ALU_REG_C: C[f_cur] <= c_res2;
`ALU_REG_D: D[f_cur] <= c_res2; `ALU_REG_D: D[f_cur] <= c_res2;
`ALU_REG_D0: D0[f_cur*4+:4] <= c_res2;
`ALU_REG_D1: D1[f_cur*4+:4] <= c_res2;
`ALU_REG_R0: R0[f_cur] <= c_res2; `ALU_REG_R0: R0[f_cur] <= c_res2;
`ALU_REG_R1: R1[f_cur] <= c_res2; `ALU_REG_R1: R1[f_cur] <= c_res2;
`ALU_REG_R2: R2[f_cur] <= c_res2; `ALU_REG_R2: R2[f_cur] <= c_res2;
`ALU_REG_R3: R3[f_cur] <= c_res2; `ALU_REG_R3: R3[f_cur] <= c_res2;
`ALU_REG_R4: R4[f_cur] <= c_res2; `ALU_REG_R4: R4[f_cur] <= c_res2;
// `ALU_REG_D0: D0[f_start*4+:4] <= c_res2;
// `ALU_REG_D1: D1[f_start*4+:4] <= c_res2;
// `ALU_REG_ST: ST[f_start*4+:4] <= c_res2; // `ALU_REG_ST: ST[f_start*4+:4] <= c_res2;
// `ALU_REG_P: P <= c_res2; // `ALU_REG_P: P <= c_res2;
// `ALU_REG_HST: HST <= c_res2; // `ALU_REG_HST: HST <= c_res2;
@ -792,6 +828,8 @@ always @(posedge i_clk) begin
if (do_alu_save) begin if (do_alu_save) begin
case (alu_op) case (alu_op)
`ALU_OP_2CMPL: CARRY <= !is_zero; `ALU_OP_2CMPL: CARRY <= !is_zero;
`ALU_OP_DEC,
`ALU_OP_ADD,
`ALU_OP_TEST_EQ, `ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ: CARRY <= c_carry; `ALU_OP_TEST_NEQ: CARRY <= c_carry;
endcase endcase
@ -964,32 +1002,69 @@ end
wire [19:0] next_pc; wire [19:0] next_pc;
wire [19:0] goyes_off; wire [19:0] goyes_off;
wire [19:0] goyes_pc; wire [19:0] goyes_pc;
wire [0:0] is_jmp_rel2;
wire [0:0] is_rtn_rel2;
wire [0:0] jmp_carry_test;
wire [0:0] exec_rtn_rel2;
wire [0:0] set_jmp_rel2;
wire [0:0] exec_jmp_rel2;
wire [0:0] update_pc; wire [0:0] update_pc;
wire [0:0] uncond_jmp; wire [0:0] set_unc_jmp;
wire [0:0] exec_unc_jmp;
wire [0:0] exec_unc_rtn;
wire [0:0] pop_pc; wire [0:0] pop_pc;
wire [0:0] reload_pc; wire [0:0] reload_pc;
wire [0:0] push_pc; wire [0:0] push_pc;
assign next_pc = (is_alu_op_jump && alu_finish)?jump_pc:PC + 1;
assign goyes_off = {{12{i_imm_value[3]}}, i_imm_value, jump_off[3:0]}; assign goyes_off = {{12{i_imm_value[3]}}, i_imm_value, jump_off[3:0]};
assign goyes_pc = jump_bse + goyes_off; assign goyes_pc = jump_bse + goyes_off;
// rtnyes is already handled by i_ins_test_go
assign is_rtn_rel2 = (alu_op == `ALU_OP_JMP_REL2) && (goyes_off == 0);
assign is_jmp_rel2 = (alu_op == `ALU_OP_JMP_REL2) && !(goyes_off == 0);
assign jmp_carry_test = (i_test_carry && (CARRY == i_carry_val));
assign exec_rtn_rel2 = is_rtn_rel2 && jmp_carry_test && alu_done;
assign set_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_finish;
assign exec_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_done;
assign update_pc = !o_alu_stall_dec || is_alu_op_jump || just_reset;
assign uncond_jmp = is_alu_op_jump && alu_done; assign set_unc_jmp = is_alu_op_unc_jump && alu_finish;
assign pop_pc = i_pop && i_ins_rtn && assign exec_unc_jmp = is_alu_op_unc_jump && alu_done;
((!i_ins_test_go) || assign exec_unc_rtn = i_pop && i_ins_rtn;
(i_ins_test_go && c_carry));
assign reload_pc = uncond_jmp || pop_pc || just_reset; assign pop_pc = i_pop && i_ins_rtn &&
((!i_ins_test_go) ||
(i_ins_test_go && CARRY));
assign next_pc = (set_unc_jmp || set_jmp_rel2)?jump_pc:PC + 1;
assign update_pc = !o_alu_stall_dec || exec_unc_jmp || exec_jmp_rel2 || just_reset;
assign reload_pc = (exec_unc_jmp || pop_pc || just_reset || exec_jmp_rel2);
assign push_pc = update_pc && i_push && alu_finish; assign push_pc = update_pc && i_push && alu_finish;
always @(posedge i_clk) begin always @(posedge i_clk) begin
/*
* initializes the PC
*
*/
if (i_reset) begin if (i_reset) begin
PC <= ~0; PC <= ~0;
o_bus_load_pc <= 0; o_bus_load_pc <= 0;
rstk_ptr <= 0;
end end
/*
* Similarly to the data registers,
* initializes the RSTK while the PC is first loaded
*
*/
if (alu_initializing)
RSTK[f_cur[2:0]] <= 0;
// necessary for the write to memory above // necessary for the write to memory above
// otherwise we get a conflict on o_bus_address // otherwise we get a conflict on o_bus_address
if (setup_load_dp) if (setup_load_dp)
@ -1016,16 +1091,18 @@ always @(posedge i_clk) begin
`ifdef SIM `ifdef SIM
if (alu_debug_pc) if (alu_debug_pc)
$display({"ALU_PC 3: !stl %b | nx %5h | done %b | fin %b | ", $display({"ALU_PC 3: !stl %b | nx %5h | done %b | fin %b | ",
"jmp %b | ins_rtn %b | push %b | ", "uncjmp %b | ins_rtn %b | push %b | imm %h | ",
"imm %h | j_bs %h | go_off %h | go_pc %h"}, "c_test %b | jmpr2 %b | rtn[n]c %b |",
"j_bs %h | go_off %h | go_pc %h | update %b | PC <= %h"},
!o_alu_stall_dec, next_pc, alu_done, alu_finish, !o_alu_stall_dec, next_pc, alu_done, alu_finish,
is_alu_op_jump, i_ins_rtn, i_push, is_alu_op_unc_jump, i_ins_rtn, i_push, i_imm_value,
i_imm_value, jump_bse, goyes_off, goyes_pc); jmp_carry_test, exec_jmp_rel2, exec_rtn_rel2,
jump_bse, goyes_off, goyes_pc, update_pc, pop_pc ? RSTK[rstk_ptr - 1] : next_pc);
`endif `endif
// this may do wierd things with C=RSTK... // this may do wierd things with C=RSTK...
if (update_pc) begin if (update_pc) begin
PC <= pop_pc ? RSTK[rstk_ptr-1] : next_pc; PC <= pop_pc ? RSTK[rstk_ptr - 1] : next_pc;
end end
if (reload_pc) begin if (reload_pc) begin
@ -1066,12 +1143,16 @@ end
* *
****************************************************************************/ ****************************************************************************/
always @(posedge i_clk) always @(posedge i_clk) begin
if (i_reset)
DEC <= 0;
// changing calculation modes // changing calculation modes
if (do_alu_mode) begin if (do_alu_mode) begin
$display("SETTING MODE TO %s", i_mode_dec?"DEC":"HEX"); $display("SETTING MODE TO %s", i_mode_dec?"DEC":"HEX");
DEC <= i_mode_dec; DEC <= i_mode_dec;
end end
end
endmodule endmodule

View file

@ -86,6 +86,16 @@ assign en_bus_ecmd = i_en_bus_ecmd && !i_stalled;
* *
****************************************************************************/ ****************************************************************************/
// tests on last_cmd
wire [0:0] last_cmd_pc_read;
wire [0:0] last_cmd_dp_read;
wire [0:0] last_cmd_dp_write;
assign last_cmd_pc_read = (last_cmd == `BUSCMD_PC_READ);
assign last_cmd_dp_read = (last_cmd == `BUSCMD_DP_READ);
assign last_cmd_dp_write = (last_cmd == `BUSCMD_DP_WRITE);
// declarations // declarations
reg [0:0] cmd_pc_read_s; reg [0:0] cmd_pc_read_s;
@ -98,7 +108,7 @@ reg [0:0] cmd_reset_s;
wire [0:0] addr_s; wire [0:0] addr_s;
wire [0:0] do_cmd_pc_read; wire [0:0] do_cmd_pc_read;
wire [0:0] do_display_stalled; wire [0:0] do_display_stalled;
wire [0:0] do_cmd_load_dp; wire [0:0] do_cmd_load_dp;
wire [0:0] do_dp_read_data; wire [0:0] do_dp_read_data;
@ -108,6 +118,7 @@ wire [0:0] do_pc_read_after_dp_read;
wire [0:0] do_cleanup_after_dp_read; wire [0:0] do_cleanup_after_dp_read;
wire [0:0] do_cmd_dp_write; wire [0:0] do_cmd_dp_write;
wire [0:0] cmd_dp_write_data;
wire [0:0] do_dp_write_data; wire [0:0] do_dp_write_data;
wire [0:0] do_pc_read_after_dp_write; wire [0:0] do_pc_read_after_dp_write;
wire [0:0] cmd_load_dp_dp_write_uc; wire [0:0] cmd_load_dp_dp_write_uc;
@ -122,8 +133,10 @@ wire [0:0] do_pc_read_after_reset;
wire [0:0] cmd_reset_sc; wire [0:0] cmd_reset_sc;
wire [0:0] cmd_reset_uc; wire [0:0] cmd_reset_uc;
wire [0:0] do_unstall;
wire [0:0] do_cleanup; wire [0:0] do_cleanup;
wire [0:0] do_stall;
wire [0:0] do_unstall;
wire [0:0] do_stop_loop;
// assigns // assigns
@ -138,7 +151,8 @@ assign do_pc_read_after_dp_read = i_read_stall && !i_cmd_dp_read && cmd_load_dp
assign do_cleanup_after_dp_read = !i_read_stall && !i_cmd_dp_read && cmd_load_dp_s && !addr_s && dp_read_s; assign do_cleanup_after_dp_read = !i_read_stall && !i_cmd_dp_read && cmd_load_dp_s && !addr_s && dp_read_s;
assign do_cmd_dp_write = i_cmd_dp_write && cmd_load_dp_s && addr_s && !cmd_dp_write_s; assign do_cmd_dp_write = i_cmd_dp_write && cmd_load_dp_s && addr_s && !cmd_dp_write_s;
assign do_dp_write_data = i_cmd_dp_write && cmd_load_dp_s && addr_s && cmd_dp_write_s; assign cmd_dp_write_data = i_cmd_dp_write && cmd_load_dp_s && addr_s && cmd_dp_write_s;
assign do_dp_write_data = en_bus_send && cmd_dp_write_data && last_cmd_dp_write;
assign do_pc_read_after_dp_write = !i_cmd_dp_write && cmd_load_dp_s && cmd_dp_write_s; assign do_pc_read_after_dp_write = !i_cmd_dp_write && cmd_load_dp_s && cmd_dp_write_s;
assign cmd_load_dp_dp_write_uc = cmd_load_dp_s && cmd_dp_write_s && cmd_pc_read_s; assign cmd_load_dp_dp_write_uc = cmd_load_dp_s && cmd_dp_write_s && cmd_pc_read_s;
@ -163,18 +177,28 @@ assign do_display_stalled = en_bus_recv && i_read_stall && !o_stalled_by_
do_dp_read_data || do_dp_read_data ||
do_pc_read_after_dp_read || do_pc_read_after_dp_read ||
do_cmd_dp_write || do_cmd_dp_write ||
do_dp_write_data || cmd_dp_write_data ||
do_pc_read_after_dp_write); do_pc_read_after_dp_write);
assign do_unstall = do_dp_read_data_uc || assign do_cleanup = en_bus_send &&
cmd_load_dp_dp_write_uc || (do_cleanup_after_dp_read ||
cmd_config_uc || cmd_load_dp_dp_write_uc ||
cmd_reset_uc; cmd_config_uc ||
cmd_reset_uc);
assign do_stall = en_bus_ecmd &&
(do_dp_read_data_sc ||
cmd_reset_sc ||
cmd_config_sc);
assign do_unstall = en_bus_ecmd &&
(do_dp_read_data_uc ||
cmd_load_dp_dp_write_uc ||
cmd_config_uc ||
cmd_reset_uc);
assign do_stop_loop = en_bus_ecmd && addr_s;
assign do_cleanup = do_cleanup_after_dp_read ||
cmd_load_dp_dp_write_uc ||
cmd_config_uc ||
cmd_reset_uc;
/****************************************************************************** /******************************************************************************
* *
* test rom * test rom
@ -184,22 +208,24 @@ assign do_cleanup = do_cleanup_after_dp_read ||
`ifdef SIM `ifdef SIM
`define ROMBITS 20 `define ROMBITS 20
`else `else
`define ROMBITS 16 `define ROMBITS 12
`endif `endif
reg [3:0] rom [0:2**`ROMBITS-1]; reg [3:0] rom [0:2**`ROMBITS-1];
wire [0:0] last_cmd_pc_read;
wire [0:0] last_cmd_dp_read;
wire [0:0] do_read_from_bus; wire [0:0] do_read_from_bus;
wire [0:0] use_pc_as_pointer; wire [0:0] use_pc_as_pointer;
wire [0:0] use_dp_as_pointer;
wire [0:0] do_read_from_bus_with_pc;
wire [0:0] do_read_from_bus_with_dp;
wire [`ROMBITS-1:0] read_pointer; wire [`ROMBITS-1:0] read_pointer;
assign last_cmd_pc_read = (last_cmd == `BUSCMD_PC_READ); assign do_read_from_bus = en_bus_recv && (!i_read_stall || do_dp_read_data) && (last_cmd_pc_read || last_cmd_dp_read);
assign last_cmd_dp_read = (last_cmd == `BUSCMD_DP_READ); assign use_pc_as_pointer = last_cmd_pc_read;
assign do_read_from_bus = en_bus_recv && (!i_read_stall || do_dp_read_data) && (last_cmd_pc_read || last_cmd_dp_read); assign use_dp_as_pointer = last_cmd_dp_read;
assign use_pc_as_pointer = last_cmd_pc_read ; assign read_pointer = use_pc_as_pointer?local_pc[`ROMBITS-1:0]:local_dp[`ROMBITS-1:0];
assign read_pointer = use_pc_as_pointer?local_pc[`ROMBITS-1:0]:local_dp[`ROMBITS-1:0]; assign do_read_from_bus_with_pc = do_read_from_bus && use_pc_as_pointer;
assign do_read_from_bus_with_dp = do_read_from_bus && use_dp_as_pointer;
/****************************************************************************** /******************************************************************************
* *
@ -210,7 +236,7 @@ assign read_pointer = use_pc_as_pointer?local_pc[`ROMBITS-1:0]:local_dp[`RO
initial begin initial begin
// `ifdef SIM // `ifdef SIM
$readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1); $readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1);
// $readmemh( "testrom-2.hex", rom); // $readmemh( "testrom-2.hex", rom);
`ifdef SIM `ifdef SIM
// $monitor({"o_stalled_by_bus %b | i_read_stall %b | i_cmd_dp_read %b |", // $monitor({"o_stalled_by_bus %b | i_read_stall %b | i_cmd_dp_read %b |",
@ -243,6 +269,19 @@ always @(posedge i_clk) begin
cmd_reset_s <= 0; cmd_reset_s <= 0;
end end
/*
* reset flags
*/
if (do_cleanup) begin
// $display("--------------------------------------------- BUS STATES CLEANUP");
cmd_pc_read_s <= 0;
dp_read_s <= 0;
cmd_dp_write_s <= 0;
cmd_load_dp_s <= 0;
cmd_config_s <= 0;
cmd_reset_s <= 0;
end
/* /*
* *
* sending commands or data to the bus * sending commands or data to the bus
@ -250,20 +289,6 @@ always @(posedge i_clk) begin
*/ */
if (en_bus_send) begin if (en_bus_send) begin
/*
* reset flags
*/
if (do_cleanup) begin
// $display("--------------------------------------------- BUS STATES CLEANUP");
cmd_pc_read_s <= 0;
dp_read_s <= 0;
cmd_dp_write_s <= 0;
cmd_load_dp_s <= 0;
cmd_config_s <= 0;
cmd_reset_s <= 0;
end
/* /*
* send the PC_READ command to restore the instruction flow * send the PC_READ command to restore the instruction flow
* after a data transfer * after a data transfer
@ -342,46 +367,54 @@ always @(posedge i_clk) begin
addr_cnt <= addr_cnt + 1; addr_cnt <= addr_cnt + 1;
o_bus_strobe <= 1; o_bus_strobe <= 1;
end end
/*
* nothing to do for reading data
*/
/*
* writing data to the bus,
* send DP_WRITE first if necessary
*/
if (do_dp_write_data) begin
if (last_cmd == `BUSCMD_DP_WRITE) begin
$display("BUS_SEND %0d: [%d] WRITE %h =>", `PH_BUS_SEND, i_cycle_ctr, i_nibble);
o_bus_data <= i_nibble;
o_bus_strobe <= 1;
end
end
end end
/* /******************************************************************************
*
* writing data to the bus,
* will wait for DP_WRITE to be sent
*
****************************************************************************/
if (do_dp_write_data) begin
$display("BUS_SEND %0d: [%d] WRITE %h =>", `PH_BUS_SEND, i_cycle_ctr, i_nibble);
o_bus_data <= i_nibble;
o_bus_strobe <= 1;
end
/****************************************************************************
* *
* reading data from the bus * reading data from the bus
* *
*/ ***************************************************************************/
if (do_read_from_bus) begin /*
* only display during simulation
*/
`ifdef SIM `ifdef SIM
if (do_read_from_bus)
$display("BUS_RECV %0d: [%d] <= READ(%s) [%5h] %h", $display("BUS_RECV %0d: [%d] <= READ(%s) [%5h] %h",
`PH_BUS_RECV, i_cycle_ctr, use_pc_as_pointer?"PC":"DP", `PH_BUS_RECV, i_cycle_ctr, use_pc_as_pointer?"PC":"DP",
read_pointer, rom[read_pointer]); read_pointer, rom[read_pointer]);
`endif `endif
if (do_read_from_bus)
o_nibble <= rom[read_pointer]; o_nibble <= rom[read_pointer];
if (use_pc_as_pointer) local_pc <= local_pc + 1;
else begin
local_dp <= local_dp + 1; if (do_read_from_bus_with_pc)
dp_read_s <= 1; local_pc <= local_pc + 1;
end
end if (do_read_from_bus_with_dp) begin
local_dp <= local_dp + 1;
dp_read_s <= 1;
end
if (do_display_stalled) begin if (do_display_stalled) begin
$display("BUS_RECV %0d: [%d] STALLED", `PH_BUS_RECV, i_cycle_ctr); $display("BUS_RECV %0d: [%d] STALLED", `PH_BUS_RECV, i_cycle_ctr);
@ -397,28 +430,35 @@ always @(posedge i_clk) begin
o_bus_cmd_data <= 1; o_bus_cmd_data <= 1;
end end
/******************************************************************************
*
* execute stalling the core by the bus controller
*
*****************************************************************************/
if (do_stall) begin
// $display("-------------------------------------- STALL");
o_stalled_by_bus <= 1;
end
if (do_unstall) begin
// $display("-------------------------------------- NO - STALL");
o_stalled_by_bus <= 0;
addr_cnt <= 0;
end
/*
* reset the adress sending loop
*
*/
if (do_stop_loop) begin
send_addr <= 0;
end
if (en_bus_ecmd) begin if (en_bus_ecmd) begin
// stalling and unstalling stuff
if (do_dp_read_data_sc || cmd_reset_sc || cmd_config_sc) begin
// $display("-------------------------------------- STALL");
o_stalled_by_bus <= 1;
end
if (do_unstall) begin
// $display("-------------------------------------- NO - STALL");
o_stalled_by_bus <= 0;
addr_cnt <= 0;
end
if (addr_s) begin
send_addr <= 0;
end
// command automatic switchover // command automatic switchover
case (last_cmd) case (last_cmd)
`BUSCMD_NOP: begin end `BUSCMD_NOP: begin end
`BUSCMD_LOAD_PC, `BUSCMD_LOAD_PC,
@ -446,9 +486,6 @@ always @(posedge i_clk) begin
`BUSCMD_RESET: begin end `BUSCMD_RESET: begin end
default: $display("------------ UNHANDLED BUSCMD %h", last_cmd); default: $display("------------ UNHANDLED BUSCMD %h", last_cmd);
endcase endcase
end end

View file

@ -22,23 +22,51 @@
`ifdef SIM `ifdef SIM
module saturn_core ( module saturn_core (
input clk, i_clk,
input reset, i_reset,
output [0:0] halt, o_halt,
output [3:0] busstate,
output [11:0] decstate i_bus_data_in,
o_bus_data_out,
o_bus_strobe,
o_bus_cmd_data
); );
input wire [0:0] i_clk;
input wire [0:0] i_reset;
output wire [0:0] o_halt;
input wire [3:0] i_bus_data_in;
output wire [3:0] o_bus_data_out;
output wire [0:0] o_bus_strobe;
output wire [0:0] o_bus_cmd_data;
`else `else
module saturn_core ( module saturn_core (
input clk_25mhz, clk_25mhz,
input [6:0] btn, btn,
output [7:0] led led,
);
wire clk;
wire reset;
assign clk = clk_25mhz; i_bus_data_in,
assign reset = btn[1]; o_bus_data_out,
o_bus_strobe,
o_bus_cmd_data
);
input wire [0:0] clk_25mhz;
input wire [6:0] btn;
output reg [7:0] led;
wire [0:0] i_clk;
wire [0:0] i_reset;
assign i_clk = clk_25mhz;
assign i_reset = btn[1];
input wire [3:0] i_bus_data_in;
output wire [3:0] o_bus_data_out;
output wire [0:0] o_bus_strobe;
output wire [0:0] o_bus_cmd_data;
`endif `endif
@ -65,10 +93,6 @@ reg [0:0] clock_end;
reg [31:0] cycle_ctr; reg [31:0] cycle_ctr;
reg [31:0] max_cycle; reg [31:0] max_cycle;
// state machine stuff
wire [0:0] halt;
// hp48_bus bus_ctrl ( // hp48_bus bus_ctrl (
// .strobe (bus_strobe), // .strobe (bus_strobe),
// .reset (reset), // .reset (reset),
@ -80,8 +104,8 @@ wire [0:0] halt;
// ); // );
saturn_decoder m_decoder ( saturn_decoder m_decoder (
.i_clk (clk), .i_clk (i_clk),
.i_reset (reset), .i_reset (i_reset),
.i_cycles (cycle_ctr), .i_cycles (cycle_ctr),
.i_en_dbg (ck_debugger), .i_en_dbg (ck_debugger),
.i_en_dec (ck_inst_dec), .i_en_dec (ck_inst_dec),
@ -116,6 +140,7 @@ saturn_decoder m_decoder (
.o_ins_rtn (ins_rtn), .o_ins_rtn (ins_rtn),
.o_set_xm (set_xm), .o_set_xm (set_xm),
.o_set_carry (set_carry), .o_set_carry (set_carry),
.o_test_carry (test_carry),
.o_carry_val (carry_val), .o_carry_val (carry_val),
.o_ins_set_mode (ins_set_mode), .o_ins_set_mode (ins_set_mode),
.o_mode_dec (mode_dec), .o_mode_dec (mode_dec),
@ -149,6 +174,7 @@ wire [4:0] reg_src2;
wire [0:0] ins_rtn; wire [0:0] ins_rtn;
wire [0:0] set_xm; wire [0:0] set_xm;
wire [0:0] set_carry; wire [0:0] set_carry;
wire [0:0] test_carry;
wire [0:0] carry_val; wire [0:0] carry_val;
wire [0:0] ins_set_mode; wire [0:0] ins_set_mode;
wire [0:0] mode_dec; wire [0:0] mode_dec;
@ -160,8 +186,8 @@ wire [0:0] ins_unconfig;
saturn_alu m_alu ( saturn_alu m_alu (
.i_clk (clk), .i_clk (i_clk),
.i_reset (reset), .i_reset (i_reset),
.i_cycle_ctr (cycle_ctr), .i_cycle_ctr (cycle_ctr),
.i_en_alu_dump (ck_alu_dump), .i_en_alu_dump (ck_alu_dump),
.i_en_alu_prep (ck_alu_prep), .i_en_alu_prep (ck_alu_prep),
@ -207,6 +233,7 @@ saturn_alu m_alu (
.i_mode_dec (mode_dec), .i_mode_dec (mode_dec),
.i_set_xm (set_xm), .i_set_xm (set_xm),
.i_set_carry (set_carry), .i_set_carry (set_carry),
.i_test_carry (test_carry),
.i_carry_val (carry_val), .i_carry_val (carry_val),
.o_reg_p (reg_p), .o_reg_p (reg_p),
@ -238,8 +265,8 @@ wire [19:0] reg_pc;
saturn_bus_ctrl m_bus_ctrl ( saturn_bus_ctrl m_bus_ctrl (
// basic stuff // basic stuff
.i_clk (clk), .i_clk (i_clk),
.i_reset (reset), .i_reset (i_reset),
.i_cycle_ctr (cycle_ctr), .i_cycle_ctr (cycle_ctr),
.i_en_bus_send (ck_bus_send), .i_en_bus_send (ck_bus_send),
.i_en_bus_recv (ck_bus_recv), .i_en_bus_recv (ck_bus_recv),
@ -249,10 +276,10 @@ saturn_bus_ctrl m_bus_ctrl (
.o_stalled_by_bus (bus_stalls_core), .o_stalled_by_bus (bus_stalls_core),
//bus i/o //bus i/o
.i_bus_data (bus_data_in), .i_bus_data (i_bus_data_in),
.o_bus_data (bus_data_out), .o_bus_data (o_bus_data_out),
.o_bus_strobe (bus_strobe), .o_bus_strobe (o_bus_strobe),
.o_bus_cmd_data (bus_cmd_data), .o_bus_cmd_data (o_bus_cmd_data),
// interface to the rest of the machine // interface to the rest of the machine
.i_alu_pc (reg_pc), .i_alu_pc (reg_pc),
@ -271,11 +298,11 @@ saturn_bus_ctrl m_bus_ctrl (
reg [0:0] mem_ctrl_stall; reg [0:0] mem_ctrl_stall;
wire [0:0] bus_stalls_core; wire [0:0] bus_stalls_core;
// bus to external modules // // bus to external modules
reg [3:0] bus_data_in; // reg [3:0] bus_data_in;
wire [3:0] bus_data_out; // wire [3:0] bus_data_out;
wire [0:0] bus_strobe; // wire [0:0] bus_strobe;
wire [0:0] bus_cmd_data; // wire [0:0] bus_cmd_data;
// `define DEBUG_CLOCKS // `define DEBUG_CLOCKS
@ -318,8 +345,8 @@ initial begin
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
always @(posedge clk) begin always @(posedge i_clk) begin
if (!reset) begin if (!i_reset) begin
clk_phase <= clk_phase + 1; clk_phase <= clk_phase + 1;
ck_debugger <= clk_phase[1:0] == `PH_DEBUGGER; ck_debugger <= clk_phase[1:0] == `PH_DEBUGGER;
@ -363,7 +390,7 @@ always @(posedge clk) begin
clock_end <= 0; clock_end <= 0;
cycle_ctr <= ~0; cycle_ctr <= ~0;
max_cycle <= 450; max_cycle <= 650;
mem_ctrl_stall <= 0; mem_ctrl_stall <= 0;
`ifndef SIM `ifndef SIM
@ -382,8 +409,9 @@ wire dec_stalled;
wire alu_stalled; wire alu_stalled;
assign dec_stalled = alu_stalls_dec || bus_stalls_core; assign dec_stalled = alu_stalls_dec || bus_stalls_core;
assign alu_stalled = bus_stalls_core; assign alu_stalled = bus_stalls_core;
assign halt = clock_end || inv_opcode; `ifdef SIM
assign o_halt = clock_end || inv_opcode;
`endif
// Verilator lint_off UNUSED // Verilator lint_off UNUSED
//wire [N-1:0] unused; //wire [N-1:0] unused;
@ -394,25 +422,32 @@ endmodule
`ifdef SIM `ifdef SIM
module saturn_tb; module saturn_tb;
reg clk;
reg reset;
wire halt;
wire [3:0] busstate;
wire [11:0] decstate;
saturn_core saturn ( saturn_core saturn (
.clk (clk), .i_clk (clk),
.reset (reset), .i_reset (reset),
.halt (halt), .o_halt (halt),
.busstate (busstate), .i_bus_data_in (core_bus_data_in),
.decstate (decstate) .o_bus_data_out (core_bus_data_out),
.o_bus_strobe (core_bus_strobe),
.o_bus_cmd_data (core_bus_cmd_data)
); );
reg [0:0] clk;
reg [0:0] reset;
wire [0:0] halt;
reg [3:0] core_bus_data_in;
wire [3:0] core_bus_data_out;
wire [0:0] core_bus_strobe;
wire [0:0] core_bus_cmd_data;
always always
#10 clk = (clk === 1'b0); #10 clk = (clk === 1'b0);
initial begin initial begin
//$monitor ("c %b | r %b | run %h | dec %h", clk, reset, runstate, decstate); // $monitor ("c %b | r %b | in %h | out %h | str %b | cd %b",
// clk, reset, core_bus_data_in, core_bus_data_out, core_bus_strobe, core_bus_cmd_data);
end end
initial begin initial begin

View file

@ -191,6 +191,7 @@ always @(posedge i_clk) begin
o_ins_set_mode <= 0; o_ins_set_mode <= 0;
o_ins_reset <= 0; o_ins_reset <= 0;
o_ins_config <= 0; o_ins_config <= 0;
o_test_carry <= 0;
end end
if (decoder_active) begin if (decoder_active) begin
@ -290,6 +291,7 @@ always @(posedge i_clk) begin
// 4xy GOC // 4xy GOC
// 500 RTNNC // 500 RTNNC
// 5xy GONC // 5xy GONC
o_alu_debug <= 1;
o_alu_no_stall <= 1; o_alu_no_stall <= 1;
o_alu_op <= `ALU_OP_JMP_REL2; o_alu_op <= `ALU_OP_JMP_REL2;
mem_load_max <= 1; mem_load_max <= 1;
@ -319,6 +321,13 @@ always @(posedge i_clk) begin
o_fields_table <= `FT_TABLE_a; o_fields_table <= `FT_TABLE_a;
block_Ax <= 1; block_Ax <= 1;
end end
4'hB: begin
go_fields_table <= 1;
// we don't know, safe bet is table a, but could be table b,
// works either way, table is fixed on the next nibble
o_fields_table <= `FT_TABLE_a;
block_Bx <= 1;
end
4'hC: block_Cx <= 1; 4'hC: block_Cx <= 1;
4'hD: block_Dx <= 1; 4'hD: block_Dx <= 1;
4'hF: block_Fx <= 1; 4'hF: block_Fx <= 1;
@ -572,6 +581,15 @@ always @(posedge i_clk) begin
`include "saturn_decoder_block_8.v" `include "saturn_decoder_block_8.v"
/*
* Block Axx
* ra=ra+rb a
* ra=ra-1 a
* ra=0 b
* ra=rb b
* rarbEX b
*/
if (do_block_Ax) begin if (do_block_Ax) begin
o_fields_table <= i_nibble[3]?`FT_TABLE_b:`FT_TABLE_a; o_fields_table <= i_nibble[3]?`FT_TABLE_b:`FT_TABLE_a;
block_Aax <= !i_nibble[3]; block_Aax <= !i_nibble[3];
@ -597,10 +615,67 @@ always @(posedge i_clk) begin
block_Abx <= 0; block_Abx <= 0;
end end
/*
* Block Bxx
*
*
*/
if (do_block_Bx) begin
o_fields_table <= i_nibble[3]?`FT_TABLE_b:`FT_TABLE_a;
block_Bax <= !i_nibble[3];
block_Bbx <= i_nibble[3];
block_Bx <= 0;
end
if (do_block_Bax) begin
`ifdef SIM
$display("block_Bax %h", i_nibble);
`endif
o_ins_alu_op <= 1;
case ({i_nibble[3],i_nibble[2]})
2'b00: o_alu_op <= `ALU_OP_SUB;
2'b01: o_alu_op <= `ALU_OP_INC;
2'b10: o_alu_op <= `ALU_OP_SUB;
2'b11: o_alu_op <= `ALU_OP_SUB;
endcase
next_nibble <= 0;
o_ins_decoded <= 1;
`ifdef SIM
o_unimplemented <= 0;
`endif
block_Bax <= 0;
end
if (do_block_Bbx) begin
o_ins_alu_op <= 1;
case ({i_nibble[3],i_nibble[2]})
2'b00: o_alu_op <= `ALU_OP_SHL;
2'b01: o_alu_op <= `ALU_OP_SHR;
2'b10: o_alu_op <= `ALU_OP_2CMPL;
2'b11: o_alu_op <= `ALU_OP_1CMPL;
endcase
next_nibble <= 0;
o_ins_decoded <= 1;
`ifdef SIM
o_unimplemented <= 0;
`endif
block_Bbx <= 0;
end
/*
* Block Cx
*
*
*/
if (do_block_Cx) begin if (do_block_Cx) begin
`ifdef SIM `ifdef SIM
$display("block_Cx %h", i_nibble); $display("block_Cx %h", i_nibble);
`endif `endif
// o_alu_debug <= 1;
o_fields_table <= `FT_TABLE_f; o_fields_table <= `FT_TABLE_f;
o_ins_alu_op <= 1; o_ins_alu_op <= 1;
o_alu_op <= (i_nibble[3] && i_nibble[2])?`ALU_OP_DEC:`ALU_OP_ADD; o_alu_op <= (i_nibble[3] && i_nibble[2])?`ALU_OP_DEC:`ALU_OP_ADD;
@ -628,6 +703,10 @@ always @(posedge i_clk) begin
end end
if (do_block_Fx) begin if (do_block_Fx) begin
`ifdef SIM
`endif
case (i_nibble) case (i_nibble)
4'h8, 4'h9, 4'hA, 4'hB: // r=-r A 4'h8, 4'h9, 4'hA, 4'hB: // r=-r A
begin begin

View file

@ -109,6 +109,18 @@ reg block_Abx;
wire do_block_Abx; wire do_block_Abx;
assign do_block_Abx = do_on_other_nibbles && block_Abx; assign do_block_Abx = do_on_other_nibbles && block_Abx;
reg block_Bx;
wire do_block_Bx;
assign do_block_Bx = do_on_other_nibbles && block_Bx;
reg block_Bax;
wire do_block_Bax;
assign do_block_Bax = do_on_other_nibbles && block_Bax;
reg block_Bbx;
wire do_block_Bbx;
assign do_block_Bbx = do_on_other_nibbles && block_Bbx;
reg block_Cx; reg block_Cx;
wire do_block_Cx; wire do_block_Cx;
assign do_block_Cx = do_on_other_nibbles && block_Cx; assign do_block_Cx = do_on_other_nibbles && block_Cx;

View file

@ -222,6 +222,8 @@ always @(posedge i_clk) begin
`ALU_REG_B: $write("B"); `ALU_REG_B: $write("B");
`ALU_REG_C: $write("C"); `ALU_REG_C: $write("C");
`ALU_REG_D: $write("D"); `ALU_REG_D: $write("D");
`ALU_REG_D0: $write("D0");
`ALU_REG_D1: $write("D1");
`ALU_REG_RSTK: $write("RSTK"); `ALU_REG_RSTK: $write("RSTK");
`ALU_REG_IMM: $write("\t%0d", o_imm_value+1); `ALU_REG_IMM: $write("\t%0d", o_imm_value+1);
default: $write("[src2:%0d]", o_reg_src2); default: $write("[src2:%0d]", o_reg_src2);

View file

@ -63,6 +63,11 @@ always @(posedge i_clk) begin
o_field <= 0; o_field <= 0;
o_field_valid <= 0; o_field_valid <= 0;
case (i_nibble) case (i_nibble)
4'h4, 4'h5: begin // RTNC / GOC / RTNNC / GONC
$display("------------------------------------------------ 4/5xx JUMP setting fields");
o_field_start <= 0;
o_field_last <= 1;
end
4'h6, 4'h7: begin // GOTO / GOSUB 4'h6, 4'h7: begin // GOTO / GOSUB
o_field_start <= 0; o_field_start <= 0;
o_field_last <= 2; o_field_last <= 2;

View file

@ -35,7 +35,7 @@ always @(posedge i_clk) begin
if (do_on_first_nibble) begin if (do_on_first_nibble) begin
// reset values on instruction decode start // reset values on instruction decode start
case (i_nibble) case (i_nibble)
4'h6, 4'h7: begin 4'h4, 4'h5, 4'h6, 4'h7: begin
o_reg_dest <= 0; o_reg_dest <= 0;
o_reg_src1 <= `ALU_REG_IMM; o_reg_src1 <= `ALU_REG_IMM;
o_reg_src2 <= 0; o_reg_src2 <= 0;
@ -125,7 +125,8 @@ always @(posedge i_clk) begin
if (do_block_13x) begin if (do_block_13x) begin
o_reg_dest <= i_nibble[1]?reg_A_C:reg_D0D1; o_reg_dest <= i_nibble[1]?reg_A_C:reg_D0D1;
o_reg_src1 <= i_nibble[1]?reg_D0D1:reg_A_C; o_reg_src1 <= i_nibble[2]?`ALU_REG_C:`ALU_REG_A;
o_reg_src2 <= i_nibble[1]?reg_D0D1:0;
end end
if (do_block_14x_15xx) begin if (do_block_14x_15xx) begin
@ -190,29 +191,60 @@ always @(posedge i_clk) begin
if (do_block_Abx || do_block_Dx) begin if (do_block_Abx || do_block_Dx) begin
case ({i_nibble[3],i_nibble[2]}) case ({i_nibble[3],i_nibble[2]})
2'b00: begin 2'b00: begin
o_reg_dest <= reg_ABCD; o_reg_dest <= reg_ABCD;
o_reg_src1 <= `ALU_REG_ZERO; o_reg_src1 <= `ALU_REG_ZERO;
o_reg_src2 <= 0; o_reg_src2 <= 0;
end end
2'b01: begin 2'b01: begin
o_reg_dest <= reg_ABCD; o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_BCAC; o_reg_src1 <= reg_BCAC;
o_reg_src2 <= 0; o_reg_src2 <= 0;
end end
2'b10: begin 2'b10: begin
o_reg_dest <= reg_BCAC; o_reg_dest <= reg_BCAC;
o_reg_src1 <= reg_ABCD; o_reg_src1 <= reg_ABCD;
o_reg_src2 <= 0; o_reg_src2 <= 0;
end end
2'b11: begin // exch 2'b11: begin // exch
o_reg_dest <= reg_ABAC; o_reg_dest <= reg_ABAC;
o_reg_src1 <= reg_ABAC; o_reg_src1 <= reg_ABAC;
o_reg_src2 <= reg_BCCD; o_reg_src2 <= reg_BCCD;
end end
endcase endcase
end end
if (do_block_Bax) begin
case ({i_nibble[3],i_nibble[2]})
2'b00: begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_ABCD;
o_reg_src2 <= reg_BCAC;
end
2'b01: begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_ABCD;
o_reg_src2 <= 0;
end
2'b10: begin
o_reg_dest <= reg_BCAC;
o_reg_src1 <= reg_BCAC;
o_reg_src2 <= reg_ABCD;
end
2'b11: begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_BCAC;
o_reg_src2 <= reg_ABCD;
end
endcase
end
if (do_block_Bbx) begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_ABCD;
o_reg_src2 <= 0;
end
if (do_block_Cx) begin if (do_block_Cx) begin
case ({i_nibble[3],i_nibble[2]}) case ({i_nibble[3],i_nibble[2]})
2'b00: begin 2'b00: begin

View file

@ -1,2 +1,3 @@
3 4 1 0 0 0 0 2 3
F A // NOP3 4 D F
3 1 4 3