mirror of
https://github.com/sxpert/hp-saturn
synced 2025-01-20 10:26:31 +01:00
implement the pieces to replicate the bus data transfers for writing data out.
This commit is contained in:
parent
128921c364
commit
8fc7cde507
5 changed files with 244 additions and 80 deletions
171
saturn_alu.v
171
saturn_alu.v
|
@ -16,6 +16,7 @@
|
||||||
module saturn_alu (
|
module saturn_alu (
|
||||||
i_clk,
|
i_clk,
|
||||||
i_reset,
|
i_reset,
|
||||||
|
i_cycle_ctr,
|
||||||
i_en_alu_dump,
|
i_en_alu_dump,
|
||||||
i_en_alu_prep,
|
i_en_alu_prep,
|
||||||
i_en_alu_calc,
|
i_en_alu_calc,
|
||||||
|
@ -26,6 +27,8 @@ module saturn_alu (
|
||||||
o_bus_address,
|
o_bus_address,
|
||||||
o_bus_load_pc,
|
o_bus_load_pc,
|
||||||
o_bus_load_dp,
|
o_bus_load_dp,
|
||||||
|
o_bus_read_pc,
|
||||||
|
o_bus_write_dp,
|
||||||
o_bus_nibble_out,
|
o_bus_nibble_out,
|
||||||
|
|
||||||
i_push,
|
i_push,
|
||||||
|
@ -61,6 +64,7 @@ module saturn_alu (
|
||||||
|
|
||||||
input wire [0:0] i_clk;
|
input wire [0:0] i_clk;
|
||||||
input wire [0:0] i_reset;
|
input wire [0:0] i_reset;
|
||||||
|
input wire [31:0] i_cycle_ctr;
|
||||||
input wire [0:0] i_en_alu_dump;
|
input wire [0:0] i_en_alu_dump;
|
||||||
input wire [0:0] i_en_alu_prep;
|
input wire [0:0] i_en_alu_prep;
|
||||||
input wire [0:0] i_en_alu_calc;
|
input wire [0:0] i_en_alu_calc;
|
||||||
|
@ -71,6 +75,8 @@ input wire [0:0] i_stalled;
|
||||||
output reg [19:0] o_bus_address;
|
output reg [19:0] o_bus_address;
|
||||||
output reg [0:0] o_bus_load_pc;
|
output reg [0:0] o_bus_load_pc;
|
||||||
output reg [0:0] o_bus_load_dp;
|
output reg [0:0] o_bus_load_dp;
|
||||||
|
output reg [0:0] o_bus_read_pc;
|
||||||
|
output reg [0:0] o_bus_write_dp;
|
||||||
output reg [3:0] o_bus_nibble_out;
|
output reg [3:0] o_bus_nibble_out;
|
||||||
|
|
||||||
input wire [0:0] i_push;
|
input wire [0:0] i_push;
|
||||||
|
@ -261,7 +267,7 @@ wire do_alu_pc;
|
||||||
wire do_alu_mode;
|
wire do_alu_mode;
|
||||||
|
|
||||||
assign do_busclean = alu_active && i_en_alu_dump;
|
assign do_busclean = alu_active && i_en_alu_dump;
|
||||||
assign do_alu_init = alu_active && i_en_alu_init && i_ins_alu_op && !alu_run;
|
assign do_alu_init = alu_active && i_en_alu_init && i_ins_alu_op && !alu_run && !write_done;
|
||||||
assign do_alu_prep = alu_active && i_en_alu_prep && alu_run;
|
assign do_alu_prep = alu_active && i_en_alu_prep && alu_run;
|
||||||
assign do_alu_calc = alu_active && i_en_alu_calc && alu_run;
|
assign do_alu_calc = alu_active && i_en_alu_calc && alu_run;
|
||||||
assign do_alu_save = alu_active && i_en_alu_save && alu_run;
|
assign do_alu_save = alu_active && i_en_alu_save && alu_run;
|
||||||
|
@ -277,7 +283,9 @@ assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go;
|
||||||
|
|
||||||
// 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 = alu_run && (!i_alu_no_stall || alu_finish || alu_go_test);
|
assign o_alu_stall_dec = (!no_extra_cycles) ||
|
||||||
|
(alu_run &&
|
||||||
|
(!i_alu_no_stall || alu_finish || alu_go_test));
|
||||||
|
|
||||||
wire alu_start;
|
wire alu_start;
|
||||||
wire alu_finish;
|
wire alu_finish;
|
||||||
|
@ -309,9 +317,9 @@ assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) ||
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
|
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
if (i_stalled && i_en_alu_dump)
|
// if (i_stalled && i_en_alu_dump)
|
||||||
$display("ALU STALLED");
|
// $display("ALU STALLED");
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef ALU_DEBUG_DBG
|
`ifdef ALU_DEBUG_DBG
|
||||||
$display("iad %b | AD %b | ad %b | ADD %b | add %b | ADJ %b | adj %b | ADP %b | adp %b",
|
$display("iad %b | AD %b | ad %b | ADD %b | add %b | ADJ %b | adj %b | ADP %b | adp %b",
|
||||||
|
@ -376,18 +384,6 @@ always @(posedge i_clk) begin
|
||||||
reg_src2 <= i_reg_src2;
|
reg_src2 <= i_reg_src2;
|
||||||
f_last <= i_field_last;
|
f_last <= i_field_last;
|
||||||
|
|
||||||
if (is_mem_xfer) begin
|
|
||||||
`ifdef SIM
|
|
||||||
$display("ALU_XFER 3: read %b | write %b | mem_reg DAT%b",
|
|
||||||
is_mem_read, is_mem_write, mem_reg[0]);
|
|
||||||
$display(".------------------------------------.");
|
|
||||||
$display("| SHOULD TELL THE BUS CONTROLLER TO |");
|
|
||||||
$display("| LOAD D0 OR D1 INTO MODULES' DP REG |");
|
|
||||||
$display("`------------------------------------´");
|
|
||||||
`endif
|
|
||||||
// DO SOMETHING TO GET THE BUS CONTROLLER TO SEND OUT
|
|
||||||
// THE CONTENTS OF D0 OR D1 AS THE DP
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -398,6 +394,7 @@ end
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
|
|
||||||
if (do_alu_init) begin
|
if (do_alu_init) begin
|
||||||
|
$display("------------------------------------------------- DO_ALU_INIT");
|
||||||
alu_run <= 1;
|
alu_run <= 1;
|
||||||
f_first <= i_field_start;
|
f_first <= i_field_start;
|
||||||
f_cur <= i_field_start;
|
f_cur <= i_field_start;
|
||||||
|
@ -552,7 +549,7 @@ always @(posedge i_clk) begin
|
||||||
if (do_alu_calc) begin
|
if (do_alu_calc) begin
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
if (alu_debug)
|
if (alu_debug)
|
||||||
$display("ALU_CALC 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | dest %d | src1 %h | src2 %h | p_carry %b",
|
$display("ALU_CALC 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | dest %d | psrc1 %h | psrc2 %h | p_carry %b",
|
||||||
alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, reg_dest, p_src1, p_src2, p_carry);
|
alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, reg_dest, p_src1, p_src2, p_carry);
|
||||||
if (alu_debug_jump)
|
if (alu_debug_jump)
|
||||||
$display("ALU_JUMP 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | jbs %5h | jof %5h | jpc %5h | fin %b",
|
$display("ALU_JUMP 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | jbs %5h | jof %5h | jpc %5h | fin %b",
|
||||||
|
@ -650,15 +647,18 @@ always @(posedge i_clk) begin
|
||||||
`ALU_OP_ADD,
|
`ALU_OP_ADD,
|
||||||
`ALU_OP_CLR_MASK:
|
`ALU_OP_CLR_MASK:
|
||||||
case (reg_dest)
|
case (reg_dest)
|
||||||
`ALU_REG_A: A[f_cur*4+:4] <= c_res1;
|
`ALU_REG_A: A[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_B: B[f_cur*4+:4] <= c_res1;
|
`ALU_REG_B: B[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_C: C[f_cur*4+:4] <= c_res1;
|
`ALU_REG_C: C[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_D: D[f_cur*4+:4] <= c_res1;
|
`ALU_REG_D: D[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_D0: D0[f_cur*4+:4] <= c_res1;
|
`ALU_REG_D0: D0[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_D1: D1[f_cur*4+:4] <= c_res1;
|
`ALU_REG_D1: D1[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_ST: ST[f_cur*4+:4] <= c_res1;
|
`ALU_REG_ST: ST[f_cur*4+:4] <= c_res1;
|
||||||
`ALU_REG_P: P <= c_res1;
|
`ALU_REG_P: P <= c_res1;
|
||||||
`ALU_REG_HST: HST <= c_res1;
|
`ALU_REG_DAT0,
|
||||||
|
`ALU_REG_DAT1: o_bus_nibble_out <= c_res1;
|
||||||
|
`ALU_REG_HST: HST <= c_res1;
|
||||||
|
default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op);
|
||||||
endcase
|
endcase
|
||||||
`ALU_OP_RST_BIT,
|
`ALU_OP_RST_BIT,
|
||||||
`ALU_OP_SET_BIT:
|
`ALU_OP_SET_BIT:
|
||||||
|
@ -733,6 +733,11 @@ 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;
|
||||||
|
|
||||||
|
reg [1:0] extra_cycles;
|
||||||
|
wire [0:0] no_extra_cycles;
|
||||||
|
wire [1:0] cycles_to_go;
|
||||||
|
reg [0:0] write_done;
|
||||||
|
|
||||||
assign next_pc = (is_alu_op_jump && alu_finish)?jump_pc:PC + 1;
|
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;
|
||||||
|
@ -745,10 +750,17 @@ assign pop_pc = i_pop && i_ins_rtn &&
|
||||||
assign reload_pc = uncond_jmp || pop_pc || just_reset;
|
assign reload_pc = uncond_jmp || pop_pc || just_reset;
|
||||||
assign push_pc = update_pc && i_push && alu_finish;
|
assign push_pc = update_pc && i_push && alu_finish;
|
||||||
|
|
||||||
|
assign no_extra_cycles = (extra_cycles == 0);
|
||||||
|
assign cycles_to_go = extra_cycles - 1;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_reset) begin
|
if (i_reset) begin
|
||||||
PC <= ~0;
|
PC <= ~0;
|
||||||
just_reset <= 1;
|
just_reset <= 1;
|
||||||
|
extra_cycles <= 0;
|
||||||
|
o_bus_load_pc <= 0;
|
||||||
|
o_bus_load_dp <= 0;
|
||||||
|
o_bus_write_dp <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -766,8 +778,74 @@ always @(posedge i_clk) begin
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* updates the PC
|
*
|
||||||
|
* Request the D0 or D1 pointers to be loaded to other
|
||||||
|
* modules through the bus
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// $display("[!no_ec %b] || ( [run %b] && ( [!nstll %b] || [fin %b] || [test %b] ))",
|
||||||
|
// !no_extra_cycles, alu_run, !i_alu_no_stall, alu_finish, alu_go_test);
|
||||||
|
|
||||||
|
|
||||||
|
if (do_alu_init) begin
|
||||||
|
if (is_mem_xfer && !write_done) begin
|
||||||
|
`ifdef SIM
|
||||||
|
$display("ALU_XFER 3: read %b | write %b | mem_reg DAT%b",
|
||||||
|
is_mem_read, is_mem_write, mem_reg[0]);
|
||||||
|
// $display(".------------------------------------.");
|
||||||
|
// $display("| SHOULD TELL THE BUS CONTROLLER TO |");
|
||||||
|
// $display("| LOAD D0 OR D1 INTO MODULES' DP REG |");
|
||||||
|
// $display("`------------------------------------´");
|
||||||
|
`endif
|
||||||
|
// DO SOMETHING TO GET THE BUS CONTROLLER TO SEND OUT
|
||||||
|
// THE CONTENTS OF D0 OR D1 AS THE DP
|
||||||
|
case (mem_reg[0])
|
||||||
|
0: o_bus_address <= D0;
|
||||||
|
1: o_bus_address <= D1;
|
||||||
|
endcase
|
||||||
|
o_bus_load_dp <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_busclean && alu_run && !write_done)
|
||||||
|
if (is_mem_write && !o_bus_write_dp) begin
|
||||||
|
// $display("ALUWRITE %0d: [%d] setting up write", `PH_ALU_DUMP, i_cycle_ctr);
|
||||||
|
o_bus_write_dp <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
// writing needs one more cycle as the DP_WRITE command
|
||||||
|
// needs to be send
|
||||||
|
if (do_alu_save && alu_finish && is_mem_write && (extra_cycles == 0)) begin
|
||||||
|
// $display("ALUWRITE %0d: [%d] 2 EXTRA CYCLES", `PH_ALU_SAVE, i_cycle_ctr);
|
||||||
|
extra_cycles <= 2;
|
||||||
|
write_done <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_en_alu_calc && !no_extra_cycles) begin
|
||||||
|
// $display("ALUWRITE %0d: [%d] %0d CYCLES TO GO", `PH_ALU_SAVE, i_cycle_ctr, cycles_to_go);
|
||||||
|
extra_cycles <= cycles_to_go;
|
||||||
|
if (cycles_to_go == 1) begin
|
||||||
|
o_bus_write_dp <= 0;
|
||||||
|
o_bus_read_pc <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_en_alu_dump && no_extra_cycles && o_bus_read_pc) begin
|
||||||
|
// $display("ALUWRITE %0d: [%d] RELEASE DECODER", `PH_ALU_DUMP, i_cycle_ctr);
|
||||||
|
o_bus_read_pc <= 0;
|
||||||
|
write_done <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Update the PC.
|
||||||
|
* Request the new PC be loaded to the other modules through
|
||||||
|
* the bus if necessary
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
if (do_alu_pc) begin
|
if (do_alu_pc) begin
|
||||||
// $display("DO ALU PC");
|
// $display("DO ALU PC");
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
|
@ -778,19 +856,20 @@ always @(posedge i_clk) begin
|
||||||
!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_jump, i_ins_rtn, i_push,
|
||||||
i_imm_value, jump_bse, goyes_off, goyes_pc);
|
i_imm_value, jump_bse, goyes_off, goyes_pc);
|
||||||
if (reload_pc) begin
|
// if (reload_pc) begin
|
||||||
$display(".---------------------------------.");
|
// $display(".---------------------------------.");
|
||||||
$display("| SHOULD TELL THE BUS CONTROLLER |");
|
// $display("| SHOULD TELL THE BUS CONTROLLER |");
|
||||||
$display("| TO LOAD PC INTO MODULES' PC REG |");
|
// $display("| TO LOAD PC INTO MODULES' PC REG |");
|
||||||
$display("`---------------------------------´");
|
// $display("`---------------------------------´");
|
||||||
end
|
// end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// if we just came out of reset, simulate a long jump to 0
|
// if we just came out of reset, simulate a long jump to 0
|
||||||
if (just_reset) begin
|
if (just_reset) begin
|
||||||
$display("ALU_RSET 3: simulating GOVLNG to PC");
|
// $display("ALU_RSET 3: simulating GOVLNG to PC");
|
||||||
// cancel this signal for good once reset is gone
|
// cancel this signal for good once reset is gone
|
||||||
just_reset <= 0;
|
just_reset <= 0;
|
||||||
|
o_bus_read_pc <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
// this may do wierd things with C=RSTK...
|
// this may do wierd things with C=RSTK...
|
||||||
|
@ -799,7 +878,7 @@ always @(posedge i_clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
if (reload_pc) begin
|
if (reload_pc) begin
|
||||||
$display("ALU_PC 3: $$$$ RELOADING PC $$$$");
|
// $display("ALU_PC 3: $$$$ RELOADING PC $$$$");
|
||||||
o_bus_address <= pop_pc ? RSTK[rstk_ptr-1] : next_pc;
|
o_bus_address <= pop_pc ? RSTK[rstk_ptr-1] : next_pc;
|
||||||
o_bus_load_pc <= 1;
|
o_bus_load_pc <= 1;
|
||||||
end
|
end
|
||||||
|
@ -819,9 +898,17 @@ always @(posedge i_clk) begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// deactivate o_load_pc
|
/*
|
||||||
if (do_busclean && o_bus_load_pc)
|
*
|
||||||
o_bus_load_pc <= 0;
|
* Deactivate the load_pc or load_dp enables on the next clock
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (do_busclean && (o_bus_load_pc || o_bus_load_dp)) begin
|
||||||
|
$display("BUSCLEAN %0d: cleaning the various bus control bits", `PH_ALU_DUMP);
|
||||||
|
o_bus_load_pc <= 0;
|
||||||
|
o_bus_load_dp <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ module saturn_bus_ctrl (
|
||||||
i_address,
|
i_address,
|
||||||
i_load_pc,
|
i_load_pc,
|
||||||
i_load_dp,
|
i_load_dp,
|
||||||
|
i_read_pc,
|
||||||
|
i_write_dp,
|
||||||
i_nibble,
|
i_nibble,
|
||||||
o_nibble
|
o_nibble
|
||||||
);
|
);
|
||||||
|
@ -52,6 +54,8 @@ input wire [19:0] i_alu_pc;
|
||||||
input wire [19:0] i_address;
|
input wire [19:0] i_address;
|
||||||
input wire [0:0] i_load_pc;
|
input wire [0:0] i_load_pc;
|
||||||
input wire [0:0] i_load_dp;
|
input wire [0:0] i_load_dp;
|
||||||
|
input wire [0:0] i_read_pc;
|
||||||
|
input wire [0:0] i_write_dp;
|
||||||
input wire [3:0] i_nibble;
|
input wire [3:0] i_nibble;
|
||||||
output reg [3:0] o_nibble;
|
output reg [3:0] o_nibble;
|
||||||
|
|
||||||
|
@ -84,21 +88,23 @@ initial begin
|
||||||
// $readmemh( "testrom-2.hex", rom);
|
// $readmemh( "testrom-2.hex", rom);
|
||||||
// $monitor("addr %5h | strb %b | c/d %b | cnt %0d | odata %h | idata %h",
|
// $monitor("addr %5h | strb %b | c/d %b | cnt %0d | odata %h | idata %h",
|
||||||
// i_address, o_bus_strobe, o_bus_cmd_data, addr_cnt, o_bus_data, i_bus_data);
|
// i_address, o_bus_strobe, o_bus_cmd_data, addr_cnt, o_bus_data, i_bus_data);
|
||||||
|
|
||||||
|
// $monitor("MONITOR : strb %b | o_bus_data %h | i_bus_data %h", o_bus_strobe, o_bus_data, i_bus_data);
|
||||||
`endif
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [2:0] addr_cnt;
|
reg [3:0] last_cmd;
|
||||||
|
reg [2:0] addr_cnt;
|
||||||
reg [0:0] send_addr;
|
reg [0:0] send_addr;
|
||||||
|
|
||||||
reg [19:0] local_pc;
|
reg [19:0] local_pc;
|
||||||
|
reg [19:0] local_dp;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_reset) begin
|
if (i_reset) begin
|
||||||
o_stalled_by_bus <= 0;
|
o_stalled_by_bus <= 0;
|
||||||
o_bus_strobe <= 0;
|
o_bus_strobe <= 0;
|
||||||
o_bus_cmd_data <= 1; // 1 is the default level
|
o_bus_cmd_data <= 1; // 1 is the default level
|
||||||
addr_cnt <= 0;
|
addr_cnt <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -108,35 +114,90 @@ always @(posedge i_clk) begin
|
||||||
*/
|
*/
|
||||||
if (en_bus_send) begin
|
if (en_bus_send) begin
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sending LOAD_PC or LOAD_DP
|
||||||
|
*/
|
||||||
|
|
||||||
if (i_load_pc) begin
|
if (i_load_pc) begin
|
||||||
$display("BUS_SEND %0d: loading pc %h", `PH_BUS_SEND, i_address);
|
$display("BUS_SEND %0d: [%d] LOAD_PC %h", `PH_BUS_SEND, i_cycle_ctr, i_address);
|
||||||
o_bus_data <= `BUSCMD_LOAD_PC;
|
o_bus_data <= `BUSCMD_LOAD_PC;
|
||||||
|
last_cmd <= `BUSCMD_LOAD_PC;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (i_load_dp) begin
|
if (i_load_dp) begin
|
||||||
$display("BUS_SEND %0d: loading dp %h", `PH_BUS_SEND, i_address);
|
$display("BUS_SEND %0d: [%d] LOAD_DP %h", `PH_BUS_SEND, i_cycle_ctr, i_address);
|
||||||
o_bus_data <= `BUSCMD_LOAD_DP;
|
o_bus_data <= `BUSCMD_LOAD_DP;
|
||||||
|
last_cmd <= `BUSCMD_LOAD_DP;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (i_load_pc || i_load_dp) begin
|
if (i_load_pc || i_load_dp) begin
|
||||||
o_stalled_by_bus <= 1;
|
o_stalled_by_bus <= 1;
|
||||||
o_bus_cmd_data <= 0;
|
o_bus_cmd_data <= 0;
|
||||||
addr_cnt <= 0;
|
addr_cnt <= 0;
|
||||||
send_addr <= 1;
|
send_addr <= 1;
|
||||||
|
o_bus_strobe <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// sending address bits
|
||||||
if (send_addr) begin
|
if (send_addr) begin
|
||||||
$display("BUS_SEND %0d: send addr nibble %0d [%h]", `PH_BUS_SEND, addr_cnt, i_address[addr_cnt*4+:4]);
|
$display("BUS_SEND %0d: [%d] addr[%0d] %h =>",
|
||||||
|
`PH_BUS_SEND, i_cycle_ctr, addr_cnt, i_address[addr_cnt*4+:4]);
|
||||||
o_bus_data <= i_address[addr_cnt*4+:4];
|
o_bus_data <= i_address[addr_cnt*4+:4];
|
||||||
addr_cnt <= addr_cnt + 1;
|
addr_cnt <= addr_cnt + 1;
|
||||||
|
o_bus_strobe <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (!i_read_stall || send_addr)
|
/*
|
||||||
|
* send the PC_READ command to restore the instruction flow
|
||||||
|
* after a data transfer
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (i_read_pc) begin
|
||||||
|
if (last_cmd != `BUSCMD_PC_READ) begin
|
||||||
|
$display("BUS_SEND %0d: [%d] PC_READ", `PH_BUS_SEND, i_cycle_ctr);
|
||||||
|
o_bus_data <= `BUSCMD_PC_READ;
|
||||||
|
last_cmd <= `BUSCMD_PC_READ;
|
||||||
|
end
|
||||||
|
o_bus_strobe <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if ((last_cmd == `BUSCMD_PC_READ) && !i_read_stall)
|
||||||
|
o_bus_strobe <= 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* writing data to the bus,
|
||||||
|
* send DP_WRITE first if necessary
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (i_write_dp && (addr_cnt == 5)) begin
|
||||||
|
if (last_cmd != `BUSCMD_DP_WRITE) begin
|
||||||
|
$display("BUS_SEND %0d: [%d] DP_WRITE", `PH_BUS_SEND, i_cycle_ctr);
|
||||||
|
o_bus_data <= `BUSCMD_DP_WRITE;
|
||||||
|
last_cmd <= `BUSCMD_DP_WRITE;
|
||||||
o_bus_strobe <= 1;
|
o_bus_strobe <= 1;
|
||||||
|
end else 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
|
||||||
|
|
||||||
if (en_bus_ecmd && send_addr && (addr_cnt == 5)) begin
|
if (en_bus_ecmd && send_addr && (addr_cnt == 5)) begin
|
||||||
$display("BUS_ECMD %0d: releasing stall after sending addr", `PH_BUS_ECMD);
|
case (last_cmd)
|
||||||
|
`BUSCMD_LOAD_PC: begin
|
||||||
|
$display("BUS_ECMD %0d: [%d] <= PC_READ mode", `PH_BUS_ECMD, i_cycle_ctr);
|
||||||
|
last_cmd <= `BUSCMD_PC_READ;
|
||||||
|
local_pc <= i_address;
|
||||||
|
end
|
||||||
|
`BUSCMD_LOAD_DP: begin
|
||||||
|
$display("BUS_ECMD %0d: [%d] <= DP_READ mode", `PH_BUS_ECMD, i_cycle_ctr);
|
||||||
|
last_cmd <= `BUSCMD_DP_READ;
|
||||||
|
local_dp <= i_address;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
send_addr <= 0;
|
send_addr <= 0;
|
||||||
o_stalled_by_bus = 0;
|
o_stalled_by_bus = 0;
|
||||||
end
|
end
|
||||||
|
@ -146,9 +207,15 @@ always @(posedge i_clk) begin
|
||||||
* reading data from the bus
|
* reading data from the bus
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
if (en_bus_recv && !i_read_stall) begin
|
if (en_bus_recv && !i_read_stall) begin
|
||||||
$display("BUS_RECV %0d: [%d] nibble %h", `PH_BUS_RECV, i_cycle_ctr, rom[i_alu_pc[`ROMBITS-1:0]]);
|
if (last_cmd == `BUSCMD_PC_READ) begin
|
||||||
o_nibble <= rom[i_alu_pc[`ROMBITS-1:0]];
|
$display("BUS_RECV %0d: [%d] <= READ %h", `PH_BUS_RECV, i_cycle_ctr, rom[local_pc[`ROMBITS-1:0]]);
|
||||||
|
o_nibble <= rom[local_pc[`ROMBITS-1:0]];
|
||||||
|
local_pc <= local_pc + 1;
|
||||||
|
end else
|
||||||
|
$display("BUS_RECV %0d: [%d] UNKNOWN COMMAND %h", `PH_BUS_RECV, i_cycle_ctr, last_cmd);
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -86,6 +86,7 @@ saturn_decoder m_decoder (
|
||||||
.i_en_dbg (ck_debugger),
|
.i_en_dbg (ck_debugger),
|
||||||
.i_en_dec (ck_inst_dec),
|
.i_en_dec (ck_inst_dec),
|
||||||
.i_pc (reg_pc),
|
.i_pc (reg_pc),
|
||||||
|
.i_bus_load_pc (bus_load_pc),
|
||||||
.i_stalled (dec_stalled),
|
.i_stalled (dec_stalled),
|
||||||
.i_nibble (bus_nibble_in),
|
.i_nibble (bus_nibble_in),
|
||||||
|
|
||||||
|
@ -156,6 +157,7 @@ wire [0:0] ins_test_go;
|
||||||
saturn_alu m_alu (
|
saturn_alu m_alu (
|
||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
.i_reset (reset),
|
.i_reset (reset),
|
||||||
|
.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),
|
||||||
.i_en_alu_calc (ck_alu_calc),
|
.i_en_alu_calc (ck_alu_calc),
|
||||||
|
@ -166,6 +168,8 @@ saturn_alu m_alu (
|
||||||
.o_bus_address (bus_address),
|
.o_bus_address (bus_address),
|
||||||
.o_bus_load_pc (bus_load_pc),
|
.o_bus_load_pc (bus_load_pc),
|
||||||
.o_bus_load_dp (bus_load_dp),
|
.o_bus_load_dp (bus_load_dp),
|
||||||
|
.o_bus_read_pc (bus_read_pc),
|
||||||
|
.o_bus_write_dp (bus_write_dp),
|
||||||
.o_bus_nibble_out (bus_nibble_out),
|
.o_bus_nibble_out (bus_nibble_out),
|
||||||
|
|
||||||
.i_push (push),
|
.i_push (push),
|
||||||
|
@ -204,6 +208,8 @@ saturn_alu m_alu (
|
||||||
wire [19:0] bus_address;
|
wire [19:0] bus_address;
|
||||||
wire [0:0] bus_load_pc;
|
wire [0:0] bus_load_pc;
|
||||||
wire [0:0] bus_load_dp;
|
wire [0:0] bus_load_dp;
|
||||||
|
wire [0:0] bus_read_pc;
|
||||||
|
wire [0:0] bus_write_dp;
|
||||||
|
|
||||||
wire [3:0] bus_nibble_in;
|
wire [3:0] bus_nibble_in;
|
||||||
wire [3:0] bus_nibble_out;
|
wire [3:0] bus_nibble_out;
|
||||||
|
@ -241,6 +247,8 @@ saturn_bus_ctrl m_bus_ctrl (
|
||||||
.i_address (bus_address),
|
.i_address (bus_address),
|
||||||
.i_load_pc (bus_load_pc),
|
.i_load_pc (bus_load_pc),
|
||||||
.i_load_dp (bus_load_dp),
|
.i_load_dp (bus_load_dp),
|
||||||
|
.i_read_pc (bus_read_pc),
|
||||||
|
.i_write_dp (bus_write_dp),
|
||||||
.i_nibble (bus_nibble_out),
|
.i_nibble (bus_nibble_out),
|
||||||
.o_nibble (bus_nibble_in)
|
.o_nibble (bus_nibble_in)
|
||||||
);
|
);
|
||||||
|
@ -313,7 +321,6 @@ always @(posedge clk) begin
|
||||||
ck_alu_save <= clk_phase[1:0] == `PH_ALU_SAVE;
|
ck_alu_save <= clk_phase[1:0] == `PH_ALU_SAVE;
|
||||||
|
|
||||||
cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) };
|
cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) };
|
||||||
// stop after 50 clocks
|
|
||||||
if (cycle_ctr == (max_cycle + 1)) begin
|
if (cycle_ctr == (max_cycle + 1)) begin
|
||||||
$display(".-------------------.");
|
$display(".-------------------.");
|
||||||
$display("| OUT OF CYCLES |");
|
$display("| OUT OF CYCLES |");
|
||||||
|
@ -340,7 +347,7 @@ always @(posedge clk) begin
|
||||||
|
|
||||||
clock_end <= 0;
|
clock_end <= 0;
|
||||||
cycle_ctr <= ~0;
|
cycle_ctr <= ~0;
|
||||||
max_cycle <= 20;
|
max_cycle <= 155;
|
||||||
|
|
||||||
mem_ctrl_stall <= 0;
|
mem_ctrl_stall <= 0;
|
||||||
`ifndef SIM
|
`ifndef SIM
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
`include "def-alu.v"
|
`include "def-alu.v"
|
||||||
|
|
||||||
module saturn_decoder(
|
module saturn_decoder(
|
||||||
i_clk, i_reset, i_cycles, i_en_dbg, i_en_dec, i_stalled,
|
i_clk, i_reset, i_cycles, i_en_dbg, i_en_dec,
|
||||||
|
i_bus_load_pc, i_stalled,
|
||||||
i_pc, i_nibble,
|
i_pc, i_nibble,
|
||||||
|
|
||||||
i_reg_p,
|
i_reg_p,
|
||||||
|
@ -41,26 +42,27 @@ module saturn_decoder(
|
||||||
input wire [0:0] i_clk;
|
input wire [0:0] i_clk;
|
||||||
input wire [0:0] i_reset;
|
input wire [0:0] i_reset;
|
||||||
input wire [31:0] i_cycles;
|
input wire [31:0] i_cycles;
|
||||||
input wire i_en_dbg;
|
input wire [0:0] i_en_dbg;
|
||||||
input wire i_en_dec;
|
input wire [0:0] i_en_dec;
|
||||||
input wire i_stalled;
|
input wire [0:0] i_bus_load_pc;
|
||||||
|
input wire [0:0] i_stalled;
|
||||||
input wire [19:0] i_pc;
|
input wire [19:0] i_pc;
|
||||||
input wire [3:0] i_nibble;
|
input wire [3:0] i_nibble;
|
||||||
|
|
||||||
input wire [3:0] i_reg_p;
|
input wire [3:0] i_reg_p;
|
||||||
|
|
||||||
output reg o_inc_pc;
|
output reg [0:0] o_inc_pc;
|
||||||
output reg o_push;
|
output reg [0:0] o_push;
|
||||||
output reg o_pop;
|
output reg [0:0] o_pop;
|
||||||
output reg o_dec_error;
|
output reg [0:0] o_dec_error;
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
output reg [0:0] o_unimplemented;
|
output reg [0:0] o_unimplemented;
|
||||||
`endif
|
`endif
|
||||||
output reg o_alu_debug;
|
output reg [0:0] o_alu_debug;
|
||||||
|
|
||||||
// instructions related outputs
|
// instructions related outputs
|
||||||
output reg [19:0] o_ins_addr;
|
output reg [19:0] o_ins_addr;
|
||||||
output reg o_ins_decoded;
|
output reg [0:0] o_ins_decoded;
|
||||||
|
|
||||||
output reg [1:0] o_fields_table;
|
output reg [1:0] o_fields_table;
|
||||||
output reg [3:0] o_field;
|
output reg [3:0] o_field;
|
||||||
|
@ -76,20 +78,20 @@ output reg [4:0] o_reg_src1;
|
||||||
output reg [4:0] o_reg_src2;
|
output reg [4:0] o_reg_src2;
|
||||||
|
|
||||||
// rtn specific
|
// rtn specific
|
||||||
output reg o_ins_rtn;
|
output reg [0:0] o_ins_rtn;
|
||||||
output reg o_set_xm;
|
output reg [0:0] o_set_xm;
|
||||||
output reg o_set_carry;
|
output reg [0:0] o_set_carry;
|
||||||
output reg o_test_carry;
|
output reg [0:0] o_test_carry;
|
||||||
output reg o_carry_val;
|
output reg [0:0] o_carry_val;
|
||||||
output reg o_en_intr;
|
output reg [0:0] o_en_intr;
|
||||||
|
|
||||||
// setdec/hex
|
// setdec/hex
|
||||||
output reg o_ins_set_mode;
|
output reg [0:0] o_ins_set_mode;
|
||||||
output reg o_mode_dec;
|
output reg [0:0] o_mode_dec;
|
||||||
|
|
||||||
// alu_operations
|
// alu_operations
|
||||||
output reg o_ins_alu_op;
|
output reg [0:0] o_ins_alu_op;
|
||||||
output reg o_ins_test_go;
|
output reg [0:0] o_ins_test_go;
|
||||||
|
|
||||||
/* data used by the debugger
|
/* data used by the debugger
|
||||||
*
|
*
|
||||||
|
@ -434,6 +436,7 @@ always @(posedge i_clk) begin
|
||||||
block_13x <= 1;
|
block_13x <= 1;
|
||||||
4'h4, 4'h5: // DAT[01]=[AC] <field>
|
4'h4, 4'h5: // DAT[01]=[AC] <field>
|
||||||
begin
|
begin
|
||||||
|
o_alu_debug <= 0;
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
$display("block_1x %h | use table <= %b", i_nibble, i_nibble[0]);
|
$display("block_1x %h | use table <= %b", i_nibble, i_nibble[0]);
|
||||||
`endif
|
`endif
|
||||||
|
|
|
@ -8,7 +8,7 @@ wire [19:0] new_pc;
|
||||||
assign new_pc = i_pc + 1;
|
assign new_pc = i_pc + 1;
|
||||||
|
|
||||||
wire run_debugger;
|
wire run_debugger;
|
||||||
assign run_debugger = !i_reset && i_en_dbg && !i_stalled && !next_nibble;
|
assign run_debugger = !i_reset && i_en_dbg && !i_stalled && !i_bus_load_pc && !next_nibble;
|
||||||
|
|
||||||
wire is_short_transfer;
|
wire is_short_transfer;
|
||||||
assign is_short_transfer = (o_field_last == 3) &&
|
assign is_short_transfer = (o_field_last == 3) &&
|
||||||
|
|
Loading…
Reference in a new issue