diff --git a/history.txt b/history.txt index 7c56a52..fe9f2dc 100644 --- a/history.txt +++ b/history.txt @@ -41,3 +41,4 @@ second delay is posedge $glbnet$clk -> 2019-02-17 21:21 1734 71.16MHz 32.10ns 12.05ns 11359 73.56MHz 17.19ns 3.73ns 2019-02-17 22:31 1573 77.32MHz 32.91ns 12.77ns 10265 70.53MHz 17.35ns 4.13ns 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 diff --git a/saturn_alu.v b/saturn_alu.v index 71ea49b..63dba75 100644 --- a/saturn_alu.v +++ b/saturn_alu.v @@ -26,10 +26,12 @@ module saturn_alu ( o_bus_address, o_bus_pc_read, + o_bus_dp_read, o_bus_dp_write, o_bus_load_pc, o_bus_load_dp, o_bus_config, + i_bus_nibble_in, o_bus_nibble_out, i_push, @@ -77,10 +79,12 @@ input wire [0:0] i_stalled; output reg [19:0] o_bus_address; output reg [0:0] o_bus_pc_read; +output reg [0:0] o_bus_dp_read; output reg [0:0] o_bus_dp_write; output reg [0:0] o_bus_load_pc; output reg [0:0] o_bus_load_dp; output reg [0:0] o_bus_config; +input wire [3:0] i_bus_nibble_in; output reg [3:0] o_bus_nibble_out; input wire [0:0] i_push; @@ -292,7 +296,7 @@ assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go; assign o_alu_stall_dec = (!no_extra_cycles) || (alu_run && - (!i_alu_no_stall || alu_finish || alu_go_test)); + (!i_alu_no_stall || alu_finish || alu_go_test || o_bus_dp_read)); wire alu_start; wire alu_finish; @@ -465,17 +469,6 @@ always @(posedge i_clk) begin alu_done <= 0; end - - // if (do_alu_save && alu_done) - // case (alu_op) - // `ALU_OP_TEST_EQ, - // `ALU_OP_TEST_NEQ: - // begin - // $display("#### UNBLOCK THE DECODER"); - // alu_go_test <= 1; - // end - // endcase - end @@ -519,6 +512,8 @@ always @(posedge i_clk) begin `ALU_REG_D0: p_src1 <= D0[f_cur*4+:4]; `ALU_REG_D1: p_src1 <= D1[f_cur*4+:4]; `ALU_REG_P: p_src1 <= P; + `ALU_REG_DAT0, + `ALU_REG_DAT1: p_src1 <= i_bus_nibble_in; `ALU_REG_HST: p_src1 <= HST; `ALU_REG_IMM: p_src1 <= i_imm_value; `ALU_REG_ZERO: p_src1 <= 0; @@ -816,26 +811,53 @@ end reg [0:0] write_done; reg [1:0] extra_cycles; +wire [0:0] read_done; +wire [0:0] setup_load_dp_read; +wire [0:0] setup_load_dp_write; wire [0:0] setup_load_dp; wire [0:0] no_extra_cycles; wire [1:0] cycles_to_go; -assign setup_load_dp = do_alu_init && is_mem_xfer && !write_done; -assign no_extra_cycles = (extra_cycles == 0); -assign cycles_to_go = extra_cycles - 1; +assign read_done = is_mem_read && do_alu_save && ((f_cur +1) == f_last); +assign setup_load_dp_read = do_alu_init && is_mem_read && !read_done; +assign setup_load_dp_write = do_alu_init && is_mem_write && !write_done; +assign setup_load_dp = setup_load_dp_read || setup_load_dp_write; +assign no_extra_cycles = (extra_cycles == 0); +assign cycles_to_go = extra_cycles - 1; always @(posedge i_clk) begin // reset stuff if (i_reset) begin + // read_done <= 0; write_done <= 0; extra_cycles <= 0; o_bus_load_dp <= 0; + o_bus_dp_read <= 0; o_bus_dp_write <= 0; end + /* + * reading + * note: starts immediately + */ + + if (setup_load_dp_read) begin + o_bus_load_dp <= 1; + o_bus_dp_read <= 1; + end + + if (read_done) begin + o_bus_load_dp <= 0; + o_bus_dp_read <= 0; + end + + /* + * writing + */ + // setup the order to load DP in time - if (setup_load_dp) begin + if (setup_load_dp_write) begin o_bus_load_dp <= 1; end diff --git a/saturn_bus_ctrl.v b/saturn_bus_ctrl.v index d2dd916..1afad7b 100644 --- a/saturn_bus_ctrl.v +++ b/saturn_bus_ctrl.v @@ -29,6 +29,7 @@ module saturn_bus_ctrl ( i_load_pc, i_cmd_load_dp, i_read_pc, + i_cmd_dp_read, i_cmd_dp_write, i_cmd_reset, i_cmd_config, @@ -57,6 +58,7 @@ input wire [19:0] i_address; input wire [0:0] i_load_pc; input wire [0:0] i_cmd_load_dp; input wire [0:0] i_read_pc; +input wire [0:0] i_cmd_dp_read; input wire [0:0] i_cmd_dp_write; input wire [0:0] i_cmd_reset; input wire [0:0] i_cmd_config; @@ -84,6 +86,7 @@ wire [0:0] addr_s; assign addr_s = addr_cnt == 5; reg [0:0] cmd_pc_read_s; +reg [0:0] dp_read_s; reg [0:0] cmd_dp_write_s; reg [0:0] cmd_load_dp_s; reg [0:0] cmd_config_s; @@ -93,6 +96,12 @@ wire [0:0] do_cmd_pc_read; wire [0:0] do_display_stalled; wire [0:0] do_cmd_load_dp; +wire [0:0] do_dp_read_data; +wire [0:0] do_dp_read_data_sc; +wire [0:0] do_dp_read_data_uc; +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] do_dp_write_data; wire [0:0] do_pc_read_after_dp_write; @@ -109,8 +118,16 @@ wire [0:0] cmd_reset_sc; wire [0:0] cmd_reset_uc; wire [0:0] do_unstall; +wire [0:0] do_cleanup; assign do_cmd_load_dp = i_cmd_load_dp && !cmd_load_dp_s; + +assign do_dp_read_data = i_cmd_dp_read && cmd_load_dp_s && (addr_s || dp_read_s); +assign do_dp_read_data_sc = i_cmd_dp_read && cmd_load_dp_s && addr_s && !dp_read_s; +assign do_dp_read_data_uc = i_cmd_dp_read && cmd_load_dp_s && addr_s && dp_read_s; +assign do_pc_read_after_dp_read = i_read_stall && !i_cmd_dp_read && cmd_load_dp_s && !addr_s && dp_read_s; +assign do_cleanup_after_dp_read = !i_read_stall && !i_cmd_dp_read && cmd_load_dp_s && !addr_s && dp_read_s; + assign do_cmd_dp_write = i_cmd_dp_write && cmd_load_dp_s && addr_s && !cmd_dp_write_s; assign do_dp_write_data = i_cmd_dp_write && cmd_load_dp_s && addr_s && cmd_dp_write_s; assign do_pc_read_after_dp_write = !i_cmd_dp_write && cmd_load_dp_s && cmd_dp_write_s; @@ -127,17 +144,26 @@ assign cmd_reset_sc = !o_stalled_by_bus && i_cmd_reset && !cmd_rese assign cmd_reset_uc = cmd_reset_s && cmd_pc_read_s; assign do_cmd_pc_read = !cmd_pc_read_s && - (do_pc_read_after_dp_write || + (do_pc_read_after_dp_read || + do_pc_read_after_dp_write || do_pc_read_after_config || do_pc_read_after_reset); assign do_display_stalled = i_read_stall && !o_stalled_by_bus && !(do_cmd_pc_read || + do_dp_read_data || + do_pc_read_after_dp_read || do_cmd_dp_write || do_dp_write_data || do_pc_read_after_dp_write); -assign do_unstall = cmd_load_dp_dp_write_uc || +assign do_unstall = do_dp_read_data_uc || + cmd_load_dp_dp_write_uc || + cmd_config_uc || + cmd_reset_uc; + +assign do_cleanup = do_cleanup_after_dp_read || + cmd_load_dp_dp_write_uc || cmd_config_uc || cmd_reset_uc; /* @@ -146,7 +172,7 @@ assign do_unstall = cmd_load_dp_dp_write_uc || `ifdef SIM `define ROMBITS 20 `else -`define ROMBITS 10 +`define ROMBITS 16 `endif reg [3:0] rom [0:2**`ROMBITS-1]; @@ -155,13 +181,11 @@ initial begin `ifdef SIM $readmemh("rom-gx-r.hex", rom); // $readmemh( "testrom-2.hex", rom); -// $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); -// $monitor("MONITOR : strb %b | o_bus_data %h | i_bus_data %h", o_bus_strobe, o_bus_data, i_bus_data); - - // $monitor("MONITOR : i_cmd_dp_write %b | cmd_load_dp_s %b | addr_s %b | dp_write_reset %b", - // i_cmd_dp_write, cmd_load_dp_s, addr_s, cmd_load_dp_dp_write_uc); +// $monitor({"o_stalled_by_bus %b | i_read_stall %b | i_cmd_dp_read %b |", +// " cmd_load_dp_s %b | addr_s %b | dp_read_s %b |do_dp_read_data %b"}, +// o_stalled_by_bus, i_read_stall, i_cmd_dp_read, cmd_load_dp_s, +// addr_s, dp_read_s, do_dp_read_data); `endif end @@ -171,10 +195,6 @@ reg [0:0] send_addr; reg [19:0] local_pc; reg [19:0] local_dp; -reg [0:0] reset_sent; -reg [0:0] config_sent; -reg [0:0] send_pc_read; - always @(posedge i_clk) begin if (i_reset) begin last_cmd <= 0; @@ -183,11 +203,9 @@ always @(posedge i_clk) begin o_bus_cmd_data <= 1; // 1 is the default level addr_cnt <= 0; send_addr <= 0; - reset_sent <= 0; - config_sent <= 0; - send_pc_read <= 0; cmd_pc_read_s <= 0; + dp_read_s <= 0; cmd_dp_write_s <= 0; cmd_load_dp_s <= 0; cmd_config_s <= 0; @@ -205,8 +223,10 @@ always @(posedge i_clk) begin * reset flags */ - if (do_unstall) begin + 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; @@ -290,14 +310,17 @@ always @(posedge i_clk) begin 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 - end else 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; @@ -315,13 +338,19 @@ always @(posedge i_clk) begin if (en_bus_recv) begin - if (!i_read_stall) + if (!i_read_stall || do_dp_read_data) case (last_cmd) `BUSCMD_PC_READ: begin - $display("BUS_RECV %0d: [%d] <= READ [%5h] %h", `PH_BUS_RECV, i_cycle_ctr, local_pc, rom[local_pc[`ROMBITS-1:0]]); + $display("BUS_RECV %0d: [%d] <= READ(PC) [%5h] %h", `PH_BUS_RECV, i_cycle_ctr, local_pc, rom[local_pc[`ROMBITS-1:0]]); o_nibble <= rom[local_pc[`ROMBITS-1:0]]; local_pc <= local_pc + 1; end + `BUSCMD_DP_READ: begin + $display("BUS_RECV %0d: [%d] <= READ(DP) [%5h] %h", `PH_BUS_RECV, i_cycle_ctr, local_dp, rom[local_dp[`ROMBITS-1:0]]); + o_nibble <= rom[local_dp[`ROMBITS-1:0]]; + local_dp <= local_dp + 1; + dp_read_s <= 1; + end endcase if (do_display_stalled) begin @@ -343,14 +372,13 @@ always @(posedge i_clk) begin // stalling and unstalling stuff - if (cmd_reset_sc) - o_stalled_by_bus <= 1; - - if (cmd_config_sc) begin + 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 @@ -375,9 +403,13 @@ always @(posedge i_clk) begin `BUSCMD_LOAD_DP: local_dp <= i_address; endcase send_addr <= 0; - o_stalled_by_bus <= 0; + if (!do_dp_read_data) begin + // $display("-------------------------------------- NO - STALL (auto-change mode)"); + o_stalled_by_bus <= 0; + end end `BUSCMD_PC_READ: begin end + `BUSCMD_DP_READ: begin end `BUSCMD_DP_WRITE: begin end `BUSCMD_CONFIGURE: begin end `BUSCMD_RESET: begin end diff --git a/saturn_core.v b/saturn_core.v index 6b54886..b858536 100644 --- a/saturn_core.v +++ b/saturn_core.v @@ -174,8 +174,10 @@ saturn_alu m_alu ( .o_bus_load_pc (bus_load_pc), .o_bus_load_dp (bus_load_dp), .o_bus_pc_read (bus_pc_read), + .o_bus_dp_read (bus_dp_read), .o_bus_dp_write (bus_dp_write), .o_bus_config (bus_config), + .i_bus_nibble_in (bus_nibble_in), .o_bus_nibble_out (bus_nibble_out), .i_push (push), @@ -214,10 +216,11 @@ saturn_alu m_alu ( // interconnections wire [19:0] bus_address; +wire [0:0] bus_pc_read; +wire [0:0] bus_dp_read; +wire [0:0] bus_dp_write; wire [0:0] bus_load_pc; wire [0:0] bus_load_dp; -wire [0:0] bus_pc_read; -wire [0:0] bus_dp_write; wire [0:0] bus_config; wire [3:0] bus_nibble_in; @@ -257,6 +260,7 @@ saturn_bus_ctrl m_bus_ctrl ( .i_load_pc (bus_load_pc), .i_cmd_load_dp (bus_load_dp), .i_read_pc (bus_pc_read), + .i_cmd_dp_read (bus_dp_read), .i_cmd_dp_write (bus_dp_write), .i_cmd_reset (ins_reset), .i_cmd_config (bus_config), @@ -267,6 +271,7 @@ 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; @@ -358,7 +363,7 @@ always @(posedge clk) begin clock_end <= 0; cycle_ctr <= ~0; - max_cycle <= 405; + max_cycle <= 420; mem_ctrl_stall <= 0; `ifndef SIM @@ -377,14 +382,6 @@ wire dec_stalled; wire alu_stalled; assign dec_stalled = alu_stalls_dec || bus_stalls_core; assign alu_stalled = bus_stalls_core; - -wire read_nibble_to_dec; -assign read_nibble_to_dec = ck_bus_recv && !dec_stalled; -wire dec_stalled_no_read; -assign dec_stalled_no_read = ck_bus_recv && !bus_stalls_core && dec_stalled; -wire bus_is_stalled; -assign bus_is_stalled = ck_bus_recv && bus_stalls_core; - assign halt = clock_end || inv_opcode; diff --git a/saturn_decoder.v b/saturn_decoder.v index 1667219..625ca77 100644 --- a/saturn_decoder.v +++ b/saturn_decoder.v @@ -515,6 +515,10 @@ always @(posedge i_clk) begin o_alu_op <= `ALU_OP_COPY; go_fields_table <= use_fields_tbl; use_fields_tbl <= 0; + + // do not block when we're reading + o_alu_no_stall <= !use_fields_tbl && i_nibble[1]; + // o_alu_debug <= i_nibble[1]; block_15xx <= use_fields_tbl; @@ -528,10 +532,11 @@ always @(posedge i_clk) begin `ifdef SIM $display("block_15xx %h", i_nibble); `endif - o_ins_alu_op <= 1; - o_ins_decoded <= 1; - next_nibble <= 0; - block_15xx <= 0; + o_alu_no_stall <= i_nibble[1]; + o_ins_alu_op <= 1; + o_ins_decoded <= 1; + next_nibble <= 0; + block_15xx <= 0; end if (do_block_pointer_arith_const) begin