mirror of
https://github.com/sxpert/hp-saturn
synced 2024-11-16 19:50:19 +01:00
finished blocks 1, 2 and 3
This commit is contained in:
parent
c357160ab3
commit
aa1d8efd85
5 changed files with 329 additions and 80 deletions
|
@ -28,11 +28,11 @@
|
|||
`define ALU_OP_DEC 10
|
||||
`define ALU_OP_ADD 11
|
||||
`define ALU_OP_SUB 12
|
||||
`define ALU_OP_ADD_CST 13
|
||||
`define ALU_OP_SUB_CST 14
|
||||
// tests
|
||||
`define ALU_OP_TEST_EQ 15
|
||||
`define ALU_OP_TEST_NEQ 16
|
||||
`define ALU_OP_TEST_EQ 13
|
||||
`define ALU_OP_TEST_NEQ 14
|
||||
// 15
|
||||
// 16
|
||||
|
||||
|
||||
`define ALU_REG_A 0
|
||||
|
@ -57,5 +57,6 @@
|
|||
`define ALU_REG_ST 19
|
||||
`define ALU_REG_P 20
|
||||
`define ALU_REG_M 21
|
||||
`define ALU_REG_IMM 22
|
||||
|
||||
`endif
|
|
@ -21,3 +21,4 @@
|
|||
2019-02-12 22:20 49 112.10MHz 14.34ns 3.64ns 241 171.50MHz 4.55ns 2.33ns
|
||||
2019-02-12 23:27 55 202.72MHz 13.14ns 4.61ns 344 162.63MHz 4.88ns 2.21ns
|
||||
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
|
||||
|
|
|
@ -238,14 +238,11 @@ always @(posedge clk)
|
|||
reg_pc <= reg_pc + 1;
|
||||
`ifdef SIM
|
||||
else
|
||||
$write("\nnot incrementing PC");
|
||||
$write("not incrementing PC\n");
|
||||
`endif
|
||||
end
|
||||
if (en_bus_recv) begin
|
||||
if (!stalled) begin
|
||||
`ifdef SIM
|
||||
$write("%h", rom[reg_pc]);
|
||||
`endif
|
||||
nibble_in <= rom[reg_pc];
|
||||
end
|
||||
end
|
||||
|
|
348
saturn-decoder.v
348
saturn-decoder.v
|
@ -32,9 +32,9 @@ module saturn_decoder(
|
|||
o_field_valid,
|
||||
o_field_start,
|
||||
o_field_last,
|
||||
o_imm_value,
|
||||
|
||||
o_alu_op,
|
||||
|
||||
o_reg_dest,
|
||||
o_reg_src1,
|
||||
o_reg_src2,
|
||||
|
@ -47,7 +47,12 @@ module saturn_decoder(
|
|||
o_carry_val,
|
||||
o_ins_set_mode,
|
||||
o_mode_dec,
|
||||
o_ins_alu_op
|
||||
o_ins_alu_op,
|
||||
|
||||
o_dbg_nibbles,
|
||||
o_dbg_nb_nbls,
|
||||
o_mem_load,
|
||||
o_mem_pos
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -78,6 +83,7 @@ output reg [3:0] o_field;
|
|||
output reg o_field_valid;
|
||||
output reg [3:0] o_field_start;
|
||||
output reg [3:0] o_field_last;
|
||||
output reg [3:0] o_imm_value;
|
||||
|
||||
output reg [4:0] o_alu_op;
|
||||
|
||||
|
@ -102,6 +108,13 @@ output reg o_mode_dec;
|
|||
// alu_operations
|
||||
output reg o_ins_alu_op;
|
||||
|
||||
/* data used by the debugger
|
||||
*
|
||||
*/
|
||||
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;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -109,15 +122,19 @@ output reg o_ins_alu_op;
|
|||
*/
|
||||
|
||||
reg [31:0] instr_ctr;
|
||||
reg [0:0] next_nibble;
|
||||
|
||||
reg inval_opcode_regs;
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef SIM
|
||||
// $monitor({"i_clk %b | i_reset %b | i_cycles %d | i_en_dec %b | i_en_exec %b |",
|
||||
// " continue %b | instr_start %b | i_nibble %h"},
|
||||
// i_clk, i_reset, i_cycles, i_en_dec, i_en_exec, continue,
|
||||
// " next_nibble %b | instr_start %b | i_nibble %h"},
|
||||
// i_clk, i_reset, i_cycles, i_en_dec, i_en_exec, next_nibble,
|
||||
// instr_start, i_nibble);
|
||||
// $monitor("i_en_dec %b | i_cycles %d | nb %h | cont %b | b0x %b | rtn %b | sxm %b | sc %b | cv %b",
|
||||
// i_en_dec, i_cycles, i_nibble, continue, block_0x, ins_rtn, set_xm, set_carry, carry_val);
|
||||
// i_en_dec, i_cycles, i_nibble, next_nibble, block_0x, ins_rtn, set_xm, set_carry, carry_val);
|
||||
`endif
|
||||
end
|
||||
|
||||
|
@ -130,12 +147,31 @@ wire [19:0] new_pc;
|
|||
assign new_pc = i_pc + 1;
|
||||
|
||||
wire run_debugger;
|
||||
assign run_debugger = !i_reset && i_en_dbg && !i_stalled && !continue;
|
||||
assign run_debugger = !i_reset && i_en_dbg && !i_stalled && !next_nibble;
|
||||
|
||||
wire is_short_transfer;
|
||||
assign is_short_transfer = (o_field_last == 3) &&
|
||||
((o_reg_dest[4:1] == 4'b0010) || (o_reg_src1[4:1] == 4'b0010));
|
||||
|
||||
wire p_is_dest;
|
||||
wire is_load_imm;
|
||||
wire is_d0_eq;
|
||||
wire is_d1_eq;
|
||||
wire is_p_eq;
|
||||
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_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;
|
||||
assign is_la_hex = is_load_imm && (o_reg_dest == `ALU_REG_A);
|
||||
assign is_lc_hex = is_load_imm && (o_reg_dest == `ALU_REG_C);
|
||||
assign disp_nb_nibbles = is_d0_eq || is_d1_eq;
|
||||
|
||||
reg [4:0] nibble_pos;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (run_debugger) begin
|
||||
/*
|
||||
|
@ -144,7 +180,16 @@ always @(posedge i_clk) begin
|
|||
*/
|
||||
`ifdef SIM
|
||||
if (o_ins_decoded) begin
|
||||
$write("\n%5h ", o_ins_addr);
|
||||
$write("%5h ", o_ins_addr);
|
||||
|
||||
// $write("[%2d] ", o_dbg_nb_nbls);
|
||||
|
||||
for(nibble_pos=0; nibble_pos!=o_dbg_nb_nbls; nibble_pos=nibble_pos+1)
|
||||
$write("%h", o_dbg_nibbles[nibble_pos*4+:4]);
|
||||
for(nibble_pos=o_dbg_nb_nbls; nibble_pos!=22; nibble_pos=nibble_pos+1)
|
||||
$write(" ");
|
||||
|
||||
// display decoded instruction
|
||||
if (o_ins_rtn) begin
|
||||
$write("RT%s", o_en_intr?"I":"N");
|
||||
if (o_set_xm) $write("SXM");
|
||||
|
@ -159,7 +204,9 @@ always @(posedge i_clk) begin
|
|||
case (o_reg_dest)
|
||||
`ALU_REG_A: $write("A");
|
||||
`ALU_REG_B: $write("B");
|
||||
`ALU_REG_C: $write("C");
|
||||
`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");
|
||||
|
@ -169,6 +216,8 @@ always @(posedge i_clk) begin
|
|||
`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);
|
||||
|
@ -180,7 +229,9 @@ always @(posedge i_clk) begin
|
|||
`ALU_OP_AND,
|
||||
`ALU_OP_OR,
|
||||
`ALU_OP_INC,
|
||||
`ALU_OP_DEC: $write("=");
|
||||
`ALU_OP_DEC,
|
||||
`ALU_OP_ADD,
|
||||
`ALU_OP_SUB: if (!is_lc_hex) $write("=");
|
||||
`ALU_OP_EXCH: begin end
|
||||
default: $write("[op:%d]", o_alu_op);
|
||||
endcase
|
||||
|
@ -191,7 +242,9 @@ always @(posedge i_clk) begin
|
|||
`ALU_OP_AND,
|
||||
`ALU_OP_OR,
|
||||
`ALU_OP_INC,
|
||||
`ALU_OP_DEC:
|
||||
`ALU_OP_DEC,
|
||||
`ALU_OP_ADD,
|
||||
`ALU_OP_SUB:
|
||||
case (o_reg_src1)
|
||||
`ALU_REG_A: $write("A");
|
||||
`ALU_REG_B: $write("B");
|
||||
|
@ -205,13 +258,18 @@ always @(posedge i_clk) begin
|
|||
`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: $write("ST");
|
||||
`ALU_REG_P: $write("P");
|
||||
`ALU_REG_IMM:
|
||||
if (disp_nb_nibbles)
|
||||
if (o_mem_pos < 9) $write("(%1d)", o_mem_pos+1);
|
||||
else $write("(%2d)", o_mem_pos+1);
|
||||
default: $write("[src1:%d]", o_reg_src1);
|
||||
endcase
|
||||
endcase
|
||||
|
||||
|
||||
if ((o_alu_op == `ALU_OP_COPY) && is_short_transfer)
|
||||
$write("S");
|
||||
|
||||
|
@ -220,10 +278,14 @@ always @(posedge i_clk) begin
|
|||
|
||||
case (o_alu_op)
|
||||
`ALU_OP_AND,
|
||||
`ALU_OP_OR: begin
|
||||
`ALU_OP_OR,
|
||||
`ALU_OP_ADD,
|
||||
`ALU_OP_SUB: begin
|
||||
case (o_alu_op)
|
||||
`ALU_OP_AND: $write("&");
|
||||
`ALU_OP_OR: $write("!");
|
||||
`ALU_OP_ADD: $write("+");
|
||||
`ALU_OP_SUB: $write("-");
|
||||
default: $write("[op:%d]", o_alu_op);
|
||||
endcase
|
||||
|
||||
|
@ -233,6 +295,9 @@ always @(posedge i_clk) begin
|
|||
`ALU_REG_C: $write("C");
|
||||
`ALU_REG_D: $write("D");
|
||||
`ALU_REG_RSTK: $write("RSTK");
|
||||
`ALU_REG_IMM:
|
||||
if (o_imm_value < 9) $write("\t%1d", o_imm_value+1);
|
||||
else $write("\t%2d", o_imm_value+1);
|
||||
default: $write("[src2:%d]", o_reg_src2);
|
||||
endcase
|
||||
end
|
||||
|
@ -247,38 +312,52 @@ always @(posedge i_clk) begin
|
|||
// (o_reg_dest == `ALU_REG_ST) || (o_reg_src1 == `ALU_REG_ST ) ||
|
||||
// (o_reg_dest == `ALU_REG_P) || (o_reg_src1 == `ALU_REG_P ))) begin
|
||||
$write("\t");
|
||||
if (o_field_valid)
|
||||
case (o_field)
|
||||
`FT_FIELD_P: $write("P");
|
||||
`FT_FIELD_WP: $write("WP");
|
||||
`FT_FIELD_XS: $write("XS");
|
||||
`FT_FIELD_X: $write("X");
|
||||
`FT_FIELD_S: $write("S");
|
||||
`FT_FIELD_M: $write("M");
|
||||
`FT_FIELD_B: $write("B");
|
||||
`FT_FIELD_W: $write("W");
|
||||
`FT_FIELD_A: $write("A");
|
||||
endcase
|
||||
else
|
||||
$write("[f:%d-%h:%h]", o_field, o_field_start, o_field_last);
|
||||
|
||||
if (o_field_valid) begin
|
||||
// $write("[FT%d]", o_fields_table);
|
||||
if (o_fields_table != `FT_TABLE_value)
|
||||
case (o_field)
|
||||
`FT_FIELD_P: $write("P");
|
||||
`FT_FIELD_WP: $write("WP");
|
||||
`FT_FIELD_XS: $write("XS");
|
||||
`FT_FIELD_X: $write("X");
|
||||
`FT_FIELD_S: $write("S");
|
||||
`FT_FIELD_M: $write("M");
|
||||
`FT_FIELD_B: $write("B");
|
||||
`FT_FIELD_W: $write("W");
|
||||
`FT_FIELD_A: $write("A");
|
||||
endcase
|
||||
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
|
||||
$display("");
|
||||
end
|
||||
end
|
||||
$display("new [%5h]--------------------------------------------------------------------", new_pc);
|
||||
// $display("new [%5h]--------------------------------------------------------------------", new_pc);
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* handle decoding of the fist nibble
|
||||
* that's pretty simple though, will get tougher later on :-)
|
||||
* handles part of the instruction decoding,
|
||||
* acts as the main FSM
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// general variables
|
||||
reg continue;
|
||||
reg use_fields_tbl;
|
||||
|
||||
reg block_0x;
|
||||
|
@ -289,8 +368,9 @@ reg block_rest_from_R_W;
|
|||
reg block_exch_with_R_W;
|
||||
reg block_pointer_assign_exch;
|
||||
reg block_mem_transfer;
|
||||
reg block_pointer_aryth_const;
|
||||
reg block_load_pointer_imm;
|
||||
reg block_pointer_arith_const;
|
||||
reg block_load_p;
|
||||
reg block_load_c_hex;
|
||||
|
||||
reg go_fields_table;
|
||||
|
||||
|
@ -302,8 +382,8 @@ wire do_on_first_nibble;
|
|||
wire do_on_other_nibbles;
|
||||
|
||||
assign decoder_active = !i_reset && i_en_dec && !i_stalled;
|
||||
assign do_on_first_nibble = decoder_active && !continue;
|
||||
assign do_on_other_nibbles = decoder_active && continue;
|
||||
assign do_on_first_nibble = decoder_active && !next_nibble;
|
||||
assign do_on_other_nibbles = decoder_active && next_nibble;
|
||||
|
||||
wire do_block_0x;
|
||||
wire do_block_0Efx;
|
||||
|
@ -314,8 +394,9 @@ wire do_block_exch_with_R_W;
|
|||
wire do_block_Rn_A_C;
|
||||
wire do_block_pointer_assign_exch;
|
||||
wire do_block_mem_transfer;
|
||||
wire do_block_pointer_aryth_const;
|
||||
wire do_block_load_pointer_imm;
|
||||
wire do_block_pointer_arith_const;
|
||||
wire do_block_load_p;
|
||||
wire do_block_load_c_hex;
|
||||
assign do_block_0x = do_on_other_nibbles && block_0x;
|
||||
assign do_block_0Efx = do_on_other_nibbles && block_0Efx;
|
||||
assign do_block_1x = do_on_other_nibbles && block_1x;
|
||||
|
@ -328,22 +409,35 @@ assign do_block_Rn_A_C = do_on_other_nibbles &&
|
|||
block_exch_with_R_W );
|
||||
assign do_block_pointer_assign_exch = do_on_other_nibbles && block_pointer_assign_exch;
|
||||
assign do_block_mem_transfer = do_on_other_nibbles && block_mem_transfer;
|
||||
assign do_block_pointer_aryth_const = do_on_other_nibbles && block_pointer_aryth_const;
|
||||
assign do_block_load_pointer_imm = do_on_other_nibbles && block_load_pointer_imm;
|
||||
assign do_block_pointer_arith_const = do_on_other_nibbles && block_pointer_arith_const;
|
||||
//assign do_block_load_pointer_imm = do_on_other_nibbles && block_load_pointer_imm;
|
||||
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;
|
||||
|
||||
reg block_load_reg_imm;
|
||||
wire do_load_reg_imm;
|
||||
assign do_load_reg_imm = do_on_other_nibbles && block_load_reg_imm;
|
||||
|
||||
wire in_fields_table;
|
||||
assign in_fields_table = go_fields_table && !fields_table_done;
|
||||
|
||||
/*
|
||||
* variables specific to a particular use
|
||||
*/
|
||||
|
||||
reg [4:0] mem_load_max;
|
||||
|
||||
/* most instructions are groupped by sets of 4 with
|
||||
* varrying series of registers that are common
|
||||
* this generates all the required series from i_nibble
|
||||
*/
|
||||
|
||||
wire [4:0] dbg_write_pos;
|
||||
assign dbg_write_pos = (!next_nibble?0:o_dbg_nb_nbls);
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
continue <= 0;
|
||||
next_nibble <= 0;
|
||||
use_fields_tbl <= 0;
|
||||
o_inc_pc <= 1;
|
||||
o_dec_error <= 0;
|
||||
|
@ -355,14 +449,16 @@ always @(posedge i_clk) begin
|
|||
/*
|
||||
* stuff that is always done
|
||||
*/
|
||||
o_inc_pc <= 1; // may be set to 0 later
|
||||
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
|
||||
|
||||
/*
|
||||
* cleanup
|
||||
*/
|
||||
if (do_on_first_nibble) begin
|
||||
continue <= 1;
|
||||
next_nibble <= 1;
|
||||
use_fields_tbl <= 0;
|
||||
|
||||
o_push <= 0;
|
||||
|
@ -381,8 +477,11 @@ always @(posedge i_clk) begin
|
|||
block_exch_with_R_W <= 0;
|
||||
block_pointer_assign_exch <= 0;
|
||||
block_mem_transfer <= 0;
|
||||
block_pointer_aryth_const <= 0;
|
||||
block_load_pointer_imm <= 0;
|
||||
block_pointer_arith_const <= 0;
|
||||
block_load_p <= 0;
|
||||
block_load_c_hex <= 0;
|
||||
|
||||
block_load_reg_imm <= 0;
|
||||
|
||||
// cleanup fields table variables
|
||||
go_fields_table <= 0;
|
||||
|
@ -406,14 +505,19 @@ always @(posedge i_clk) begin
|
|||
|
||||
o_ins_alu_op <= 0;
|
||||
|
||||
o_dbg_nb_nbls <= 1;
|
||||
o_mem_pos <= 0;
|
||||
|
||||
/*
|
||||
* x first nibble
|
||||
*/
|
||||
|
||||
// assign block regs
|
||||
case (i_nibble)
|
||||
4'h0: block_0x <= 1;
|
||||
4'h1: block_1x <= 1;
|
||||
4'h0: block_0x <= 1;
|
||||
4'h1: block_1x <= 1;
|
||||
4'h2: block_load_p <= 1;
|
||||
4'h3: block_load_c_hex <= 1;
|
||||
default: begin
|
||||
`ifdef SIM
|
||||
$display("new_instruction: nibble %h not handled", i_nibble);
|
||||
|
@ -456,7 +560,7 @@ always @(posedge i_clk) begin
|
|||
* C=RSTK
|
||||
* those 2 are alu copy ops between RSTK and C
|
||||
*/
|
||||
4'h6, 6'h7: begin
|
||||
4'h6, 4'h7: begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_COPY;
|
||||
o_push <= !i_nibble[0];
|
||||
|
@ -489,7 +593,7 @@ always @(posedge i_clk) begin
|
|||
o_dec_error <= 1;
|
||||
end
|
||||
endcase
|
||||
continue <= (i_nibble == 4'hE);
|
||||
next_nibble <= (i_nibble == 4'hE);
|
||||
block_0Efx <= (i_nibble == 4'hE);
|
||||
go_fields_table <= (i_nibble == 4'hE);
|
||||
o_ins_decoded <= (i_nibble != 4'hE);
|
||||
|
@ -504,7 +608,7 @@ always @(posedge i_clk) begin
|
|||
if (do_block_0Efx && !in_fields_table) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= (!i_nibble[3])?`ALU_OP_AND:`ALU_OP_OR;
|
||||
continue <= 0;
|
||||
next_nibble <= 0;
|
||||
o_ins_decoded <= 1;
|
||||
end
|
||||
|
||||
|
@ -527,12 +631,21 @@ always @(posedge i_clk) begin
|
|||
block_pointer_assign_exch <= 1;
|
||||
4'h4, 4'h5: begin
|
||||
block_mem_transfer <= 1;
|
||||
use_fields_tbl <= i_nibble[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
|
||||
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
|
||||
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_op <= `ALU_OP_COPY;
|
||||
end
|
||||
4'h6, 4'h7, 4'h8, 4'hC:
|
||||
block_pointer_aryth_const <= 1;
|
||||
4'h9, 4'hA, 4'hB, 4'hD, 4'hE, 4'hF:
|
||||
block_load_pointer_imm <= 1;
|
||||
endcase
|
||||
block_1x <= 0;
|
||||
end
|
||||
|
@ -540,7 +653,7 @@ always @(posedge i_clk) begin
|
|||
if (do_block_save_to_R_W || do_block_rest_from_R_W) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_COPY;
|
||||
continue <= 0;
|
||||
next_nibble <= 0;
|
||||
o_ins_decoded <= 1;
|
||||
block_save_to_R_W <= 0;
|
||||
block_rest_from_R_W <= 0;
|
||||
|
@ -549,31 +662,63 @@ always @(posedge i_clk) begin
|
|||
if (do_block_exch_with_R_W) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_EXCH;
|
||||
continue <= 0;
|
||||
next_nibble <= 0;
|
||||
o_ins_decoded <= 1;
|
||||
end
|
||||
|
||||
if (do_block_pointer_assign_exch) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= i_nibble[1]?`ALU_OP_EXCH:`ALU_OP_COPY;
|
||||
continue <= 0;
|
||||
next_nibble <= 0;
|
||||
o_ins_decoded <= 1;
|
||||
end
|
||||
|
||||
if (do_block_mem_transfer) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_COPY;
|
||||
o_fields_table <= i_nibble[3]?`FT_TABLE_value:`FT_TABLE_a;
|
||||
// we continue if we need the fields table (nibble2 was 5)
|
||||
// we next_nibble if we need the fields table (nibble2 was 5)
|
||||
go_fields_table <= use_fields_tbl;
|
||||
continue <= use_fields_tbl;
|
||||
o_ins_decoded <= !use_fields_tbl;
|
||||
next_nibble <= use_fields_tbl;
|
||||
use_fields_tbl <= 0;
|
||||
o_ins_decoded <= !(use_fields_tbl);
|
||||
end
|
||||
|
||||
if (do_block_pointer_aryth_const) begin
|
||||
if (do_block_pointer_arith_const) begin
|
||||
next_nibble <= 0;
|
||||
o_imm_value <= i_nibble;
|
||||
o_ins_decoded <= 1;
|
||||
end
|
||||
|
||||
if (do_block_load_pointer_imm) begin
|
||||
if (do_block_load_p) begin
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_COPY;
|
||||
o_imm_value <= i_nibble;
|
||||
next_nibble <= 0;
|
||||
o_ins_decoded <= 1;
|
||||
end
|
||||
|
||||
if (do_block_load_c_hex) begin
|
||||
// $write("block load C hex %h\n", i_nibble);
|
||||
mem_load_max <= i_nibble + 1;
|
||||
o_mem_pos <= 0;
|
||||
o_ins_alu_op <= 1;
|
||||
o_alu_op <= `ALU_OP_COPY;
|
||||
block_load_reg_imm <= 1;
|
||||
block_load_c_hex <= 0;
|
||||
end
|
||||
|
||||
// utilities
|
||||
|
||||
if (do_load_reg_imm) begin
|
||||
// $write("load reg imm %h | ", i_nibble);
|
||||
// $write("pos %d | max %d | ", o_mem_pos, mem_load_max);
|
||||
// $write("next %b | dec %b | ", (o_mem_pos+1) != mem_load_max, (o_mem_pos+1) == mem_load_max);
|
||||
// $write("\n");
|
||||
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)};
|
||||
next_nibble <= (o_mem_pos+1) != mem_load_max;
|
||||
o_ins_decoded <= (o_mem_pos+1) == mem_load_max;
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -605,16 +750,18 @@ assign reg_A_C = { 3'b000, i_nibble[2], 1'b0};
|
|||
always @(posedge i_clk) begin
|
||||
|
||||
if (i_reset) begin
|
||||
o_reg_dest <= 0;
|
||||
o_reg_src1 <= 0;
|
||||
o_reg_src2 <= 0;
|
||||
o_reg_dest <= 0;
|
||||
o_reg_src1 <= 0;
|
||||
o_reg_src2 <= 0;
|
||||
inval_opcode_regs <= 0;
|
||||
end
|
||||
|
||||
if (do_on_first_nibble) begin
|
||||
// reset values on instruction decode start
|
||||
o_reg_dest <= 0;
|
||||
o_reg_src1 <= 0;
|
||||
o_reg_src2 <= 0;
|
||||
o_reg_dest <= 0;
|
||||
o_reg_src1 <= 0;
|
||||
o_reg_src2 <= 0;
|
||||
inval_opcode_regs <= 0;
|
||||
end
|
||||
|
||||
|
||||
|
@ -647,6 +794,9 @@ always @(posedge i_clk) begin
|
|||
o_reg_dest <= `ALU_REG_P;
|
||||
o_reg_src1 <= `ALU_REG_P;
|
||||
end
|
||||
default: begin
|
||||
// inval_opcode_regs <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -656,6 +806,28 @@ always @(posedge i_clk) begin
|
|||
o_reg_src2 <= i_nibble[2]?reg_ABCD:reg_BCAC;
|
||||
end
|
||||
|
||||
if (do_block_1x) begin
|
||||
case (i_nibble)
|
||||
4'h6, 4'h8: begin
|
||||
o_reg_dest <= `ALU_REG_D0;
|
||||
o_reg_src1 <= `ALU_REG_D0;
|
||||
end
|
||||
4'h7, 4'hC: begin
|
||||
o_reg_dest <= `ALU_REG_D1;
|
||||
o_reg_src1 <= `ALU_REG_D1;
|
||||
end
|
||||
4'h9, 4'hA, 4'hB: begin
|
||||
o_reg_dest <= `ALU_REG_D0;
|
||||
o_reg_src1 <= `ALU_REG_IMM;
|
||||
end
|
||||
4'hD, 4'hE, 4'hF: begin
|
||||
o_reg_dest <= `ALU_REG_D1;
|
||||
o_reg_src1 <= `ALU_REG_IMM;
|
||||
end
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (do_block_save_to_R_W) begin
|
||||
o_reg_dest <= {2'b01, i_nibble[2:0]};
|
||||
o_reg_src1 <= {3'b000, i_nibble[3]?2'b10:2'b00};
|
||||
|
@ -676,6 +848,19 @@ always @(posedge i_clk) begin
|
|||
o_reg_src1 <= i_nibble[1]?reg_DAT0DAT1:reg_A_C;
|
||||
end
|
||||
|
||||
if (do_block_pointer_arith_const) begin
|
||||
o_reg_src2 <= `ALU_REG_IMM;
|
||||
end
|
||||
|
||||
if (do_block_load_p) begin
|
||||
o_reg_dest <= `ALU_REG_P;
|
||||
o_reg_src1 <= `ALU_REG_IMM;
|
||||
end
|
||||
|
||||
if (do_block_load_c_hex) begin
|
||||
o_reg_dest <= `ALU_REG_C;
|
||||
o_reg_src1 <= `ALU_REG_IMM;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -760,6 +945,7 @@ always @(posedge i_clk) begin
|
|||
o_field_start <= 0;
|
||||
o_field_last <= 3;
|
||||
end
|
||||
default: begin end // don't care
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -773,6 +959,24 @@ always @(posedge i_clk) begin
|
|||
o_field_last <= i_nibble[3]?3:4;
|
||||
end
|
||||
|
||||
if (do_block_mem_transfer && !do_fields_table) begin
|
||||
o_field <= i_nibble[3]?`FT_FIELD_B:`FT_FIELD_A;
|
||||
o_field_start <= 0;
|
||||
o_field_last <= i_nibble[3]?1:4;
|
||||
o_field_valid <= 1;
|
||||
end
|
||||
|
||||
if (do_block_mem_transfer && do_fields_table && table_value) begin
|
||||
o_field_start <= 0;
|
||||
o_field_last <= i_nibble;
|
||||
o_field_valid <= 1;
|
||||
end
|
||||
|
||||
if (do_block_pointer_arith_const) begin
|
||||
o_field_start <= 0;
|
||||
o_field_last <= 4;
|
||||
end
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* set field from a table
|
||||
|
@ -789,7 +993,7 @@ always @(posedge i_clk) begin
|
|||
$display("table_f_cond: %b", table_f_cond);
|
||||
$display("table_f : %b", table_f_nb_ok);
|
||||
// $display("table_f nbl : %h", {4{o_fields_table == `FT_TABLE_f}} );
|
||||
$display("table_f val : %h", table_f_nibble_value);
|
||||
//$display("table_f val : %h", table_f_nibble_value);
|
||||
$display("case nibble : %h", table_a_f_b_case_value);
|
||||
end
|
||||
`endif
|
||||
|
@ -870,12 +1074,12 @@ always @(posedge i_clk) begin
|
|||
$display("fields_table: field A");
|
||||
`endif
|
||||
end
|
||||
`ifdef SIM
|
||||
default: begin
|
||||
o_dec_error <= 1;
|
||||
`ifdef SIM
|
||||
$display("fields_table: table %h nibble %h not handled", o_fields_table, i_nibble);
|
||||
`endif
|
||||
end
|
||||
`endif
|
||||
endcase
|
||||
o_field_valid <= 1;
|
||||
fields_table_done <= 1;
|
||||
|
|
46
testrom.hex
46
testrom.hex
|
@ -111,4 +111,50 @@
|
|||
1 4 E // C=DAT0 B
|
||||
1 4 F // C=DAT1 B
|
||||
|
||||
1 5 0 0 // DAT0=A a
|
||||
1 5 1 1 // DAT1=A a
|
||||
1 5 2 2 // A=DAT0 a
|
||||
1 5 3 3 // A=DAT1 a
|
||||
1 5 4 4 // DAT0=C a
|
||||
1 5 5 5 // DAT1=C a
|
||||
1 5 6 6 // C=DAT0 a
|
||||
1 5 7 7 // C=DAT1 a
|
||||
1 5 8 8 // DAT0=A x+1
|
||||
1 5 9 9 // DAT1=A x+1
|
||||
1 5 A A // A=DAT0 x+1
|
||||
1 5 B B // A=DAT1 x+1
|
||||
1 5 C C // DAT0=C x+1
|
||||
1 5 D D // DAT1=C x+1
|
||||
1 5 E E // C=DAT0 x+1
|
||||
1 5 F F // C=DAT1 x+1
|
||||
|
||||
// pointer arithmetic
|
||||
|
||||
1 6 2 // D0=D0+ n+1
|
||||
1 7 8 // D1=D1+ n+1
|
||||
1 8 A // D0=D0- n+1
|
||||
1 C F // D1=D1- n+1
|
||||
|
||||
// pointer load
|
||||
|
||||
1 9 1 2 // D0=(2) 21
|
||||
1 A 3 4 5 6 // D0=(4) 6543
|
||||
1 B 7 8 9 A B // D0=(5) BA987
|
||||
|
||||
1 D 1 2 // D1=(2) 21
|
||||
1 E 3 4 5 6 // D1=(4) 6543
|
||||
1 F 7 8 9 A B // D1=(5) BA987
|
||||
|
||||
// load P with immediate value
|
||||
|
||||
2 3 // P= 3
|
||||
|
||||
// load c with immediate value
|
||||
// start on nibble pointed by p
|
||||
|
||||
3 5 0 1 2 3 4 5
|
||||
3 F 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
|
||||
|
||||
|
||||
F // end
|
Loading…
Reference in a new issue