add alu stuff

This commit is contained in:
Raphael Jacquot 2019-02-10 18:46:26 +01:00
parent ec83140ff3
commit f21dcd8c23
8 changed files with 327 additions and 113 deletions

View file

@ -2,57 +2,59 @@
`define _DECSTATES
`define DEC_START 12'h000 // X
`define DEC_0X 12'h001 // 0X
`define DEC_1X 12'h100 // 1X
`define DEC_13X 12'h130 // 13X
`define DEC_14X 12'h140 // 14X
`define DEC_15X 12'h150 // 15X
`define DEC_15X_FIELD 12'h151 // 15XX
`define DEC_MEMAXX 12'h152 // 1[45]x[y]
`define DEC_START 12'h000 // X
`define DEC_0X 12'h001 // 0X
`define DEC_1X 12'h100 // 1X
`define DEC_13X 12'h130 // 13X
`define DEC_14X 12'h140 // 14X
`define DEC_15X 12'h150 // 15X
`define DEC_15X_FIELD 12'h151 // 15XX
`define DEC_MEMAXX 12'h152 // 1[45]x[y]
`define DEC_MEMAXX_END 12'h153
`define DEC_PTR_MATH 12'h160 // 1[678C]n D[01]=D[01][+-] (n+1)
`define DEC_D0_EQ_4N 12'h1A0 // 1B
`define DEC_D0_EQ_5N 12'h1B0 // 1B
`define DEC_D0_EQ_LOOP 12'h1B1 // 1Bxxxxx (exec)
`define DEC_D1_EQ_4N 12'h1E0 // 1E
`define DEC_D1_EQ_5N 12'h1F0 // 1F
`define DEC_D1_EQ_LOOP 12'h1F1 // 1[EF]xxxxx (exec)
`define DEC_P_EQ_N 12'h200 // 2n
`define DEC_LC_LEN 12'h300 // 3n...
`define DEC_LC 12'h301 // 3n[x]
`define DEC_GOTO 12'h600 // 6
`define DEC_GOTO_LOOP 12'h601 // 6[x] -> exec
`define DEC_GOSUB 12'h700 // 7
`define DEC_GOSUB_LOOP 12'h701 // 7[x] -> exec
`define DEC_8X 12'h800 // 8X
`define DEC_80X 12'h801 // 80X
`define DEC_808X 12'h808 // 808X
`define DEC_AC_BIT_SET_TEST 12'h809 // 808[4-B]x
`define DEC_C_EQ_P_N 12'h80C // 80Cn C=P n
`define DEC_P_EQ_C_N 12'h80D // 80Dn P=C n
`define DEC_82X_CLRHST 12'h820 // 82X
`define DEC_ST_EQ_0_N 12'h840 // 84n ST=0 n
`define DEC_ST_EQ_1_N 12'h850 // 85n ST=1 n
`define DEC_PTR_MATH 12'h160 // 1[678C]n D[01]=D[01][+-] (n+1)
`define DEC_D0_EQ_4N 12'h1A0 // 1B
`define DEC_D0_EQ_5N 12'h1B0 // 1B
`define DEC_D0_EQ_LOOP 12'h1B1 // 1Bxxxxx (exec)
`define DEC_D1_EQ_4N 12'h1E0 // 1E
`define DEC_D1_EQ_5N 12'h1F0 // 1F
`define DEC_D1_EQ_LOOP 12'h1F1 // 1[EF]xxxxx (exec)
`define DEC_P_EQ_N 12'h200 // 2n
`define DEC_LC_LEN 12'h300 // 3n...
`define DEC_LC 12'h301 // 3n[x]
`define DEC_GOTO 12'h600 // 6
`define DEC_GOTO_LOOP 12'h601 // 6[x] -> exec
`define DEC_GOSUB 12'h700 // 7
`define DEC_GOSUB_LOOP 12'h701 // 7[x] -> exec
`define DEC_8X 12'h800 // 8X
`define DEC_80X 12'h801 // 80X
`define DEC_808X 12'h808 // 808X
`define DEC_AC_BIT_SET_TEST 12'h809 // 808[4-B]x
`define DEC_C_EQ_P_N 12'h80C // 80Cn C=P n
`define DEC_P_EQ_C_N 12'h80D // 80Dn P=C n
`define DEC_82X_CLRHST 12'h820 // 82X
`define DEC_ST_EQ_0_N 12'h840 // 84n ST=0 n
`define DEC_ST_EQ_1_N 12'h850 // 85n ST=1 n
`define DEC_TEST_ST_EQ_0_N 12'h860 // 86n ?ST=0 n
`define DEC_TEST_ST_EQ_1_N 12'h870 // 87n ?ST=1 n
`define DEC_TEST_P_NEQ_N 12'h880 // 88n ?P# n
`define DEC_TEST_P_EQ_N 12'h890 // 89n ?P= n
`define DEC_8AX 12'h8A0 // 8Ax
`define DEC_GOVLNG 12'h8D0 // 8D
`define DEC_GOVLNG_LOOP 12'h8D1 // 8D[x]
`define DEC_GOVLNG_EXEC 12'h8D2 // 8Dxxxxx -> exec
`define DEC_GOSBVL 12'h8F0 // 8F
`define DEC_GOSBVL_LOOP 12'h8F1 // 8F[x]
`define DEC_GOSBVL_EXEC 12'h8F2 // 8Fxxxxx -> exec
`define DEC_AX 12'hA00 // Ax
`define DEC_AaX_EXEC 12'hA01 // Aax
`define DEC_AbX_EXEC 12'hA02 // Abx
`define DEC_BX 12'hB00 // Bx
`define DEC_CX 12'hC00 // Cx
`define DEC_DX 12'hD00 // Dx
`define DEC_FX 12'hF00 // Fx
`define DEC_TEST_GO 12'hFFE // GOYES / RTNYES nibble 1
`define DEC_TEST_GO_1 12'hFFF // GOYES / RTNYES nibble 2
`define DEC_8AX 12'h8A0 // 8Ax
`define DEC_GOVLNG 12'h8D0 // 8D
`define DEC_GOVLNG_LOOP 12'h8D1 // 8D[x]
`define DEC_GOVLNG_EXEC 12'h8D2 // 8Dxxxxx -> exec
`define DEC_GOSBVL 12'h8F0 // 8F
`define DEC_GOSBVL_LOOP 12'h8F1 // 8F[x]
`define DEC_GOSBVL_EXEC 12'h8F2 // 8Fxxxxx -> exec
`define DEC_Axx_EXEC 12'hA00 // A[ab]x
`define DEC_Bxx_EXEC 12'hB00 // B[ab]x
`define DEC_CX 12'hC00 // Cx
`define DEC_DX 12'hD00 // Dx
`define DEC_FX 12'hF00 // Fx
`define DEC_TEST_GO 12'hFF0 // GOYES / RTNYES nibble 1
`define DEC_TEST_GO_1 12'hFF1 // GOYES / RTNYES nibble 2
`define DEC_ALU_INIT 12'hFF8 // Start ALU operations
`define DEC_ALU_CONT 12'hFF9 // Subsequent ALU operations
`define DEC_ab_FIELDS 12'hFFE // a and b fields table
`define DEC_f_FIELDS 12'hFFF // f fields table
`endif

View file

@ -16,6 +16,11 @@
`define T_FTYPE_FIELD 0
`define T_TTYPE_LEN 1
`define T_TABLE_A 0
`define T_TABLE_B 1
`define T_TABLE_F 2
`define T_TABLE_Z 3 // unused
`define T_FIELD_P 0
`define T_FIELD_WP 1
`define T_FIELD_XS 2
@ -26,4 +31,17 @@
`define T_FIELD_W 7
`define T_FIELD_A 15
`define ALU_OP_ZERO 0
`define ALU_OP_COPY 1
`define ALU_OP_EXCH 2
`define ALU_OP_SHL 3
`define ALU_OP_SHR 4
`define ALU_OP_INC 8
`define ALU_REG_A 0
`define ALU_REG_B 1
`define ALU_REG_C 2
`define ALU_REG_D 3
`endif

View file

@ -10,69 +10,48 @@
`include "decstates.v"
`include "fields.v"
`DEC_AX: begin
if (!nb_in[3]) begin // table a
case (nb_in)
4'h0: t_field <= `T_FIELD_P;
4'h1: t_field <= `T_FIELD_WP;
4'h2: t_field <= `T_FIELD_XS;
4'h3: t_field <= `T_FIELD_X;
4'h4: t_field <= `T_FIELD_S;
4'h5: t_field <= `T_FIELD_M;
4'h6: t_field <= `T_FIELD_B;
4'h7: t_field <= `T_FIELD_W;
endcase
decstate <= `DEC_AaX_EXEC;
end else begin // table b
case (nb_in)
4'h8: t_field <= `T_FIELD_P;
4'h9: t_field <= `T_FIELD_WP;
4'hA: t_field <= `T_FIELD_XS;
4'hB: t_field <= `T_FIELD_X;
4'hC: t_field <= `T_FIELD_S;
4'hD: t_field <= `T_FIELD_M;
4'hE: t_field <= `T_FIELD_B;
4'hF: t_field <= `T_FIELD_W;
endcase
decstate <= `DEC_AbX_EXEC;
end
end
`DEC_AaX_EXEC: begin
case (nb_in)
default: begin
$display("ERROR : DEC_AaX_EXEC");
`DEC_Axx_EXEC: begin
if (!field_table[0]) begin
$display("table 'a' not handled yet");
decode_error <= 1;
end
endcase
end
`DEC_AbX_EXEC: begin
case (nb_in)
4'h2: begin // C=0 b
case (t_field)
`T_FIELD_B: C[7:0] <= 0;
default: begin
$display("ERROR :");
end else begin
if (!nb_in[3]) begin
alu_reg_dest <= {2'b0, nb_in[1:0]};
if (!nb_in[2]) alu_op <= `ALU_OP_ZERO;
else begin
alu_op <= `ALU_OP_COPY;
alu_reg_src1 <= {nb_in[0], (!(nb_in[0] | nb_in[1])) & nb_in[2]};
end;
end else begin
$display("DEC_Axx_EXEC %h", nb_in);
decode_error <= 1;
end
endcase
end
alu_debug <= 1;
next_cycle <= `BUSCMD_NOP;
decstate <= `DEC_ALU_INIT;
`ifdef SIM
$write("%5h C=0\t", inst_start_PC);
case (t_field)
`T_FIELD_P: $display("P");
`T_FIELD_WP: $display("WP");
`T_FIELD_XS: $display("XS");
`T_FIELD_X: $display("X");
`T_FIELD_S: $display("S");
`T_FIELD_M: $display("M");
`T_FIELD_B: $display("B");
`T_FIELD_W: $display("W");
$write("%5h ", inst_start_PC);
if (!nb_in[3])
case (nb_in[1:0])
2'b00: $write("A=%s",(!nb_in[2])?"0":"B");
2'b01: $write("B=%s",(!nb_in[2])?"0":"C");
2'b10: $write("C=%s",(!nb_in[2])?"0":"A");
2'b11: $write("D=%s",(!nb_in[2])?"0":"C");
endcase
`endif
end
default: begin
$display("ERROR : DEC_AbX_EXEC");
decode_error <= 1;
else begin
$write("NOT HANDLED");
end
$write("\t");
case (field)
`T_FIELD_P: $display("P");
`T_FIELD_WP: $display("WP");
`T_FIELD_XS: $display("XS");
`T_FIELD_X: $display("X");
`T_FIELD_S: $display("S");
`T_FIELD_M: $display("M");
`T_FIELD_B: $display("B");
`T_FIELD_W: $display("W");
endcase
decstate <= `DEC_START;
`endif
end

32
opcodes/B[ab]x.v Normal file
View file

@ -0,0 +1,32 @@
/******************************************************************************
* B[ab]x
*
* lots of things there
*
*/
`include "decstates.v"
`include "fields.v"
`DEC_Bxx_EXEC: begin
if (!field_table[0]) begin
if (!nb_in[3]) begin
alu_reg_dest <= {2'b0, nb_in[1:0]};
alu_reg_src1 <= {2'b0, nb_in[1:0]};
if (!nb_in[2]) begin
end else alu_op <= `ALU_OP_INC;
end else begin
$display("Bxx table 'a' not handled yet");
decode_error <= 1;
end
end else begin
alu_reg_dest <= {2'b0, nb_in[1:0]};
$display("Bxx table 'b' not handled yet");
decode_error <= 1;
end
alu_debug <= 1;
next_cycle <= `BUSCMD_NOP;
decstate <= `DEC_ALU_INIT;
end

44
opcodes/z_alu_phase_2.v Normal file
View file

@ -0,0 +1,44 @@
case (decstate)
`DEC_ALU_INIT, `DEC_ALU_CONT: begin
`ifdef SIM
if (alu_debug) begin
$display("------------------------------- z_alu_phase_2 ---------------------------------");
$display("ALU OP %h | FRST %h | LAST %h | SRC1 %h | SRC2 %h | DEST %h",
alu_op, alu_first, alu_last, alu_reg_src1, alu_reg_src2,alu_reg_dest);
$display("CARRY %b | STICKY-BIT %b", Carry, HST[1]);
case (alu_reg_dest)
`ALU_REG_A: $display("A: %h", A);
`ALU_REG_B: $display("B: %h", B);
`ALU_REG_C: $display("C: %h", C);
`ALU_REG_D: $display("D: %h", D);
endcase
$write("xxx");
for (display_counter = 15; display_counter != 255; display_counter = display_counter - 1)
case (display_counter[3:0])
alu_last:
if (alu_first == alu_last) $write("!");
else $write("L");
alu_first: $write("^");
default: $write(".");
endcase
$display("");
end
`endif
case (alu_op)
`ALU_OP_INC: begin
case (alu_reg_src1)
`ALU_REG_A: alu_src1 <= A[alu_first*4+:4];
`ALU_REG_B: alu_src1 <= B[alu_first*4+:4];
`ALU_REG_C: alu_src1 <= C[alu_first*4+:4];
`ALU_REG_D: alu_src1 <= D[alu_first*4+:4];
endcase
alu_carry <= (decstate == `DEC_ALU_INIT)?1:Carry;
end
default: begin
`ifdef SIM
$display("nothing to do I suppose");
`endif
end
endcase
end
endcase

54
opcodes/z_alu_phase_3.v Normal file
View file

@ -0,0 +1,54 @@
/*
* Alu module
* calculations are in here
*/
`include "fields.v"
`DEC_ALU_INIT, `DEC_ALU_CONT: begin
`ifdef SIM
if (alu_debug) begin
$display("------------------------------- z_alu_phase_3 ---------------------------------");
$display("alu_src1 %h | alu_src2 %h | alu_tmp %h | alu_carry %b",
alu_src1, alu_src2, alu_tmp, alu_carry);
end
`endif
case (alu_op)
`ALU_OP_ZERO: begin
$display("ALU_OP_ZERO");
case (alu_reg_dest)
`ALU_REG_A: A[alu_first*4+:4] <= 0;
`ALU_REG_B: B[alu_first*4+:4] <= 0;
`ALU_REG_C: C[alu_first*4+:4] <= 0;
`ALU_REG_D: D[alu_first*4+:4] <= 0;
default: $display("ALU_OP_ZERO register not handled");
endcase
alu_first <= (alu_first + 1) & 4'hF;
end
`ALU_OP_SHR: begin
end
`ALU_OP_INC: begin
$display("ALU_OP_INC");
case (alu_reg_dest)
`ALU_REG_D: {Carry, D[alu_first*4+:4]} <= alu_src1 + alu_carry;
default: $display("ALU_OP_INC register not handled");
endcase
alu_first <= (alu_first + 1) & 4'hF;
end
default: begin
`ifdef SIM
`endif
end
endcase
if (alu_last == alu_first) begin
// the alu is done
decstate <= `DEC_START;
alu_requested_halt <= alu_halt;
end else decstate <= `DEC_ALU_CONT;
end

49
opcodes/z_fields.v Normal file
View file

@ -0,0 +1,49 @@
`include "fields.v"
`DEC_ab_FIELDS: begin
field_table <= {1'b0, nb_in[3]};
$display("DEC_ab_FIELDS %b %h", {1'b0, !nb_in[3]}, nb_in[2:0]);
case (nb_in[2:0])
4'h0: begin
field <= `T_FIELD_P;
alu_first <= P;
alu_last <= P;
end
4'h1: begin
field <= `T_FIELD_WP;
alu_first <= 0;
alu_last <= P;
end
4'h2: begin
field <= `T_FIELD_XS;
alu_first <= 2;
alu_last <= 2;
end
4'h3: begin
field <= `T_FIELD_X;
alu_first <= 0;
alu_last <= 2;
end
4'h4: begin
field <= `T_FIELD_S;
alu_first <= 15;
alu_last <= 15;
end
4'h5: begin
field <= `T_FIELD_M;
alu_first <= 3;
alu_last <= 14;
end
4'h6: begin
field <= `T_FIELD_B;
alu_first <= 0;
alu_last <= 1;
end
4'h7: begin
field <= `T_FIELD_W;
alu_first <= 0;
alu_last <= 15;
end
endcase
decstate <= fields_return;
end

View file

@ -73,6 +73,7 @@ reg read_nibble;
reg first_nibble;
reg [11:0] decstate;
reg [11:0] fields_return;
reg [3:0] regdump;
// bus access
@ -85,7 +86,7 @@ reg bus_load_pc;
reg en_bus_load_pc;
// should go away, the rom should work like any other bus module
reg rom_enable;
reg [7:0] display_counter;
// internal registers
reg [19:0] new_PC;
@ -119,6 +120,28 @@ reg [19:0] add_out;
reg t_set_test;
reg t_set_test_val;
reg t_add_sub;
reg [3:0] t_first;
reg [3:0] t_last;
// alu control
reg [3:0] field;
reg [1:0] field_table;
reg [3:0] alu_op;
reg [3:0] alu_first;
reg [3:0] alu_last;
reg [3:0] alu_reg_src1;
reg [3:0] alu_reg_src2;
reg [3:0] alu_reg_dest;
reg [3:0] alu_src1;
reg [3:0] alu_src2;
reg [3:0] alu_tmp;
reg alu_carry;
reg alu_debug;
reg alu_halt;
reg alu_requested_halt;
// processor registers
reg [19:0] PC;
@ -174,6 +197,8 @@ initial
read_next_pc = 1;
execute_cycle = 0;
inc_pc = 0;
alu_halt = 0;
alu_requested_halt = 0;
$display("should be initializing registers");
hex_dec = `MODE_HEX;
PC = 0;
@ -327,12 +352,13 @@ always @(posedge ph1)
begin
end
always @(posedge ph2)
begin
end
always @(posedge ph2) begin
`include "decstates.v"
`include "opcodes/z_alu_phase_2.v"
end
always @(posedge ph3) begin
if (cycle_ctr == 580)
if (cycle_ctr == 630)
debug_stop <= 1;
end
@ -345,6 +371,7 @@ end
`include "decstates.v"
always @(posedge dec_strobe) begin
if (alu_requested_halt) decode_error <= 1;
if ((next_cycle == `BUSCMD_LOAD_PC)|
(next_cycle == `BUSCMD_CONFIGURE)|
(next_cycle == `BUSCMD_RESET)|
@ -381,8 +408,14 @@ always @(posedge dec_strobe) begin
4'h6: decstate <= `DEC_GOTO;
4'h7: decstate <= `DEC_GOSUB;
4'h8: decstate <= `DEC_8X;
4'hA: decstate <= `DEC_AX;
4'hB: decstate <= `DEC_BX;
4'hA: begin
fields_return <= `DEC_Axx_EXEC;
decstate <= `DEC_ab_FIELDS;
end
4'hB: begin
fields_return <= `DEC_Bxx_EXEC;
decstate <= `DEC_ab_FIELDS;
end
4'hC: decstate <= `DEC_CX;
4'hD: decstate <= `DEC_DX;
4'hF: decstate <= `DEC_FX;
@ -413,11 +446,14 @@ always @(posedge dec_strobe) begin
`include "opcodes/8Ax_test_[n]eq_A.v"
`include "opcodes/8[DF]xxxxx_GO.v"
`include "opcodes/A[ab]x.v"
`include "opcodes/Bx_math_ops_shift.v"
`include "opcodes/B[ab]x.v"
`include "opcodes/Cx.v"
`include "opcodes/Dx_regs_field_A.v"
`include "opcodes/Fx.v"
`include "opcodes/xx_RTNYES_GOYES.v"
`include "opcodes/z_alu_phase_3.v"
`include "opcodes/z_fields.v"
default: begin
$display("ERROR : GENERAL");
decode_error <= 1;