mirror of
https://github.com/sxpert/hp-saturn
synced 2024-09-28 15:20:27 +02:00
alu coming up nicely, decoder gaining weight
This commit is contained in:
parent
f076cf6fb9
commit
fd69407de0
6 changed files with 465 additions and 150 deletions
26
def-alu.v
26
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
228
saturn-alu.v
228
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
324
saturn-decoder.v
324
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] <field>
|
||||
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]) <stuff>
|
||||
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
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
3 1 4 5
|
||||
6 3 0 0
|
||||
3 F 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
6 3 2 7 // NOP3
|
Loading…
Reference in a new issue