mirror of
https://github.com/sxpert/hp-saturn
synced 2024-12-26 09:58:09 +01:00
implement the ALU as it should be
This commit is contained in:
parent
137d9b3b5a
commit
b2ae484450
4 changed files with 162 additions and 31 deletions
2
run.sh
2
run.sh
|
@ -15,7 +15,7 @@ iverilog -v -Wall -DSIM -o z_saturn_test.iv -s saturn_top \
|
|||
saturn_bus.v saturn_hp48gx_rom.v \
|
||||
saturn_bus_controller.v saturn_debugger.v \
|
||||
saturn_control_unit.v saturn_inst_decoder.v\
|
||||
saturn_regs_pc_rstk.v saturn_alu_module.v
|
||||
saturn_regs_pc_rstk.v #saturn_alu_module.v
|
||||
IVERILOG_STATUS=$?
|
||||
#./mask_gen_tb
|
||||
echo "--------------------------------------------------------------------"
|
||||
|
|
|
@ -171,7 +171,7 @@ always @(posedge i_clk) begin
|
|||
end
|
||||
|
||||
`ifdef SIM
|
||||
if (cycle_ctr == 136) begin
|
||||
if (cycle_ctr == 138) begin
|
||||
bus_halt <= 1'b1;
|
||||
$display("BUS %0d: [%d] enough cycles for now", phase, cycle_ctr);
|
||||
end
|
||||
|
|
|
@ -309,30 +309,30 @@ wire [19:0] reg_PC;
|
|||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
saturn_alu_module alu_module (
|
||||
.i_clk (i_clk),
|
||||
.i_clk_en (i_clk_en),
|
||||
.i_reset (i_reset),
|
||||
.i_phases (i_phases),
|
||||
.i_phase (i_phase),
|
||||
.i_cycle_ctr (i_cycle_ctr),
|
||||
// saturn_alu_module alu_module (
|
||||
// .i_clk (i_clk),
|
||||
// .i_clk_en (i_clk_en),
|
||||
// .i_reset (i_reset),
|
||||
// .i_phases (i_phases),
|
||||
// .i_phase (i_phase),
|
||||
// .i_cycle_ctr (i_cycle_ctr),
|
||||
|
||||
.i_opcode (alu_opcode),
|
||||
.i_ptr_begin (alu_ptr_begin),
|
||||
.i_ptr_end (alu_ptr_end),
|
||||
// .i_opcode (alu_opcode),
|
||||
// .i_ptr_begin (alu_ptr_begin),
|
||||
// .i_ptr_end (alu_ptr_end),
|
||||
|
||||
.i_run (alu_run),
|
||||
.i_done (alu_done),
|
||||
// .i_run (alu_run),
|
||||
// .i_done (alu_done),
|
||||
|
||||
.i_prep_src_1_val (alu_prep_src_1_val),
|
||||
.i_prep_src_2_val (alu_prep_src_2_val),
|
||||
.i_prep_carry (alu_prep_carry),
|
||||
// .i_prep_src_1_val (alu_prep_src_1_val),
|
||||
// .i_prep_src_2_val (alu_prep_src_2_val),
|
||||
// .i_prep_carry (alu_prep_carry),
|
||||
|
||||
.i_calc_pos (alu_calc_pos),
|
||||
.o_calc_res_1_val (alu_calc_res_1_val),
|
||||
.o_calc_res_2_val (alu_calc_res_2_val),
|
||||
.o_calc_carry (alu_calc_carry)
|
||||
);
|
||||
// .i_calc_pos (alu_calc_pos),
|
||||
// .o_calc_res_1_val (alu_calc_res_1_val),
|
||||
// .o_calc_res_2_val (alu_calc_res_2_val),
|
||||
// .o_calc_carry (alu_calc_carry)
|
||||
// );
|
||||
|
||||
/*
|
||||
* ALU control variable
|
||||
|
@ -357,9 +357,9 @@ reg [0:0] alu_prep_done;
|
|||
|
||||
reg [0:0] alu_calc_run;
|
||||
reg [3:0] alu_calc_pos;
|
||||
wire [3:0] alu_calc_res_1_val;
|
||||
wire [3:0] alu_calc_res_2_val;
|
||||
wire [0:0] alu_calc_carry;
|
||||
reg [3:0] alu_calc_res_1_val;
|
||||
reg [3:0] alu_calc_res_2_val;
|
||||
reg [0:0] alu_calc_carry;
|
||||
reg [0:0] alu_calc_done;
|
||||
|
||||
reg [0:0] alu_save_run;
|
||||
|
@ -550,7 +550,11 @@ always @(posedge i_clk) begin
|
|||
alu_calc_done <= 1'b0;
|
||||
alu_save_done <= 1'b0;
|
||||
|
||||
if (aluop_zero) alu_save_run <= 1'b1;
|
||||
if (aluop_zero)
|
||||
begin
|
||||
alu_calc_res_1_val <= 4'h0;
|
||||
alu_save_run <= 1'b1;
|
||||
end
|
||||
else alu_prep_run <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
@ -681,41 +685,114 @@ always @(posedge i_clk) begin
|
|||
|
||||
/******************************************************************************************
|
||||
*
|
||||
* ALU control
|
||||
* ALU pipeline
|
||||
*
|
||||
*****************************************************************************************/
|
||||
|
||||
if (i_clk_en && control_unit_ready) begin
|
||||
|
||||
/**********
|
||||
*
|
||||
* ALU prepare source values
|
||||
*
|
||||
*/
|
||||
|
||||
if (alu_start && alu_prep_run && !alu_prep_done) begin
|
||||
$display("ALU_PREP %0d: [%d] b %h | p %h | e %h", i_phase, i_cycle_ctr, alu_ptr_begin, alu_prep_pos, alu_ptr_end);
|
||||
|
||||
case (dec_alu_reg_src_1)
|
||||
`ALU_REG_A: alu_prep_src_1_val <= reg_A[alu_prep_pos];
|
||||
`ALU_REG_B: alu_prep_src_1_val <= reg_B[alu_prep_pos];
|
||||
`ALU_REG_C: alu_prep_src_1_val <= reg_C[alu_prep_pos];
|
||||
`ALU_REG_D: alu_prep_src_1_val <= reg_D[alu_prep_pos];
|
||||
default: $display("ALU_PREP %0d: [%d] unhandled src1 register %0d", i_phase, i_cycle_ctr, dec_alu_reg_src_1);
|
||||
endcase
|
||||
|
||||
case (dec_alu_reg_src_2)
|
||||
`ALU_REG_A: alu_prep_src_2_val <= reg_A[alu_prep_pos];
|
||||
`ALU_REG_B: alu_prep_src_2_val <= reg_B[alu_prep_pos];
|
||||
`ALU_REG_C: alu_prep_src_2_val <= reg_C[alu_prep_pos];
|
||||
`ALU_REG_D: alu_prep_src_2_val <= reg_D[alu_prep_pos];
|
||||
`ALU_REG_NONE: begin end
|
||||
default: $display("ALU_PREP %0d: [%d] unhandled src2 register %0d", i_phase, i_cycle_ctr, dec_alu_reg_src_2);
|
||||
endcase
|
||||
|
||||
/* need to prepare the carry here */
|
||||
|
||||
if (alu_prep_pos == alu_ptr_end) begin
|
||||
alu_prep_done <= 1'b1;
|
||||
alu_prep_run <= 1'b0;
|
||||
end
|
||||
alu_prep_pos <= alu_prep_pos + 4'h1;
|
||||
/* start the calc thread */
|
||||
alu_calc_run <= 1'b1;
|
||||
end
|
||||
|
||||
/**********
|
||||
*
|
||||
* ALU calculations
|
||||
*
|
||||
*/
|
||||
|
||||
if (alu_start && alu_calc_run && !alu_calc_done) begin
|
||||
$display("ALU_CALC %0d: [%d] b %h | p %h | e %h", i_phase, i_cycle_ctr, alu_ptr_begin, alu_calc_pos, alu_ptr_end);
|
||||
$display("ALU_CALC %0d: [%d] b %h | p %h | e %h | s1 %h | s2 %h | c %b",
|
||||
i_phase, i_cycle_ctr, alu_ptr_begin, alu_calc_pos, alu_ptr_end,
|
||||
alu_prep_src_1_val, alu_prep_src_2_val, alu_prep_carry);
|
||||
|
||||
case (alu_opcode)
|
||||
`ALU_OP_ZERO: begin end // this doesn't run, handled directly by the save below
|
||||
`ALU_OP_COPY: alu_calc_res_1_val <= alu_prep_src_1_val;
|
||||
`ALU_OP_EXCH:
|
||||
begin
|
||||
alu_calc_res_1_val <= alu_prep_src_2_val;
|
||||
alu_calc_res_2_val <= alu_prep_src_1_val;
|
||||
end
|
||||
default: $display("ALU_CALC %0d: [%d] unhandled opcode %0d", i_phase, i_cycle_ctr, alu_opcode);
|
||||
endcase
|
||||
|
||||
if (alu_calc_pos == alu_ptr_end) begin
|
||||
alu_calc_done <= 1'b1;
|
||||
alu_calc_run <= 1'b0;
|
||||
end
|
||||
alu_calc_pos <= alu_calc_pos + 4'h1;
|
||||
/* start the save thread */
|
||||
alu_save_run <= 1'b1;
|
||||
end
|
||||
|
||||
/**********
|
||||
*
|
||||
* ALU save results to registers
|
||||
*
|
||||
*/
|
||||
|
||||
if (alu_start && alu_save_run && !alu_save_done) begin
|
||||
$display("ALU_SAVE %0d: [%d] b %h | p %h | e %h | r1 %h | r2 %h | c %b",
|
||||
$display("ALU_SAVE %0d: [%d] b %h | p %h | e %h | r1 %h | r2 %h | c %b | rs1 %d | rs2 %d | d %d",
|
||||
i_phase, i_cycle_ctr,
|
||||
alu_ptr_begin, alu_save_pos, alu_ptr_end,
|
||||
alu_calc_res_1_val, alu_calc_res_2_val, alu_calc_carry);
|
||||
alu_calc_res_1_val, alu_calc_res_2_val, alu_calc_carry,
|
||||
alu_reg_src_1, alu_reg_src_2, alu_reg_dest);
|
||||
|
||||
case (alu_reg_dest)
|
||||
`ALU_REG_C: reg_C[alu_save_pos] <= alu_calc_res_1_val;
|
||||
`ALU_REG_A: reg_A[alu_save_pos] <= alu_calc_res_1_val;
|
||||
`ALU_REG_B: reg_B[alu_save_pos] <= alu_calc_res_1_val;
|
||||
`ALU_REG_C: reg_C[alu_save_pos] <= alu_calc_res_1_val;
|
||||
`ALU_REG_D: reg_D[alu_save_pos] <= alu_calc_res_1_val;
|
||||
`ALU_REG_D0: reg_D0[alu_save_pos[2:0]] <= alu_calc_res_1_val;
|
||||
`ALU_REG_D1: reg_D1[alu_save_pos[2:0]] <= alu_calc_res_1_val;
|
||||
default: $display("ALU_SAVE %0d: [%d] dest register %0d not supported", i_phase, i_cycle_ctr, alu_reg_dest);
|
||||
endcase
|
||||
|
||||
if (alu_opcode == `ALU_OP_EXCH)
|
||||
case (alu_reg_src_2)
|
||||
`ALU_REG_A: reg_A[alu_save_pos] <= alu_calc_res_2_val;
|
||||
`ALU_REG_B: reg_B[alu_save_pos] <= alu_calc_res_2_val;
|
||||
`ALU_REG_C: reg_C[alu_save_pos] <= alu_calc_res_2_val;
|
||||
`ALU_REG_D: reg_D[alu_save_pos] <= alu_calc_res_2_val;
|
||||
`ALU_REG_D0: reg_D0[alu_save_pos[2:0]] <= alu_calc_res_2_val;
|
||||
`ALU_REG_D1: reg_D1[alu_save_pos[2:0]] <= alu_calc_res_2_val;
|
||||
default: $display("ALU_SAVE %0d: [%d] exch: src_2 register %0d not supported", i_phase, i_cycle_ctr, alu_reg_src_2);
|
||||
endcase
|
||||
|
||||
if (alu_save_pos == alu_ptr_end) begin
|
||||
alu_save_done <= 1'b1;
|
||||
alu_save_run <= 1'b0;
|
||||
|
@ -723,6 +800,13 @@ always @(posedge i_clk) begin
|
|||
alu_save_pos <= alu_save_pos + 4'h1;
|
||||
end
|
||||
|
||||
|
||||
/**********
|
||||
*
|
||||
* ALU end of operations
|
||||
*
|
||||
*/
|
||||
|
||||
if (i_phases[2] && alu_start && alu_save_done) begin
|
||||
$display("CTRL %0d: [%d] end of ALU operation", i_phase, i_cycle_ctr);
|
||||
alu_start <= 1'b0;
|
||||
|
|
|
@ -144,6 +144,7 @@ reg [0:0] block_84x_85x;
|
|||
reg [0:0] block_Ax;
|
||||
reg [0:0] block_Aax;
|
||||
reg [0:0] block_Abx;
|
||||
reg [0:0] block_Dx;
|
||||
|
||||
reg [0:0] block_JUMP;
|
||||
reg [0:0] block_LOAD;
|
||||
|
@ -195,6 +196,7 @@ initial begin
|
|||
block_Ax = 1'b0;
|
||||
block_Aax = 1'b0;
|
||||
block_Abx = 1'b0;
|
||||
block_Dx = 1'b0;
|
||||
|
||||
block_JUMP = 1'b0;
|
||||
block_LOAD = 1'b0;
|
||||
|
@ -217,6 +219,9 @@ end
|
|||
*/
|
||||
|
||||
wire [4:0] regs_ABCD = { 3'b000, i_nibble[1:0] };
|
||||
wire [4:0] regs_BCAC = { 3'b000, i_nibble[0], !(i_nibble[1] | i_nibble[0]) };
|
||||
wire [4:0] regs_ABAC = { 3'b000, i_nibble[1] & i_nibble[0], !i_nibble[1] & i_nibble[0] };
|
||||
wire [4:0] regs_BCCD = { 3'b000, i_nibble[1] | i_nibble[0], !i_nibble[1] ^ i_nibble[0] };
|
||||
|
||||
/****************************
|
||||
*
|
||||
|
@ -271,6 +276,7 @@ always @(posedge i_clk) begin
|
|||
block_FIELDS <= 1'b1;
|
||||
fields_table <= `FT_A_B;
|
||||
end
|
||||
4'hD: block_Dx <= 1'b1;
|
||||
default:
|
||||
begin
|
||||
$display("invalid instruction");
|
||||
|
@ -497,6 +503,46 @@ always @(posedge i_clk) begin
|
|||
block_Abx <= 1'b0;
|
||||
end
|
||||
|
||||
if (block_Dx) begin
|
||||
$display("DECODER %0d: [%d] block_Dx %h", i_phase, i_cycle_ctr, i_nibble);
|
||||
o_instr_type <= `INSTR_TYPE_ALU;
|
||||
o_alu_field <= `FT_FIELD_A;
|
||||
o_alu_ptr_begin <= 4'h0;
|
||||
o_alu_ptr_end <= 4'h4;
|
||||
o_alu_reg_src_2 <= `ALU_REG_NONE;
|
||||
case ({i_nibble[3], i_nibble[2]})
|
||||
2'b00:
|
||||
begin
|
||||
o_alu_opcode <= `ALU_OP_ZERO;
|
||||
o_alu_reg_dest <= regs_ABCD;
|
||||
o_alu_reg_src_1 <= `ALU_REG_NONE;
|
||||
end
|
||||
2'b01:
|
||||
begin
|
||||
o_alu_opcode <= `ALU_OP_COPY;
|
||||
o_alu_reg_dest <= regs_ABCD;
|
||||
o_alu_reg_src_1 <= regs_BCAC;
|
||||
end
|
||||
2'b10:
|
||||
begin
|
||||
o_alu_opcode <= `ALU_OP_COPY;
|
||||
o_alu_reg_dest <= regs_BCAC;
|
||||
o_alu_reg_src_1 <= regs_ABCD;
|
||||
end
|
||||
2'b11:
|
||||
begin
|
||||
o_alu_opcode <= `ALU_OP_EXCH;
|
||||
o_alu_reg_dest <= regs_ABAC;
|
||||
o_alu_reg_src_1 <= regs_ABAC;
|
||||
o_alu_reg_src_2 <= regs_BCCD;
|
||||
end
|
||||
endcase
|
||||
o_instr_decoded <= 1'b1;
|
||||
o_instr_execute <= 1'b1;
|
||||
decode_started <= 1'b0;
|
||||
block_Dx <= 1'b0;
|
||||
end
|
||||
|
||||
/* special cases */
|
||||
|
||||
if (block_JUMP) begin
|
||||
|
@ -649,6 +695,7 @@ always @(posedge i_clk) begin
|
|||
block_Ax <= 1'b0;
|
||||
block_Aax <= 1'b0;
|
||||
block_Abx <= 1'b0;
|
||||
block_Dx <= 1'b0;
|
||||
|
||||
block_JUMP <= 1'b0;
|
||||
block_LOAD <= 1'b0;
|
||||
|
|
Loading…
Reference in a new issue