start handling ALU related stuff

This commit is contained in:
Raphael Jacquot 2019-02-12 12:43:36 +01:00
parent bcb44743de
commit 88620f217c
6 changed files with 301 additions and 124 deletions

View file

@ -1,4 +1,7 @@
`ifndef _DEF_ALU
`define _DEF_ALU
// stuff (where should that go ?)
`define T_SET 0
`define T_TEST 1
@ -8,21 +11,28 @@
`define T_PTR_0 0
`define T_PTR_1 1
// copy / exchange
`define ALU_OP_ZERO 0
`define ALU_OP_COPY 1
`define ALU_OP_EXCH 2
// shifts
`define ALU_OP_SHL 3
`define ALU_OP_SHR 4
`define ALU_OP_2CMPL 5
`define ALU_OP_1CMPL 6
`define ALU_OP_INC 8
`define ALU_OP_DEC 9
`define ALU_OP_ADD 10
`define ALU_OP_SUB 11
`define ALU_OP_ADD_CST 12
`define ALU_OP_SUB_CST 13
`define ALU_OP_TEST_EQ 14
`define ALU_OP_TEST_NEQ 15
// logic
`define ALU_OP_AND 5
`define ALU_OP_OR 6
// arithmetic
`define ALU_OP_2CMPL 7
`define ALU_OP_1CMPL 8
`define ALU_OP_INC 9
`define ALU_OP_DEC 10
`define ALU_OP_ADD 11
`define ALU_OP_SUB 12
`define ALU_OP_ADD_CST 13
`define ALU_OP_SUB_CST 14
// tests
`define ALU_OP_TEST_EQ 15
`define ALU_OP_TEST_NEQ 16
`define ALU_REG_A 0
@ -41,3 +51,5 @@
`define ALU_REG_CST 13
`define ALU_REG_M 14
`define ALU_REG_0 15
`endif

View file

@ -1,5 +1,5 @@
`ifndef _FIELDS
`define _FIELDS
`ifndef _DEF_FIELDS
`define _DEF_FIELDS
`define FT_TABLE_a 0
`define FT_TABLE_b 1

View file

@ -1,16 +1,54 @@
`ifndef _SATURN_ALU
`define _SATURN_ALU
`include "def-alu.v"
module saturn_alu (
i_clk,
i_reset,
i_en_alu_prep,
i_en_alu_calc,
i_en_alu_save
i_en_alu_save,
i_field_start,
i_field_last,
i_alu_op,
o_reg_p
);
input wire i_clk;
input wire i_reset;
input wire i_en_alu_prep;
input wire i_en_alu_calc;
input wire i_en_alu_save;
input wire [0:0] i_clk;
input wire [0:0] i_reset;
input wire [0:0] i_en_alu_prep;
input wire [0:0] i_en_alu_calc;
input wire [0:0] i_en_alu_save;
input wire [3:0] i_field_start;
input wire [3:0] i_field_last;
input wire [4:0] i_alu_op;
output wire [3:0] o_reg_p;
assign o_reg_p = P;
reg [3:0] P;
initial begin
P = 3;
end
always @(posedge i_clk) begin
if (!i_reset) begin
if (i_en_alu_prep) begin
`ifdef SIM
$display("ALU_PREP: alu_op %h | f_start %h | f_last %h", i_alu_op, i_field_start, i_field_last);
`endif
end
end
end
endmodule

View file

@ -58,20 +58,6 @@ reg [31:0] max_cycle;
// state machine stuff
wire halt;
wire inc_pc;
wire dec_error;
// decoder outputs
wire [19:0] ins_addr;
wire ins_decoded;
wire direction;
wire ins_rtn;
wire set_xm;
wire set_carry;
wire carry_val;
wire ins_set_mode;
wire mode_dec;
wire ins_rstk_c;
// hp48_bus bus_ctrl (
@ -85,37 +71,83 @@ wire ins_rstk_c;
// );
saturn_decoder m_decoder (
.i_clk (clk),
.i_reset (reset),
.i_cycles (cycle_ctr),
.i_en_dbg (en_debugger),
.i_en_dec (en_inst_dec),
.i_pc (reg_pc),
.i_stalled (stalled),
.i_nibble (nibble_in),
.o_inc_pc (inc_pc),
.o_dec_error (dec_error),
.i_clk (clk),
.i_reset (reset),
.i_cycles (cycle_ctr),
.i_en_dbg (en_debugger),
.i_en_dec (en_inst_dec),
.i_pc (reg_pc),
.i_stalled (stalled),
.i_nibble (nibble_in),
.o_ins_addr (ins_addr),
.o_ins_decoded (ins_decoded),
.o_direction (direction),
.o_ins_rtn (ins_rtn),
.o_set_xm (set_xm),
.o_set_carry (set_carry),
.o_carry_val (carry_val),
.o_ins_set_mode (ins_set_mode),
.o_mode_dec (mode_dec),
.o_ins_rstk_c (ins_rstk_c)
.i_reg_p (reg_p),
.o_inc_pc (inc_pc),
.o_dec_error (inv_opcode),
.o_ins_addr (ins_addr),
.o_ins_decoded (ins_decoded),
.o_fields_table (fields_table),
.o_field (field),
.o_field_start (field_start),
.o_field_last (field_last),
.o_alu_op (alu_op),
.o_direction (direction),
.o_ins_rtn (ins_rtn),
.o_set_xm (set_xm),
.o_set_carry (set_carry),
.o_carry_val (carry_val),
.o_ins_set_mode (ins_set_mode),
.o_mode_dec (mode_dec),
.o_ins_rstk_c (ins_rstk_c)
);
wire inc_pc;
wire inv_opcode;
wire [19:0] ins_addr;
wire ins_decoded;
wire [1:0] fields_table;
wire [3:0] field;
wire [3:0] field_start;
wire [3:0] field_last;
wire [4:0] alu_op;
wire direction;
wire ins_rtn;
wire set_xm;
wire set_carry;
wire carry_val;
wire ins_set_mode;
wire mode_dec;
wire ins_rstk_c;
saturn_alu m_alu (
.i_clk (clk),
.i_reset (reset),
.i_clk (clk),
.i_reset (reset),
.i_en_alu_prep (en_alu_prep),
.i_en_alu_calc (en_alu_calc),
.i_en_alu_save (en_alu_save)
.i_en_alu_save (en_alu_save),
.i_field_start (field_start),
.i_field_last (field_last),
.i_alu_op (alu_op),
.o_reg_p (reg_p)
);
// interconnections
wire [3:0] reg_p;
/*
* test rom...
*/
@ -125,18 +157,18 @@ reg [3:0] rom [0:1024];
initial
begin
$readmemh( "testrom.hex", rom);
clk_phase = 0;
en_debugger = 0; // phase 0
en_bus_send = 0; // phase 0
en_bus_recv = 0; // phase 1
en_alu_prep = 0; // phase 1
en_alu_calc = 0; // phase 2
en_inst_dec = 0; // phase 2
en_alu_save = 0; // phase 3
en_inst_exec = 0; // phase 3
clock_end = 0;
cycle_ctr = 0;
reg_pc = 0;
clk_phase = 0;
en_debugger = 0; // phase 0
en_bus_send = 0; // phase 0
en_bus_recv = 0; // phase 1
en_alu_prep = 0; // phase 1
en_alu_calc = 0; // phase 2
en_inst_dec = 0; // phase 2
en_alu_save = 0; // phase 3
en_inst_exec = 0; // phase 3
clock_end = 0;
cycle_ctr = 0;
reg_pc = 0;
`ifdef DEBUG_CLOCKS
$monitor("RST %b | CLK %b | CLKP %d | CYCL %d | eRST %b | eDBG %b | eBSND %b | eBRECV %b | eAPR %b | eACALC %b | eINDC %b | eASAVE %b | eINDX %b",
@ -182,7 +214,7 @@ always @(posedge clk) begin
clock_end <= 0;
cycle_ctr <= ~0;
stalled <= 0;
max_cycle <= 50;
max_cycle <= 1024;
`ifndef SIM
led[7:0] <= reg_pc[7:0];
`endif
@ -195,13 +227,9 @@ end
//
//--------------------------------------------------------------------------------------------------
reg [3:0] nibble_in;
reg [19:0] reg_pc;
reg stalled;
reg stalled;
always @(posedge clk)
if (reset)
@ -225,7 +253,7 @@ always @(posedge clk)
end
end
assign halt = clock_end || dec_error;
assign halt = clock_end || inv_opcode;
// Verilator lint_off UNUSED

View file

@ -4,7 +4,8 @@
*
*****************************************************************************/
`include "def_fields.v"
`include "def-fields.v"
`include "def-alu.v"
module saturn_decoder(
i_clk,
@ -15,6 +16,9 @@ module saturn_decoder(
i_stalled,
i_pc,
i_nibble,
i_reg_p,
o_inc_pc,
o_dec_error,
@ -26,6 +30,8 @@ module saturn_decoder(
o_field_start,
o_field_last,
o_alu_op,
o_direction,
o_ins_rtn,
o_set_xm,
@ -33,14 +39,15 @@ module saturn_decoder(
o_carry_val,
o_ins_set_mode,
o_mode_dec,
o_ins_rstk_c
o_ins_rstk_c,
o_ins_alu_op
);
/*
* module input / output ports
*/
input wire i_clk;
input wire i_reset;
input wire [0:0] i_clk;
input wire [0:0] i_reset;
input wire [31:0] i_cycles;
input wire i_en_dbg;
input wire i_en_dec;
@ -48,6 +55,8 @@ input wire i_stalled;
input wire [19:0] i_pc;
input wire [3:0] i_nibble;
input wire [3:0] i_reg_p;
output reg o_inc_pc;
output reg o_dec_error;
@ -60,6 +69,8 @@ output reg [3:0] o_field;
output reg [3:0] o_field_start;
output reg [3:0] o_field_last;
output reg [4:0] o_alu_op;
// generic
output reg o_direction;
@ -76,6 +87,9 @@ output reg o_mode_dec;
// rstk and c
output reg o_ins_rstk_c;
// alu_operations
output reg o_ins_alu_op;
/*
@ -102,22 +116,28 @@ end
always @(posedge i_clk) begin
if (!i_reset && i_en_dbg && !i_stalled)
if (o_ins_decoded) begin
`ifdef SIM
$write("%5h ", o_ins_addr);
if (o_ins_rtn) begin
$write("RTN");
if (o_set_xm) $write("SXM");
if (o_set_carry) $write("%sC", o_carry_val?"S":"C");
$display("");
if (!continue) begin
`ifdef SIM
$display("-------------------------------------------------------------------------------");
if (o_ins_decoded) begin
$write("%5h ", o_ins_addr);
if (o_ins_rtn) begin
$write("RTN");
if (o_set_xm) $write("SXM");
if (o_set_carry) $write("%sC", o_carry_val?"S":"C");
$display("");
end
if (o_ins_set_mode) begin
$display("SET%s", o_mode_dec?"DEC":"HEX");
end
if (o_ins_rstk_c) begin
$display("%s", o_direction?"C=RSTK":"RSTK=C");
end
if (o_ins_alu_op) begin
$display("an alu operation (debugger code missing)");
end
end
if (o_ins_set_mode) begin
$display("SET%s", o_mode_dec?"DEC":"HEX");
end
if (o_ins_rstk_c) begin
$display("%s", o_direction?"C=RSTK":"RSTK=C");
end
`endif
`endif
end
end
@ -156,6 +176,7 @@ always @(posedge i_clk) begin
*/
if (!continue) begin
continue <= 1;
$display("resetting o_ins_decoded");
o_ins_decoded <= 0;
// store the address where the instruction starts
o_ins_addr <= i_pc;
@ -171,6 +192,8 @@ always @(posedge i_clk) begin
o_field_start <= 0;
o_field_last <= 0;
o_alu_op <= 0;
// cleanup
o_direction <= 0;
@ -183,6 +206,8 @@ always @(posedge i_clk) begin
o_mode_dec <= 0;
o_ins_rstk_c <= 0;
o_ins_alu_op <= 0;
end
/*
@ -194,9 +219,9 @@ always @(posedge i_clk) begin
case (i_nibble)
4'h0: block_0x <= 1;
default: begin
`ifdef SIM
`ifdef SIM
$display("new_instruction: nibble %h not handled", i_nibble);
`endif
`endif
o_dec_error <= 1;
end
endcase
@ -258,11 +283,10 @@ always @(posedge i_clk) begin
*****************************************************************************/
if (continue && block_0Efx && !fields_table) begin
`ifdef SIM
$display("block_0Efx: nibble %h not handled", i_nibble);
`endif
continue <= 0;
o_dec_error <= 1;
o_ins_alu_op <= 1;
o_alu_op <= (!i_nibble[3])?`ALU_OP_AND:`ALU_OP_OR;
continue <= 0;
o_ins_decoded <= 1;
end
/******************************************************************************
@ -272,12 +296,16 @@ always @(posedge i_clk) begin
*
*****************************************************************************/
// `define DEBUG_FIELDS_TABLE
`ifdef SIM
//`define DEBUG_FIELDS_TABLE
`endif
if (continue && fields_table) begin
if (fields_table != `FT_TABLE_value) begin
`ifdef DEBUG_FIELDS_TABLE
`ifdef SIM
// debug info
`ifdef DEBUG_FIELDS_TABLE
$display("====== fields_table | table %h | nibble %b", o_fields_table, i_nibble);
$display("table_a : %b", ((o_fields_table == `FT_TABLE_a) && (!i_nibble[3])));
$display("table_b : %b", ((o_fields_table == `FT_TABLE_b) && ( i_nibble[3])));
@ -286,44 +314,113 @@ always @(posedge i_clk) begin
$display("table_f nbl : %h", {4{o_fields_table == `FT_TABLE_f}} );
$display("table_f val : %h", (i_nibble & {4{o_fields_table == `FT_TABLE_f}}) );
$display("case nibble : %h", ((i_nibble & 4'h7) | (i_nibble & {4{fields_table == `FT_TABLE_f}})) );
`endif
`endif
`endif
//
if (((o_fields_table == `FT_TABLE_a) && (!i_nibble[3])) ||
((o_fields_table == `FT_TABLE_b) && ( i_nibble[3])) ||
((o_fields_table == `FT_TABLE_f) && ((!i_nibble[3]) || (i_nibble == 4'hF) ))) begin
case ((i_nibble & 4'h7) | (i_nibble & {4{o_fields_table == `FT_TABLE_f}}))
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
if (o_fields_table == `FT_TABLE_f) begin
`ifdef SIM
o_field <= `FT_FIELD_A;
o_field_start <= 0;
o_field_last <= 4;
`ifdef DEBUG_FIELDS_TABLE
$display("fields_table: field A");
`endif
`endif
end else begin
// should never happen...
`ifdef SIM
// should never get here
o_dec_error <= 1;
`ifdef SIM
$display("fields_table: table %h nibble %h", o_fields_table, i_nibble);
`endif
`endif
end
end
default: begin
`ifdef SIM
$display("fields_table: table %h nibble %h not handled", o_fields_table, i_nibble);
`endif
o_dec_error <= 1;
`ifdef SIM
$display("fields_table: table %h nibble %h not handled", o_fields_table, i_nibble);
`endif
end
endcase
end else begin
`ifdef SIM
$display("fields_table: table %h invalid nibble %h", o_fields_table, i_nibble);
`endif
o_dec_error <= 1;
`ifdef SIM
$display("fields_table: table %h invalid nibble %h", o_fields_table, i_nibble);
`endif
end
end else begin
`ifdef SIM
$display("fields_table: there is nothing to decode for table FT_TABLE_value");
`endif
o_dec_error <= 1;
`ifdef SIM
$display("fields_table: there is nothing to decode for table FT_TABLE_value");
`endif
end
fields_table <= 0;
end

View file

@ -16,5 +16,7 @@
0 E 6 0 // A=A&B B
0 E 7 0 // A=A&B W
0 E F 0 // A=A&B A
0 E 8 0 // invalid
0 E 0 8 // A=A!B P
F // end