From 0d3c3ecd3e78456021413c86c1fec5eff31a8e96 Mon Sep 17 00:00:00 2001 From: Raphael Jacquot Date: Sun, 17 Feb 2019 19:29:39 +0100 Subject: [PATCH] implement CONFIG cleanup the bus controller --- def-alu.v | 1 + history.txt | 1 + saturn_alu.v | 73 ++++++++++++----- saturn_bus_ctrl.v | 164 +++++++++++++++++++++++++++---------- saturn_core.v | 30 ++++--- saturn_decoder.v | 8 +- saturn_decoder_block_8.v | 6 ++ saturn_decoder_fields.v | 11 ++- saturn_decoder_registers.v | 9 ++ 9 files changed, 228 insertions(+), 75 deletions(-) diff --git a/def-alu.v b/def-alu.v index 09f30b1..22a1169 100644 --- a/def-alu.v +++ b/def-alu.v @@ -69,6 +69,7 @@ `define ALU_REG_P 20 `define ALU_REG_M 21 `define ALU_REG_IMM 22 +`define ALU_REG_ADDR 23 `define ALU_REG_ZERO 31 diff --git a/history.txt b/history.txt index d23795d..02f3c23 100644 --- a/history.txt +++ b/history.txt @@ -35,3 +35,4 @@ second delay is posedge $glbnet$clk -> 2019-02-16 12:18 1453 62.31MHz 33.86ns 12.05ns 10323 70.66MHz 16.96ns 3.59ns 2019-02-16 22:54 1629 60.66MHz 33.62ns 12.05ns 11562 56.91MHz 17.11ns 3.84ns 2019-02-17 12:58 1679 68.43MHz 38.91ns 12.77ns 10906 70.19MHz 18.76ns 4.00ns +2019-02-17 15:11 1677 70.29MHz 34.92ns 13.01ns 11788 74.69MHz 17.42ns 3.88ns diff --git a/saturn_alu.v b/saturn_alu.v index fc82ee1..918d861 100644 --- a/saturn_alu.v +++ b/saturn_alu.v @@ -25,10 +25,11 @@ module saturn_alu ( i_stalled, o_bus_address, + o_bus_pc_read, + o_bus_dp_write, o_bus_load_pc, o_bus_load_dp, - o_bus_read_pc, - o_bus_write_dp, + o_bus_config, o_bus_nibble_out, i_push, @@ -52,6 +53,8 @@ module saturn_alu ( i_ins_test_go, i_ins_set_mode, i_ins_rtn, + i_ins_config, + i_ins_unconfig, i_mode_dec, i_set_xm, @@ -73,10 +76,11 @@ input wire [0:0] i_en_alu_save; 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_write; output reg [0:0] o_bus_load_pc; 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 [0:0] o_bus_config; output reg [3:0] o_bus_nibble_out; input wire [0:0] i_push; @@ -109,6 +113,8 @@ input wire [0:0] i_ins_alu_op; input wire [0:0] i_ins_test_go; input wire [0:0] i_ins_set_mode; input wire [0:0] i_ins_rtn; +input wire [0:0] i_ins_config; +input wire [0:0] i_ins_unconfig; input wire [0:0] i_mode_dec; input wire [0:0] i_set_xm; @@ -345,8 +351,8 @@ always @(posedge i_clk) begin $display("D: %h R3: %h RSTK2: %5h", D, R3, RSTK[2]); $display("D0: %h D1: %h R4: %h RSTK1: %5h", D0, D1, R4, RSTK[1]); - $display(" RSTK0: %5h", - RSTK[0]); + $display(" ADDR: %5h RSTK0: %5h", + o_bus_address, RSTK[0]); end `endif end @@ -394,7 +400,7 @@ end always @(posedge i_clk) begin if (do_alu_init) begin - $display("------------------------------------------------- DO_ALU_INIT"); + // $display("------------------------------------------------- DO_ALU_INIT"); alu_run <= 1; f_first <= i_field_start; f_cur <= i_field_start; @@ -658,6 +664,7 @@ always @(posedge i_clk) begin `ALU_REG_DAT0, `ALU_REG_DAT1: o_bus_nibble_out <= c_res1; `ALU_REG_HST: HST <= c_res1; + `ALU_REG_ADDR: begin end // done down below where o_bus_addr is accessible default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op); endcase `ALU_OP_RST_BIT, @@ -768,7 +775,7 @@ always @(posedge i_clk) begin write_done <= 0; extra_cycles <= 0; o_bus_load_dp <= 0; - o_bus_write_dp <= 0; + o_bus_dp_write <= 0; end // setup the order to load DP in time @@ -778,8 +785,8 @@ always @(posedge i_clk) begin // tell the bus to start the write cycle // 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_write_dp) - o_bus_write_dp <= 1; + if (do_busclean && alu_run && !write_done && is_mem_write && !o_bus_dp_write) + o_bus_dp_write <= 1; // writing takes 2 more cycles : // - one used up above @@ -794,14 +801,14 @@ always @(posedge i_clk) begin if (i_en_alu_calc && !no_extra_cycles) begin extra_cycles <= cycles_to_go; if (cycles_to_go == 1) begin - o_bus_write_dp <= 0; - o_bus_read_pc <= 1; + o_bus_dp_write <= 0; + o_bus_pc_read <= 1; end end // once the PC_READ command has been sent, remove the stall on the decoder - if (i_en_alu_dump && no_extra_cycles && o_bus_read_pc) begin - o_bus_read_pc <= 0; + if (i_en_alu_dump && no_extra_cycles && o_bus_pc_read) begin + o_bus_pc_read <= 0; write_done <= 0; end @@ -810,6 +817,33 @@ always @(posedge i_clk) begin end +/***************************************************************************** + * + * config and unconfig + * + ****************************************************************************/ + +wire is_bus_config; +assign is_bus_config = (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR); +wire send_config; +assign send_config = alu_active && i_en_alu_calc && i_ins_alu_op && alu_run && alu_finish; + +always @(posedge i_clk) begin + if (i_reset) + o_bus_config <= 0; + + // $display("send_config %b | is_bus_cfg %b | i_ins_cfg %b", send_config, is_bus_config, i_ins_config); + if (send_config && is_bus_config && i_ins_config) + o_bus_config <= 1; + + + if (do_busclean && o_bus_config) + o_bus_config <= 0; + +end + + + /***************************************************************************** * * Handles all changes to PC @@ -853,6 +887,11 @@ always @(posedge i_clk) begin 1: o_bus_address <= D1; endcase + // 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 + o_bus_address[f_cur*4+:4] <= c_res1; + end + /** * * Update the PC. @@ -871,12 +910,6 @@ always @(posedge i_clk) begin !o_alu_stall_dec, next_pc, alu_done, alu_finish, is_alu_op_jump, i_ins_rtn, i_push, i_imm_value, jump_bse, goyes_off, goyes_pc); - // if (reload_pc) begin - // $display(".---------------------------------."); - // $display("| SHOULD TELL THE BUS CONTROLLER |"); - // $display("| TO LOAD PC INTO MODULES' PC REG |"); - // $display("`---------------------------------´"); - // end `endif // this may do wierd things with C=RSTK... diff --git a/saturn_bus_ctrl.v b/saturn_bus_ctrl.v index 732dbed..9a928a4 100644 --- a/saturn_bus_ctrl.v +++ b/saturn_bus_ctrl.v @@ -31,6 +31,7 @@ module saturn_bus_ctrl ( i_read_pc, i_write_dp, i_cmd_reset, + i_cmd_config, i_nibble, o_nibble ); @@ -58,6 +59,8 @@ input wire [0:0] i_load_dp; input wire [0:0] i_read_pc; input wire [0:0] i_write_dp; input wire [0:0] i_cmd_reset; +input wire [0:0] i_cmd_config; + input wire [3:0] i_nibble; output reg [3:0] o_nibble; @@ -65,7 +68,6 @@ output reg [3:0] o_nibble; * events */ - wire en_bus_send; assign en_bus_send = i_en_bus_send && !i_stalled; wire en_bus_recv; @@ -73,6 +75,44 @@ assign en_bus_recv = i_en_bus_recv && !i_stalled; wire en_bus_ecmd; assign en_bus_ecmd = i_en_bus_ecmd && !i_stalled; +/* + * states + */ + +wire [0:0] addr_s; + +assign addr_s = addr_cnt == 5; + +reg [0:0] cmd_pc_read_s; +reg [0:0] cmd_config_s; +reg [0:0] cmd_reset_s; + +wire [0:0] do_pc_read; + +wire [0:0] do_cmd_config; +wire [0:0] do_pc_read_after_config; +wire [0:0] cmd_config_sc; +wire [0:0] cmd_config_uc; + +wire [0:0] do_cmd_reset; +wire [0:0] do_pc_read_after_reset; +wire [0:0] cmd_reset_sc; +wire [0:0] cmd_reset_uc; + + +assign do_cmd_config = i_cmd_config && !cmd_config_s; +assign do_pc_read_after_config = i_cmd_config && cmd_config_s && addr_s; +assign cmd_config_sc = !o_stalled_by_bus && i_cmd_config && !cmd_config_s; +assign cmd_config_uc = cmd_config_s && cmd_pc_read_s; + +assign do_cmd_reset = i_cmd_reset && !cmd_reset_s; +assign do_pc_read_after_reset = i_cmd_reset && cmd_reset_s; +assign cmd_reset_sc = !o_stalled_by_bus && i_cmd_reset && !cmd_reset_s; +assign cmd_reset_uc = cmd_reset_s && cmd_pc_read_s; + +assign do_pc_read = !cmd_pc_read_s && + (do_pc_read_after_config || + do_pc_read_after_reset); /* * test rom... */ @@ -98,11 +138,13 @@ end reg [3:0] last_cmd; reg [2:0] addr_cnt; reg [0:0] send_addr; -reg [0:0] reset_sent; -reg [0:0] send_pc_read; 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; @@ -112,7 +154,12 @@ always @(posedge i_clk) begin addr_cnt <= 0; send_addr <= 0; reset_sent <= 0; + config_sent <= 0; send_pc_read <= 0; + + cmd_pc_read_s <= 0; + cmd_config_s <= 0; + cmd_reset_s <= 0; end /* @@ -122,6 +169,16 @@ always @(posedge i_clk) begin */ if (en_bus_send) begin + /* + * reset flags + */ + + if (cmd_reset_uc || cmd_config_uc) begin + cmd_config_s <= 0; + cmd_reset_s <= 0; + cmd_pc_read_s <= 0; + end + /* * Sending LOAD_PC or LOAD_DP */ @@ -138,7 +195,24 @@ always @(posedge i_clk) begin last_cmd <= `BUSCMD_LOAD_DP; end - if (i_load_pc || i_load_dp) begin + if (do_cmd_config) begin + $display("BUS_SEND %0d: [%d] CONFIGURE %h", `PH_BUS_SEND, i_cycle_ctr, i_address); + o_bus_data <= `BUSCMD_CONFIGURE; + last_cmd <= `BUSCMD_CONFIGURE; + cmd_config_s <= 1; + end + + if (do_cmd_reset) begin + $display("BUS_SEND %0d: [%d] RESET", `PH_BUS_SEND, i_cycle_ctr); + o_bus_data <= `BUSCMD_RESET; + last_cmd <= `BUSCMD_RESET; + cmd_reset_s <= 1; + o_bus_strobe <= 1; + end + + // configure loop to send i_address to the bus + // used for LOAD_PC, LOAD_DP, CONFIGURE, + if (i_load_pc || i_load_dp || do_cmd_config) begin o_stalled_by_bus <= 1; o_bus_cmd_data <= 0; addr_cnt <= 0; @@ -160,15 +234,11 @@ always @(posedge i_clk) begin * after a data transfer */ - if (i_read_pc || send_pc_read) 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; - send_pc_read <= 0; - end - - o_bus_strobe <= 1; + if (do_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; + cmd_pc_read_s <= 1; end if ((last_cmd == `BUSCMD_PC_READ) && !i_read_stall) @@ -192,23 +262,15 @@ always @(posedge i_clk) begin end end - if (i_cmd_reset && !reset_sent) begin - $display("BUS_SEND %0d: [%d] RESET", `PH_BUS_SEND, i_cycle_ctr); - o_bus_data <= `BUSCMD_RESET; - last_cmd <= `BUSCMD_RESET; - reset_sent <= 1; - o_bus_strobe <= 1; - end - - end + + /* * * reading data from the bus * */ - if (en_bus_recv) begin if (!i_read_stall) @@ -224,11 +286,13 @@ always @(posedge i_clk) begin $write("BUS_RECV %0d: [%d] STALLED (last ", `PH_BUS_RECV, i_cycle_ctr); case (last_cmd) `BUSCMD_PC_READ: $write("PC_READ"); + `BUSCMD_DP_READ: $write("DP_READ"); + `BUSCMD_DP_WRITE: $write("DP_WRITE"); `BUSCMD_RESET: $write("RESET"); default: $write("%h", last_cmd); endcase $display(")"); - end + end /* * @@ -241,20 +305,46 @@ always @(posedge i_clk) begin end + if (en_bus_ecmd) begin + + if (cmd_reset_sc) + o_stalled_by_bus <= 1; + + if (cmd_reset_uc) begin + o_stalled_by_bus <= 0; + end + + if (cmd_config_sc) begin + o_stalled_by_bus <= 1; + end + + if (cmd_config_uc) begin + o_stalled_by_bus <= 0; + addr_cnt <= 0; + end + + if (addr_s) begin + send_addr <= 0; + end + + end + + + + // command automatic switchover if (en_bus_ecmd) begin - if (i_cmd_reset && !reset_sent) - o_stalled_by_bus <= 1; - case (last_cmd) `BUSCMD_LOAD_PC, `BUSCMD_LOAD_DP: if (send_addr && (addr_cnt == 5)) begin - $display("BUS_ECMD %0d: [%d] <= %sC_READ mode", + // reset the addr count for next time + addr_cnt <= 0; + $display("BUS_ECMD %0d: [%d] <= %s_READ mode", `PH_BUS_ECMD, i_cycle_ctr, - (last_cmd == `BUSCMD_LOAD_PC)?"P":"D"); + (last_cmd == `BUSCMD_LOAD_PC)?"PC":"DP"); last_cmd <= (last_cmd == `BUSCMD_LOAD_PC)?`BUSCMD_PC_READ:`BUSCMD_DP_READ; case (last_cmd) `BUSCMD_LOAD_PC: local_pc <= i_address; @@ -263,18 +353,10 @@ always @(posedge i_clk) begin send_addr <= 0; o_stalled_by_bus <= 0; end - `BUSCMD_PC_READ: begin - if (o_stalled_by_bus && reset_sent) begin - // $display("BUS_ECMD %0d: [%d] (pc_read unstall)", `PH_BUS_ECMD, i_cycle_ctr); - o_stalled_by_bus <= 0; - end - end - `BUSCMD_RESET: begin - if (o_stalled_by_bus && reset_sent) begin - // $display("BUS_ECMD %0d: [%d] (reset, send pc_read)", `PH_BUS_ECMD, i_cycle_ctr); - send_pc_read <= 1; - end - end + `BUSCMD_PC_READ: begin end + `BUSCMD_CONFIGURE: begin end + `BUSCMD_RESET: begin end + default: $display("------------ UNHANDLED BUSCMD %h", last_cmd); endcase diff --git a/saturn_core.v b/saturn_core.v index 7105bcb..f1994d6 100644 --- a/saturn_core.v +++ b/saturn_core.v @@ -121,7 +121,8 @@ saturn_decoder m_decoder ( .o_mode_dec (mode_dec), .o_ins_alu_op (ins_alu_op), .o_ins_test_go (ins_test_go), - .o_ins_reset (ins_reset) + .o_ins_reset (ins_reset), + .o_ins_config (ins_config) ); wire [0:0] inc_pc; @@ -154,6 +155,8 @@ wire [0:0] mode_dec; wire [0:0] ins_alu_op; wire [0:0] ins_test_go; wire [0:0] ins_reset; +wire [0:0] ins_config; +wire [0:0] ins_unconfig; saturn_alu m_alu ( @@ -170,8 +173,9 @@ saturn_alu m_alu ( .o_bus_address (bus_address), .o_bus_load_pc (bus_load_pc), .o_bus_load_dp (bus_load_dp), - .o_bus_read_pc (bus_read_pc), - .o_bus_write_dp (bus_write_dp), + .o_bus_pc_read (bus_pc_read), + .o_bus_dp_write (bus_dp_write), + .o_bus_config (bus_config), .o_bus_nibble_out (bus_nibble_out), .i_push (push), @@ -195,6 +199,8 @@ saturn_alu m_alu ( .i_ins_test_go (ins_test_go), .i_ins_set_mode (ins_set_mode), .i_ins_rtn (ins_rtn), + .i_ins_config (ins_config), + .i_ins_unconfig (ins_unconfig), .i_mode_dec (mode_dec), .i_set_xm (set_xm), @@ -210,8 +216,9 @@ saturn_alu m_alu ( wire [19:0] bus_address; wire [0:0] bus_load_pc; wire [0:0] bus_load_dp; -wire [0:0] bus_read_pc; -wire [0:0] bus_write_dp; +wire [0:0] bus_pc_read; +wire [0:0] bus_dp_write; +wire [0:0] bus_config; wire [3:0] bus_nibble_in; wire [3:0] bus_nibble_out; @@ -249,9 +256,10 @@ saturn_bus_ctrl m_bus_ctrl ( .i_address (bus_address), .i_load_pc (bus_load_pc), .i_load_dp (bus_load_dp), - .i_read_pc (bus_read_pc), - .i_write_dp (bus_write_dp), + .i_read_pc (bus_pc_read), + .i_write_dp (bus_dp_write), .i_cmd_reset (ins_reset), + .i_cmd_config (bus_config), .i_nibble (bus_nibble_out), .o_nibble (bus_nibble_in) ); @@ -325,9 +333,9 @@ always @(posedge clk) begin cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) }; if (cycle_ctr == (max_cycle + 1)) begin - $display(".-------------------."); - $display("| OUT OF CYCLES |"); - $display("`-------------------´"); + $display(".-----------------------------."); + $display("| OUT OF CYCLES %d |", cycle_ctr); + $display("`-----------------------------´"); clock_end <= 1; end end else begin @@ -350,7 +358,7 @@ always @(posedge clk) begin clock_end <= 0; cycle_ctr <= ~0; - max_cycle <= 155; + max_cycle <= 170; mem_ctrl_stall <= 0; `ifndef SIM diff --git a/saturn_decoder.v b/saturn_decoder.v index 4c1a214..684c36f 100644 --- a/saturn_decoder.v +++ b/saturn_decoder.v @@ -32,7 +32,7 @@ module saturn_decoder( o_set_carry, o_test_carry, o_carry_val, o_ins_set_mode, o_mode_dec, o_ins_alu_op, o_ins_test_go, - o_ins_reset, + o_ins_reset, o_ins_config, o_dbg_nibbles, o_dbg_nb_nbls, o_mem_load, o_mem_pos ); @@ -96,6 +96,7 @@ output reg [0:0] o_ins_test_go; // bus operations output reg [0:0] o_ins_reset; +output reg [0:0] o_ins_config; /* data used by the debugger * @@ -189,6 +190,7 @@ always @(posedge i_clk) begin o_pop <= 0; o_ins_set_mode <= 0; o_ins_reset <= 0; + o_ins_config <= 0; end if (decoder_active) begin @@ -256,7 +258,9 @@ always @(posedge i_clk) begin // bus instructions o_ins_reset <= 0; + o_ins_config <= 0; + // counters for debugger info o_dbg_nb_nbls <= 1; o_mem_pos <= 0; @@ -274,7 +278,7 @@ always @(posedge i_clk) begin block_jump_test <= 0; end else begin // assign block regs - $display("FIRST NIBBLE %h", i_nibble); + // $display("FIRST NIBBLE %h", i_nibble); case (i_nibble) 4'h0: block_0x <= 1; 4'h1: block_1x <= 1; diff --git a/saturn_decoder_block_8.v b/saturn_decoder_block_8.v index 723c9a3..012293b 100644 --- a/saturn_decoder_block_8.v +++ b/saturn_decoder_block_8.v @@ -51,13 +51,19 @@ `endif case (i_nibble) 4'h5: begin // CONFIG + o_ins_alu_op <= 1; + o_alu_op <= `ALU_OP_COPY; next_nibble <= 0; o_ins_decoded <= 1; + o_ins_config <= 1; end 4'hA: begin // RESET o_ins_reset <= 1; next_nibble <= 0; o_ins_decoded <= 1; + `ifdef SIM + o_unimplemented <= 0; + `endif end 4'hC: block_80Cx <= 1; default: begin diff --git a/saturn_decoder_fields.v b/saturn_decoder_fields.v index 491e34e..f53d893 100644 --- a/saturn_decoder_fields.v +++ b/saturn_decoder_fields.v @@ -6,7 +6,7 @@ *****************************************************************************/ `ifdef SIM -`define DEBUG_FIELDS_TABLE +// `define DEBUG_FIELDS_TABLE `endif reg fields_table_done; @@ -153,6 +153,15 @@ always @(posedge i_clk) begin endcase end + if (do_block_80x) begin + case (i_nibble) + 4'h5: begin + o_field_start <= 0; + o_field_last <= 4; + end + endcase + end + if (do_block_80Cx) begin o_field_start <= i_nibble; o_field_last <= i_nibble; diff --git a/saturn_decoder_registers.v b/saturn_decoder_registers.v index 8d7076f..3005681 100644 --- a/saturn_decoder_registers.v +++ b/saturn_decoder_registers.v @@ -161,6 +161,15 @@ always @(posedge i_clk) begin endcase end + if (do_block_80x) begin + case (i_nibble) + 4'h5: begin + o_reg_dest <= `ALU_REG_ADDR; + o_reg_src1 <= `ALU_REG_C; + end + endcase + end + if (do_block_80Cx) begin o_reg_dest <= `ALU_REG_C; o_reg_src1 <= `ALU_REG_P;