mirror of
https://github.com/sxpert/hp-saturn
synced 2025-01-31 19:57:50 +01:00
entirely rework the DP_WRITE and WRITE_DP case
This commit is contained in:
parent
7d63f0f57a
commit
30d7e6c8df
9 changed files with 570 additions and 207 deletions
|
@ -43,3 +43,4 @@ second delay is posedge $glbnet$clk -> <async>
|
||||||
2019-02-17 22:48 1067 69.94MHz 32.87ns 12.77ns 6427 74.33MHz 17.71ns 3.96ns
|
2019-02-17 22:48 1067 69.94MHz 32.87ns 12.77ns 6427 74.33MHz 17.71ns 3.96ns
|
||||||
2019-02-17 23:04 1158 64.11MHz 37.87ns 12.77ns 7149 66.74MHz 19.03ns 4.06ns
|
2019-02-17 23:04 1158 64.11MHz 37.87ns 12.77ns 7149 66.74MHz 19.03ns 4.06ns
|
||||||
2019-02-18 07:45 1128 74.65MHz 36.49ns 13.73ns 7586 75.72MHz 17.57ns 3.99ns
|
2019-02-18 07:45 1128 74.65MHz 36.49ns 13.73ns 7586 75.72MHz 17.57ns 3.99ns
|
||||||
|
2019-02-19 16:26 1500 64.68MHz 42.16ns 17.32ns 10387 63.05MHz 19.43ns 7.69ns
|
381
saturn_alu.v
381
saturn_alu.v
|
@ -28,7 +28,7 @@
|
||||||
// `define ALU_DEBUG_DBG
|
// `define ALU_DEBUG_DBG
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`define ALU_DEBUG 1'b0
|
`define ALU_DEBUG 1'b1
|
||||||
`define ALU_DEBUG_DUMP 1'b1
|
`define ALU_DEBUG_DUMP 1'b1
|
||||||
`define ALU_DEBUG_JUMP 1'b0
|
`define ALU_DEBUG_JUMP 1'b0
|
||||||
`define ALU_DEBUG_PC 1'b0
|
`define ALU_DEBUG_PC 1'b0
|
||||||
|
@ -46,15 +46,19 @@ module saturn_alu (
|
||||||
i_stalled,
|
i_stalled,
|
||||||
|
|
||||||
o_bus_address,
|
o_bus_address,
|
||||||
|
i_bus_data_ptr,
|
||||||
|
o_bus_data_nibl,
|
||||||
o_bus_xfr_cnt,
|
o_bus_xfr_cnt,
|
||||||
|
i_bus_nibble_in,
|
||||||
|
o_bus_nibble_out,
|
||||||
|
|
||||||
o_bus_pc_read,
|
o_bus_pc_read,
|
||||||
o_bus_dp_read,
|
o_bus_dp_read,
|
||||||
o_bus_dp_write,
|
o_bus_dp_write,
|
||||||
o_bus_load_pc,
|
o_bus_load_pc,
|
||||||
o_bus_load_dp,
|
o_bus_load_dp,
|
||||||
o_bus_config,
|
o_bus_config,
|
||||||
i_bus_nibble_in,
|
i_bus_done,
|
||||||
o_bus_nibble_out,
|
|
||||||
|
|
||||||
i_push,
|
i_push,
|
||||||
i_pop,
|
i_pop,
|
||||||
|
@ -103,30 +107,34 @@ input wire [0:0] i_en_alu_init;
|
||||||
input wire [0:0] i_en_alu_save;
|
input wire [0:0] i_en_alu_save;
|
||||||
input wire [0:0] i_stalled;
|
input wire [0:0] i_stalled;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O to the bus controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* data to and from the bus controller */
|
||||||
output reg [19:0] o_bus_address;
|
output reg [19:0] o_bus_address;
|
||||||
|
input wire [3:0] i_bus_data_ptr;
|
||||||
|
output reg [3:0] o_bus_data_nibl;
|
||||||
output reg [3:0] o_bus_xfr_cnt;
|
output reg [3:0] o_bus_xfr_cnt;
|
||||||
|
input wire [3:0] i_bus_nibble_in;
|
||||||
|
output reg [3:0] o_bus_nibble_out;
|
||||||
|
|
||||||
|
/* control lines to the bus controller */
|
||||||
output reg [0:0] o_bus_pc_read;
|
output reg [0:0] o_bus_pc_read;
|
||||||
output reg [0:0] o_bus_dp_read;
|
output reg [0:0] o_bus_dp_read;
|
||||||
output reg [0:0] o_bus_dp_write;
|
output reg [0:0] o_bus_dp_write;
|
||||||
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_config;
|
output reg [0:0] o_bus_config;
|
||||||
input wire [3:0] i_bus_nibble_in;
|
input wire [0:0] i_bus_done;
|
||||||
output reg [3:0] o_bus_nibble_out;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lines from the decoder
|
||||||
|
*/
|
||||||
input wire [0:0] i_push;
|
input wire [0:0] i_push;
|
||||||
input wire [0:0] i_pop;
|
input wire [0:0] i_pop;
|
||||||
input wire [0:0] i_alu_debug;
|
input wire [0:0] i_alu_debug;
|
||||||
|
|
||||||
wire alu_debug;
|
|
||||||
wire alu_debug_dump;
|
|
||||||
wire alu_debug_jump;
|
|
||||||
wire alu_debug_pc;
|
|
||||||
assign alu_debug = `ALU_DEBUG || i_alu_debug;
|
|
||||||
assign alu_debug_dump = `ALU_DEBUG_DUMP || i_alu_debug;
|
|
||||||
assign alu_debug_jump = `ALU_DEBUG_JUMP || i_alu_debug;
|
|
||||||
assign alu_debug_pc = `ALU_DEBUG_PC || i_alu_debug;
|
|
||||||
|
|
||||||
output wire [0:0] o_alu_stall_dec;
|
output wire [0:0] o_alu_stall_dec;
|
||||||
input wire [0:0] i_ins_decoded;
|
input wire [0:0] i_ins_decoded;
|
||||||
|
|
||||||
|
@ -161,10 +169,32 @@ output wire [19:0] o_pc;
|
||||||
assign o_reg_p = P;
|
assign o_reg_p = P;
|
||||||
assign o_pc = PC;
|
assign o_pc = PC;
|
||||||
|
|
||||||
/* internal registers */
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* clock phases definitions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
wire [1:0] phase;
|
wire [1:0] phase;
|
||||||
assign phase = i_clk_ph + 3;
|
assign phase = i_clk_ph + 3;
|
||||||
|
|
||||||
|
wire [0:0] phase_0;
|
||||||
|
wire [0:0] phase_1;
|
||||||
|
wire [0:0] phase_2;
|
||||||
|
wire [0:0] phase_3;
|
||||||
|
|
||||||
|
assign phase_0 = (phase == 0);
|
||||||
|
assign phase_1 = (phase == 1);
|
||||||
|
assign phase_2 = (phase == 2);
|
||||||
|
assign phase_3 = (phase == 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* internal registers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/* copy of arguments */
|
/* copy of arguments */
|
||||||
reg [4:0] alu_op;
|
reg [4:0] alu_op;
|
||||||
reg [4:0] reg_dest;
|
reg [4:0] reg_dest;
|
||||||
|
@ -204,8 +234,8 @@ reg [2:0] rstk_ptr;
|
||||||
|
|
||||||
reg [19:0] PC;
|
reg [19:0] PC;
|
||||||
|
|
||||||
reg [19:0] D0;
|
reg [3:0] D0[0:4];
|
||||||
reg [19:0] D1;
|
reg [3:0] D1[0:4];
|
||||||
|
|
||||||
//reg [63:0] A;
|
//reg [63:0] A;
|
||||||
reg [3:0] A[0:15];
|
reg [3:0] A[0:15];
|
||||||
|
@ -231,6 +261,260 @@ reg [19:0] RSTK[0:7];
|
||||||
initial begin
|
initial begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* ALU debug modes
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
wire alu_debug;
|
||||||
|
wire alu_debug_dump;
|
||||||
|
wire alu_debug_jump;
|
||||||
|
wire alu_debug_pc;
|
||||||
|
assign alu_debug = `ALU_DEBUG || i_alu_debug;
|
||||||
|
assign alu_debug_dump = `ALU_DEBUG_DUMP || i_alu_debug;
|
||||||
|
assign alu_debug_jump = `ALU_DEBUG_JUMP || i_alu_debug;
|
||||||
|
assign alu_debug_pc = `ALU_DEBUG_PC || i_alu_debug;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* states decoding
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ALU : modes of operation
|
||||||
|
*
|
||||||
|
* - classical alu used for calculations
|
||||||
|
* - data transfer to and from memory
|
||||||
|
* - jump calculations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* module 1:
|
||||||
|
* src1 and src2 can only be written here
|
||||||
|
* address can only be written here
|
||||||
|
* registers can only be read here
|
||||||
|
*/
|
||||||
|
|
||||||
|
// the ALU is in memory transfer mode
|
||||||
|
reg [0:0] f_mode_xfr;
|
||||||
|
|
||||||
|
wire [0:0] mode_xfr;
|
||||||
|
wire [0:0] mode_set;
|
||||||
|
wire [0:0] start_in_xfr_mode;
|
||||||
|
|
||||||
|
assign mode_xfr = i_ins_mem_xfr || f_mode_xfr;
|
||||||
|
assign mode_set = f_mode_xfr;
|
||||||
|
assign start_in_xfr_mode = phase_3 && i_ins_mem_xfr && !mode_set;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wires for all modes
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* source 1 */
|
||||||
|
wire [0:0] src1_A;
|
||||||
|
wire [0:0] src1_C;
|
||||||
|
wire [0:0] src1_DAT0;
|
||||||
|
wire [0:0] src1_DAT1;
|
||||||
|
|
||||||
|
assign src1_A = (i_reg_src1 == `ALU_REG_A);
|
||||||
|
assign src1_C = (i_reg_src1 == `ALU_REG_C);
|
||||||
|
assign src1_DAT0 = (i_reg_src1 == `ALU_REG_DAT0);
|
||||||
|
assign src1_DAT1 = (i_reg_src1 == `ALU_REG_DAT1);
|
||||||
|
|
||||||
|
/* destination */
|
||||||
|
wire [0:0] dest_DAT0;
|
||||||
|
wire [0:0] dest_DAT1;
|
||||||
|
|
||||||
|
assign dest_DAT0 = (i_reg_dest == `ALU_REG_DAT0);
|
||||||
|
assign dest_DAT1 = (i_reg_dest == `ALU_REG_DAT1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wires specific to the XFR mode
|
||||||
|
*
|
||||||
|
* sources of address data used for XFR mode:
|
||||||
|
* - A [ PC=(A) ]
|
||||||
|
* - C [ CONFIG, UNCNFG, PC=(C) ]
|
||||||
|
* - D0 [ DAT0=reg, reg=DAT0 ]
|
||||||
|
* - D1 [ DAT1=reg, reg=DAT1 ]
|
||||||
|
*/
|
||||||
|
reg [3:0] xfr_data[0:15];
|
||||||
|
reg [3:0] data_counter;
|
||||||
|
|
||||||
|
// copy the address into the transfer buffer
|
||||||
|
|
||||||
|
wire [0:0] addr_src_A;
|
||||||
|
wire [0:0] addr_src_C;
|
||||||
|
wire [0:0] addr_src_D0;
|
||||||
|
wire [0:0] addr_src_D1;
|
||||||
|
wire [0:0] addr_src_xfr_0;
|
||||||
|
wire [0:0] addr_src_xfr_1;
|
||||||
|
wire [1:0] addr_src_xfr;
|
||||||
|
wire [1:0] addr_src;
|
||||||
|
wire [0:0] copy_done;
|
||||||
|
wire [0:0] copy_address;
|
||||||
|
wire [0:0] start_load_dp;
|
||||||
|
|
||||||
|
assign addr_src_A = (!f_mode_xfr) && src1_A;
|
||||||
|
assign addr_src_C = (!f_mode_xfr) && src1_C;
|
||||||
|
assign addr_src_D0 = ( f_mode_xfr) && (src1_DAT0 || dest_DAT0);
|
||||||
|
assign addr_src_D1 = ( f_mode_xfr) && (src1_DAT1 || dest_DAT1);
|
||||||
|
assign addr_src_xfr_0 = !addr_src_A && !addr_src_C && !addr_src_D0 && addr_src_D1;
|
||||||
|
assign addr_src_xfr_1 = !addr_src_A && !addr_src_C && (addr_src_D0 || addr_src_D1);
|
||||||
|
assign addr_src_xfr = {addr_src_xfr_1, addr_src_xfr_0};
|
||||||
|
assign addr_src = {2{f_mode_xfr}} & addr_src_xfr;
|
||||||
|
assign copy_done = data_counter == 5;
|
||||||
|
assign copy_address = f_mode_xfr && !copy_done && !xfr_init_done;
|
||||||
|
assign start_load_dp = start_in_xfr_mode;
|
||||||
|
|
||||||
|
// now copy the data aligning the first nibble with index 0 of the buffer
|
||||||
|
// copy nibbles 0-4 at the end so as not to clobber the address set previously
|
||||||
|
// while the bus controller is sending it
|
||||||
|
|
||||||
|
reg [0:0] xfr_init_done;
|
||||||
|
reg [0:0] xfr_data_done;
|
||||||
|
wire [0:0] xfr_data_init;
|
||||||
|
wire [3:0] xfr_data_ctr;
|
||||||
|
wire [0:0] xfr_data_copy;
|
||||||
|
wire [0:0] xfr_copy_done;
|
||||||
|
|
||||||
|
assign xfr_data_init = f_mode_xfr && copy_done && !xfr_init_done && !xfr_data_done && phase_3;
|
||||||
|
assign xfr_data_ctr = data_counter + i_field_start;
|
||||||
|
assign xfr_copy_done = xfr_init_done && copy_done && !xfr_data_init && !xfr_data_done;
|
||||||
|
assign xfr_data_copy = xfr_data_init || xfr_init_done && !xfr_data_done && !copy_done && !xfr_copy_done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sources specific pointers
|
||||||
|
*/
|
||||||
|
wire [3:0] src1_ptr;
|
||||||
|
|
||||||
|
assign src1_ptr = ( {4{copy_address}} & data_counter );
|
||||||
|
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
|
||||||
|
// initializes modes
|
||||||
|
if (i_reset) begin
|
||||||
|
f_mode_xfr <= 0;
|
||||||
|
data_counter <= 0;
|
||||||
|
xfr_init_done <= 0;
|
||||||
|
xfr_data_done <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// always update the data out to the controller
|
||||||
|
o_bus_data_nibl <= xfr_data[i_bus_data_ptr];
|
||||||
|
|
||||||
|
if (start_in_xfr_mode) begin
|
||||||
|
$display("ALU %0d: [%d] memory transfer started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded);
|
||||||
|
$display("ALU %0d: [%d] addr_src A %b | C %b | D0 %b | D1 %b | b1 %b | b0 %b | src %2b", phase, i_cycle_ctr,
|
||||||
|
addr_src_A, addr_src_C, addr_src_D0, addr_src_D1, addr_src_xfr_1, addr_src_xfr_0, addr_src);
|
||||||
|
$display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr);
|
||||||
|
f_mode_xfr <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (start_load_dp) begin
|
||||||
|
o_bus_load_dp <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (copy_address) begin
|
||||||
|
$display("ALU %0d: [%d] copy address f_mode_xfr %b && !copy_done %b && !xfr_init_done %b", phase, i_cycle_ctr, f_mode_xfr, !copy_done, !xfr_init_done);
|
||||||
|
$write("ALU %0d: [%d] xfr_data[%0d] = ", phase, i_cycle_ctr, data_counter);
|
||||||
|
case (addr_src)
|
||||||
|
2'b00: begin
|
||||||
|
$display("A[%0d] %h", src1_ptr, A[src1_ptr]);
|
||||||
|
xfr_data[data_counter] <= A[src1_ptr];
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
$display("C[%0d] %h", src1_ptr, C[src1_ptr]);
|
||||||
|
xfr_data[data_counter] <= C[src1_ptr];
|
||||||
|
end
|
||||||
|
2'b10: begin
|
||||||
|
$display("D0[%0d] %h", src1_ptr, D0[src1_ptr[2:0]]);
|
||||||
|
xfr_data[data_counter] <= D0[src1_ptr[2:0]];
|
||||||
|
end
|
||||||
|
2'b11: begin
|
||||||
|
$display("D1[%0d] %h", src1_ptr, D1[src1_ptr[2:0]]);
|
||||||
|
xfr_data[data_counter] <= D1[src1_ptr[2:0]];
|
||||||
|
end
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
data_counter <= data_counter + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
// do not need to update the data counter, which is already at 5
|
||||||
|
if (xfr_data_init) begin
|
||||||
|
$display("ALU %0d: [%d] initialize copy data | s %h | l %h | xdc %h",phase, i_cycle_ctr, i_field_start, i_field_last, xfr_data_ctr);
|
||||||
|
xfr_init_done <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (xfr_data_copy) begin
|
||||||
|
$display("ALU %0d: [%d] copy data | dc %h | xdc %h | xdd %b",phase, i_cycle_ctr, data_counter, xfr_data_ctr, xfr_data_done);
|
||||||
|
data_counter <= data_counter + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (xfr_copy_done) begin
|
||||||
|
$display("ALU %0d: [%d] xfr_copy_done %h %b %b",phase, i_cycle_ctr, data_counter, xfr_init_done, xfr_data_done);
|
||||||
|
xfr_init_done <= 0;
|
||||||
|
xfr_data_done <= 1;
|
||||||
|
o_bus_load_dp <= 0;
|
||||||
|
// right on time to start the actual transfer
|
||||||
|
o_bus_dp_write <= i_xfr_dir_out;
|
||||||
|
o_bus_dp_read <= !i_xfr_dir_out;
|
||||||
|
o_bus_xfr_cnt <= (i_field_last - i_field_start);
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reset all things that were changed
|
||||||
|
*/
|
||||||
|
if (i_bus_done) begin
|
||||||
|
$display("ALU %0d: [%d] bus controller is done, cleaning all variables used",phase, i_cycle_ctr);
|
||||||
|
/* variables for the XFR mode */
|
||||||
|
f_mode_xfr <= 0;
|
||||||
|
data_counter <= 0;
|
||||||
|
xfr_init_done <= 0;
|
||||||
|
xfr_data_done <= 0;
|
||||||
|
|
||||||
|
/* bus controller control lines */
|
||||||
|
o_bus_dp_write <= 0;
|
||||||
|
o_bus_dp_read <= 0;
|
||||||
|
o_bus_xfr_cnt <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* can the alu function ?
|
* can the alu function ?
|
||||||
*/
|
*/
|
||||||
|
@ -249,6 +533,7 @@ assign do_reg_dump = alu_active && i_en_alu_dump && !o_bus_load_pc &&
|
||||||
assign do_alu_shpc = alu_active && i_en_alu_dump;
|
assign do_alu_shpc = alu_active && i_en_alu_dump;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
||||||
wire do_busclean;
|
wire do_busclean;
|
||||||
wire do_alu_init;
|
wire do_alu_init;
|
||||||
wire do_alu_prep;
|
wire do_alu_prep;
|
||||||
|
@ -268,7 +553,6 @@ assign do_alu_mode = alu_active && i_en_alu_save && i_ins_set_mode;
|
||||||
|
|
||||||
wire do_go_init;
|
wire do_go_init;
|
||||||
wire do_go_prep;
|
wire do_go_prep;
|
||||||
wire do_go_calc;
|
|
||||||
|
|
||||||
assign do_go_init = alu_active && i_en_alu_save && i_ins_test_go;
|
assign do_go_init = alu_active && i_en_alu_save && i_ins_test_go;
|
||||||
assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go;
|
assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go;
|
||||||
|
@ -301,10 +585,10 @@ end
|
||||||
// the decoder may request the ALU to not stall it
|
// the decoder may request the ALU to not stall it
|
||||||
|
|
||||||
wire bus_commands;
|
wire bus_commands;
|
||||||
assign bus_commands = o_bus_config || o_bus_dp_write ;
|
assign bus_commands = o_bus_config ;
|
||||||
|
|
||||||
assign o_alu_stall_dec = alu_initializing ||
|
assign o_alu_stall_dec = alu_initializing ||
|
||||||
(alu_run && (!i_alu_no_stall || alu_finish || i_ins_mem_xfr)) ||
|
((alu_run || f_mode_xfr) && (!i_alu_no_stall || alu_finish || i_ins_mem_xfr)) ||
|
||||||
i_stalled || bus_commands;
|
i_stalled || bus_commands;
|
||||||
|
|
||||||
|
|
||||||
|
@ -397,7 +681,13 @@ always @(posedge i_clk) begin
|
||||||
$write("%h", R3[alu_dbg_ctr]);
|
$write("%h", R3[alu_dbg_ctr]);
|
||||||
$write(" RSTK2: %5h\n", RSTK[2]);
|
$write(" RSTK2: %5h\n", RSTK[2]);
|
||||||
|
|
||||||
$write("D0: %h D1: %h R4: ", D0, D1);
|
$write("D0: ");
|
||||||
|
for(alu_dbg_ctr=4;alu_dbg_ctr!=31;alu_dbg_ctr=alu_dbg_ctr-1)
|
||||||
|
$write("%h", D0[alu_dbg_ctr]);
|
||||||
|
$write(" D1: ");
|
||||||
|
for(alu_dbg_ctr=4;alu_dbg_ctr!=31;alu_dbg_ctr=alu_dbg_ctr-1)
|
||||||
|
$write("%h", D1[alu_dbg_ctr]);
|
||||||
|
$write(" R4: ");
|
||||||
for(alu_dbg_ctr=15;alu_dbg_ctr!=31;alu_dbg_ctr=alu_dbg_ctr-1)
|
for(alu_dbg_ctr=15;alu_dbg_ctr!=31;alu_dbg_ctr=alu_dbg_ctr-1)
|
||||||
$write("%h", R4[alu_dbg_ctr]);
|
$write("%h", R4[alu_dbg_ctr]);
|
||||||
$write(" RSTK1: %5h\n", RSTK[1]);
|
$write(" RSTK1: %5h\n", RSTK[1]);
|
||||||
|
@ -548,8 +838,8 @@ always @(posedge i_clk) begin
|
||||||
`ALU_REG_R2: p_src1 <= R2[f_cur];
|
`ALU_REG_R2: p_src1 <= R2[f_cur];
|
||||||
`ALU_REG_R3: p_src1 <= R3[f_cur];
|
`ALU_REG_R3: p_src1 <= R3[f_cur];
|
||||||
`ALU_REG_R4: p_src1 <= R4[f_cur];
|
`ALU_REG_R4: p_src1 <= R4[f_cur];
|
||||||
`ALU_REG_D0: p_src1 <= D0[f_cur*4+:4];
|
`ALU_REG_D0: p_src1 <= D0[f_cur[2:0]];
|
||||||
`ALU_REG_D1: p_src1 <= D1[f_cur*4+:4];
|
`ALU_REG_D1: p_src1 <= D1[f_cur[2:0]];
|
||||||
`ALU_REG_P: p_src1 <= P;
|
`ALU_REG_P: p_src1 <= P;
|
||||||
`ALU_REG_DAT0,
|
`ALU_REG_DAT0,
|
||||||
`ALU_REG_DAT1: p_src1 <= i_bus_nibble_in;
|
`ALU_REG_DAT1: p_src1 <= i_bus_nibble_in;
|
||||||
|
@ -591,8 +881,8 @@ always @(posedge i_clk) begin
|
||||||
`ALU_REG_R2: p_src2 <= R2[f_cur];
|
`ALU_REG_R2: p_src2 <= R2[f_cur];
|
||||||
`ALU_REG_R3: p_src2 <= R3[f_cur];
|
`ALU_REG_R3: p_src2 <= R3[f_cur];
|
||||||
`ALU_REG_R4: p_src2 <= R4[f_cur];
|
`ALU_REG_R4: p_src2 <= R4[f_cur];
|
||||||
`ALU_REG_D0: p_src2 <= D0[f_cur*4+:4];
|
`ALU_REG_D0: p_src2 <= D0[f_cur[2:0]];
|
||||||
`ALU_REG_D1: p_src2 <= D1[f_cur*4+:4];
|
`ALU_REG_D1: p_src2 <= D1[f_cur[2:0]];
|
||||||
`ALU_REG_P: p_src2 <= P;
|
`ALU_REG_P: p_src2 <= P;
|
||||||
`ALU_REG_HST: p_src2 <= HST;
|
`ALU_REG_HST: p_src2 <= HST;
|
||||||
`ALU_REG_IMM: p_src2 <= i_imm_value;
|
`ALU_REG_IMM: p_src2 <= i_imm_value;
|
||||||
|
@ -733,8 +1023,6 @@ always @(posedge i_clk) begin
|
||||||
alu_initializing <= 1;
|
alu_initializing <= 1;
|
||||||
CARRY <= 0;
|
CARRY <= 0;
|
||||||
P <= 0;
|
P <= 0;
|
||||||
D0 <= 0;
|
|
||||||
D1 <= 0;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (alu_initializing) begin
|
if (alu_initializing) begin
|
||||||
|
@ -742,6 +1030,8 @@ always @(posedge i_clk) begin
|
||||||
B[f_cur] <= 0;
|
B[f_cur] <= 0;
|
||||||
C[f_cur] <= 0;
|
C[f_cur] <= 0;
|
||||||
D[f_cur] <= 0;
|
D[f_cur] <= 0;
|
||||||
|
D0[f_cur[2:0]] <= 0;
|
||||||
|
D1[f_cur[2:0]] <= 0;
|
||||||
R0[f_cur] <= 0;
|
R0[f_cur] <= 0;
|
||||||
R1[f_cur] <= 0;
|
R1[f_cur] <= 0;
|
||||||
R2[f_cur] <= 0;
|
R2[f_cur] <= 0;
|
||||||
|
@ -814,8 +1104,8 @@ always @(posedge i_clk) begin
|
||||||
`ALU_REG_R2: R2[f_cur] <= c_res1;
|
`ALU_REG_R2: R2[f_cur] <= c_res1;
|
||||||
`ALU_REG_R3: R3[f_cur] <= c_res1;
|
`ALU_REG_R3: R3[f_cur] <= c_res1;
|
||||||
`ALU_REG_R4: R4[f_cur] <= c_res1;
|
`ALU_REG_R4: R4[f_cur] <= c_res1;
|
||||||
`ALU_REG_D0: D0[f_cur*4+:4] <= c_res1;
|
`ALU_REG_D0: D0[f_cur[2:0]] <= c_res1;
|
||||||
`ALU_REG_D1: D1[f_cur*4+:4] <= c_res1;
|
`ALU_REG_D1: D1[f_cur[2:0]] <= 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_DAT0,
|
`ALU_REG_DAT0,
|
||||||
|
@ -849,8 +1139,8 @@ 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_D0: D0[f_cur[2:0]] <= c_res2;
|
||||||
`ALU_REG_D1: D1[f_cur*4+:4] <= c_res2;
|
`ALU_REG_D1: D1[f_cur[2:0]] <= 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;
|
||||||
|
@ -977,8 +1267,8 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
if (read_done) begin
|
if (read_done) begin
|
||||||
$display("============================================= old read_done");
|
$display("============================================= old read_done");
|
||||||
o_bus_load_dp <= 0;
|
// o_bus_load_dp <= 0;
|
||||||
o_bus_dp_read <= 0;
|
// o_bus_dp_read <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -992,9 +1282,17 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
// tell the bus to start the write cycle
|
// tell the bus to start the write cycle
|
||||||
// this will take 1 cycle because we need to send the DP_WRITE command
|
// this will take 1 cycle because we need to send the DP_WRITE command
|
||||||
if (do_busclean && alu_run && !write_done && is_mem_write && !o_bus_dp_write)
|
if (do_busclean && alu_run && !write_done && is_mem_write && !o_bus_dp_write) begin
|
||||||
o_bus_dp_write <= 1;
|
o_bus_dp_write <= 1;
|
||||||
|
$display("ALU %0d: %0d nibbles to write", phase, f_last - f_first + 1);
|
||||||
|
o_bus_xfr_cnt <= f_last - f_first;
|
||||||
|
end
|
||||||
|
|
||||||
|
// if (do_alu_calc && alu_run && alu_finish && o_bus_dp_write) begin
|
||||||
|
// $display("ALU %0d: end of write", phase);
|
||||||
|
// write_done <= 1;
|
||||||
|
// o_bus_dp_write <= 0;
|
||||||
|
// end
|
||||||
// writing takes 2 more cycles :
|
// writing takes 2 more cycles :
|
||||||
// - one used up above
|
// - one used up above
|
||||||
// - one used down below to restore the PC_READ command
|
// - one used down below to restore the PC_READ command
|
||||||
|
@ -1015,12 +1313,13 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
// once the PC_READ command has been sent, remove the stall on the decoder
|
// once the PC_READ command has been sent, remove the stall on the decoder
|
||||||
if (i_en_alu_dump && no_extra_cycles && o_bus_pc_read) begin
|
if (i_en_alu_dump && no_extra_cycles && o_bus_pc_read) begin
|
||||||
|
|
||||||
o_bus_pc_read <= 0;
|
o_bus_pc_read <= 0;
|
||||||
write_done <= 0;
|
write_done <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_busclean && o_bus_load_dp)
|
// if (do_busclean && o_bus_load_dp)
|
||||||
o_bus_load_dp <= 0;
|
// o_bus_load_dp <= 0;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1129,11 +1428,11 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
// 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)
|
||||||
case (mem_reg[0])
|
// case (mem_reg[0])
|
||||||
0: o_bus_address <= D0;
|
// 0: o_bus_address <= D0;
|
||||||
1: o_bus_address <= D1;
|
// 1: o_bus_address <= D1;
|
||||||
endcase
|
// endcase
|
||||||
|
|
||||||
// this is moved here for access conflicts to o_bus_address
|
// this is moved here for access conflicts to o_bus_address
|
||||||
if (do_alu_save && (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR)) begin
|
if (do_alu_save && (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR)) begin
|
||||||
|
|
|
@ -44,6 +44,7 @@ module saturn_bus_ctrl (
|
||||||
i_alu_busy,
|
i_alu_busy,
|
||||||
|
|
||||||
o_stall_alu,
|
o_stall_alu,
|
||||||
|
o_bus_done,
|
||||||
|
|
||||||
// bus i/o
|
// bus i/o
|
||||||
o_bus_reset,
|
o_bus_reset,
|
||||||
|
@ -55,6 +56,8 @@ module saturn_bus_ctrl (
|
||||||
// interface to the rest of the machine
|
// interface to the rest of the machine
|
||||||
i_alu_pc,
|
i_alu_pc,
|
||||||
i_address,
|
i_address,
|
||||||
|
i_data_nibl,
|
||||||
|
o_data_ptr,
|
||||||
i_cmd_load_pc,
|
i_cmd_load_pc,
|
||||||
i_cmd_load_dp,
|
i_cmd_load_dp,
|
||||||
i_read_pc,
|
i_read_pc,
|
||||||
|
@ -77,6 +80,7 @@ input wire [0:0] i_stalled;
|
||||||
input wire [0:0] i_alu_busy;
|
input wire [0:0] i_alu_busy;
|
||||||
|
|
||||||
output reg [0:0] o_stall_alu;
|
output reg [0:0] o_stall_alu;
|
||||||
|
output reg [0:0] o_bus_done;
|
||||||
|
|
||||||
output reg [0:0] o_bus_reset;
|
output reg [0:0] o_bus_reset;
|
||||||
input wire [3:0] i_bus_data;
|
input wire [3:0] i_bus_data;
|
||||||
|
@ -86,6 +90,8 @@ output reg [0:0] o_bus_cmd_data;
|
||||||
|
|
||||||
input wire [19:0] i_alu_pc;
|
input wire [19:0] i_alu_pc;
|
||||||
input wire [19:0] i_address;
|
input wire [19:0] i_address;
|
||||||
|
input wire [3:0] i_data_nibl;
|
||||||
|
output reg [3:0] o_data_ptr;
|
||||||
input wire [0:0] i_cmd_load_pc;
|
input wire [0:0] i_cmd_load_pc;
|
||||||
input wire [0:0] i_cmd_load_dp;
|
input wire [0:0] i_cmd_load_dp;
|
||||||
input wire [0:0] i_read_pc;
|
input wire [0:0] i_read_pc;
|
||||||
|
@ -254,7 +260,7 @@ assign cmd_DP_WRITE_0 = phase_0 && cmd_DP_WRITE_TST; // sets cmd_DP_WRITE_F0
|
||||||
assign cmd_DP_WRITE_STR = cmd_DP_WRITE_0;
|
assign cmd_DP_WRITE_STR = cmd_DP_WRITE_0;
|
||||||
assign cmd_DP_WRITE_US0 = phase_2 && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1 && o_stall_alu;
|
assign cmd_DP_WRITE_US0 = phase_2 && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1 && o_stall_alu;
|
||||||
// after all nibbles were sent
|
// after all nibbles were sent
|
||||||
assign cmd_DP_WRITE_1 = phase_3 && !i_cmd_dp_write && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1; // sets cmd_DP_WRITE_F1
|
assign cmd_DP_WRITE_1 = phase_3 && (o_data_ptr == i_xfr_cnt) && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1; // sets cmd_DP_WRITE_F1
|
||||||
assign cmd_DP_WRITE_US1 = phase_2 && cmd_DP_WRITE_F1;
|
assign cmd_DP_WRITE_US1 = phase_2 && cmd_DP_WRITE_F1;
|
||||||
assign cmd_DP_WRITE_C = phase_3 && cmd_DP_WRITE_F1;
|
assign cmd_DP_WRITE_C = phase_3 && cmd_DP_WRITE_F1;
|
||||||
|
|
||||||
|
@ -304,7 +310,7 @@ wire [0:0] cmd_LOAD_DP_0;
|
||||||
wire [0:0] cmd_LOAD_DP_STR;
|
wire [0:0] cmd_LOAD_DP_STR;
|
||||||
wire [0:0] cmd_LOAD_DP_C;
|
wire [0:0] cmd_LOAD_DP_C;
|
||||||
|
|
||||||
assign cmd_LOAD_DP_TST = i_cmd_load_dp;
|
assign cmd_LOAD_DP_TST = i_cmd_load_dp && !cmd_LOAD_DP_F;
|
||||||
assign cmd_LOAD_DP_0 = phase_0 && cmd_LOAD_DP_TST; // sets cmd_LOAD_DP_F
|
assign cmd_LOAD_DP_0 = phase_0 && cmd_LOAD_DP_TST; // sets cmd_LOAD_DP_F
|
||||||
assign cmd_LOAD_DP_STR = cmd_LOAD_DP_TST;
|
assign cmd_LOAD_DP_STR = cmd_LOAD_DP_TST;
|
||||||
assign cmd_LOAD_DP_C = phase_3 && do_auto_DP_READ_TST;
|
assign cmd_LOAD_DP_C = phase_3 && do_auto_DP_READ_TST;
|
||||||
|
@ -316,7 +322,7 @@ wire [0:0] do_auto_DP_READ_TST;
|
||||||
wire [0:0] do_auto_DP_READ_0;
|
wire [0:0] do_auto_DP_READ_0;
|
||||||
wire [0:0] do_auto_DP_READ_US0;
|
wire [0:0] do_auto_DP_READ_US0;
|
||||||
|
|
||||||
assign do_auto_DP_READ_TST = cmd_LOAD_DP_F && addr_loop_done && !cmd_DP_READ_F;
|
assign do_auto_DP_READ_TST = cmd_LOAD_DP_F && addr_loop_done;
|
||||||
assign do_auto_DP_READ_0 = phase_1 && do_auto_DP_READ_TST;
|
assign do_auto_DP_READ_0 = phase_1 && do_auto_DP_READ_TST;
|
||||||
// does nothing ?
|
// does nothing ?
|
||||||
assign do_auto_DP_READ_US0 = phase_3 && o_stall_alu && do_auto_DP_READ_TST && cmd_LOAD_DP_F && !(cmd_DP_WRITE_F0); // || cmd_DP_READ_F);
|
assign do_auto_DP_READ_US0 = phase_3 && o_stall_alu && do_auto_DP_READ_TST && cmd_LOAD_DP_F && !(cmd_DP_WRITE_F0); // || cmd_DP_READ_F);
|
||||||
|
@ -395,10 +401,9 @@ assign do_unstall = o_stall_alu &&
|
||||||
|
|
||||||
wire [0:0] do_load_clean;
|
wire [0:0] do_load_clean;
|
||||||
wire [0:0] do_clean;
|
wire [0:0] do_clean;
|
||||||
assign do_load_clean = cmd_LOAD_PC_C;
|
assign do_load_clean = cmd_LOAD_PC_C || cmd_LOAD_DP_C;
|
||||||
assign do_clean = do_read_dp_US2 || cmd_DP_WRITE_C || cmd_CONFIGURE_C || cmd_RESET_C;
|
assign do_clean = do_read_dp_US2 || cmd_DP_WRITE_C || cmd_CONFIGURE_C || cmd_RESET_C;
|
||||||
|
|
||||||
reg [2:0] addr_loop_counter;
|
|
||||||
reg [0:0] addr_loop_done;
|
reg [0:0] addr_loop_done;
|
||||||
reg [0:0] init_addr_loop;
|
reg [0:0] init_addr_loop;
|
||||||
reg [0:0] run_addr_loop;
|
reg [0:0] run_addr_loop;
|
||||||
|
@ -413,8 +418,8 @@ assign do_init_addr_loop = phase_0 &&
|
||||||
cmd_LOAD_DP_TST ||
|
cmd_LOAD_DP_TST ||
|
||||||
cmd_CONFIGURE_0);
|
cmd_CONFIGURE_0);
|
||||||
assign do_run_addr_loop = phase_0 && run_addr_loop && !is_loop_finished;
|
assign do_run_addr_loop = phase_0 && run_addr_loop && !is_loop_finished;
|
||||||
assign will_loop_finish = addr_loop_counter == 4;
|
assign will_loop_finish = o_data_ptr == 4;
|
||||||
assign is_loop_finished = addr_loop_counter == 5;
|
assign is_loop_finished = o_data_ptr == 5;
|
||||||
assign do_reset_loop_counter = phase_3 && is_loop_finished;
|
assign do_reset_loop_counter = phase_3 && is_loop_finished;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -450,6 +455,14 @@ initial begin
|
||||||
// i_clk, i_phase, o_stall_alu, i_alu_busy,
|
// i_clk, i_phase, o_stall_alu, i_alu_busy,
|
||||||
// i_cmd_dp_write, cmd_LOAD_DP_F, addr_loop_done, do_auto_DP_READ_TST, cmd_DP_WRITE_F0, cmd_DP_WRITE_F1);
|
// i_cmd_dp_write, cmd_LOAD_DP_F, addr_loop_done, do_auto_DP_READ_TST, cmd_DP_WRITE_F0, cmd_DP_WRITE_F1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* debug dp_read
|
||||||
|
*/
|
||||||
|
// $monitor({"BUS - clk %b | ph %0d | osta %b | iabs %b | ",
|
||||||
|
// "i_cmd_dp_read %b | cmd_LOAD_DP_F %b | addr_loop_done %b | do_auto_DP_READ_TST %b | cmd_DP_WRITE_F0 %b | cnd_DP_WRITE_F1 %b"},
|
||||||
|
// i_clk, i_phase, o_stall_alu, i_alu_busy,
|
||||||
|
// i_cmd_dp_read, cmd_LOAD_DP_F, addr_loop_done, do_auto_DP_READ_TST, cmd_DP_WRITE_F0, cmd_DP_WRITE_F1);
|
||||||
|
|
||||||
/* debug strobe for reading
|
/* debug strobe for reading
|
||||||
*/
|
*/
|
||||||
// $monitor({"BUS - clk %b | ph %0d | osta %b | iabs %b | ",
|
// $monitor({"BUS - clk %b | ph %0d | osta %b | iabs %b | ",
|
||||||
|
@ -487,14 +500,17 @@ always @(posedge i_clk) begin
|
||||||
strobe_on <= 0;
|
strobe_on <= 0;
|
||||||
o_bus_cmd_data <= 1; // 1 is the default level
|
o_bus_cmd_data <= 1; // 1 is the default level
|
||||||
bus_out_of_reset <= 1;
|
bus_out_of_reset <= 1;
|
||||||
|
o_data_ptr <= 0;
|
||||||
// local states
|
// local states
|
||||||
|
|
||||||
// address loop
|
// address loop
|
||||||
init_addr_loop <= 0;
|
init_addr_loop <= 0;
|
||||||
run_addr_loop <= 0;
|
run_addr_loop <= 0;
|
||||||
addr_loop_counter <= 0;
|
|
||||||
addr_loop_done <= 0;
|
addr_loop_done <= 0;
|
||||||
|
|
||||||
|
// read and write loops
|
||||||
|
o_data_ptr <= 0;
|
||||||
|
|
||||||
cmd_PC_READ_F <= 0;
|
cmd_PC_READ_F <= 0;
|
||||||
cmd_DP_READ_F <= 0;
|
cmd_DP_READ_F <= 0;
|
||||||
cmd_DP_WRITE_F0 <= 0;
|
cmd_DP_WRITE_F0 <= 0;
|
||||||
|
@ -537,8 +553,9 @@ always @(posedge i_clk) begin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (cmd_DP_WRITE_0) begin
|
if (cmd_DP_WRITE_0) begin
|
||||||
$display("BUS_CTRL %1d: [%d] DP_WRITE", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] DP_WRITE (%0d nibble to write - ctr %0d)", i_phase, i_cycle_ctr, i_xfr_cnt + 1, o_data_ptr);
|
||||||
cmd_DP_WRITE_F0 <= 1;
|
cmd_DP_WRITE_F0 <= 1;
|
||||||
|
o_data_ptr <= 0;
|
||||||
last_cmd <= `BUSCMD_DP_WRITE;
|
last_cmd <= `BUSCMD_DP_WRITE;
|
||||||
o_bus_data <= `BUSCMD_DP_WRITE;
|
o_bus_data <= `BUSCMD_DP_WRITE;
|
||||||
o_bus_cmd_data <= 0;
|
o_bus_cmd_data <= 0;
|
||||||
|
@ -556,11 +573,13 @@ always @(posedge i_clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
if (cmd_DP_WRITE_US1) begin
|
if (cmd_DP_WRITE_US1) begin
|
||||||
$display("BUS_CTRL %1d: [%d] cmd_DP_WRITE_US1", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] cmd_DP_WRITE_US1 (signal done)", i_phase, i_cycle_ctr);
|
||||||
|
o_bus_done <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (cmd_DP_WRITE_C) begin
|
if (cmd_DP_WRITE_C) begin
|
||||||
$display("BUS_CTRL %1d: [%d] cmd_DP_WRITE_C", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] cmd_DP_WRITE_C", i_phase, i_cycle_ctr);
|
||||||
|
o_bus_done <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -611,7 +630,7 @@ always @(posedge i_clk) begin
|
||||||
/* automatic DP_READ after LOAD_DP */
|
/* automatic DP_READ after LOAD_DP */
|
||||||
|
|
||||||
if (do_auto_DP_READ_0) begin
|
if (do_auto_DP_READ_0) begin
|
||||||
$display("BUS_CTRL %1d: [%d] auto DP_READ", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] auto DP_READ (%0d nibble to read - ctr %0d)", i_phase, i_cycle_ctr, i_xfr_cnt + 1, o_data_ptr);
|
||||||
cmd_DP_READ_F <= 1;
|
cmd_DP_READ_F <= 1;
|
||||||
last_cmd <= `BUSCMD_DP_READ;
|
last_cmd <= `BUSCMD_DP_READ;
|
||||||
end
|
end
|
||||||
|
@ -666,28 +685,29 @@ always @(posedge i_clk) begin
|
||||||
if (do_init_addr_loop) begin
|
if (do_init_addr_loop) begin
|
||||||
// $display("BUS_CTRL %1d: [%d] init addr loop", i_phase, i_cycle_ctr);
|
// $display("BUS_CTRL %1d: [%d] init addr loop", i_phase, i_cycle_ctr);
|
||||||
addr_loop_done <= 0;
|
addr_loop_done <= 0;
|
||||||
addr_loop_counter <= 0;
|
o_data_ptr <= 0;
|
||||||
run_addr_loop <= 1;
|
run_addr_loop <= 1;
|
||||||
init_addr_loop <= 0;
|
init_addr_loop <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_run_addr_loop) begin
|
if (do_run_addr_loop) begin
|
||||||
$write("BUS_CTRL %1d: [%d] ADDR(%0d)-> %h ",
|
$write("BUS_CTRL %1d: [%d] ADDR(%0d)-> %h ",
|
||||||
i_phase, i_cycle_ctr, addr_loop_counter,
|
i_phase, i_cycle_ctr, o_data_ptr,
|
||||||
i_address[addr_loop_counter*4+:4]);
|
i_data_nibl);
|
||||||
if (will_loop_finish) $write("done");
|
if (will_loop_finish) $write("done");
|
||||||
$write("\n");
|
$write("\n");
|
||||||
|
|
||||||
o_bus_data <= i_address[addr_loop_counter*4+:4];
|
if (LC_load_pc) o_bus_data <= i_address[o_data_ptr*4+:4];
|
||||||
|
if (LC_load_dp) o_bus_data <= i_data_nibl;
|
||||||
// clean up at the end of loop
|
// clean up at the end of loop
|
||||||
addr_loop_counter <= addr_loop_counter + 1;
|
o_data_ptr <= o_data_ptr + 1;
|
||||||
run_addr_loop <= !will_loop_finish;
|
run_addr_loop <= !will_loop_finish;
|
||||||
addr_loop_done <= will_loop_finish;
|
addr_loop_done <= will_loop_finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_reset_loop_counter) begin
|
if (do_reset_loop_counter) begin
|
||||||
// $display("BUS_CTRL %1d: [%d] reset loop counter", i_phase, i_cycle_ctr);
|
// $display("BUS_CTRL %1d: [%d] reset loop counter", i_phase, i_cycle_ctr);
|
||||||
addr_loop_counter <= 0;
|
o_data_ptr <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -703,12 +723,14 @@ always @(posedge i_clk) begin
|
||||||
if (do_load_clean) begin
|
if (do_load_clean) begin
|
||||||
$display("BUS_CTRL %1d: [%d] cleanup after load", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] cleanup after load", i_phase, i_cycle_ctr);
|
||||||
cmd_LOAD_PC_F <= 0;
|
cmd_LOAD_PC_F <= 0;
|
||||||
|
cmd_LOAD_DP_F <= 0;
|
||||||
|
o_data_ptr <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_clean) begin
|
if (do_clean) begin
|
||||||
$display("BUS_CTRL %1d: [%d] cleanup", i_phase, i_cycle_ctr);
|
$display("BUS_CTRL %1d: [%d] cleanup", i_phase, i_cycle_ctr);
|
||||||
cmd_PC_READ_F <= 0;
|
cmd_PC_READ_F <= 0;
|
||||||
do_read_dp_s <= 0;
|
cmd_DP_READ_F <= 0;
|
||||||
cmd_DP_WRITE_F0 <= 0;
|
cmd_DP_WRITE_F0 <= 0;
|
||||||
cmd_DP_WRITE_F1 <= 0;
|
cmd_DP_WRITE_F1 <= 0;
|
||||||
cmd_CONFIGURE_F0 <= 0;
|
cmd_CONFIGURE_F0 <= 0;
|
||||||
|
@ -738,8 +760,9 @@ always @(posedge i_clk) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_WRITE_DP_0) begin
|
if (do_WRITE_DP_0) begin
|
||||||
$display("BUS_CTRL %1d: [%d] WRITE %h", i_phase, i_cycle_ctr, i_nibble);
|
$display("BUS_CTRL %1d: [%d] WRITE %h (%0d to go)", i_phase, i_cycle_ctr, i_data_nibl, i_xfr_cnt - o_data_ptr);
|
||||||
o_bus_data <= i_nibble;
|
o_bus_data <= i_data_nibl;
|
||||||
|
o_data_ptr <= (o_data_ptr == i_xfr_cnt)?o_data_ptr: o_data_ptr + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (do_read_stalled_by_alu) begin
|
if (do_read_stalled_by_alu) begin
|
||||||
|
|
147
saturn_core.v
147
saturn_core.v
|
@ -225,15 +225,19 @@ saturn_alu m_alu (
|
||||||
.i_stalled (alu_stalled),
|
.i_stalled (alu_stalled),
|
||||||
|
|
||||||
.o_bus_address (alu_bus_address),
|
.o_bus_address (alu_bus_address),
|
||||||
|
.i_bus_data_ptr (ctrl_bus_data_ptr),
|
||||||
|
.o_bus_data_nibl (alu_bus_data_nibl),
|
||||||
.o_bus_xfr_cnt (alu_bus_xfr_cnt),
|
.o_bus_xfr_cnt (alu_bus_xfr_cnt),
|
||||||
|
.i_bus_nibble_in (ctrl_bus_nibble_in),
|
||||||
|
.o_bus_nibble_out (alu_bus_nibble_out),
|
||||||
|
|
||||||
.o_bus_load_pc (alu_bus_load_pc),
|
.o_bus_load_pc (alu_bus_load_pc),
|
||||||
.o_bus_load_dp (alu_bus_load_dp),
|
.o_bus_load_dp (alu_bus_load_dp),
|
||||||
.o_bus_pc_read (alu_bus_pc_read),
|
.o_bus_pc_read (alu_bus_pc_read),
|
||||||
.o_bus_dp_read (alu_bus_dp_read),
|
.o_bus_dp_read (alu_bus_dp_read),
|
||||||
.o_bus_dp_write (alu_bus_dp_write),
|
.o_bus_dp_write (alu_bus_dp_write),
|
||||||
.o_bus_config (alu_bus_config),
|
.o_bus_config (alu_bus_config),
|
||||||
.i_bus_nibble_in (ctrl_bus_nibble_in),
|
.i_bus_done (ctrl_bus_done),
|
||||||
.o_bus_nibble_out (alu_bus_nibble_out),
|
|
||||||
|
|
||||||
.i_push (push),
|
.i_push (push),
|
||||||
.i_pop (pop),
|
.i_pop (pop),
|
||||||
|
@ -274,6 +278,7 @@ saturn_alu m_alu (
|
||||||
|
|
||||||
// interconnections
|
// interconnections
|
||||||
wire [19:0] alu_bus_address;
|
wire [19:0] alu_bus_address;
|
||||||
|
wire [3:0] alu_bus_data_nibl;
|
||||||
wire [3:0] alu_bus_xfr_cnt;
|
wire [3:0] alu_bus_xfr_cnt;
|
||||||
wire [0:0] alu_bus_pc_read;
|
wire [0:0] alu_bus_pc_read;
|
||||||
wire [0:0] alu_bus_dp_read;
|
wire [0:0] alu_bus_dp_read;
|
||||||
|
@ -282,7 +287,6 @@ wire [0:0] alu_bus_load_pc;
|
||||||
wire [0:0] alu_bus_load_dp;
|
wire [0:0] alu_bus_load_dp;
|
||||||
wire [0:0] alu_bus_config;
|
wire [0:0] alu_bus_config;
|
||||||
|
|
||||||
wire [3:0] ctrl_bus_nibble_in;
|
|
||||||
wire [3:0] alu_bus_nibble_out;
|
wire [3:0] alu_bus_nibble_out;
|
||||||
|
|
||||||
wire [0:0] alu_stalls_dec;
|
wire [0:0] alu_stalls_dec;
|
||||||
|
@ -303,7 +307,9 @@ saturn_bus_ctrl m_bus_ctrl (
|
||||||
.i_cycle_ctr (cycle_ctr),
|
.i_cycle_ctr (cycle_ctr),
|
||||||
.i_stalled (mem_ctrl_stall),
|
.i_stalled (mem_ctrl_stall),
|
||||||
.i_alu_busy (dec_stalled),
|
.i_alu_busy (dec_stalled),
|
||||||
|
|
||||||
.o_stall_alu (bus_stalls_core),
|
.o_stall_alu (bus_stalls_core),
|
||||||
|
.o_bus_done (ctrl_bus_done),
|
||||||
|
|
||||||
//bus i/o
|
//bus i/o
|
||||||
.o_bus_reset (o_bus_reset),
|
.o_bus_reset (o_bus_reset),
|
||||||
|
@ -315,6 +321,8 @@ saturn_bus_ctrl m_bus_ctrl (
|
||||||
// interface to the rest of the machine
|
// interface to the rest of the machine
|
||||||
.i_alu_pc (reg_pc),
|
.i_alu_pc (reg_pc),
|
||||||
.i_address (alu_bus_address),
|
.i_address (alu_bus_address),
|
||||||
|
.i_data_nibl (alu_bus_data_nibl),
|
||||||
|
.o_data_ptr (ctrl_bus_data_ptr),
|
||||||
.i_cmd_load_pc (alu_bus_load_pc),
|
.i_cmd_load_pc (alu_bus_load_pc),
|
||||||
.i_cmd_load_dp (alu_bus_load_dp),
|
.i_cmd_load_dp (alu_bus_load_dp),
|
||||||
.i_read_pc (alu_bus_pc_read),
|
.i_read_pc (alu_bus_pc_read),
|
||||||
|
@ -331,6 +339,9 @@ 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;
|
||||||
|
wire [0:0] ctrl_bus_done;
|
||||||
|
wire [3:0] ctrl_bus_data_ptr;
|
||||||
|
wire [3:0] ctrl_bus_nibble_in;
|
||||||
|
|
||||||
// `define DEBUG_CLOCKS
|
// `define DEBUG_CLOCKS
|
||||||
|
|
||||||
|
@ -418,7 +429,7 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
clock_end <= 0;
|
clock_end <= 0;
|
||||||
cycle_ctr <= ~0;
|
cycle_ctr <= ~0;
|
||||||
max_cycle <= 72;
|
max_cycle <= 30;
|
||||||
|
|
||||||
mem_ctrl_stall <= 0;
|
mem_ctrl_stall <= 0;
|
||||||
`ifndef SIM
|
`ifndef SIM
|
||||||
|
@ -450,133 +461,7 @@ endmodule
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
|
|
||||||
`include "def-buscmd.v"
|
`include "def-buscmd.v"
|
||||||
|
`include "saturn_test_rom.v"
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* test rom
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
module test_rom (
|
|
||||||
i_phase,
|
|
||||||
|
|
||||||
i_reset,
|
|
||||||
i_bus_data_in,
|
|
||||||
o_bus_data_out,
|
|
||||||
i_bus_strobe,
|
|
||||||
i_bus_cmd_data
|
|
||||||
);
|
|
||||||
|
|
||||||
input wire [1:0] i_phase;
|
|
||||||
|
|
||||||
input wire [0:0] i_reset;
|
|
||||||
input wire [3:0] i_bus_data_in;
|
|
||||||
output reg [3:0] o_bus_data_out;
|
|
||||||
input wire [0:0] i_bus_strobe;
|
|
||||||
input wire [0:0] i_bus_cmd_data;
|
|
||||||
|
|
||||||
reg [31:0] cycles;
|
|
||||||
|
|
||||||
`ifdef SIM
|
|
||||||
`define ROMBITS 20
|
|
||||||
`else
|
|
||||||
`define ROMBITS 12
|
|
||||||
`endif
|
|
||||||
|
|
||||||
reg [3:0] rom [0:2**`ROMBITS-1];
|
|
||||||
|
|
||||||
reg [19:0] local_pc;
|
|
||||||
reg [19:0] local_dp;
|
|
||||||
|
|
||||||
reg [3:0] last_bus_cmd;
|
|
||||||
reg [2:0] addr_c;
|
|
||||||
wire [0:0] s_load_pc;
|
|
||||||
wire [0:0] s_load_dp;
|
|
||||||
wire [0:0] s_pc_read;
|
|
||||||
wire [0:0] s_dp_read;
|
|
||||||
wire [0:0] s_dp_write;
|
|
||||||
assign s_load_pc = (last_bus_cmd == `BUSCMD_LOAD_PC);
|
|
||||||
assign s_load_dp = (last_bus_cmd == `BUSCMD_LOAD_DP);
|
|
||||||
assign s_pc_read = (last_bus_cmd == `BUSCMD_PC_READ);
|
|
||||||
assign s_dp_read = (last_bus_cmd == `BUSCMD_DP_READ);
|
|
||||||
assign s_dp_write = (last_bus_cmd == `BUSCMD_DP_WRITE);
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
$readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1);
|
|
||||||
// $monitor("rst %b | strb %b | c/d %b | bus_i %h | bus_o %h | last %h | slpc %b | addr_c %0d | lpc %5h | ldp %5h",
|
|
||||||
// i_reset, i_bus_strobe, i_bus_cmd_data, i_bus_data_in, o_bus_data_out,
|
|
||||||
// last_bus_cmd, s_load_pc, addr_c, local_pc, local_dp);
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge i_bus_strobe) begin
|
|
||||||
|
|
||||||
if (i_reset) begin
|
|
||||||
cycles <= 0;
|
|
||||||
last_bus_cmd <= `BUSCMD_NOP;
|
|
||||||
addr_c <= 0;
|
|
||||||
local_pc <= 0;
|
|
||||||
local_dp <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (!i_reset)
|
|
||||||
cycles <= cycles + 1;
|
|
||||||
|
|
||||||
|
|
||||||
if (!i_bus_cmd_data) begin
|
|
||||||
|
|
||||||
$write("ROM %0d: [%d] COMMAND ", i_phase, cycles);
|
|
||||||
case (i_bus_data_in)
|
|
||||||
`BUSCMD_PC_READ: $write("PC_READ"); // 2
|
|
||||||
`BUSCMD_DP_WRITE: $write("DP_WRITE"); // 5
|
|
||||||
`BUSCMD_LOAD_PC: $write("LOAD_PC"); // 6
|
|
||||||
`BUSCMD_LOAD_DP: $write("LOAD_DP"); // 7
|
|
||||||
`BUSCMD_CONFIGURE: $write("CONFIGURE (ignore)"); // 8
|
|
||||||
`BUSCMD_RESET: $write("RESET (ignore)"); // 15
|
|
||||||
endcase
|
|
||||||
$write(" (%h)\n", i_bus_data_in);
|
|
||||||
|
|
||||||
last_bus_cmd <= i_bus_data_in;
|
|
||||||
end
|
|
||||||
|
|
||||||
// if (i_bus_cmd_data) begin
|
|
||||||
// $display("BUS DATA %h", i_bus_data_in);
|
|
||||||
// end
|
|
||||||
|
|
||||||
if (i_bus_cmd_data && s_load_pc) begin
|
|
||||||
$display("ROM %0d: [%d] ADDR_IN(%0d) %h => PC [%5h]", i_phase, cycles, addr_c, i_bus_data_in, local_pc);
|
|
||||||
local_pc[addr_c*4+:4] <= i_bus_data_in;
|
|
||||||
if (addr_c == 4) $display("ROM : [%d] auto PC_READ [%5h]", cycles, {i_bus_data_in, local_pc[15:0]});
|
|
||||||
last_bus_cmd <= (addr_c == 4)?`BUSCMD_PC_READ:last_bus_cmd;
|
|
||||||
addr_c <= (addr_c == 4)?0:addr_c + 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i_bus_cmd_data && s_load_dp) begin
|
|
||||||
$display("ROM %0d: [%d] ADDR_IN(%0d) %h => DP [%5h]", i_phase, cycles, addr_c, i_bus_data_in, local_dp);
|
|
||||||
local_dp[addr_c*4+:4] <= i_bus_data_in;
|
|
||||||
if (addr_c == 4) $display("ROM : [%d] auto DP_READ [%5h]", cycles, {i_bus_data_in, local_dp[15:0]});
|
|
||||||
last_bus_cmd <= (addr_c == 4)?`BUSCMD_DP_READ:last_bus_cmd;
|
|
||||||
addr_c <= (addr_c == 4)?0:addr_c + 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i_bus_cmd_data && s_pc_read) begin
|
|
||||||
o_bus_data_out <= rom[local_pc];
|
|
||||||
$display("ROM %0d: [%d] %h <= PC_READ [%5h]", i_phase, cycles, rom[local_pc], local_pc);
|
|
||||||
local_pc <= local_pc + 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i_bus_cmd_data && s_dp_read) begin
|
|
||||||
o_bus_data_out <= rom[local_dp];
|
|
||||||
$display("ROM %0d: [%d] %h <= DP_READ [%5h]", i_phase, cycles, rom[local_dp], local_dp);
|
|
||||||
local_dp <= local_dp + 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i_bus_cmd_data && s_dp_write) begin
|
|
||||||
$display("ROM %0d: [%d] %h => DP_WRITE [%5h] (ignored)", i_phase, cycles, i_bus_data_in, local_dp);
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
|
|
|
@ -556,21 +556,21 @@ always @(posedge i_clk) begin
|
||||||
`endif
|
`endif
|
||||||
// o_alu_debug <= 1;
|
// o_alu_debug <= 1;
|
||||||
o_fields_table <= i_nibble[3]?`FT_TABLE_value:`FT_TABLE_a;
|
o_fields_table <= i_nibble[3]?`FT_TABLE_value:`FT_TABLE_a;
|
||||||
o_alu_op <= `ALU_OP_COPY;
|
// o_alu_op <= `ALU_OP_COPY;
|
||||||
go_fields_table <= use_fields_tbl;
|
go_fields_table <= use_fields_tbl;
|
||||||
use_fields_tbl <= 0;
|
use_fields_tbl <= 0;
|
||||||
|
|
||||||
// do not block when we're reading
|
// do not block when we're reading
|
||||||
o_alu_no_stall <= !use_fields_tbl && i_nibble[1];
|
// o_alu_no_stall <= !use_fields_tbl && i_nibble[1];
|
||||||
// o_alu_debug <= i_nibble[1];
|
// o_alu_debug <= i_nibble[1];
|
||||||
|
|
||||||
// set the info about this being a memory transfer
|
// set the info about this being a memory transfer
|
||||||
o_ins_mem_xfr <= 1;
|
o_ins_mem_xfr <= !(use_fields_tbl);
|
||||||
o_xfr_dir_out <= !i_nibble[1];
|
o_xfr_dir_out <= !i_nibble[1];
|
||||||
|
|
||||||
block_15xx <= use_fields_tbl;
|
block_15xx <= use_fields_tbl;
|
||||||
|
|
||||||
o_ins_alu_op <= !(use_fields_tbl);
|
// o_ins_alu_op <= !(use_fields_tbl);
|
||||||
next_nibble <= use_fields_tbl;
|
next_nibble <= use_fields_tbl;
|
||||||
o_ins_decoded <= !(use_fields_tbl);
|
o_ins_decoded <= !(use_fields_tbl);
|
||||||
block_14x_15xx <= 0;
|
block_14x_15xx <= 0;
|
||||||
|
@ -581,8 +581,9 @@ always @(posedge i_clk) begin
|
||||||
$display("block_15xx %h", i_nibble);
|
$display("block_15xx %h", i_nibble);
|
||||||
`endif
|
`endif
|
||||||
o_alu_debug <= 1;
|
o_alu_debug <= 1;
|
||||||
o_alu_no_stall <= 1;
|
// o_alu_no_stall <= 1;
|
||||||
o_ins_alu_op <= 1;
|
// o_ins_alu_op <= 1;
|
||||||
|
o_ins_mem_xfr <= 1;
|
||||||
o_ins_decoded <= 1;
|
o_ins_decoded <= 1;
|
||||||
next_nibble <= 0;
|
next_nibble <= 0;
|
||||||
block_15xx <= 0;
|
block_15xx <= 0;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
(c) Raphaël Jacquot 2019
|
||||||
|
|
||||||
This file is part of hp_saturn.
|
This file is part of hp_saturn.
|
||||||
|
|
||||||
hp_saturn is free software: you can redistribute it and/or modify
|
hp_saturn is free software: you can redistribute it and/or modify
|
||||||
|
|
|
@ -272,7 +272,7 @@ always @(posedge i_clk) begin
|
||||||
$write("\t");
|
$write("\t");
|
||||||
if (o_field_valid) begin
|
if (o_field_valid) begin
|
||||||
|
|
||||||
// $write("[FT%d]", o_fields_table);
|
$write("[FT%d]", o_fields_table);
|
||||||
if (o_fields_table != `FT_TABLE_value)
|
if (o_fields_table != `FT_TABLE_value)
|
||||||
case (o_field)
|
case (o_field)
|
||||||
`FT_FIELD_P: $write("P");
|
`FT_FIELD_P: $write("P");
|
||||||
|
|
152
saturn_test_rom.v
Normal file
152
saturn_test_rom.v
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
(c) Raphaël Jacquot 2019
|
||||||
|
|
||||||
|
This file is part of hp_saturn.
|
||||||
|
|
||||||
|
hp_saturn is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
hp_saturn is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Foobar. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
`ifndef _SATURN_TEST_ROM
|
||||||
|
`define _SATURN_TEST_ROM
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* test rom
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
module test_rom (
|
||||||
|
i_phase,
|
||||||
|
|
||||||
|
i_reset,
|
||||||
|
i_bus_data_in,
|
||||||
|
o_bus_data_out,
|
||||||
|
i_bus_strobe,
|
||||||
|
i_bus_cmd_data
|
||||||
|
);
|
||||||
|
|
||||||
|
input wire [1:0] i_phase;
|
||||||
|
|
||||||
|
input wire [0:0] i_reset;
|
||||||
|
input wire [3:0] i_bus_data_in;
|
||||||
|
output reg [3:0] o_bus_data_out;
|
||||||
|
input wire [0:0] i_bus_strobe;
|
||||||
|
input wire [0:0] i_bus_cmd_data;
|
||||||
|
|
||||||
|
reg [31:0] cycles;
|
||||||
|
|
||||||
|
`ifdef SIM
|
||||||
|
`define ROMBITS 20
|
||||||
|
`else
|
||||||
|
`define ROMBITS 12
|
||||||
|
`endif
|
||||||
|
|
||||||
|
reg [3:0] rom [0:2**`ROMBITS-1];
|
||||||
|
|
||||||
|
reg [19:0] local_pc;
|
||||||
|
reg [19:0] local_dp;
|
||||||
|
|
||||||
|
reg [3:0] last_bus_cmd;
|
||||||
|
reg [2:0] addr_c;
|
||||||
|
wire [0:0] s_load_pc;
|
||||||
|
wire [0:0] s_load_dp;
|
||||||
|
wire [0:0] s_pc_read;
|
||||||
|
wire [0:0] s_dp_read;
|
||||||
|
wire [0:0] s_dp_write;
|
||||||
|
assign s_load_pc = (last_bus_cmd == `BUSCMD_LOAD_PC);
|
||||||
|
assign s_load_dp = (last_bus_cmd == `BUSCMD_LOAD_DP);
|
||||||
|
assign s_pc_read = (last_bus_cmd == `BUSCMD_PC_READ);
|
||||||
|
assign s_dp_read = (last_bus_cmd == `BUSCMD_DP_READ);
|
||||||
|
assign s_dp_write = (last_bus_cmd == `BUSCMD_DP_WRITE);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// $readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1);
|
||||||
|
$readmemh("testrom-2.hex", rom, 0, 2**`ROMBITS-1);
|
||||||
|
// $monitor("rst %b | strb %b | c/d %b | bus_i %h | bus_o %h | last %h | slpc %b | addr_c %0d | lpc %5h | ldp %5h",
|
||||||
|
// i_reset, i_bus_strobe, i_bus_cmd_data, i_bus_data_in, o_bus_data_out,
|
||||||
|
// last_bus_cmd, s_load_pc, addr_c, local_pc, local_dp);
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge i_bus_strobe) begin
|
||||||
|
|
||||||
|
if (i_reset) begin
|
||||||
|
cycles <= 0;
|
||||||
|
last_bus_cmd <= `BUSCMD_NOP;
|
||||||
|
addr_c <= 0;
|
||||||
|
local_pc <= 0;
|
||||||
|
local_dp <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (!i_reset)
|
||||||
|
cycles <= cycles + 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (!i_bus_cmd_data) begin
|
||||||
|
|
||||||
|
$write("ROM %0d: [%d] COMMAND ", i_phase, cycles);
|
||||||
|
case (i_bus_data_in)
|
||||||
|
`BUSCMD_PC_READ: $write("PC_READ"); // 2
|
||||||
|
`BUSCMD_DP_WRITE: $write("DP_WRITE"); // 5
|
||||||
|
`BUSCMD_LOAD_PC: $write("LOAD_PC"); // 6
|
||||||
|
`BUSCMD_LOAD_DP: $write("LOAD_DP"); // 7
|
||||||
|
`BUSCMD_CONFIGURE: $write("CONFIGURE (ignore)"); // 8
|
||||||
|
`BUSCMD_RESET: $write("RESET (ignore)"); // 15
|
||||||
|
endcase
|
||||||
|
$write(" (%h)\n", i_bus_data_in);
|
||||||
|
|
||||||
|
last_bus_cmd <= i_bus_data_in;
|
||||||
|
end
|
||||||
|
|
||||||
|
// if (i_bus_cmd_data) begin
|
||||||
|
// $display("BUS DATA %h", i_bus_data_in);
|
||||||
|
// end
|
||||||
|
|
||||||
|
if (i_bus_cmd_data && s_load_pc) begin
|
||||||
|
$display("ROM %0d: [%d] ADDR_IN(%0d) %h => PC [%5h]", i_phase, cycles, addr_c, i_bus_data_in, local_pc);
|
||||||
|
local_pc[addr_c*4+:4] <= i_bus_data_in;
|
||||||
|
if (addr_c == 4) $display("ROM : [%d] auto PC_READ [%5h]", cycles, {i_bus_data_in, local_pc[15:0]});
|
||||||
|
last_bus_cmd <= (addr_c == 4)?`BUSCMD_PC_READ:last_bus_cmd;
|
||||||
|
addr_c <= (addr_c == 4)?0:addr_c + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_bus_cmd_data && s_load_dp) begin
|
||||||
|
$display("ROM %0d: [%d] ADDR_IN(%0d) %h => DP [%5h]", i_phase, cycles, addr_c, i_bus_data_in, local_dp);
|
||||||
|
local_dp[addr_c*4+:4] <= i_bus_data_in;
|
||||||
|
if (addr_c == 4) $display("ROM : [%d] auto DP_READ [%5h]", cycles, {i_bus_data_in, local_dp[15:0]});
|
||||||
|
last_bus_cmd <= (addr_c == 4)?`BUSCMD_DP_READ:last_bus_cmd;
|
||||||
|
addr_c <= (addr_c == 4)?0:addr_c + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_bus_cmd_data && s_pc_read) begin
|
||||||
|
o_bus_data_out <= rom[local_pc];
|
||||||
|
$display("ROM %0d: [%d] %h <= PC_READ [%5h]", i_phase, cycles, rom[local_pc], local_pc);
|
||||||
|
local_pc <= local_pc + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_bus_cmd_data && s_dp_read) begin
|
||||||
|
o_bus_data_out <= rom[local_dp];
|
||||||
|
$display("ROM %0d: [%d] %h <= DP_READ [%5h]", i_phase, cycles, rom[local_dp], local_dp);
|
||||||
|
local_dp <= local_dp + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_bus_cmd_data && s_dp_write) begin
|
||||||
|
$display("ROM %0d: [%d] %h => DP_WRITE [%5h] (ignored)", i_phase, cycles, i_bus_data_in, local_dp);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`endif
|
|
@ -1,3 +1,3 @@
|
||||||
2 3
|
1 B 5 4 3 2 1
|
||||||
4 D F
|
1 4 c
|
||||||
3 1 4 3
|
2 0
|
Loading…
Add table
Reference in a new issue