diff --git a/def-alu.v b/def-alu.v index ac04fee..895cecb 100644 --- a/def-alu.v +++ b/def-alu.v @@ -21,19 +21,25 @@ // logic `define ALU_OP_AND 5 `define ALU_OP_OR 6 +// bit set/reset +`define ALU_OP_RST_BIT 7 +`define ALU_OP_SET_BIT 8 // arithmetic -`define ALU_OP_2CMPL 7 -`define ALU_OP_1CMPL 8 -`define ALU_OP_INC 9 -`define ALU_OP_DEC 10 -`define ALU_OP_ADD 11 -`define ALU_OP_SUB 12 +`define ALU_OP_2CMPL 9 +`define ALU_OP_1CMPL 10 +`define ALU_OP_INC 11 +`define ALU_OP_DEC 12 +`define ALU_OP_ADD 13 +`define ALU_OP_SUB 14 // tests -`define ALU_OP_TEST_EQ 13 -`define ALU_OP_TEST_NEQ 14 +`define ALU_OP_TEST_EQ 15 +`define ALU_OP_TEST_NEQ 16 // relative jump -`define ALU_OP_JMP_REL2 15 -`define ALU_OP_JMP_REL3 16 +`define ALU_OP_JMP_REL2 17 +`define ALU_OP_JMP_REL3 18 +`define ALU_OP_JMP_REL4 19 +`define ALU_OP_JMP_ABS5 20 + // registers diff --git a/history.txt b/history.txt index 4563ea2..932db49 100644 --- a/history.txt +++ b/history.txt @@ -23,3 +23,4 @@ 2019-02-13 07:46 48 98.83MHz 13.86ns 2.92ns 241 169.41MHz 4.11ns 1.92ns 2019-02-13 14:53 51 153.35MHz 16.74ns 3.40ns 273 155.47MHz 5.53ns 2.09ns 2019-02-13 23:21 318 113.77MHz 25.44ns 13.97ns 3061 117.75MHz 9.56ns 4.08ns +2019-02-14 09:00 353 118.23MHz 26.00ns 12.28ns 3334 119.40MHz 10.08ns 3.84ns diff --git a/saturn-alu.v b/saturn-alu.v index 157a654..0c2791b 100644 --- a/saturn-alu.v +++ b/saturn-alu.v @@ -3,7 +3,14 @@ `include "def-alu.v" -`define ALU_DEBUG +`ifdef SIM +// `define ALU_DEBUG_DBG +`endif + +`define ALU_DEBUG 1'b0 +`define ALU_DEBUG_DUMP 1'b1 +`define ALU_DEBUG_JUMP 1'b0 +`define ALU_DEBUG_PC 1'b0 module saturn_alu ( i_clk, @@ -14,6 +21,10 @@ module saturn_alu ( i_en_alu_init, i_en_alu_save, + i_push, + i_pop, + i_alu_debug, + o_alu_stall_dec, i_ins_decoded, @@ -41,6 +52,19 @@ input wire [0:0] i_en_alu_calc; input wire [0:0] i_en_alu_init; input wire [0:0] i_en_alu_save; +input wire [0:0] i_push; +input wire [0:0] i_pop; +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; input wire [0:0] i_ins_decoded; @@ -62,6 +86,42 @@ output wire [19:0] o_pc; assign o_reg_p = P; assign o_pc = PC; +/* internal registers */ + +/* copy of arguments */ +reg [4:0] alu_op; +reg [4:0] reg_dest; +reg [4:0] reg_src1; +reg [4:0] reg_src2; +reg [3:0] f_start; +reg [3:0] f_last; + +/* internal pointers */ + +reg [3:0] p_src1; +reg [3:0] p_src2; +reg p_carry; +reg [3:0] c_res1; +reg [3:0] c_res2; +reg c_carry; + +/* alu status */ + +reg alu_run; +reg alu_done; + +/* + * next PC in case of jump + */ +reg [19:0] jump_bse; +reg [19:0] jump_off; +wire [19:0] jump_pc; +assign jump_pc = (alu_op == `ALU_OP_JMP_ABS5)?jump_off:(jump_bse + jump_off); + +reg [2:0] rstk_ptr; + +/* public registers */ + reg [19:0] PC; reg [19:0] D0; @@ -84,12 +144,18 @@ reg [3:0] P; reg [3:0] HST; reg [15:0] ST; -reg [2:0] rstk_ptr; reg [19:0] RSTK[0:7]; initial begin // alu internal control bits + alu_op = 0; + reg_dest = 0; + reg_src1 = 0; + reg_src2 = 0; + f_start = 0; + f_last = 0; + alu_run = 0; alu_done = 0; // o_alu_stall_dec = 0; @@ -143,33 +209,26 @@ assign do_alu_save = (!i_reset) && i_en_alu_save && alu_run; assign do_alu_shpc = (!i_reset) && i_en_alu_dump; assign do_alu_pc = (!i_reset) && i_en_alu_save; -reg alu_run; -reg alu_done; -wire test_finish; -wire [3:0] f_next; - -assign test_finish = f_start == f_last; -assign f_next = (f_start + 1) & 4'hF; - // the decoder may request the ALU to not stall it +assign o_alu_stall_dec = alu_run && (!i_alu_no_stall || alu_finish); -assign o_alu_stall_dec = alu_run && (!i_alu_no_stall || test_finish); +wire alu_start; +wire alu_finish; +wire [3:0] f_next; -reg [4:0] alu_op; -reg [4:0] reg_dest; -reg [4:0] reg_src1; -reg [4:0] reg_src2; -reg [3:0] f_start; -reg [3:0] f_last; +assign alu_start = f_start == 0; +assign alu_finish = f_start == f_last; +assign f_next = (f_start + 1) & 4'hF; -reg [3:0] p_src1; -reg [3:0] p_src2; -reg p_carry; -reg [3:0] c_res1; -reg [3:0] c_res2; -reg c_carry; +/* + * test things on alu_op + */ +wire is_alu_op_jump; +assign is_alu_op_jump = ((alu_op == `ALU_OP_JMP_REL3) || + (alu_op == `ALU_OP_JMP_REL4) || + (alu_op == `ALU_OP_JMP_ABS5)); /* * dump all registers @@ -178,9 +237,18 @@ reg c_carry; */ always @(posedge i_clk) begin - if (do_reg_dump) begin - $display("ALU_DUMP 0: run %b | done %b ", alu_run, alu_done); + `ifdef ALU_DEBUG_DBG + $display("iad %b | AD %b | ad %b | ADD %b | add %b | ADJ %b | adj %b | ADP %b | adp %b", + i_alu_debug, + `ALU_DEBUG, i_alu_debug, + `ALU_DEBUG_DUMP, alu_debug_dump, + `ALU_DEBUG_JUMP, alu_debug_jump, + `ALU_DEBUG_PC, alu_debug_pc ); + `endif + + if (do_reg_dump && alu_debug_dump) begin `ifdef SIM + $display("ALU_DUMP 0: run %b | done %b", alu_run, alu_done); // display registers $display("PC: %05h Carry: %b h: %s rp: %h RSTK7: %05h", PC, CARRY, DEC?"DEC":"HEX", rstk_ptr, RSTK[7]); @@ -202,10 +270,14 @@ end always @(posedge i_clk) begin // this happens in phase 3, right after the instruction decoder (in phase 2) is finished if (do_alu_init) begin - $display({"ALU_INIT 3: run %b | done %b | stall %b | op %d | s %h | l %h ", - "| ialu %b | dest %d | src1 %d | src2 %d"}, - alu_run, alu_done, o_alu_stall_dec, i_alu_op,i_field_start, i_field_last, - i_ins_alu_op, i_reg_dest, i_reg_src1, i_reg_src2); + + if (alu_debug) + $display({"ALU_INIT 3: run %b | done %b | stall %b | op %d | s %h | l %h ", + "| ialu %b | dest %d | src1 %d | src2 %d"}, + alu_run, alu_done, o_alu_stall_dec, i_alu_op,i_field_start, i_field_last, + i_ins_alu_op, i_reg_dest, i_reg_src1, i_reg_src2); + + jump_bse <= PC; alu_op <= i_alu_op; reg_dest <= i_reg_dest; reg_src1 <= i_reg_src1; @@ -227,7 +299,7 @@ always @(posedge i_clk) begin end if (do_alu_calc) begin // $display("ALU_TEST 2: tf %b | nxt %h", test_finish, f_next); - alu_done <= test_finish; + alu_done <= alu_finish; // f_next <= (f_start + 1) & 4'hF; end if (do_alu_save) begin @@ -241,21 +313,28 @@ always @(posedge i_clk) begin end +`define ALU_DEBUG +`define JUMP_DEBUG always @(posedge i_clk) begin if (do_alu_prep) begin - `ifdef ALU_DEBUG - $display("ALU_PREP 1: run %b | done %b | stall %b | op %d | s %h | l %h", - alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last); - `endif - + if (alu_debug) begin + `ifdef SIM + $display("ALU_PREP 1: run %b | done %b | stall %b | op %d | s %h | l %h", + alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last); + `endif + end // setup value for src1 case (alu_op) `ALU_OP_ZERO: begin end // no source required `ALU_OP_COPY, - `ALU_OP_JMP_REL3: + `ALU_OP_RST_BIT, + `ALU_OP_SET_BIT, + `ALU_OP_JMP_REL3, + `ALU_OP_JMP_REL4, + `ALU_OP_JMP_ABS5: case (reg_src1) `ALU_REG_A: p_src1 <= A [f_start*4+:4]; `ALU_REG_B: p_src1 <= B [f_start*4+:4]; @@ -275,14 +354,37 @@ end always @(posedge i_clk) begin if (do_alu_calc) begin - `ifdef ALU_DEBUG - $display("ALU_CALC 2: run %b | done %b | stall %b | op %d | s %h | l %h | src1 %h | src2 %h | p_carry %b", - alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last, p_src1, p_src2, p_carry); + `ifdef SIM + if (alu_debug) + $display("ALU_CALC 2: run %b | done %b | stall %b | op %d | s %h | l %h | dest %d | src1 %h | src2 %h | p_carry %b", + alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last, reg_dest, p_src1, p_src2, p_carry); + if (alu_debug_jump) + $display("ALU_JUMP 2: run %b | done %b | stall %b | op %d | s %h | l %h | jbs %5h | jof %5h | jpc %5h | fin %b", + alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last, jump_bse, jump_off, jump_pc, alu_finish); `endif case (alu_op) - `ALU_OP_ZERO: c_res1 <= 0; - `ALU_OP_COPY: c_res1 <= p_src1; + `ALU_OP_JMP_REL3, + `ALU_OP_JMP_REL4, + `ALU_OP_JMP_ABS5: if (alu_start) + jump_off <= { 16'b0, p_src1 }; + endcase + + case (alu_op) + `ALU_OP_ZERO: c_res1 <= 0; + `ALU_OP_COPY, + `ALU_OP_RST_BIT, + `ALU_OP_SET_BIT: c_res1 <= p_src1; + `ALU_OP_JMP_REL3, + `ALU_OP_JMP_REL4, + `ALU_OP_JMP_ABS5: jump_off[f_start*4+:4] <= p_src1; + endcase + + case (alu_op) + `ALU_OP_JMP_REL3: if (alu_finish) + jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] }; + `ALU_OP_JMP_REL4: if (alu_finish) + jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] }; endcase end end @@ -290,10 +392,14 @@ end always @(posedge i_clk) begin if (do_alu_save) begin `ifdef ALU_DEBUG - $display({"ALU_SAVE 3: run %b | done %b | stall %b | op %d | s %h | l %h |", - " res1 %h | res2 %h | c_carry %b"}, - alu_run, alu_done, o_alu_stall_dec, alu_op, - f_start, f_last, c_res1, c_res2, c_carry); + if (alu_debug) + $display({"ALU_SAVE 3: run %b | done %b | stall %b | op %d | s %h | l %h |", + " dest %d | res1 %h | res2 %h | c_carry %b"}, + alu_run, alu_done, o_alu_stall_dec, alu_op, + f_start, f_last, reg_dest, c_res1, c_res2, c_carry); + if (alu_debug_jump) + $display( "ALU_JUMP 3: run %b | done %b | stall %b | op %d | s %h | l %h | bse %5h | jof %5h | jpc %5h | fin %b", + alu_run, alu_done, o_alu_stall_dec, alu_op, f_start, f_last, jump_bse, jump_off, jump_pc, alu_finish); `endif case (alu_op) @@ -303,31 +409,49 @@ always @(posedge i_clk) begin `ALU_REG_C: C [f_start*4+:4] <= c_res1; `ALU_REG_D0: D0[f_start*4+:4] <= c_res1; `ALU_REG_D1: D1[f_start*4+:4] <= c_res1; + `ALU_REG_ST: ST[f_start*4+:4] <= c_res1; `ALU_REG_P: P <= c_res1; endcase + `ALU_OP_RST_BIT, + `ALU_OP_SET_BIT: + case (reg_dest) + `ALU_REG_ST: ST[c_res1] <= alu_op==`ALU_OP_SET_BIT?1:0; + default: + $display("invalid register for op"); + endcase endcase end end wire [19:0] next_pc; -assign next_pc = PC + 1; +assign next_pc = (is_alu_op_jump && alu_finish)?jump_pc:PC + 1; always @(posedge i_clk) begin if (i_reset) PC <= ~0; - if (do_alu_shpc) begin - // if (!o_alu_stall_dec) - // $display("ALU_SHPC 0: pc %5h", PC); + `ifdef SIM + if (do_alu_shpc && alu_debug_pc) begin + if (!o_alu_stall_dec) + $display("ALU_SHPC 0: pc %5h", PC); if (o_alu_stall_dec) $display("ALU_SHPC 0: STALL"); end + `endif + /* + * updates the PC on phase 3 to be ready for the next + * thing to do... + */ if (do_alu_pc) begin - // if (!o_alu_stall_dec) - // $display("ALU_PC 3: nx %5h", next_pc); - if (!o_alu_stall_dec) + `ifdef SIM + if (alu_debug_pc) + $display("ALU_PC 3: !stl %b | nx %5h | jmp %b | push %b", + !o_alu_stall_dec, next_pc, is_alu_op_jump, i_push); + `endif + if (!o_alu_stall_dec || is_alu_op_jump) begin PC <= next_pc; + end end end diff --git a/saturn-core.v b/saturn-core.v index 5ede547..7caba57 100644 --- a/saturn-core.v +++ b/saturn-core.v @@ -85,7 +85,10 @@ saturn_decoder m_decoder ( .i_reg_p (reg_p), .o_inc_pc (inc_pc), + .o_push (push), + .o_pop (pop), .o_dec_error (inv_opcode), + .o_alu_debug (alu_debug), .o_ins_addr (ins_addr), .o_ins_decoded (ins_decoded), @@ -112,8 +115,11 @@ saturn_decoder m_decoder ( .o_ins_alu_op (ins_alu_op) ); -wire inc_pc; -wire inv_opcode; +wire [0:0] inc_pc; +wire [0:0] push; +wire [0:0] pop; +wire [0:0] inv_opcode; +wire [0:0] alu_debug; wire [19:0] ins_addr; wire ins_decoded; @@ -149,6 +155,10 @@ saturn_alu m_alu ( .i_en_alu_init (en_alu_init), .i_en_alu_save (en_alu_save), + .i_push (push), + .i_pop (pop), + .i_alu_debug (alu_debug), + .o_alu_stall_dec (alu_stall), .i_ins_decoded (ins_decoded), @@ -184,13 +194,14 @@ reg [3:0] rom [0:2**20]; reg [3:0] rom [0:2**10]; `endif +// `define DEBUG_CLOCKS + initial begin - `ifndef SIM + `ifdef SIM $readmemh("rom-gx-r.hex", rom); - `else - $readmemh( "testrom-2.hex", rom); + // $readmemh( "testrom-2.hex", rom); `endif clk_phase = 0; @@ -207,8 +218,8 @@ initial cycle_ctr = 0; `ifdef DEBUG_CLOCKS - $monitor("RST %b | CLK %b | CLKP %d | CYCL %d | eRST %b | eDBG %b | eBSND %b | eBRECV %b | eAPR %b | eACALC %b | eINDC %b | eASAVE %b | eINDX %b", - reset, clk, clk_phase, cycle_ctr, en_reset, + $monitor("RST %b | CLK %b | CLKP %d | CYCL %d | PC %5h | eRST %b | eDBG %b | eBSND %b | eBRECV %b | eAPR %b | eACALC %b | eINDC %b | eASAVE %b | eINDX %b", + reset, clk, clk_phase, cycle_ctr, reg_pc, en_reset, en_debugger, en_bus_send, en_bus_recv, en_alu_prep, en_alu_calc, en_inst_dec, @@ -222,13 +233,15 @@ initial // //-------------------------------------------------------------------------------------------------- +`define PH_BUS_RECV 1 + always @(posedge clk) begin if (!reset) begin clk_phase <= clk_phase + 1; en_alu_dump <= clk_phase[1:0] == 0; en_debugger <= clk_phase[1:0] == 0; en_bus_send <= clk_phase[1:0] == 0; - en_bus_recv <= clk_phase[1:0] == 1; + en_bus_recv <= clk_phase[1:0] == `PH_BUS_RECV; en_alu_prep <= clk_phase[1:0] == 1; en_alu_calc <= clk_phase[1:0] == 2; en_inst_dec <= clk_phase[1:0] == 2; @@ -253,7 +266,7 @@ always @(posedge clk) begin en_inst_exec <= 0; clock_end <= 0; cycle_ctr <= ~0; - max_cycle <= 1024; + max_cycle <= 40; `ifndef SIM led[7:0] <= reg_pc[7:0]; `endif @@ -287,6 +300,7 @@ always @(posedge clk) end if (en_bus_recv) begin if (!stalled) begin + $display("BUS_RECV %1d: [%d] %5h => %1h", `PH_BUS_RECV, cycle_ctr, reg_pc, rom[reg_pc]); nibble_in <= rom[reg_pc]; end end diff --git a/saturn-decoder.v b/saturn-decoder.v index ddb6c00..5eb5156 100644 --- a/saturn-decoder.v +++ b/saturn-decoder.v @@ -23,6 +23,7 @@ module saturn_decoder( o_push, o_pop, o_dec_error, + o_alu_debug, o_ins_addr, o_ins_decoded, @@ -74,6 +75,7 @@ output reg o_inc_pc; output reg o_push; output reg o_pop; output reg o_dec_error; +output reg o_alu_debug; // instructions related outputs output reg [19:0] o_ins_addr; @@ -115,7 +117,7 @@ output reg o_ins_alu_op; output reg [(21*4-1):0] o_dbg_nibbles; output reg [4:0] o_dbg_nb_nbls; output reg [63:0] o_mem_load; -output reg [3:0] o_mem_pos; +output reg [4:0] o_mem_pos; /* @@ -164,7 +166,13 @@ wire is_la_hex; wire is_lc_hex; wire disp_nb_nibbles; assign p_is_dest = (o_reg_dest == `ALU_REG_P); -assign is_load_imm = (o_alu_op ==`ALU_OP_COPY) && (o_reg_src1 == `ALU_REG_IMM); +assign is_load_imm = ((o_alu_op == `ALU_OP_COPY) || + (o_alu_op == `ALU_OP_RST_BIT) || + (o_alu_op == `ALU_OP_SET_BIT) || + (o_alu_op == `ALU_OP_JMP_REL3) || + (o_alu_op == `ALU_OP_JMP_REL4) || + (o_alu_op == `ALU_OP_JMP_ABS5)) + && (o_reg_src1 == `ALU_REG_IMM); assign is_d0_eq = is_load_imm && (o_reg_dest == `ALU_REG_D0); assign is_d1_eq = is_load_imm && (o_reg_dest == `ALU_REG_D1); assign is_p_eq = is_load_imm && p_is_dest; @@ -204,38 +212,52 @@ always @(posedge i_clk) begin end if (o_ins_alu_op) begin - case (o_reg_dest) - `ALU_REG_A: $write("A"); - `ALU_REG_B: $write("B"); - `ALU_REG_C: - if (is_lc_hex) $write("LCHEX"); - else $write("C"); - `ALU_REG_D: $write("D"); - `ALU_REG_D0: $write("D0"); - `ALU_REG_D1: $write("D1"); - `ALU_REG_RSTK: $write("RSTK"); - `ALU_REG_R0: $write("R0"); - `ALU_REG_R1: $write("R1"); - `ALU_REG_R2: $write("R2"); - `ALU_REG_R3: $write("R3"); - `ALU_REG_R4: $write("R4"); - `ALU_REG_DAT0: $write("DAT0"); - `ALU_REG_DAT1: $write("DAT1"); - `ALU_REG_ST: if (o_alu_op!=`ALU_OP_ZERO) $write("ST"); - `ALU_REG_P: $write("P"); - default: $write("[dest:%d]", o_reg_dest); - endcase - case (o_alu_op) - `ALU_OP_ZERO: if (o_reg_dest==`ALU_REG_ST) $write("CLRST"); else $write("=0"); + `ALU_OP_JMP_REL3: $write("GOTO"); + `ALU_OP_JMP_REL4: $write("%s", o_push?"GOSUBL":"GOLONG"); + `ALU_OP_JMP_ABS5: $write("%s", o_push?"GOSBVL":"GOVLNG"); + default: + case (o_reg_dest) + `ALU_REG_A: $write("A"); + `ALU_REG_B: $write("B"); + `ALU_REG_C: + if (is_lc_hex) $write("LCHEX"); + else $write("C"); + `ALU_REG_D: $write("D"); + `ALU_REG_D0: $write("D0"); + `ALU_REG_D1: $write("D1"); + `ALU_REG_RSTK: $write("RSTK"); + `ALU_REG_R0: $write("R0"); + `ALU_REG_R1: $write("R1"); + `ALU_REG_R2: $write("R2"); + `ALU_REG_R3: $write("R3"); + `ALU_REG_R4: $write("R4"); + `ALU_REG_DAT0: $write("DAT0"); + `ALU_REG_DAT1: $write("DAT1"); + `ALU_REG_ST: if (o_alu_op!=`ALU_OP_ZERO) $write("ST"); + `ALU_REG_P: $write("P"); + default: $write("[dest:%d]", o_reg_dest); + endcase + endcase + + case (o_alu_op) + `ALU_OP_ZERO: if (o_reg_dest==`ALU_REG_ST) + $write("CLRST"); + else $write("=0"); `ALU_OP_COPY, `ALU_OP_AND, `ALU_OP_OR, `ALU_OP_INC, `ALU_OP_DEC, `ALU_OP_ADD, - `ALU_OP_SUB: if (!is_lc_hex) $write("="); - `ALU_OP_EXCH: begin end + `ALU_OP_SUB, + `ALU_OP_RST_BIT, + `ALU_OP_SET_BIT: if (!is_lc_hex) + $write("="); + `ALU_OP_EXCH, + `ALU_OP_JMP_REL3, + `ALU_OP_JMP_REL4, + `ALU_OP_JMP_ABS5: begin end default: $write("[op:%d]", o_alu_op); endcase @@ -271,6 +293,8 @@ always @(posedge i_clk) begin else $write("(%2d)", o_mem_pos+1); default: $write("[src1:%d]", o_reg_src1); endcase + `ALU_OP_RST_BIT: $write("0"); + `ALU_OP_SET_BIT: $write("1"); endcase if ((o_alu_op == `ALU_OP_COPY) && is_short_transfer) @@ -332,19 +356,25 @@ always @(posedge i_clk) begin else if (o_field_last < 9) $write("%1d", o_field_last+1); else $write("%2d", o_field_last+1); - end else begin - if (is_load_imm) begin - if (is_p_eq) begin - if (o_imm_value < 10) $write("\t%1d", o_imm_value); - else $write("\t%2d", o_imm_value); - end else begin - for(nibble_pos=o_mem_pos; nibble_pos!=31; nibble_pos=nibble_pos-1) - $write("%h", o_mem_load[nibble_pos*4+:4]); - end - end - else if (!p_is_dest) - $write("[%h:%h]", o_field_start, o_field_last); end + + // $write("@%b@", is_load_imm); + if (is_load_imm) begin + if (is_p_eq) begin + if (o_imm_value < 10) $write("%1d", o_imm_value); + else $write("%2d", o_imm_value); + end else begin + for(nibble_pos=(o_mem_pos - 1); nibble_pos!=31; nibble_pos=nibble_pos-1) + $write("%h", o_mem_load[nibble_pos*4+:4]); + end + end + else + case (o_reg_dest) + `ALU_REG_P, + `ALU_REG_ST: begin end + default: $write("[%h:%h]", o_field_start, o_field_last); + endcase + $display("\t(%d cycles)", inst_cycles); end end @@ -374,9 +404,11 @@ reg block_mem_transfer; reg block_pointer_arith_const; reg block_load_p; reg block_load_c_hex; -reg block_jmp3_cry_set; -reg block_jmp3_cry_clr; -reg block_jmp4; +reg block_jmp2_cry_set; +reg block_jmp2_cry_clr; + +reg block_8x; +reg block_80x; reg go_fields_table; @@ -407,9 +439,11 @@ wire do_block_mem_transfer; wire do_block_pointer_arith_const; wire do_block_load_p; wire do_block_load_c_hex; -wire do_block_jmp3_cry_set; -wire do_block_jmp3_cry_clr; -wire do_block_jmp4; +wire do_block_jmp2_cry_set; +wire do_block_jmp2_cry_clr; + +wire do_block_8x; +wire do_block_80x; assign do_block_0x = do_on_other_nibbles && block_0x; assign do_block_0Efx = do_on_other_nibbles && block_0Efx; @@ -426,14 +460,25 @@ assign do_block_mem_transfer = do_on_other_nibbles && block_mem_transfer; assign do_block_pointer_arith_const = do_on_other_nibbles && block_pointer_arith_const; assign do_block_load_p = do_on_other_nibbles && block_load_p; assign do_block_load_c_hex = do_on_other_nibbles && block_load_c_hex; -assign do_block_jmp3_cry_set = do_on_other_nibbles && block_jmp3_cry_set; -assign do_block_jmp3_cry_clr = do_on_other_nibbles && block_jmp3_cry_clr; -assign do_block_jmp4 = do_on_other_nibbles && block_jmp4; +assign do_block_jmp2_cry_set = do_on_other_nibbles && block_jmp2_cry_set; +assign do_block_jmp2_cry_clr = do_on_other_nibbles && block_jmp2_cry_clr; +assign do_block_8x = do_on_other_nibbles && block_8x; +assign do_block_80x = do_on_other_nibbles && block_80x; + +/* + * subroutines + */ reg block_load_reg_imm; +reg block_jmp; +reg block_sr_bit; wire do_load_reg_imm; +wire do_block_jmp; +wire do_block_sr_bit; assign do_load_reg_imm = do_on_other_nibbles && block_load_reg_imm; +assign do_block_jmp = do_on_other_nibbles && block_jmp; +assign do_block_sr_bit = do_on_other_nibbles && block_sr_bit; wire in_fields_table; assign in_fields_table = go_fields_table && !fields_table_done; @@ -459,6 +504,7 @@ always @(posedge i_clk) begin use_fields_tbl <= 0; o_inc_pc <= 1; o_dec_error <= 0; + o_alu_debug <= 0; o_ins_decoded <= 0; o_alu_op <= 0; end @@ -467,15 +513,17 @@ always @(posedge i_clk) begin /* * stuff that is always done */ - $display("DEC_RUN 2: nibble %h", i_nibble); + `ifdef SIM + // $display("DEC_RUN 2: nibble %h", i_nibble); + `endif o_inc_pc <= 1; // may be set to 0 later o_dbg_nibbles[dbg_write_pos*4+:4] <= i_nibble; o_dbg_nb_nbls <= o_dbg_nb_nbls + 1; end - if (decoder_stalled) begin - $display("DEC_STAL 2:"); - end + // if (decoder_stalled) begin + // $display("DEC_STAL 2:"); + // end if (count_cycles) begin inst_cycles <= inst_cycles + 1; @@ -488,6 +536,7 @@ always @(posedge i_clk) begin inst_cycles <= 1; next_nibble <= 1; use_fields_tbl <= 0; + o_alu_debug <= 0; o_push <= 0; o_pop <= 0; @@ -496,7 +545,8 @@ always @(posedge i_clk) begin // store the address where the instruction starts o_ins_addr <= i_pc; - // cleanup block variables + // decoder block states + block_0x <= 0; block_0Efx <= 0; block_1x <= 0; @@ -508,11 +558,17 @@ always @(posedge i_clk) begin block_pointer_arith_const <= 0; block_load_p <= 0; block_load_c_hex <= 0; - block_jmp3_cry_set <= 0; - block_jmp3_cry_clr <= 0; - block_jmp4 <= 0; + block_jmp2_cry_set <= 0; + block_jmp2_cry_clr <= 0; + + block_8x <= 0; + block_80x <= 0; + + // decoder subroutine states block_load_reg_imm <= 0; + block_jmp <= 0; + block_sr_bit <= 0; // cleanup fields table variables go_fields_table <= 0; @@ -550,15 +606,16 @@ always @(posedge i_clk) begin 4'h1: block_1x <= 1; 4'h2: block_load_p <= 1; 4'h3: block_load_c_hex <= 1; - 4'h4: block_jmp3_cry_set <= 1; - 4'h5: block_jmp3_cry_clr <= 1; + 4'h4: block_jmp2_cry_set <= 1; + 4'h5: block_jmp2_cry_clr <= 1; 4'h6: begin o_alu_no_stall <= 1; o_alu_op <= `ALU_OP_JMP_REL3; mem_load_max <= 2; - o_mem_pos <= 0; - block_jmp4 <= 1; + o_mem_pos <= 0; + block_jmp <= 1; end + 4'h8: block_8x <= 1; default: begin `ifdef SIM $display("DEC_INIT 2: nibble %h not handled", i_nibble); @@ -661,30 +718,34 @@ always @(posedge i_clk) begin if (do_block_1x) begin case (i_nibble) - 4'h0: begin + 4'h0: // save A/C to Rn W block_save_to_R_W <= 1; - end - 4'h1: + 4'h1: // restore A/C from Rn W block_rest_from_R_W <= 1; - 4'h2: + 4'h2: // exchange A/C with Rn W block_exch_with_R_W <= 1; - 4'h3: + 4'h3: // move/exch A/C with Dn A/[0:3] block_pointer_assign_exch <= 1; - 4'h4, 4'h5: begin + 4'h4, 4'h5: // DAT[01]=[AC] + begin block_mem_transfer <= 1; o_fields_table <= i_nibble[0]?`FT_TABLE_value:`FT_TABLE_f; use_fields_tbl <= i_nibble[0]; end - 4'h6, 4'h7, 4'h8, 4'hC: begin + 4'h6, 4'h7, + 4'h8, 4'hC: // D[01]=D[01][+-] n+1; + begin block_pointer_arith_const <= 1; o_ins_alu_op <= 1; o_alu_op <= i_nibble[1]?`ALU_OP_ADD:`ALU_OP_SUB; end - 4'h9, 4'hA, 4'hB, 4'hD, 4'hE, 4'hF: begin + 4'h9, 4'hA, + 4'hB, 4'hD, + 4'hE, 4'hF: // D[0]=([245]) + begin mem_load_max <= {1'b0, i_nibble[1], !i_nibble[1], i_nibble[1] && i_nibble[0]}; o_mem_pos <= 0; block_load_reg_imm <= 1; - // o_ins_alu_op <= 1; o_alu_no_stall <= 1; o_alu_op <= `ALU_OP_COPY; end @@ -749,18 +810,63 @@ always @(posedge i_clk) begin block_load_c_hex <= 0; end - if (do_block_jmp3_cry_clr) begin + if (do_block_jmp2_cry_clr) begin end - if (do_block_jmp4) begin - o_ins_alu_op <= 1; - o_imm_value <= i_nibble; - o_mem_pos <= o_mem_pos + 1; - next_nibble <= mem_load_max != o_mem_pos; - o_ins_decoded <= mem_load_max == o_mem_pos; + + if (do_block_8x) begin + $display("block_8x %h | op %d", i_nibble, o_alu_op); + case (i_nibble) + 4'h0: // + block_80x <= 1; + 4'h4, 4'h5: // ST=[01] n + begin + o_alu_op <= i_nibble[0]?`ALU_OP_SET_BIT:`ALU_OP_RST_BIT; + block_sr_bit <= 1; + end + 4'hC, 4'hD, + 4'hE, 4'hF: // GOLONG, GOVLNG, GOSUBL, GOSBVL + begin + o_alu_no_stall <= 1; + o_alu_op <= i_nibble[0]?`ALU_OP_JMP_ABS5:`ALU_OP_JMP_REL4; + // is it a gosub ? + o_push <= i_nibble[1]; + o_alu_debug <= i_nibble[1]; + mem_load_max <= i_nibble[0]?4:3; + o_mem_pos <= 0; + block_jmp <= 1; + // debug for cases not tested + o_alu_debug <= i_nibble[1] || !i_nibble[0]; + end + default: begin + $display("block_8x %h error", i_nibble); + o_dec_error <= 1; + end + endcase + block_8x <= 0; end + if (do_block_80x) begin + $display("block_80x %h | op %d", i_nibble, o_alu_op); + case (i_nibble) + 4'hC: // C=P n + begin + o_ins_alu_op <= 1; + o_alu_op <= `ALU_OP_COPY; + o_alu_debug <= 1; + next_nibble <= 0; + o_ins_decoded <= 1; + end + default: begin + $display("block_80x %h error", i_nibble); + o_dec_error <= 1; + end + endcase + block_80x <= 0; + end + + // utilities if (do_load_reg_imm) begin @@ -771,11 +877,31 @@ always @(posedge i_clk) begin o_ins_alu_op <= 1; o_imm_value <= i_nibble; o_mem_load[o_mem_pos*4+:4] <= i_nibble; - o_mem_pos <= o_mem_pos + {3'b000, ((o_mem_pos+1) != mem_load_max)}; + o_mem_pos <= o_mem_pos + 1; next_nibble <= (o_mem_pos+1) != mem_load_max; o_ins_decoded <= (o_mem_pos+1) == mem_load_max; end + if (do_block_jmp) begin + $display("do_block_jmp %h", i_nibble); + o_ins_alu_op <= 1; + o_imm_value <= i_nibble; + o_mem_load[o_mem_pos*4+:4] <= i_nibble; + o_mem_pos <= o_mem_pos + 1; + next_nibble <= mem_load_max != o_mem_pos; + o_ins_decoded <= mem_load_max == o_mem_pos; + end + + if (do_block_sr_bit) begin + $display("do_block_sr_bit %h", i_nibble); + o_ins_alu_op <= 1; + o_imm_value <= i_nibble; + o_mem_load[3:0] <= i_nibble; + o_mem_pos <= 1; + next_nibble <= 0; + o_ins_decoded <= 1; + end + end @@ -925,6 +1051,32 @@ always @(posedge i_clk) begin o_reg_dest <= `ALU_REG_C; o_reg_src1 <= `ALU_REG_IMM; end + + if (do_block_8x) begin + case (i_nibble) + 4'h4, 4'h5, 4'h6, 4'h7: begin + o_reg_dest <= `ALU_REG_ST; + o_reg_src1 <= `ALU_REG_IMM; + end + 4'hC, 4'hD, 4'hE, 4'hF: begin + o_reg_dest <= 0; + o_reg_src1 <= `ALU_REG_IMM; + o_reg_src2 <= 0; + end + endcase + end + + if (do_block_80x) begin + case (i_nibble) + 4'hC: begin + o_reg_dest <= `ALU_REG_C; + o_reg_src1 <= `ALU_REG_P; + o_reg_src2 <= 0; + end + endcase + end + + end @@ -1069,6 +1221,24 @@ always @(posedge i_clk) begin o_field_last <= (i_nibble + i_reg_p) & 4'hF; end + if (do_block_8x) begin + case (i_nibble) + 4'hC, 4'hD, 4'hE, 4'hF: begin + o_field_start <= 0; + o_field_last <= i_nibble[3]?4:3; + end + endcase + end + + if (do_block_80x) begin + case (i_nibble) + 4'hC: begin + o_field_start <= i_nibble; + o_field_last <= i_nibble; + end + endcase + end + /****************************************************************************** * * set field from a table diff --git a/testrom-2.hex b/testrom-2.hex index 224592f..775cb3a 100644 --- a/testrom-2.hex +++ b/testrom-2.hex @@ -1,2 +1,2 @@ -3 1 4 5 -6 3 0 0 \ No newline at end of file +3 F 0 1 2 3 4 5 6 7 8 9 A B C D E F +6 3 2 7 // NOP3 \ No newline at end of file