Complete rewrite from scratch, bootstrap WIP

Rewrite to use several bus multiplexers, resulting into a less messy
microarchitecture (hopefully). Some more room for cleanup though...

Supports every instruction from the bootstrap rom, more or less.
LY hacked at 0x90 to progress through vsync instantly.
No cartridge is present yet, so we will always fail checksum test and lock up.
This commit is contained in:
2023-10-01 23:00:56 +01:00
parent e713f8de87
commit fda176d3b5
23 changed files with 1425 additions and 956 deletions

View File

@@ -3,95 +3,167 @@
import cpu_pkg::*;
module alu (
input logic clk_i,
input logic nreset_i,
input logic clk,
input logic nreset,
input logic alu_op_valid_i,
input alu_op_t alu_op_i,
input logic [7:0] operand_i,
input logic [2:0] inx8_i, // Only used for bit/set/res
input alu_ctrl_t alu_ctrl_i,
input logic rot_op_valid_i,
input rot_op_t rot_op_i,
input logic [ 7:0] operand_in_i,
output logic [ 7:0] operand_out_o,
input alu16_op_t alu16_op_i,
input logic [15:0] inx16_i,
input logic [15:0] iny16_i,
output logic [ 7:0] a_o,
output logic [ 7:0] f_o,
output logic [ 7:0] out8_o, // Only used for inc/dec reg8 and rot
output logic [15:0] out16_o
output logic [ 7:0] reg_a_o,
output logic [ 7:0] reg_f_o
);
logic a_we;
logic [ 7:0] a_r;
logic [ 7:0] a_next;
logic f_we;
logic [ 7:0] f_r;
logic [ 7:0] f_next;
logic nop_valid;
logic a_we;
logic [ 7:0] a_r;
logic [ 7:0] a_next;
logic [ 7:0] a_inc;
logic [ 7:0] f_inc;
logic f_we;
logic [ 7:0] f_r;
logic [ 7:0] f_next;
logic [ 7:0] a_xor;
logic [ 7:0] f_xor;
always_ff @(posedge clk or negedge nreset) begin
if (!nreset)
a_r <= '0;
else if (a_we)
a_r <= a_next;
end
logic [ 7:0] a_bit; // Never written, only to test
logic [ 7:0] f_bit;
always_ff @(posedge clk or negedge nreset) begin
if (!nreset)
f_r <= '0;
else if (f_we)
f_r <= f_next;
end
assign a_we = alu_ctrl_i.update_a;
assign f_we = alu_ctrl_i.update_f;
assign reg_a_o = a_r;
assign reg_f_o = f_r;
logic [ 7:0] alu_a;
logic [ 7:0] alu_f;
logic [ 7:0] shift_a;
logic [ 7:0] shift_f;
logic [ 7:0] bsr_a;
logic [ 7:0] bsr_f;
logic [ 7:0] incdec_a;
logic [ 7:0] incdec_f;
assign nop_valid = ~alu_ctrl_i.alu_op_valid &
~alu_ctrl_i.shift_op_valid &
~alu_ctrl_i.bsr_op_valid &
~alu_ctrl_i.incdec_op_valid;
assign a_next = ({8{alu_ctrl_i.alu_op_valid }} & alu_a) |
({8{alu_ctrl_i.shift_op_valid }} & shift_a) |
({8{alu_ctrl_i.bsr_op_valid }} & bsr_a) |
({8{alu_ctrl_i.incdec_op_valid}} & incdec_a) |
({8{nop_valid }} & operand_in_i);
assign f_next = ({8{alu_ctrl_i.alu_op_valid }} & alu_f) |
({8{alu_ctrl_i.shift_op_valid }} & shift_f) |
({8{alu_ctrl_i.bsr_op_valid }} & bsr_f) |
({8{alu_ctrl_i.incdec_op_valid}} & incdec_f) |
({8{nop_valid }} & operand_in_i);
logic [ 8:0] add_a;
logic [ 7:0] add_f;
logic [ 8:0] sub_a;
logic [ 7:0] sub_f;
logic [ 7:0] xor_a;
logic [ 7:0] xor_f;
logic [ 7:0] cp_a;
logic [ 7:0] cp_f;
assign alu_a = ({8{alu_ctrl_i.alu_op == ALU_OP_ADD}} & add_a) |
({8{alu_ctrl_i.alu_op == ALU_OP_SUB}} & sub_a) |
({8{alu_ctrl_i.alu_op == ALU_OP_XOR}} & xor_a) |
({8{alu_ctrl_i.alu_op == ALU_OP_CP }} & cp_a);
assign alu_f = ({8{alu_ctrl_i.alu_op == ALU_OP_ADD}} & add_f) |
({8{alu_ctrl_i.alu_op == ALU_OP_SUB}} & sub_f) |
({8{alu_ctrl_i.alu_op == ALU_OP_XOR}} & xor_f) |
({8{alu_ctrl_i.alu_op == ALU_OP_CP }} & cp_f);
assign add_a = {1'b0, a_r} + {1'b0, operand_in_i};
assign add_f = {~(|sub_a[7:0]), 1'b0, 1'b0, sub_a[8], f_r[3:0]}; // TODO: implement H
assign sub_a = {1'b0, a_r} - {1'b0, operand_in_i};
assign sub_f = {~(|sub_a[7:0]), 1'b1, 1'b0, sub_a[8], f_r[3:0]}; // TODO: implement H
assign xor_a = a_r ^ operand_in_i;
assign xor_f = {~(|xor_a), 3'b0, f_r[3:0]};
assign cp_a = a_r;
assign cp_f = sub_f;
logic [ 7:0] bit_a;
logic [ 7:0] bit_f;
assign bsr_a = ({8{alu_ctrl_i.bsr_op.b}} & bit_a);
assign bsr_f = ({8{alu_ctrl_i.bsr_op.b}} & bit_f);
assign bit_a = {7'b0, ~operand_in_i[alu_ctrl_i.bsr_op.operand]};
assign bit_f = {bit_a[0], 2'b10, f_r[4:0]};
logic [ 7:0] rl_a;
logic [ 7:0] rl_f;
assign shift_a = ({8{alu_ctrl_i.shift_op == SHIFT_OP_RL}} & rl_a);
assign shift_f = ({8{alu_ctrl_i.shift_op == SHIFT_OP_RL}} & rl_f);
assign rl_a = {operand_in_i[6:0], f_r[4]};
assign rl_f = {~(|rl_a), 2'b0, operand_in_i[7], f_r[3:0]};
logic [ 7:0] out8_incr;
logic [ 7:0] f_incr;
logic [ 7:0] incdec_input;
logic [ 7:0] inc_a;
logic [ 7:0] inc_f;
logic [ 7:0] dec_a;
logic [ 7:0] dec_f;
logic [ 7:0] out8_rl;
logic [ 7:0] f_rl;
assign incdec_input = alu_ctrl_i.incdec_op.dst_a ? a_r :
operand_in_i;
logic [15:0] out16_inc;
logic [15:0] out16_dec;
assign incdec_a = ({8{alu_ctrl_i.incdec_op.inc}} & inc_a) |
({8{alu_ctrl_i.incdec_op.dec}} & dec_a);
`DEF_FF(a_r, a_next, a_we, '0);
`DEF_FF(f_r, f_next, f_we, '0);
assign incdec_f = ({8{alu_ctrl_i.incdec_op.inc}} & inc_f) |
({8{alu_ctrl_i.incdec_op.dec}} & dec_f);
assign a_we = alu_op_valid_i;
assign a_next = (alu_op_valid_i & (alu_op_i == ALU_OP_XOR)) ? a_xor :
(alu_op_valid_i & (alu_op_i == ALU_OP_NOP)) ? operand_i :
(alu_op_valid_i & (alu_op_i == ALU_OP_INC)) ? a_inc :
(alu_op_valid_i & (alu_op_i == ALU_OP_ROT) & (rot_op_i == ROT_OP_RL)) ? out8_rl :
a_r;
assign inc_a = incdec_input + 8'h01;
assign inc_f = {~(|inc_a), 1'b0, inc_a[4], f_r[4], f_r[3:0]};
assign f_we = alu_op_valid_i | rot_op_valid_i;
assign f_next = (alu_op_valid_i & (alu_op_i == ALU_OP_XOR)) ? f_xor :
(alu_op_valid_i & (alu_op_i == ALU_OP_BIT)) ? f_bit :
(alu_op_valid_i & (alu_op_i == ALU_OP_INC)) ? f_inc :
(alu_op_valid_i & (alu_op_i == ALU_OP_INCR)) ? f_incr :
(rot_op_valid_i & (rot_op_i == ROT_OP_RL)) ? f_rl :
f_r;
assign dec_a = incdec_input - 8'h01;
assign dec_f = {~(|dec_a), 1'b1, dec_a[4], f_r[4], f_r[3:0]};
assign a_xor = (a_r ^ operand_i);
assign f_xor = {~(|a_xor), 3'b0, f_r[3:0]};
assign operand_out_o = ({8{alu_ctrl_i.shift_op_valid }} & shift_a) |
({8{alu_ctrl_i.incdec_op_valid}} & incdec_a);
assign a_inc = (a_r + 8'h01);
assign f_inc = {~(|a_inc), 1'b0, a_inc[4], f_r[3:0]};
`include "sva_common.svh"
`SVA_DEF_CLK(clk);
`SVA_DEF_NRESET(nreset);
assign a_bit = (operand_i - {4'b0, inx8_i});
assign f_bit = {~(|a_bit), 2'b10, f_r[4:0]};
`SVA_ASSERT_PROP_FATAL(undefined_alu_op,
tb_top.gb_inst.cpu_inst.instr_valid & alu_ctrl_i.alu_op_valid |-> alu_ctrl_i.alu_op inside {ALU_OP_ADD, ALU_OP_SUB, ALU_OP_XOR, ALU_OP_CP},
$sformatf("Undefined alu operation pushed: 0x%X", alu_ctrl_i.alu_op)
);
assign out8_rl = {operand_i[6:0], f_r[4]};
assign f_rl = {~(|out8_rl), 2'b0, operand_i[7], f_r[3:0]};
`SVA_ASSERT_PROP_FATAL(undefined_shift_op,
tb_top.gb_inst.cpu_inst.instr_valid & alu_ctrl_i.shift_op_valid |-> alu_ctrl_i.shift_op inside {SHIFT_OP_RL},
$sformatf("Undefined shift operation pushed: 0x%X", alu_ctrl_i.shift_op)
);
`SVA_ASSERT_PROP_FATAL(undefined_bsr_op,
tb_top.gb_inst.cpu_inst.instr_valid & alu_ctrl_i.bsr_op_valid |-> alu_ctrl_i.bsr_op.b,
$sformatf("Undefined bsr operation pushed: 0x%X", alu_ctrl_i.bsr_op)
);
assign out8_incr = (operand_i + 8'h01);
assign f_incr = {~(|out8_incr), 1'b0, out8_incr[4], f_r[3:0]};
assign out16_dec = (inx16_i - 16'h01);
assign a_o = a_r;
assign f_o = f_r;
assign out8_o = ({8{alu_op_valid_i}} & out8_incr) | {8{rot_op_valid_i}} & out8_rl;
assign out16_o = out16_dec;
endmodule : alu
endmodule : alu