mirror of
https://github.com/sxpert/hp-saturn
synced 2025-01-19 10:26:58 +01:00
separate the decoder in multiple files, it was becoming unwiedly ;-)
This commit is contained in:
parent
1f01d9bdb9
commit
25385115e0
7 changed files with 902 additions and 906 deletions
51
history.txt
51
history.txt
|
@ -1,27 +1,28 @@
|
||||||
cells speed 1 delay (a) 1 delay 1 arcs speed 2 delay (a) 2 delay 2
|
cells speed 1 delay (a) 1 delay 1 arcs speed 2 delay (a) 2 delay 2
|
||||||
2019-02-12 07:37 29 490.92MHz 2.68ns 330.14MHz 1.99ns
|
2019-02-12 07:37 29 490.92MHz 2.68ns 330.14MHz 1.99ns
|
||||||
2019-02-12 07:48 29 490.92MHz 14.34ns 2.20ns 350.39MHz 4.14ns 1.77ns
|
2019-02-12 07:48 29 490.92MHz 14.34ns 2.20ns 350.39MHz 4.14ns 1.77ns
|
||||||
2019-02-12 08:22 29 490.92MHz 14.34ns 2.68ns 330.58MHz 4.71ns 1.84ns
|
2019-02-12 08:22 29 490.92MHz 14.34ns 2.68ns 330.58MHz 4.71ns 1.84ns
|
||||||
2019-02-12 08:39 29 490.92MHz 14.10ns 3.16ns 96 335.35MHz 4.46ns 1.93ns
|
2019-02-12 08:39 29 490.92MHz 14.10ns 3.16ns 96 335.35MHz 4.46ns 1.93ns
|
||||||
2019-02-12 08:48 29 490.92MHz 14.10ns 3.16ns 96 335.35MHz 4.46ns 1.93ns
|
2019-02-12 08:48 29 490.92MHz 14.10ns 3.16ns 96 335.35MHz 4.46ns 1.93ns
|
||||||
2019-02-12 11:11 29 490.92MHz 14.58ns 2.44ns 96 330.03MHz 4.74ns 2.04ns
|
2019-02-12 11:11 29 490.92MHz 14.58ns 2.44ns 96 330.03MHz 4.74ns 2.04ns
|
||||||
2019-02-12 12:15 29 468.38MHz 14.34ns 2.68ns 96 330.58MHz 4.74ns 1.97ns
|
2019-02-12 12:15 29 468.38MHz 14.34ns 2.68ns 96 330.58MHz 4.74ns 1.97ns
|
||||||
2019-02-12 12:48 48 242.95MHz 13.38ns 2.92ns 240 162.44MHz 4.13ns 2.05ns
|
2019-02-12 12:48 48 242.95MHz 13.38ns 2.92ns 240 162.44MHz 4.13ns 2.05ns
|
||||||
2019-02-12 13:25 48 165.54MHz 14.58ns 3.64ns 240 176.46MHz 4.75ns 2.06ns
|
2019-02-12 13:25 48 165.54MHz 14.58ns 3.64ns 240 176.46MHz 4.75ns 2.06ns
|
||||||
2019-02-12 13:28 48 142.84MHz 14.34ns 3.40ns 240 168.21MHz 4.71ns 2.31ns
|
2019-02-12 13:28 48 142.84MHz 14.34ns 3.40ns 240 168.21MHz 4.71ns 2.31ns
|
||||||
2019-02-12 13:38 55 196.93MHz 14.58ns 3.16ns 343 166.53MHz 4.43ns 2.06ns
|
2019-02-12 13:38 55 196.93MHz 14.58ns 3.16ns 343 166.53MHz 4.43ns 2.06ns
|
||||||
2019-02-12 14:51 50 84.74MHz 13.38ns 3.88ns 271 170.13MHz 4.15ns 2.35ns
|
2019-02-12 14:51 50 84.74MHz 13.38ns 3.88ns 271 170.13MHz 4.15ns 2.35ns
|
||||||
2019-02-12 15:10 50 84.74MHz 13.38ns 3.88ns 271 170.13MHz 4.15ns 2.35ns
|
2019-02-12 15:10 50 84.74MHz 13.38ns 3.88ns 271 170.13MHz 4.15ns 2.35ns
|
||||||
2019-02-12 15:39 50 75.52MHz 12.90ns 5.09ns 271 166.53MHz 4.14ns 2.55ns
|
2019-02-12 15:39 50 75.52MHz 12.90ns 5.09ns 271 166.53MHz 4.14ns 2.55ns
|
||||||
2019-02-12 16:04 48 112.10MHz 14.34ns 2.92ns 241 163.99MHz 4.72ns 2.00ns
|
2019-02-12 16:04 48 112.10MHz 14.34ns 2.92ns 241 163.99MHz 4.72ns 2.00ns
|
||||||
2019-02-12 17:27 56 142.90MHz 14.34ns 3.40ns 345 160.03MHz 4.95ns 2.25ns
|
2019-02-12 17:27 56 142.90MHz 14.34ns 3.40ns 345 160.03MHz 4.95ns 2.25ns
|
||||||
2019-02-12 18:00 51 213.36MHz 13.98ns 2.92ns 273 165.43MHz 4.78ns 2.05ns
|
2019-02-12 18:00 51 213.36MHz 13.98ns 2.92ns 273 165.43MHz 4.78ns 2.05ns
|
||||||
2019-02-12 22:07 49 112.10MHz 14.58ns 3.16ns 241 168.95MHz 4.74ns 1.93ns
|
2019-02-12 22:07 49 112.10MHz 14.58ns 3.16ns 241 168.95MHz 4.74ns 1.93ns
|
||||||
2019-02-12 22:12 51 138.10MHz 15.06ns 2.92ns 273 154.61MHz 4.78ns 2.00ns
|
2019-02-12 22:12 51 138.10MHz 15.06ns 2.92ns 273 154.61MHz 4.78ns 2.00ns
|
||||||
2019-02-12 22:20 49 112.10MHz 14.34ns 3.64ns 241 171.50MHz 4.55ns 2.33ns
|
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-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 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 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-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
|
2019-02-14 09:00 353 118.23MHz 26.00ns 12.28ns 3334 119.40MHz 10.08ns 3.84ns
|
||||||
2019-02-14 22:11 403 115.09Mhz 27.38ns 11.32ns 2430 111.51Mhz 12.62ns 3.57ns
|
2019-02-14 22:11 403 115.09MHz 27.38ns 11.32ns 2430 111.51MHz 12.62ns 3.57ns
|
||||||
|
2019-02-15 07:14 535 97.16MHz 26.57ns 9.16ns 3073 96.10MHz 13.38ns 3.13ns
|
|
@ -105,7 +105,6 @@ saturn_decoder m_decoder (
|
||||||
.o_reg_src1 (reg_src1),
|
.o_reg_src1 (reg_src1),
|
||||||
.o_reg_src2 (reg_src2),
|
.o_reg_src2 (reg_src2),
|
||||||
|
|
||||||
.o_direction (direction),
|
|
||||||
.o_ins_rtn (ins_rtn),
|
.o_ins_rtn (ins_rtn),
|
||||||
.o_set_xm (set_xm),
|
.o_set_xm (set_xm),
|
||||||
.o_set_carry (set_carry),
|
.o_set_carry (set_carry),
|
||||||
|
@ -136,7 +135,6 @@ wire [4:0] reg_dest;
|
||||||
wire [4:0] reg_src1;
|
wire [4:0] reg_src1;
|
||||||
wire [4:0] reg_src2;
|
wire [4:0] reg_src2;
|
||||||
|
|
||||||
wire direction;
|
|
||||||
wire ins_rtn;
|
wire ins_rtn;
|
||||||
wire set_xm;
|
wire set_xm;
|
||||||
wire set_carry;
|
wire set_carry;
|
||||||
|
@ -278,7 +276,7 @@ always @(posedge clk) begin
|
||||||
en_inst_exec <= 0;
|
en_inst_exec <= 0;
|
||||||
clock_end <= 0;
|
clock_end <= 0;
|
||||||
cycle_ctr <= ~0;
|
cycle_ctr <= ~0;
|
||||||
max_cycle <= 100;
|
max_cycle <= 140;
|
||||||
`ifndef SIM
|
`ifndef SIM
|
||||||
led[7:0] <= reg_pc[7:0];
|
led[7:0] <= reg_pc[7:0];
|
||||||
`endif
|
`endif
|
||||||
|
|
893
saturn_decoder.v
893
saturn_decoder.v
|
@ -8,57 +8,31 @@
|
||||||
`include "def-alu.v"
|
`include "def-alu.v"
|
||||||
|
|
||||||
module saturn_decoder(
|
module saturn_decoder(
|
||||||
i_clk,
|
i_clk, i_reset, i_cycles, i_en_dbg, i_en_dec, i_stalled,
|
||||||
i_reset,
|
i_pc, i_nibble,
|
||||||
i_cycles,
|
|
||||||
i_en_dbg,
|
|
||||||
i_en_dec,
|
|
||||||
i_stalled,
|
|
||||||
i_pc,
|
|
||||||
i_nibble,
|
|
||||||
|
|
||||||
i_reg_p,
|
i_reg_p,
|
||||||
|
|
||||||
o_inc_pc,
|
o_inc_pc, o_push, o_pop,
|
||||||
o_push,
|
|
||||||
o_pop,
|
|
||||||
o_dec_error,
|
o_dec_error,
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
o_unimplemented,
|
o_unimplemented,
|
||||||
`endif
|
`endif
|
||||||
o_alu_debug,
|
o_alu_debug,
|
||||||
|
|
||||||
o_ins_addr,
|
o_ins_addr, o_ins_decoded,
|
||||||
o_ins_decoded,
|
|
||||||
|
|
||||||
o_fields_table,
|
o_fields_table, o_field, o_field_valid, o_field_start, o_field_last,
|
||||||
o_field,
|
|
||||||
o_field_valid,
|
|
||||||
o_field_start,
|
|
||||||
o_field_last,
|
|
||||||
o_imm_value,
|
o_imm_value,
|
||||||
|
|
||||||
o_alu_op,
|
o_alu_op, o_alu_no_stall, o_reg_dest, o_reg_src1, o_reg_src2,
|
||||||
o_alu_no_stall,
|
|
||||||
o_reg_dest,
|
|
||||||
o_reg_src1,
|
|
||||||
o_reg_src2,
|
|
||||||
|
|
||||||
o_direction,
|
o_ins_rtn, o_set_xm, o_en_intr,
|
||||||
o_ins_rtn,
|
o_set_carry, o_test_carry, o_carry_val,
|
||||||
o_set_xm,
|
o_ins_set_mode, o_mode_dec,
|
||||||
o_set_carry,
|
|
||||||
o_en_intr,
|
|
||||||
o_test_carry,
|
|
||||||
o_carry_val,
|
|
||||||
o_ins_set_mode,
|
|
||||||
o_mode_dec,
|
|
||||||
o_ins_alu_op,
|
o_ins_alu_op,
|
||||||
|
|
||||||
o_dbg_nibbles,
|
o_dbg_nibbles, o_dbg_nb_nbls, o_mem_load, o_mem_pos
|
||||||
o_dbg_nb_nbls,
|
|
||||||
o_mem_load,
|
|
||||||
o_mem_pos
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -101,9 +75,6 @@ output reg [4:0] o_reg_dest;
|
||||||
output reg [4:0] o_reg_src1;
|
output reg [4:0] o_reg_src1;
|
||||||
output reg [4:0] o_reg_src2;
|
output reg [4:0] o_reg_src2;
|
||||||
|
|
||||||
// generic
|
|
||||||
output reg o_direction;
|
|
||||||
|
|
||||||
// rtn specific
|
// rtn specific
|
||||||
output reg o_ins_rtn;
|
output reg o_ins_rtn;
|
||||||
output reg o_set_xm;
|
output reg o_set_xm;
|
||||||
|
@ -150,262 +121,7 @@ initial begin
|
||||||
`endif
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
`include "saturn_decoder_debugger.v"
|
||||||
* debugger
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
wire [19:0] new_pc;
|
|
||||||
assign new_pc = i_pc + 1;
|
|
||||||
|
|
||||||
wire run_debugger;
|
|
||||||
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_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;
|
|
||||||
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
|
|
||||||
/*
|
|
||||||
* this whole thing is a large print statement
|
|
||||||
* THIS PART IS NEVER GENERATED
|
|
||||||
*/
|
|
||||||
`ifdef SIM
|
|
||||||
if (o_ins_decoded) begin
|
|
||||||
$write("DBG[%5d]: ", inst_counter);
|
|
||||||
$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");
|
|
||||||
if (o_set_carry) $write("%sC", o_carry_val?"S":"C");
|
|
||||||
end
|
|
||||||
if (o_ins_set_mode) begin
|
|
||||||
$write("SET%s", o_mode_dec?"DEC":"HEX");
|
|
||||||
end
|
|
||||||
if (o_ins_alu_op) begin
|
|
||||||
|
|
||||||
case (o_alu_op)
|
|
||||||
`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");
|
|
||||||
`ALU_OP_CLR_MASK:
|
|
||||||
case (o_reg_dest)
|
|
||||||
`ALU_REG_HST:
|
|
||||||
case (o_imm_value)
|
|
||||||
4'h1: $write("XM=0");
|
|
||||||
4'h2: $write("SB=0");
|
|
||||||
4'h4: $write("SR=0");
|
|
||||||
4'h8: $write("MP=0");
|
|
||||||
default: begin
|
|
||||||
$write("CLRHST");
|
|
||||||
if (o_imm_value != 4'hF) $write("\t%1h", o_imm_value);
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
default: $write("[VLR_MASK dest:%0d]", o_reg_dest);
|
|
||||||
endcase
|
|
||||||
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:%0d]", 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,
|
|
||||||
`ALU_OP_RST_BIT,
|
|
||||||
`ALU_OP_SET_BIT: if (!is_lc_hex)
|
|
||||||
$write("=");
|
|
||||||
`ALU_OP_2CMPL: $write("=-");
|
|
||||||
`ALU_OP_EXCH,
|
|
||||||
`ALU_OP_JMP_REL3,
|
|
||||||
`ALU_OP_JMP_REL4,
|
|
||||||
`ALU_OP_JMP_ABS5,
|
|
||||||
`ALU_OP_CLR_MASK: begin end
|
|
||||||
default: $write("[op:%0d]", o_alu_op);
|
|
||||||
endcase
|
|
||||||
|
|
||||||
case (o_alu_op)
|
|
||||||
`ALU_OP_COPY,
|
|
||||||
`ALU_OP_EXCH,
|
|
||||||
`ALU_OP_AND,
|
|
||||||
`ALU_OP_OR,
|
|
||||||
`ALU_OP_INC,
|
|
||||||
`ALU_OP_DEC,
|
|
||||||
`ALU_OP_ADD,
|
|
||||||
`ALU_OP_SUB,
|
|
||||||
`ALU_OP_2CMPL:
|
|
||||||
case (o_reg_src1)
|
|
||||||
`ALU_REG_A: $write("A");
|
|
||||||
`ALU_REG_B: $write("B");
|
|
||||||
`ALU_REG_C: $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: $write("ST");
|
|
||||||
`ALU_REG_P: $write("P");
|
|
||||||
`ALU_REG_IMM:
|
|
||||||
if (disp_nb_nibbles) $write("(%0d)", o_mem_pos);
|
|
||||||
`ALU_REG_ZERO: $write("0");
|
|
||||||
default: $write("[src1:%0d]", 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)
|
|
||||||
$write("S");
|
|
||||||
|
|
||||||
if (o_alu_op == `ALU_OP_EXCH)
|
|
||||||
$write("%s", is_short_transfer?"XS":"EX");
|
|
||||||
|
|
||||||
case (o_alu_op)
|
|
||||||
`ALU_OP_AND,
|
|
||||||
`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:%0d]", o_alu_op);
|
|
||||||
endcase
|
|
||||||
|
|
||||||
case (o_reg_src2)
|
|
||||||
`ALU_REG_A: $write("A");
|
|
||||||
`ALU_REG_B: $write("B");
|
|
||||||
`ALU_REG_C: $write("C");
|
|
||||||
`ALU_REG_D: $write("D");
|
|
||||||
`ALU_REG_RSTK: $write("RSTK");
|
|
||||||
`ALU_REG_IMM: $write("\t%0d", o_imm_value+1);
|
|
||||||
default: $write("[src2:%0d]", o_reg_src2);
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
`ALU_OP_INC: $write("+1");
|
|
||||||
`ALU_OP_DEC: $write("-1");
|
|
||||||
`ALU_OP_ZERO,
|
|
||||||
`ALU_OP_COPY,
|
|
||||||
`ALU_OP_EXCH: begin end
|
|
||||||
endcase
|
|
||||||
|
|
||||||
// if (!((o_reg_dest == `ALU_REG_RSTK) || (o_reg_src1 == `ALU_REG_RSTK) ||
|
|
||||||
// (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) 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 $write("%0d", o_field_last+1);
|
|
||||||
end else begin
|
|
||||||
// $write("@%b@", is_load_imm);
|
|
||||||
if (is_load_imm) begin
|
|
||||||
if (is_p_eq) $write("%0d", o_imm_value);
|
|
||||||
else
|
|
||||||
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
|
|
||||||
else
|
|
||||||
case (o_reg_dest)
|
|
||||||
`ALU_REG_P,
|
|
||||||
`ALU_REG_ST,
|
|
||||||
`ALU_REG_HST: begin end
|
|
||||||
`ALU_REG_C:
|
|
||||||
if (o_reg_src1 == `ALU_REG_P)
|
|
||||||
$write("%0d", o_field_start);
|
|
||||||
default: $write("[%h:%h]", o_field_start, o_field_last);
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$write("\t(%0d cycles)", inst_cycles);
|
|
||||||
if (o_unimplemented)
|
|
||||||
$write("\t%C[1,31mUNIMPLEMENTED%C[0m", 27, 27);
|
|
||||||
$write("\n");
|
|
||||||
end
|
|
||||||
// $display("new [%5h]--------------------------------------------------------------------", new_pc);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -417,36 +133,6 @@ end
|
||||||
// general variables
|
// general variables
|
||||||
reg use_fields_tbl;
|
reg use_fields_tbl;
|
||||||
|
|
||||||
reg block_0x;
|
|
||||||
reg block_0Efx;
|
|
||||||
reg block_1x;
|
|
||||||
reg block_save_to_R_W;
|
|
||||||
reg block_rest_from_R_W;
|
|
||||||
reg block_exch_with_R_W;
|
|
||||||
reg block_pointer_assign_exch;
|
|
||||||
reg block_mem_transfer;
|
|
||||||
reg block_pointer_arith_const;
|
|
||||||
reg block_load_p;
|
|
||||||
reg block_load_c_hex;
|
|
||||||
reg block_jmp2_cry_set;
|
|
||||||
reg block_jmp2_cry_clr;
|
|
||||||
|
|
||||||
reg block_8x;
|
|
||||||
reg block_80x;
|
|
||||||
reg block_80Cx;
|
|
||||||
reg block_82x;
|
|
||||||
|
|
||||||
reg block_Ax;
|
|
||||||
reg block_Aax;
|
|
||||||
reg block_Abx;
|
|
||||||
|
|
||||||
reg block_Fx;
|
|
||||||
|
|
||||||
reg go_fields_table;
|
|
||||||
|
|
||||||
/* lots'o-wires to decode common states
|
|
||||||
*/
|
|
||||||
|
|
||||||
wire count_cycles;
|
wire count_cycles;
|
||||||
wire decoder_active;
|
wire decoder_active;
|
||||||
wire decoder_stalled;
|
wire decoder_stalled;
|
||||||
|
@ -459,73 +145,8 @@ assign decoder_stalled = !i_reset && i_en_dec && i_stalled;
|
||||||
assign do_on_first_nibble = decoder_active && !next_nibble;
|
assign do_on_first_nibble = decoder_active && !next_nibble;
|
||||||
assign do_on_other_nibbles = decoder_active && next_nibble;
|
assign do_on_other_nibbles = decoder_active && next_nibble;
|
||||||
|
|
||||||
wire do_block_0x;
|
// all regs and wires for the decoder states
|
||||||
wire do_block_0Efx;
|
`include "saturn_decoder_block_vars.v"
|
||||||
wire do_block_1x;
|
|
||||||
wire do_block_save_to_R_W;
|
|
||||||
wire do_block_rest_from_R_W;
|
|
||||||
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_arith_const;
|
|
||||||
wire do_block_load_p;
|
|
||||||
wire do_block_load_c_hex;
|
|
||||||
|
|
||||||
wire do_block_8x;
|
|
||||||
wire do_block_80x;
|
|
||||||
wire do_block_80Cx;
|
|
||||||
wire do_block_82x;
|
|
||||||
|
|
||||||
wire do_block_Ax;
|
|
||||||
wire do_block_Aax;
|
|
||||||
wire do_block_Abx;
|
|
||||||
|
|
||||||
wire do_block_Fx;
|
|
||||||
|
|
||||||
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;
|
|
||||||
assign do_block_save_to_R_W = do_on_other_nibbles && block_save_to_R_W;
|
|
||||||
assign do_block_rest_from_R_W = do_on_other_nibbles && block_rest_from_R_W;
|
|
||||||
assign do_block_exch_with_R_W = do_on_other_nibbles && block_exch_with_R_W;
|
|
||||||
assign do_block_Rn_A_C = do_on_other_nibbles &&
|
|
||||||
( block_save_to_R_W ||
|
|
||||||
block_rest_from_R_W ||
|
|
||||||
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_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_8x = do_on_other_nibbles && block_8x;
|
|
||||||
assign do_block_80x = do_on_other_nibbles && block_80x;
|
|
||||||
assign do_block_80Cx = do_on_other_nibbles && block_80Cx;
|
|
||||||
assign do_block_82x = do_on_other_nibbles && block_82x;
|
|
||||||
|
|
||||||
assign do_block_Ax = do_on_other_nibbles && block_Ax;
|
|
||||||
assign do_block_Aax = do_on_other_nibbles && block_Aax;
|
|
||||||
assign do_block_Abx = do_on_other_nibbles && block_Abx;
|
|
||||||
|
|
||||||
assign do_block_Fx = do_on_other_nibbles && block_Fx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* variables specific to a particular use
|
* variables specific to a particular use
|
||||||
|
@ -640,9 +261,6 @@ always @(posedge i_clk) begin
|
||||||
o_alu_op <= 0;
|
o_alu_op <= 0;
|
||||||
o_alu_no_stall <= 0;
|
o_alu_no_stall <= 0;
|
||||||
|
|
||||||
// cleanup
|
|
||||||
o_direction <= 0;
|
|
||||||
|
|
||||||
o_ins_rtn <= 0;
|
o_ins_rtn <= 0;
|
||||||
o_set_xm <= 0;
|
o_set_xm <= 0;
|
||||||
o_set_carry <= 0;
|
o_set_carry <= 0;
|
||||||
|
@ -1080,489 +698,8 @@ always @(posedge i_clk) begin
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`include "saturn_decoder_registers.v"
|
||||||
/******************************************************************************
|
`include "saturn_decoder_fields.v"
|
||||||
*
|
|
||||||
* set registers from instruction nibble
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
wire [4:0] reg_ABCD;
|
|
||||||
wire [4:0] reg_BCAC;
|
|
||||||
wire [4:0] reg_ABAC;
|
|
||||||
wire [4:0] reg_BCCD;
|
|
||||||
wire [4:0] reg_D0D1;
|
|
||||||
wire [4:0] reg_DAT0DAT1;
|
|
||||||
wire [4:0] reg_A_C;
|
|
||||||
|
|
||||||
assign reg_ABCD = { 3'b000, i_nibble[1:0]};
|
|
||||||
assign reg_BCAC = { 3'b000, i_nibble[0], !(i_nibble[1] || i_nibble[0])};
|
|
||||||
assign reg_ABAC = { 3'b000, i_nibble[1] && i_nibble[0], (!i_nibble[1]) && i_nibble[0]};
|
|
||||||
assign reg_BCCD = { 3'b000, i_nibble[1] || i_nibble[0], (!i_nibble[1]) ^ i_nibble[0]};
|
|
||||||
// assign reg_D0D1 = { 4'b0010, (i_nibble[0] && i_nibble[1]) || (i_nibble[2] && i_nibble[3])};
|
|
||||||
assign reg_D0D1 = { 4'b0010, i_nibble[0]};
|
|
||||||
assign reg_DAT0DAT1 = { 4'b1000, i_nibble[0]};
|
|
||||||
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;
|
|
||||||
inval_opcode_regs <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_on_first_nibble) begin
|
|
||||||
// reset values on instruction decode start
|
|
||||||
case (i_nibble)
|
|
||||||
4'h6: begin
|
|
||||||
o_reg_dest <= 0;
|
|
||||||
o_reg_src1 <= `ALU_REG_IMM;
|
|
||||||
o_reg_src2 <= 0;
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
o_reg_dest <= 0;
|
|
||||||
o_reg_src1 <= 0;
|
|
||||||
o_reg_src2 <= 0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
inval_opcode_regs <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
*
|
|
||||||
* set registers for specific instructions
|
|
||||||
*
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
if (do_block_0x) begin
|
|
||||||
case (i_nibble)
|
|
||||||
4'h6: begin
|
|
||||||
o_reg_dest <= `ALU_REG_RSTK;
|
|
||||||
o_reg_src1 <= `ALU_REG_C;
|
|
||||||
end
|
|
||||||
4'h7: begin
|
|
||||||
o_reg_dest <= `ALU_REG_C;
|
|
||||||
o_reg_src1 <= `ALU_REG_RSTK;
|
|
||||||
end
|
|
||||||
4'h8: o_reg_dest <= `ALU_REG_ST;
|
|
||||||
4'h9, 4'hB: begin
|
|
||||||
o_reg_dest <= `ALU_REG_C;
|
|
||||||
o_reg_src1 <= `ALU_REG_ST;
|
|
||||||
end
|
|
||||||
4'hA: begin
|
|
||||||
o_reg_dest <= `ALU_REG_ST;
|
|
||||||
o_reg_src1 <= `ALU_REG_C;
|
|
||||||
end
|
|
||||||
4'hC, 4'hD: begin
|
|
||||||
o_reg_dest <= `ALU_REG_P;
|
|
||||||
o_reg_src1 <= `ALU_REG_P;
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
// inval_opcode_regs <= 1;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_0Efx && !in_fields_table) begin
|
|
||||||
o_reg_dest <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
|
||||||
o_reg_src1 <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
|
||||||
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};
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_rest_from_R_W || do_block_exch_with_R_W) begin
|
|
||||||
o_reg_dest <= {3'b000, i_nibble[3]?2'b10:2'b00};
|
|
||||||
o_reg_src1 <= {2'b01, i_nibble[2:0]};
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_pointer_assign_exch) begin
|
|
||||||
o_reg_dest <= i_nibble[1]?reg_A_C:reg_D0D1;
|
|
||||||
o_reg_src1 <= i_nibble[1]?reg_D0D1:reg_A_C;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_mem_transfer) begin
|
|
||||||
o_reg_dest <= i_nibble[1]?reg_A_C:reg_DAT0DAT1;
|
|
||||||
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
|
|
||||||
|
|
||||||
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_80Cx) begin
|
|
||||||
o_reg_dest <= `ALU_REG_C;
|
|
||||||
o_reg_src1 <= `ALU_REG_P;
|
|
||||||
o_reg_src2 <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_82x) begin
|
|
||||||
o_reg_dest <= `ALU_REG_HST;
|
|
||||||
o_reg_src1 <= `ALU_REG_HST;
|
|
||||||
o_reg_src2 <= `ALU_REG_IMM;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_Abx) begin
|
|
||||||
case ({i_nibble[3],i_nibble[2]})
|
|
||||||
2'b00: begin
|
|
||||||
o_reg_dest <= reg_ABCD;
|
|
||||||
o_reg_src1 <= `ALU_REG_ZERO;
|
|
||||||
end
|
|
||||||
2'b01: begin
|
|
||||||
o_reg_dest <= reg_ABCD;
|
|
||||||
o_reg_src1 <= reg_BCAC;
|
|
||||||
end
|
|
||||||
2'b10: begin
|
|
||||||
o_reg_dest <= reg_BCAC;
|
|
||||||
o_reg_src1 <= reg_ABCD;
|
|
||||||
end
|
|
||||||
2'b11: begin
|
|
||||||
o_reg_dest <= reg_ABAC;
|
|
||||||
o_reg_src1 <= reg_BCCD;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
o_reg_src2 <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_Fx) begin
|
|
||||||
case (i_nibble)
|
|
||||||
4'h8, 4'h9, 4'hA, 4'hB: begin
|
|
||||||
o_reg_dest <= reg_ABCD;
|
|
||||||
o_reg_src1 <= reg_ABCD;
|
|
||||||
o_reg_src2 <= 0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* set fields from instruction nibble
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
`ifdef SIM
|
|
||||||
// `define DEBUG_FIELDS_TABLE
|
|
||||||
`endif
|
|
||||||
|
|
||||||
reg fields_table_done;
|
|
||||||
|
|
||||||
/* more wires to decode common states.
|
|
||||||
* can possibly be made less redundant / faster ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
wire do_fields_table;
|
|
||||||
assign do_fields_table = decoder_active && go_fields_table && !fields_table_done;
|
|
||||||
|
|
||||||
wire table_a;
|
|
||||||
wire table_b;
|
|
||||||
wire table_f;
|
|
||||||
wire table_value;
|
|
||||||
assign table_a = (o_fields_table == `FT_TABLE_a);
|
|
||||||
assign table_b = (o_fields_table == `FT_TABLE_b);
|
|
||||||
assign table_f = (o_fields_table == `FT_TABLE_f);
|
|
||||||
assign table_value = (o_fields_table == `FT_TABLE_value);
|
|
||||||
|
|
||||||
wire do_tables_a_f_b;
|
|
||||||
assign do_tables_a_f_b = do_fields_table && !table_value;
|
|
||||||
|
|
||||||
wire table_f_bit_3;
|
|
||||||
wire [3:0] table_a_f_b_case_value;
|
|
||||||
assign table_f_bit_3 = table_f && i_nibble[3];
|
|
||||||
assign table_a_f_b_case_value = {table_f_bit_3, i_nibble[2:0]};
|
|
||||||
|
|
||||||
/* value generation for debug
|
|
||||||
*/
|
|
||||||
|
|
||||||
wire table_a_nb_ok;
|
|
||||||
wire table_b_nb_ok;
|
|
||||||
wire table_f_cond;
|
|
||||||
wire table_f_nb_ok;
|
|
||||||
wire table_a_f_b_nb_ok;
|
|
||||||
assign table_a_nb_ok = table_a && !i_nibble[3];
|
|
||||||
assign table_b_nb_ok = table_b && i_nibble[3];
|
|
||||||
assign table_f_cond = !i_nibble[3] || (i_nibble == 4'hF);
|
|
||||||
assign table_f_nb_ok = table_f && table_f_cond;
|
|
||||||
assign table_a_f_b_nb_ok = table_a_nb_ok || table_b_nb_ok || table_f_nb_ok;
|
|
||||||
|
|
||||||
/* here we go
|
|
||||||
*/
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
if (i_reset || do_on_first_nibble) begin
|
|
||||||
// reset values
|
|
||||||
fields_table_done <= 0;
|
|
||||||
o_field <= 0;
|
|
||||||
o_field_valid <= 0;
|
|
||||||
case (i_nibble)
|
|
||||||
4'h6: begin
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 2;
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* set field for specific instructions
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
if (do_block_0x) begin
|
|
||||||
case (i_nibble)
|
|
||||||
4'h6, 4'h7: begin
|
|
||||||
// virtual A
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 4;
|
|
||||||
end
|
|
||||||
4'h8, 4'h9, 4'hA, 4'hB: begin
|
|
||||||
// ST is 0-3
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 3;
|
|
||||||
end
|
|
||||||
default: begin end // don't care
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_1x) begin
|
|
||||||
o_field_start <= 0;
|
|
||||||
case (i_nibble)
|
|
||||||
4'h9, 4'hD: begin
|
|
||||||
o_field_last <= 1;
|
|
||||||
end
|
|
||||||
4'hA, 4'hE: begin
|
|
||||||
o_field_last <= 3;
|
|
||||||
end
|
|
||||||
4'hB, 4'hF: begin
|
|
||||||
o_field_last <= 4;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_Rn_A_C) begin
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 15;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_pointer_assign_exch) begin
|
|
||||||
o_field_start <= 0;
|
|
||||||
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
|
|
||||||
|
|
||||||
if (do_block_load_c_hex) begin
|
|
||||||
o_field_start <= i_reg_p;
|
|
||||||
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_80Cx) begin
|
|
||||||
o_field_start <= i_nibble;
|
|
||||||
o_field_last <= i_nibble;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (do_block_Fx) begin
|
|
||||||
case (i_nibble)
|
|
||||||
4'h8, 4'h9, 4'hA, 4'hB: begin
|
|
||||||
o_field <= `FT_FIELD_A;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 4;
|
|
||||||
o_field_valid <= 1;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* set field from a table
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
if (do_tables_a_f_b) begin
|
|
||||||
// debug info
|
|
||||||
$display("====== fields_table | table %h | nibble %b", o_fields_table, i_nibble);
|
|
||||||
$display("table_a : %b", table_a_nb_ok);
|
|
||||||
$display("table_b : %b", table_b_nb_ok);
|
|
||||||
$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("case nibble : %h", table_a_f_b_case_value);
|
|
||||||
end
|
|
||||||
`endif
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
if (do_tables_a_f_b) begin
|
|
||||||
case (table_a_f_b_case_value)
|
|
||||||
4'h0: begin
|
|
||||||
o_field <= `FT_FIELD_P;
|
|
||||||
o_field_start <= i_reg_p;
|
|
||||||
o_field_last <= i_reg_p;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field P (%h)", i_reg_p);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h1: begin
|
|
||||||
o_field <= `FT_FIELD_WP;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= i_reg_p;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field WP (0-%h)", i_reg_p);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h2: begin
|
|
||||||
o_field <= `FT_FIELD_XS;
|
|
||||||
o_field_start <= 2;
|
|
||||||
o_field_last <= 2;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field XS");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h3: begin
|
|
||||||
o_field <= `FT_FIELD_X;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 2;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field X");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h4: begin
|
|
||||||
o_field <= `FT_FIELD_S;
|
|
||||||
o_field_start <= 15;
|
|
||||||
o_field_last <= 15;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field S");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h5: begin
|
|
||||||
o_field <= `FT_FIELD_M;
|
|
||||||
o_field_start <= 3;
|
|
||||||
o_field_last <= 14;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field M");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h6: begin
|
|
||||||
o_field <= `FT_FIELD_B;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 1;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field B");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'h7: begin
|
|
||||||
o_field <= `FT_FIELD_W;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 15;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field W");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
4'hF: begin
|
|
||||||
o_field <= `FT_FIELD_A;
|
|
||||||
o_field_start <= 0;
|
|
||||||
o_field_last <= 4;
|
|
||||||
`ifdef DEBUG_FIELDS_TABLE
|
|
||||||
$display("fields_table: field A");
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
o_dec_error <= 1;
|
|
||||||
`ifdef SIM
|
|
||||||
$display("fields_table: table %h nibble %h not handled", o_fields_table, i_nibble);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
o_field_valid <= 1;
|
|
||||||
fields_table_done <= 1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
120
saturn_decoder_block_vars.v
Normal file
120
saturn_decoder_block_vars.v
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Block vars registers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
reg block_0x;
|
||||||
|
wire do_block_0x;
|
||||||
|
assign do_block_0x = do_on_other_nibbles && block_0x;
|
||||||
|
|
||||||
|
reg block_0Efx;
|
||||||
|
wire do_block_0Efx;
|
||||||
|
assign do_block_0Efx = do_on_other_nibbles && block_0Efx;
|
||||||
|
|
||||||
|
reg block_1x;
|
||||||
|
wire do_block_1x;
|
||||||
|
assign do_block_1x = do_on_other_nibbles && block_1x;
|
||||||
|
|
||||||
|
reg block_save_to_R_W;
|
||||||
|
wire do_block_save_to_R_W;
|
||||||
|
assign do_block_save_to_R_W = do_on_other_nibbles && block_save_to_R_W;
|
||||||
|
|
||||||
|
reg block_rest_from_R_W;
|
||||||
|
wire do_block_rest_from_R_W;
|
||||||
|
assign do_block_rest_from_R_W = do_on_other_nibbles && block_rest_from_R_W;
|
||||||
|
|
||||||
|
reg block_exch_with_R_W;
|
||||||
|
wire do_block_exch_with_R_W;
|
||||||
|
assign do_block_exch_with_R_W = do_on_other_nibbles && block_exch_with_R_W;
|
||||||
|
|
||||||
|
wire do_block_Rn_A_C;
|
||||||
|
assign do_block_Rn_A_C = do_on_other_nibbles &&
|
||||||
|
( block_save_to_R_W ||
|
||||||
|
block_rest_from_R_W ||
|
||||||
|
block_exch_with_R_W );
|
||||||
|
|
||||||
|
reg block_pointer_assign_exch;
|
||||||
|
wire do_block_pointer_assign_exch;
|
||||||
|
assign do_block_pointer_assign_exch = do_on_other_nibbles && block_pointer_assign_exch;
|
||||||
|
|
||||||
|
reg block_mem_transfer;
|
||||||
|
wire do_block_mem_transfer;
|
||||||
|
assign do_block_mem_transfer = do_on_other_nibbles && block_mem_transfer;
|
||||||
|
|
||||||
|
reg block_pointer_arith_const;
|
||||||
|
wire do_block_pointer_arith_const;
|
||||||
|
assign do_block_pointer_arith_const = do_on_other_nibbles && block_pointer_arith_const;
|
||||||
|
|
||||||
|
reg block_load_p;
|
||||||
|
wire do_block_load_p;
|
||||||
|
assign do_block_load_p = do_on_other_nibbles && block_load_p;
|
||||||
|
|
||||||
|
reg block_load_c_hex;
|
||||||
|
wire do_block_load_c_hex;
|
||||||
|
assign do_block_load_c_hex = do_on_other_nibbles && block_load_c_hex;
|
||||||
|
|
||||||
|
reg block_jmp2_cry_set;
|
||||||
|
reg block_jmp2_cry_clr;
|
||||||
|
|
||||||
|
reg block_8x;
|
||||||
|
wire do_block_8x;
|
||||||
|
assign do_block_8x = do_on_other_nibbles && block_8x;
|
||||||
|
|
||||||
|
reg block_80x;
|
||||||
|
wire do_block_80x;
|
||||||
|
assign do_block_80x = do_on_other_nibbles && block_80x;
|
||||||
|
|
||||||
|
reg block_80Cx;
|
||||||
|
wire do_block_80Cx;
|
||||||
|
assign do_block_80Cx = do_on_other_nibbles && block_80Cx;
|
||||||
|
|
||||||
|
reg block_82x;
|
||||||
|
wire do_block_82x;
|
||||||
|
assign do_block_82x = do_on_other_nibbles && block_82x;
|
||||||
|
|
||||||
|
reg block_Ax;
|
||||||
|
wire do_block_Ax;
|
||||||
|
assign do_block_Ax = do_on_other_nibbles && block_Ax;
|
||||||
|
|
||||||
|
reg block_Aax;
|
||||||
|
wire do_block_Aax;
|
||||||
|
assign do_block_Aax = do_on_other_nibbles && block_Aax;
|
||||||
|
|
||||||
|
reg block_Abx;
|
||||||
|
wire do_block_Abx;
|
||||||
|
assign do_block_Abx = do_on_other_nibbles && block_Abx;
|
||||||
|
|
||||||
|
reg block_Fx;
|
||||||
|
wire do_block_Fx;
|
||||||
|
assign do_block_Fx = do_on_other_nibbles && block_Fx;
|
||||||
|
|
||||||
|
reg go_fields_table;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* subroutines
|
||||||
|
*/
|
||||||
|
|
||||||
|
reg block_load_reg_imm;
|
||||||
|
wire do_load_reg_imm;
|
||||||
|
assign do_load_reg_imm = do_on_other_nibbles && block_load_reg_imm;
|
||||||
|
|
||||||
|
reg block_jmp;
|
||||||
|
wire do_block_jmp;
|
||||||
|
assign do_block_jmp = do_on_other_nibbles && block_jmp;
|
||||||
|
|
||||||
|
reg block_sr_bit;
|
||||||
|
wire do_block_sr_bit;
|
||||||
|
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;
|
257
saturn_decoder_debugger.v
Normal file
257
saturn_decoder_debugger.v
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* debugger
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
wire [19:0] new_pc;
|
||||||
|
assign new_pc = i_pc + 1;
|
||||||
|
|
||||||
|
wire run_debugger;
|
||||||
|
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_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;
|
||||||
|
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
|
||||||
|
/*
|
||||||
|
* this whole thing is a large print statement
|
||||||
|
* THIS PART IS NEVER GENERATED
|
||||||
|
*/
|
||||||
|
`ifdef SIM
|
||||||
|
if (o_ins_decoded) begin
|
||||||
|
$write("DBG[%5d]: ", inst_counter);
|
||||||
|
$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");
|
||||||
|
if (o_set_carry) $write("%sC", o_carry_val?"S":"C");
|
||||||
|
end
|
||||||
|
if (o_ins_set_mode) begin
|
||||||
|
$write("SET%s", o_mode_dec?"DEC":"HEX");
|
||||||
|
end
|
||||||
|
if (o_ins_alu_op) begin
|
||||||
|
|
||||||
|
case (o_alu_op)
|
||||||
|
`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");
|
||||||
|
`ALU_OP_CLR_MASK:
|
||||||
|
case (o_reg_dest)
|
||||||
|
`ALU_REG_HST:
|
||||||
|
case (o_imm_value)
|
||||||
|
4'h1: $write("XM=0");
|
||||||
|
4'h2: $write("SB=0");
|
||||||
|
4'h4: $write("SR=0");
|
||||||
|
4'h8: $write("MP=0");
|
||||||
|
default: begin
|
||||||
|
$write("CLRHST");
|
||||||
|
if (o_imm_value != 4'hF) $write("\t%1h", o_imm_value);
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
default: $write("[VLR_MASK dest:%0d]", o_reg_dest);
|
||||||
|
endcase
|
||||||
|
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:%0d]", 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,
|
||||||
|
`ALU_OP_RST_BIT,
|
||||||
|
`ALU_OP_SET_BIT: if (!is_lc_hex)
|
||||||
|
$write("=");
|
||||||
|
`ALU_OP_2CMPL: $write("=-");
|
||||||
|
`ALU_OP_EXCH,
|
||||||
|
`ALU_OP_JMP_REL3,
|
||||||
|
`ALU_OP_JMP_REL4,
|
||||||
|
`ALU_OP_JMP_ABS5,
|
||||||
|
`ALU_OP_CLR_MASK: begin end
|
||||||
|
default: $write("[op:%0d]", o_alu_op);
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (o_alu_op)
|
||||||
|
`ALU_OP_COPY,
|
||||||
|
`ALU_OP_EXCH,
|
||||||
|
`ALU_OP_AND,
|
||||||
|
`ALU_OP_OR,
|
||||||
|
`ALU_OP_INC,
|
||||||
|
`ALU_OP_DEC,
|
||||||
|
`ALU_OP_ADD,
|
||||||
|
`ALU_OP_SUB,
|
||||||
|
`ALU_OP_2CMPL:
|
||||||
|
case (o_reg_src1)
|
||||||
|
`ALU_REG_A: $write("A");
|
||||||
|
`ALU_REG_B: $write("B");
|
||||||
|
`ALU_REG_C: $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: $write("ST");
|
||||||
|
`ALU_REG_P: $write("P");
|
||||||
|
`ALU_REG_IMM:
|
||||||
|
if (disp_nb_nibbles) $write("(%0d)", o_mem_pos);
|
||||||
|
`ALU_REG_ZERO: $write("0");
|
||||||
|
default: $write("[src1:%0d]", 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)
|
||||||
|
$write("S");
|
||||||
|
|
||||||
|
if (o_alu_op == `ALU_OP_EXCH)
|
||||||
|
$write("%s", is_short_transfer?"XS":"EX");
|
||||||
|
|
||||||
|
case (o_alu_op)
|
||||||
|
`ALU_OP_AND,
|
||||||
|
`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:%0d]", o_alu_op);
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (o_reg_src2)
|
||||||
|
`ALU_REG_A: $write("A");
|
||||||
|
`ALU_REG_B: $write("B");
|
||||||
|
`ALU_REG_C: $write("C");
|
||||||
|
`ALU_REG_D: $write("D");
|
||||||
|
`ALU_REG_RSTK: $write("RSTK");
|
||||||
|
`ALU_REG_IMM: $write("\t%0d", o_imm_value+1);
|
||||||
|
default: $write("[src2:%0d]", o_reg_src2);
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
`ALU_OP_INC: $write("+1");
|
||||||
|
`ALU_OP_DEC: $write("-1");
|
||||||
|
`ALU_OP_ZERO,
|
||||||
|
`ALU_OP_COPY,
|
||||||
|
`ALU_OP_EXCH: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
// if (!((o_reg_dest == `ALU_REG_RSTK) || (o_reg_src1 == `ALU_REG_RSTK) ||
|
||||||
|
// (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) 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 $write("%0d", o_field_last+1);
|
||||||
|
end else begin
|
||||||
|
// $write("@%b@", is_load_imm);
|
||||||
|
if (is_load_imm) begin
|
||||||
|
if (is_p_eq) $write("%0d", o_imm_value);
|
||||||
|
else
|
||||||
|
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
|
||||||
|
else
|
||||||
|
case (o_reg_dest)
|
||||||
|
`ALU_REG_P,
|
||||||
|
`ALU_REG_ST,
|
||||||
|
`ALU_REG_HST: begin end
|
||||||
|
`ALU_REG_C:
|
||||||
|
if (o_reg_src1 == `ALU_REG_P)
|
||||||
|
$write("%0d", o_field_start);
|
||||||
|
default: $write("[%h:%h]", o_field_start, o_field_last);
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
$write("\t(%0d cycles)", inst_cycles);
|
||||||
|
if (o_unimplemented)
|
||||||
|
$write("\t%C[1,31mUNIMPLEMENTED%C[0m", 27, 27);
|
||||||
|
$write("\n");
|
||||||
|
end
|
||||||
|
// $display("new [%5h]--------------------------------------------------------------------", new_pc);
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
end
|
275
saturn_decoder_fields.v
Normal file
275
saturn_decoder_fields.v
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* set fields from instruction nibble
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
`ifdef SIM
|
||||||
|
// `define DEBUG_FIELDS_TABLE
|
||||||
|
`endif
|
||||||
|
|
||||||
|
reg fields_table_done;
|
||||||
|
|
||||||
|
/* more wires to decode common states.
|
||||||
|
* can possibly be made less redundant / faster ?
|
||||||
|
*/
|
||||||
|
|
||||||
|
wire do_fields_table;
|
||||||
|
assign do_fields_table = decoder_active && go_fields_table && !fields_table_done;
|
||||||
|
|
||||||
|
wire table_a;
|
||||||
|
wire table_b;
|
||||||
|
wire table_f;
|
||||||
|
wire table_value;
|
||||||
|
assign table_a = (o_fields_table == `FT_TABLE_a);
|
||||||
|
assign table_b = (o_fields_table == `FT_TABLE_b);
|
||||||
|
assign table_f = (o_fields_table == `FT_TABLE_f);
|
||||||
|
assign table_value = (o_fields_table == `FT_TABLE_value);
|
||||||
|
|
||||||
|
wire do_tables_a_f_b;
|
||||||
|
assign do_tables_a_f_b = do_fields_table && !table_value;
|
||||||
|
|
||||||
|
wire table_f_bit_3;
|
||||||
|
wire [3:0] table_a_f_b_case_value;
|
||||||
|
assign table_f_bit_3 = table_f && i_nibble[3];
|
||||||
|
assign table_a_f_b_case_value = {table_f_bit_3, i_nibble[2:0]};
|
||||||
|
|
||||||
|
/* value generation for debug
|
||||||
|
*/
|
||||||
|
|
||||||
|
wire table_a_nb_ok;
|
||||||
|
wire table_b_nb_ok;
|
||||||
|
wire table_f_cond;
|
||||||
|
wire table_f_nb_ok;
|
||||||
|
wire table_a_f_b_nb_ok;
|
||||||
|
assign table_a_nb_ok = table_a && !i_nibble[3];
|
||||||
|
assign table_b_nb_ok = table_b && i_nibble[3];
|
||||||
|
assign table_f_cond = !i_nibble[3] || (i_nibble == 4'hF);
|
||||||
|
assign table_f_nb_ok = table_f && table_f_cond;
|
||||||
|
assign table_a_f_b_nb_ok = table_a_nb_ok || table_b_nb_ok || table_f_nb_ok;
|
||||||
|
|
||||||
|
/* here we go
|
||||||
|
*/
|
||||||
|
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
if (i_reset || do_on_first_nibble) begin
|
||||||
|
// reset values
|
||||||
|
fields_table_done <= 0;
|
||||||
|
o_field <= 0;
|
||||||
|
o_field_valid <= 0;
|
||||||
|
case (i_nibble)
|
||||||
|
4'h6: begin
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 2;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* set field for specific instructions
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
if (do_block_0x) begin
|
||||||
|
case (i_nibble)
|
||||||
|
4'h6, 4'h7: begin
|
||||||
|
// virtual A
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 4;
|
||||||
|
end
|
||||||
|
4'h8, 4'h9, 4'hA, 4'hB: begin
|
||||||
|
// ST is 0-3
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 3;
|
||||||
|
end
|
||||||
|
default: begin end // don't care
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_1x) begin
|
||||||
|
o_field_start <= 0;
|
||||||
|
case (i_nibble)
|
||||||
|
4'h9, 4'hD: begin
|
||||||
|
o_field_last <= 1;
|
||||||
|
end
|
||||||
|
4'hA, 4'hE: begin
|
||||||
|
o_field_last <= 3;
|
||||||
|
end
|
||||||
|
4'hB, 4'hF: begin
|
||||||
|
o_field_last <= 4;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_Rn_A_C) begin
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 15;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_pointer_assign_exch) begin
|
||||||
|
o_field_start <= 0;
|
||||||
|
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
|
||||||
|
|
||||||
|
if (do_block_load_c_hex) begin
|
||||||
|
o_field_start <= i_reg_p;
|
||||||
|
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_80Cx) begin
|
||||||
|
o_field_start <= i_nibble;
|
||||||
|
o_field_last <= i_nibble;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_Fx) begin
|
||||||
|
case (i_nibble)
|
||||||
|
4'h8, 4'h9, 4'hA, 4'hB: begin
|
||||||
|
o_field <= `FT_FIELD_A;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 4;
|
||||||
|
o_field_valid <= 1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* set field from a table
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
if (do_tables_a_f_b) begin
|
||||||
|
// debug info
|
||||||
|
$display("====== fields_table | table %h | nibble %b", o_fields_table, i_nibble);
|
||||||
|
$display("table_a : %b", table_a_nb_ok);
|
||||||
|
$display("table_b : %b", table_b_nb_ok);
|
||||||
|
$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("case nibble : %h", table_a_f_b_case_value);
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
if (do_tables_a_f_b) begin
|
||||||
|
case (table_a_f_b_case_value)
|
||||||
|
4'h0: begin
|
||||||
|
o_field <= `FT_FIELD_P;
|
||||||
|
o_field_start <= i_reg_p;
|
||||||
|
o_field_last <= i_reg_p;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field P (%h)", i_reg_p);
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h1: begin
|
||||||
|
o_field <= `FT_FIELD_WP;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= i_reg_p;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field WP (0-%h)", i_reg_p);
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h2: begin
|
||||||
|
o_field <= `FT_FIELD_XS;
|
||||||
|
o_field_start <= 2;
|
||||||
|
o_field_last <= 2;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field XS");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h3: begin
|
||||||
|
o_field <= `FT_FIELD_X;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 2;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field X");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h4: begin
|
||||||
|
o_field <= `FT_FIELD_S;
|
||||||
|
o_field_start <= 15;
|
||||||
|
o_field_last <= 15;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field S");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h5: begin
|
||||||
|
o_field <= `FT_FIELD_M;
|
||||||
|
o_field_start <= 3;
|
||||||
|
o_field_last <= 14;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field M");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h6: begin
|
||||||
|
o_field <= `FT_FIELD_B;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 1;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field B");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'h7: begin
|
||||||
|
o_field <= `FT_FIELD_W;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 15;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field W");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
4'hF: begin
|
||||||
|
o_field <= `FT_FIELD_A;
|
||||||
|
o_field_start <= 0;
|
||||||
|
o_field_last <= 4;
|
||||||
|
`ifdef DEBUG_FIELDS_TABLE
|
||||||
|
$display("fields_table: field A");
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
o_dec_error <= 1;
|
||||||
|
`ifdef SIM
|
||||||
|
$display("fields_table: table %h nibble %h not handled", o_fields_table, i_nibble);
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
o_field_valid <= 1;
|
||||||
|
fields_table_done <= 1;
|
||||||
|
end
|
||||||
|
end
|
208
saturn_decoder_registers.v
Normal file
208
saturn_decoder_registers.v
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* set registers from instruction nibble
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
wire [4:0] reg_ABCD;
|
||||||
|
wire [4:0] reg_BCAC;
|
||||||
|
wire [4:0] reg_ABAC;
|
||||||
|
wire [4:0] reg_BCCD;
|
||||||
|
wire [4:0] reg_D0D1;
|
||||||
|
wire [4:0] reg_DAT0DAT1;
|
||||||
|
wire [4:0] reg_A_C;
|
||||||
|
|
||||||
|
assign reg_ABCD = { 3'b000, i_nibble[1:0]};
|
||||||
|
assign reg_BCAC = { 3'b000, i_nibble[0], !(i_nibble[1] || i_nibble[0])};
|
||||||
|
assign reg_ABAC = { 3'b000, i_nibble[1] && i_nibble[0], (!i_nibble[1]) && i_nibble[0]};
|
||||||
|
assign reg_BCCD = { 3'b000, i_nibble[1] || i_nibble[0], (!i_nibble[1]) ^ i_nibble[0]};
|
||||||
|
// assign reg_D0D1 = { 4'b0010, (i_nibble[0] && i_nibble[1]) || (i_nibble[2] && i_nibble[3])};
|
||||||
|
assign reg_D0D1 = { 4'b0010, i_nibble[0]};
|
||||||
|
assign reg_DAT0DAT1 = { 4'b1000, i_nibble[0]};
|
||||||
|
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;
|
||||||
|
inval_opcode_regs <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_on_first_nibble) begin
|
||||||
|
// reset values on instruction decode start
|
||||||
|
case (i_nibble)
|
||||||
|
4'h6: begin
|
||||||
|
o_reg_dest <= 0;
|
||||||
|
o_reg_src1 <= `ALU_REG_IMM;
|
||||||
|
o_reg_src2 <= 0;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
o_reg_dest <= 0;
|
||||||
|
o_reg_src1 <= 0;
|
||||||
|
o_reg_src2 <= 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
inval_opcode_regs <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
*
|
||||||
|
* set registers for specific instructions
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
if (do_block_0x) begin
|
||||||
|
case (i_nibble)
|
||||||
|
4'h6: begin
|
||||||
|
o_reg_dest <= `ALU_REG_RSTK;
|
||||||
|
o_reg_src1 <= `ALU_REG_C;
|
||||||
|
end
|
||||||
|
4'h7: begin
|
||||||
|
o_reg_dest <= `ALU_REG_C;
|
||||||
|
o_reg_src1 <= `ALU_REG_RSTK;
|
||||||
|
end
|
||||||
|
4'h8: o_reg_dest <= `ALU_REG_ST;
|
||||||
|
4'h9, 4'hB: begin
|
||||||
|
o_reg_dest <= `ALU_REG_C;
|
||||||
|
o_reg_src1 <= `ALU_REG_ST;
|
||||||
|
end
|
||||||
|
4'hA: begin
|
||||||
|
o_reg_dest <= `ALU_REG_ST;
|
||||||
|
o_reg_src1 <= `ALU_REG_C;
|
||||||
|
end
|
||||||
|
4'hC, 4'hD: begin
|
||||||
|
o_reg_dest <= `ALU_REG_P;
|
||||||
|
o_reg_src1 <= `ALU_REG_P;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
// inval_opcode_regs <= 1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_0Efx && !in_fields_table) begin
|
||||||
|
o_reg_dest <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
||||||
|
o_reg_src1 <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
||||||
|
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};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_rest_from_R_W || do_block_exch_with_R_W) begin
|
||||||
|
o_reg_dest <= {3'b000, i_nibble[3]?2'b10:2'b00};
|
||||||
|
o_reg_src1 <= {2'b01, i_nibble[2:0]};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_pointer_assign_exch) begin
|
||||||
|
o_reg_dest <= i_nibble[1]?reg_A_C:reg_D0D1;
|
||||||
|
o_reg_src1 <= i_nibble[1]?reg_D0D1:reg_A_C;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_mem_transfer) begin
|
||||||
|
o_reg_dest <= i_nibble[1]?reg_A_C:reg_DAT0DAT1;
|
||||||
|
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
|
||||||
|
|
||||||
|
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_80Cx) begin
|
||||||
|
o_reg_dest <= `ALU_REG_C;
|
||||||
|
o_reg_src1 <= `ALU_REG_P;
|
||||||
|
o_reg_src2 <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_82x) begin
|
||||||
|
o_reg_dest <= `ALU_REG_HST;
|
||||||
|
o_reg_src1 <= `ALU_REG_HST;
|
||||||
|
o_reg_src2 <= `ALU_REG_IMM;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_Abx) begin
|
||||||
|
case ({i_nibble[3],i_nibble[2]})
|
||||||
|
2'b00: begin
|
||||||
|
o_reg_dest <= reg_ABCD;
|
||||||
|
o_reg_src1 <= `ALU_REG_ZERO;
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
o_reg_dest <= reg_ABCD;
|
||||||
|
o_reg_src1 <= reg_BCAC;
|
||||||
|
end
|
||||||
|
2'b10: begin
|
||||||
|
o_reg_dest <= reg_BCAC;
|
||||||
|
o_reg_src1 <= reg_ABCD;
|
||||||
|
end
|
||||||
|
2'b11: begin
|
||||||
|
o_reg_dest <= reg_ABAC;
|
||||||
|
o_reg_src1 <= reg_BCCD;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
o_reg_src2 <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (do_block_Fx) begin
|
||||||
|
case (i_nibble)
|
||||||
|
4'h8, 4'h9, 4'hA, 4'hB: begin
|
||||||
|
o_reg_dest <= reg_ABCD;
|
||||||
|
o_reg_src1 <= reg_ABCD;
|
||||||
|
o_reg_src2 <= 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue