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_set_xm,
i_set_carry,
i_test_carry,
i_carry_val,
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_set_xm;
input wire [0:0] i_set_carry;
input wire [0:0] i_test_carry;
input wire [0:0] i_carry_val;
output wire [3:0] o_reg_p;
@ -197,58 +199,6 @@ reg [19:0] RSTK[0:7];
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
/*
@ -313,7 +263,7 @@ end
// 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 &&
(!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
*/
wire is_alu_op_jump;
assign is_alu_op_jump = ((alu_op == `ALU_OP_JMP_REL3) ||
(alu_op == `ALU_OP_JMP_REL4) ||
(alu_op == `ALU_OP_JMP_ABS5) ||
i_ins_rtn);
wire is_alu_op_unc_jump;
assign is_alu_op_unc_jump = ((alu_op == `ALU_OP_JMP_REL3) ||
(alu_op == `ALU_OP_JMP_REL4) ||
(alu_op == `ALU_OP_JMP_ABS5) ||
i_ins_rtn);
wire is_alu_op_test;
assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) ||
(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;
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
if (do_alu_init) begin
@ -458,6 +417,16 @@ end
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
// $display("------------------------------------------------- DO_ALU_INIT");
alu_run <= 1;
@ -493,6 +462,14 @@ end
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 (alu_debug) begin
`ifdef SIM
@ -511,9 +488,11 @@ always @(posedge i_clk) begin
`ALU_OP_RST_BIT,
`ALU_OP_SET_BIT,
`ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_ADD,
`ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5,
@ -551,6 +530,8 @@ always @(posedge i_clk) begin
`ALU_OP_RST_BIT,
`ALU_OP_SET_BIT,
`ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5: begin end // no need for a 2nd operand
@ -584,13 +565,15 @@ always @(posedge i_clk) begin
// 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);
case (alu_op)
`ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry;
`ALU_OP_ADD: p_carry <= alu_start?0:c_carry;
`ALU_OP_TEST_NEQ: p_carry <= alu_start?0:c_carry;
`ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry;
`ALU_OP_DEC: p_carry <= alu_start?1'b0: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
// prepare jump base
case (alu_op)
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4:
begin
@ -609,7 +592,11 @@ end
always @(posedge i_clk) begin
if (i_reset) begin
c_carry <= 0;
c_res1 <= 0;
c_res2 <= 0;
c_carry <= 0;
is_zero <= 0;
jump_off <= 0;
end
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);
`endif
case (alu_op)
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5:
if (alu_start)
jump_off <= { 16'b0, p_src1 };
endcase
if(alu_start)
case (alu_op)
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4,
`ALU_OP_JMP_ABS5: jump_off <= { 16'b0, p_src1 };
endcase
// main case
case (alu_op)
@ -641,16 +628,18 @@ always @(posedge i_clk) begin
`ALU_OP_COPY,
`ALU_OP_RST_BIT,
`ALU_OP_SET_BIT: c_res1 <= p_src1;
`ALU_OP_2CMPL:
begin
`ALU_OP_2CMPL: begin
c_carry <= (~p_src1 == 4'hf) && p_carry ;
c_res1 <= ~p_src1 + {3'b000, p_carry};
is_zero <= ((~p_src1 + {3'b000, p_carry}) == 0) && alu_start?1:is_zero;
end
`ALU_OP_DEC:
{c_carry, c_res1} <= p_src1 + 4'b1111 + {4'b0000, p_carry};
`ALU_OP_ADD:
{c_carry, c_res1} <= p_src1 + p_src2 + {4'b0000, p_carry};
`ALU_OP_TEST_NEQ:
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_REL4,
`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);
endcase
case (alu_op)
`ALU_OP_JMP_REL3: if (alu_finish)
jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] };
`ALU_OP_JMP_REL4: if (alu_finish)
jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] };
endcase
if (alu_finish)
case (alu_op)
`ALU_OP_JMP_REL2: jump_off <= { {12{p_src1[3]}}, p_src1, jump_off[3:0] };
`ALU_OP_JMP_REL3: jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] };
`ALU_OP_JMP_REL4: jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] };
endcase
// $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,
@ -672,13 +661,62 @@ always @(posedge i_clk) begin
end
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};
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
/*
* 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 (alu_debug_jump) begin
`ifdef SIM
@ -714,10 +752,6 @@ always @(posedge i_clk) begin
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);
// $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
`endif
@ -726,6 +760,7 @@ always @(posedge i_clk) begin
`ALU_OP_COPY,
`ALU_OP_EXCH, // does the first assign
`ALU_OP_2CMPL,
`ALU_OP_DEC,
`ALU_OP_ADD,
`ALU_OP_CLR_MASK:
case (reg_dest)
@ -756,6 +791,7 @@ always @(posedge i_clk) begin
endcase
`ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ,
`ALU_OP_JMP_REL2,
`ALU_OP_JMP_REL3,
`ALU_OP_JMP_REL4,
`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_C: C[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_R1: R1[f_cur] <= c_res2;
`ALU_REG_R2: R2[f_cur] <= c_res2;
`ALU_REG_R3: R3[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_P: P <= c_res2;
// `ALU_REG_HST: HST <= c_res2;
@ -792,6 +828,8 @@ always @(posedge i_clk) begin
if (do_alu_save) begin
case (alu_op)
`ALU_OP_2CMPL: CARRY <= !is_zero;
`ALU_OP_DEC,
`ALU_OP_ADD,
`ALU_OP_TEST_EQ,
`ALU_OP_TEST_NEQ: CARRY <= c_carry;
endcase
@ -964,32 +1002,69 @@ end
wire [19:0] next_pc;
wire [19:0] goyes_off;
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] 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] reload_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_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 pop_pc = i_pop && i_ins_rtn &&
((!i_ins_test_go) ||
(i_ins_test_go && c_carry));
assign reload_pc = uncond_jmp || pop_pc || just_reset;
assign set_unc_jmp = is_alu_op_unc_jump && alu_finish;
assign exec_unc_jmp = is_alu_op_unc_jump && alu_done;
assign exec_unc_rtn = i_pop && i_ins_rtn;
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;
always @(posedge i_clk) begin
/*
* initializes the PC
*
*/
if (i_reset) begin
PC <= ~0;
o_bus_load_pc <= 0;
rstk_ptr <= 0;
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
// otherwise we get a conflict on o_bus_address
if (setup_load_dp)
@ -1016,16 +1091,18 @@ always @(posedge i_clk) begin
`ifdef SIM
if (alu_debug_pc)
$display({"ALU_PC 3: !stl %b | nx %5h | done %b | fin %b | ",
"jmp %b | ins_rtn %b | push %b | ",
"imm %h | j_bs %h | go_off %h | go_pc %h"},
"uncjmp %b | ins_rtn %b | push %b | imm %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,
is_alu_op_jump, i_ins_rtn, i_push,
i_imm_value, jump_bse, goyes_off, goyes_pc);
is_alu_op_unc_jump, i_ins_rtn, i_push, i_imm_value,
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
// this may do wierd things with C=RSTK...
if (update_pc) begin
PC <= pop_pc ? RSTK[rstk_ptr-1] : next_pc;
PC <= pop_pc ? RSTK[rstk_ptr - 1] : next_pc;
end
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
if (do_alu_mode) begin
$display("SETTING MODE TO %s", i_mode_dec?"DEC":"HEX");
DEC <= i_mode_dec;
end
end
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
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] 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_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_cmd_dp_write;
wire [0:0] cmd_dp_write_data;
wire [0:0] do_dp_write_data;
wire [0:0] do_pc_read_after_dp_write;
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_uc;
wire [0:0] do_unstall;
wire [0:0] do_cleanup;
wire [0:0] do_stall;
wire [0:0] do_unstall;
wire [0:0] do_stop_loop;
// 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_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 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_pc_read_after_dp_read ||
do_cmd_dp_write ||
do_dp_write_data ||
cmd_dp_write_data ||
do_pc_read_after_dp_write);
assign do_unstall = do_dp_read_data_uc ||
cmd_load_dp_dp_write_uc ||
cmd_config_uc ||
cmd_reset_uc;
assign do_cleanup = en_bus_send &&
(do_cleanup_after_dp_read ||
cmd_load_dp_dp_write_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
@ -184,22 +208,24 @@ assign do_cleanup = do_cleanup_after_dp_read ||
`ifdef SIM
`define ROMBITS 20
`else
`define ROMBITS 16
`define ROMBITS 12
`endif
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] 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;
assign last_cmd_pc_read = (last_cmd == `BUSCMD_PC_READ);
assign last_cmd_dp_read = (last_cmd == `BUSCMD_DP_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_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 do_read_from_bus = en_bus_recv && (!i_read_stall || do_dp_read_data) && (last_cmd_pc_read || last_cmd_dp_read);
assign use_pc_as_pointer = last_cmd_pc_read;
assign use_dp_as_pointer = last_cmd_dp_read;
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
// `ifdef SIM
$readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1);
// $readmemh( "testrom-2.hex", rom);
// $readmemh( "testrom-2.hex", rom);
`ifdef SIM
// $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;
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
@ -250,20 +289,6 @@ always @(posedge i_clk) 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
* after a data transfer
@ -342,46 +367,54 @@ always @(posedge i_clk) begin
addr_cnt <= addr_cnt + 1;
o_bus_strobe <= 1;
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
/*
/******************************************************************************
*
* 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
*
*/
***************************************************************************/
if (do_read_from_bus) begin
/*
* only display during simulation
*/
`ifdef SIM
if (do_read_from_bus)
$display("BUS_RECV %0d: [%d] <= READ(%s) [%5h] %h",
`PH_BUS_RECV, i_cycle_ctr, use_pc_as_pointer?"PC":"DP",
read_pointer, rom[read_pointer]);
`endif
if (do_read_from_bus)
o_nibble <= rom[read_pointer];
if (use_pc_as_pointer) local_pc <= local_pc + 1;
else begin
local_dp <= local_dp + 1;
dp_read_s <= 1;
end
end
if (do_read_from_bus_with_pc)
local_pc <= local_pc + 1;
if (do_read_from_bus_with_dp) begin
local_dp <= local_dp + 1;
dp_read_s <= 1;
end
if (do_display_stalled) begin
$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;
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
// 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
case (last_cmd)
`BUSCMD_NOP: begin end
`BUSCMD_LOAD_PC,
@ -446,9 +486,6 @@ always @(posedge i_clk) begin
`BUSCMD_RESET: begin end
default: $display("------------ UNHANDLED BUSCMD %h", last_cmd);
endcase
end

View file

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

View file

@ -191,6 +191,7 @@ always @(posedge i_clk) begin
o_ins_set_mode <= 0;
o_ins_reset <= 0;
o_ins_config <= 0;
o_test_carry <= 0;
end
if (decoder_active) begin
@ -290,6 +291,7 @@ always @(posedge i_clk) begin
// 4xy GOC
// 500 RTNNC
// 5xy GONC
o_alu_debug <= 1;
o_alu_no_stall <= 1;
o_alu_op <= `ALU_OP_JMP_REL2;
mem_load_max <= 1;
@ -319,6 +321,13 @@ always @(posedge i_clk) begin
o_fields_table <= `FT_TABLE_a;
block_Ax <= 1;
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'hD: block_Dx <= 1;
4'hF: block_Fx <= 1;
@ -572,6 +581,15 @@ always @(posedge i_clk) begin
`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
o_fields_table <= i_nibble[3]?`FT_TABLE_b:`FT_TABLE_a;
block_Aax <= !i_nibble[3];
@ -597,10 +615,67 @@ always @(posedge i_clk) begin
block_Abx <= 0;
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
`ifdef SIM
$display("block_Cx %h", i_nibble);
`endif
// o_alu_debug <= 1;
o_fields_table <= `FT_TABLE_f;
o_ins_alu_op <= 1;
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
if (do_block_Fx) begin
`ifdef SIM
`endif
case (i_nibble)
4'h8, 4'h9, 4'hA, 4'hB: // r=-r A
begin

View file

@ -109,6 +109,18 @@ reg block_Abx;
wire do_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;
wire do_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_C: $write("C");
`ALU_REG_D: $write("D");
`ALU_REG_D0: $write("D0");
`ALU_REG_D1: $write("D1");
`ALU_REG_RSTK: $write("RSTK");
`ALU_REG_IMM: $write("\t%0d", o_imm_value+1);
default: $write("[src2:%0d]", o_reg_src2);

View file

@ -63,6 +63,11 @@ always @(posedge i_clk) begin
o_field <= 0;
o_field_valid <= 0;
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
o_field_start <= 0;
o_field_last <= 2;

View file

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

View file

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