Implement RL r instruction
Some groundwork on rotation operations
This commit is contained in:
parent
da29d148bf
commit
4f892eb3f2
@ -11,6 +11,9 @@ module alu (
|
||||
input logic [7:0] operand_i,
|
||||
input logic [2:0] inx8_i, // Only used for bit/set/res
|
||||
|
||||
input logic rot_op_valid_i,
|
||||
input rot_op_t rot_op_i,
|
||||
|
||||
input alu16_op_t alu16_op_i,
|
||||
input logic [15:0] inx16_i,
|
||||
input logic [15:0] iny16_i,
|
||||
@ -18,7 +21,7 @@ module alu (
|
||||
output logic [ 7:0] a_o,
|
||||
output logic [ 7:0] f_o,
|
||||
|
||||
output logic [ 7:0] out8_o, // Only used for inc/dec reg8
|
||||
output logic [ 7:0] out8_o, // Only used for inc/dec reg8 and rot
|
||||
output logic [15:0] out16_o
|
||||
);
|
||||
|
||||
@ -39,8 +42,12 @@ module alu (
|
||||
logic [ 7:0] a_bit; // Never written, only to test
|
||||
logic [ 7:0] f_bit;
|
||||
|
||||
|
||||
logic [ 7:0] out8_incr;
|
||||
logic [ 7:0] f_incr;
|
||||
logic [ 7:0] out8_inc;
|
||||
|
||||
logic [ 7:0] out8_rl;
|
||||
logic [ 7:0] f_rl;
|
||||
|
||||
logic [15:0] out16_inc;
|
||||
logic [15:0] out16_dec;
|
||||
@ -49,17 +56,18 @@ module alu (
|
||||
`DEF_FF(f_r, f_next, f_we, '0);
|
||||
|
||||
assign a_we = alu_op_valid_i;
|
||||
assign a_next = (alu_op_i == ALU_OP_XOR) ? a_xor :
|
||||
(alu_op_i == ALU_OP_NOP) ? operand_i :
|
||||
(alu_op_i == ALU_OP_INC) ? a_inc :
|
||||
a_r;
|
||||
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 :
|
||||
a_r;
|
||||
|
||||
assign f_we = alu_op_valid_i;
|
||||
assign f_next = (alu_op_i == ALU_OP_XOR) ? f_xor :
|
||||
(alu_op_i == ALU_OP_BIT) ? f_bit :
|
||||
(alu_op_i == ALU_OP_INC) ? f_inc :
|
||||
(alu_op_i == ALU_OP_INCR) ? f_incr :
|
||||
f_r;
|
||||
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 a_xor = (a_r ^ operand_i);
|
||||
assign f_xor = {~(|a_xor), 3'b0, f_r[3:0]};
|
||||
@ -70,16 +78,19 @@ module alu (
|
||||
assign a_bit = (operand_i - {4'b0, inx8_i});
|
||||
assign f_bit = {~(|a_bit), 2'b10, f_r[4:0]};
|
||||
|
||||
assign f_incr = {~(|out8_inc), 1'b0, out8_inc[4], f_r[3:0]};
|
||||
assign out8_rl = {operand_i[6:0], f_r[4]};
|
||||
assign f_rl = {~(|out8_rl), 2'b0, operand_i[7], f_r[3:0]};
|
||||
|
||||
assign out8_inc = (operand_i + 8'h01);
|
||||
|
||||
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 = out8_inc;
|
||||
assign out8_o = ({8{alu_op_valid_i}} & out8_incr) | {8{rot_op_valid_i}} & out8_rl;
|
||||
assign out16_o = out16_dec;
|
||||
|
||||
endmodule : alu
|
@ -23,6 +23,8 @@ module control (
|
||||
output logic alu_op_valid_o,
|
||||
output alu_op_t alu_op_o,
|
||||
output logic reg_write_alu_o,
|
||||
output logic rot_op_valid_o,
|
||||
output rot_op_t rot_op_o,
|
||||
output op_src_t op_src_o,
|
||||
output op_dest_t op_dest_o,
|
||||
output reg8_t reg8_dest_o,
|
||||
@ -75,6 +77,7 @@ module control (
|
||||
logic decoder_is_multicycle;
|
||||
logic decoder_is_undef;
|
||||
logic decoder_alu_op_valid;
|
||||
logic decoder_rot_op_valid;
|
||||
logic decoder_memory_we;
|
||||
adr_src_t decoder_adr_src;
|
||||
logic decoder_sp_we;
|
||||
@ -164,6 +167,8 @@ module control (
|
||||
.alu_op_valid_o(decoder_alu_op_valid),
|
||||
.alu_op_o (alu_op_o),
|
||||
.reg_write_alu_o(reg_write_alu_o),
|
||||
.rot_op_valid_o(decoder_rot_op_valid),
|
||||
.rot_op_o (rot_op_o),
|
||||
.op_src_o (op_src_o),
|
||||
.op_dest_o (op_dest_o),
|
||||
|
||||
@ -188,6 +193,7 @@ module control (
|
||||
assign is_undef = instr_valid & decoder_is_undef;
|
||||
assign instr_valid = (state_r == ST2_EXEC | state_r == ST3_EXEC | state_r == ST4_EXEC | state_r == ST5_EXEC);
|
||||
assign alu_op_valid_o = decoder_alu_op_valid & instr_valid;
|
||||
assign rot_op_valid_o = decoder_rot_op_valid & instr_valid;
|
||||
|
||||
assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2);
|
||||
|
||||
|
@ -20,6 +20,8 @@ module cpu (
|
||||
op_dest_t op_dest;
|
||||
adr_src_t adr_src;
|
||||
logic reg_write_alu;
|
||||
logic rot_op_valid;
|
||||
rot_op_t rot_op;
|
||||
|
||||
logic [ 7:0] alu_operand;
|
||||
|
||||
@ -63,6 +65,8 @@ module cpu (
|
||||
.alu_op_valid_o(alu_op_valid),
|
||||
.alu_op_o (alu_op),
|
||||
.reg_write_alu_o(reg_write_alu),
|
||||
.rot_op_valid_o(rot_op_valid),
|
||||
.rot_op_o (rot_op),
|
||||
.op_src_o (op_src),
|
||||
.op_dest_o (op_dest),
|
||||
.instr_valid_o (instr_valid),
|
||||
@ -83,6 +87,8 @@ module cpu (
|
||||
.nreset_i (nreset_i),
|
||||
.alu_op_valid_i(alu_op_valid),
|
||||
.alu_op_i (alu_op),
|
||||
.rot_op_valid_i(rot_op_valid),
|
||||
.rot_op_i (rot_op),
|
||||
.operand_i (alu_operand),
|
||||
.inx8_i (operand8[5:3]), // Used for bit/set/res
|
||||
.a_o (rega),
|
||||
|
@ -55,6 +55,17 @@ package cpu_pkg;
|
||||
ALU_OP_INCR = 5'h11 // Increment register instead of a
|
||||
} alu_op_t;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
ROT_OP_RLC = 3'h00,
|
||||
ROT_OP_RRC = 3'h01,
|
||||
ROT_OP_RL = 3'h02,
|
||||
ROT_OP_RR = 3'h03,
|
||||
ROT_OP_SLA = 3'h04,
|
||||
ROT_OP_SRA = 3'h05,
|
||||
ROT_OP_SLL = 3'h06,
|
||||
ROT_OP_SRL = 3'h07
|
||||
} rot_op_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
ALU16_OP_ADD = 2'h00,
|
||||
ALU16_INC = 2'h01,
|
||||
|
@ -20,6 +20,8 @@ module decode (
|
||||
output logic alu_op_valid_o,
|
||||
output alu_op_t alu_op_o,
|
||||
output logic reg_write_alu_o,
|
||||
output logic rot_op_valid_o,
|
||||
output rot_op_t rot_op_o,
|
||||
output op_src_t op_src_o,
|
||||
output op_dest_t op_dest_o,
|
||||
|
||||
@ -58,6 +60,7 @@ module decode (
|
||||
logic is_ldd_hl_a;
|
||||
logic is_alu_a_r;
|
||||
logic is_bit_n_r;
|
||||
logic is_rot_r;
|
||||
logic is_inc_a;
|
||||
logic is_inc_r;
|
||||
logic is_jr_cc_n;
|
||||
@ -91,6 +94,7 @@ module decode (
|
||||
|
||||
assign is_alu_a_r = (dec_x == 3'h2);
|
||||
assign is_bit_n_r = (is_cb & instr1_i[7:6] == 2'h1);
|
||||
assign is_rot_r = (is_cb & instr1_i[7:6] == 2'h0);
|
||||
|
||||
assign is_inc_a = is_inc_r & (reg8_dest == REG8_A);
|
||||
assign is_inc_r = (dec_x == 2'h0) & (dec_z == 3'h4);
|
||||
@ -105,7 +109,8 @@ module decode (
|
||||
(is_push_rr & state_i == ST2_EXEC) ? reg8_t'({dec_p, 1'b0}) :
|
||||
(is_push_rr & state_i == ST3_EXEC) ? reg8_t'({dec_p, 1'b1}) :
|
||||
reg8_t'(dec_z);
|
||||
assign reg8_dest = reg8_t'(dec_y);
|
||||
assign reg8_dest = is_rot_r ? reg8_t'(dec_z) :
|
||||
reg8_t'(dec_y);
|
||||
|
||||
assign reg16_src = is_ldd_hl_a ? REG16_HL : reg16_t'(dec_p);
|
||||
|
||||
@ -115,7 +120,7 @@ module decode (
|
||||
|
||||
assign undef_o = ~(is_ldh_n_a | is_ld_r_r | is_ld_sp_nn | is_ld_rr_nn | is_alu_a_r | is_ldd_hl_a | is_bit_n_r |
|
||||
is_jr_cc_n | is_ld_r_n | is_ldh_c_a | is_inc_r | is_ld_rr_a | is_ld_a_rr | is_call_nn |
|
||||
is_push_rr);
|
||||
is_push_rr | (is_rot_r & (instr1_i[5:3] == 3'h02)));
|
||||
|
||||
assign sp_we_o = is_ld_sp_nn | is_call_nn | is_push_rr;
|
||||
assign sp_src_o = is_ld_sp_nn ? SP_SRC_OPERAND16 :
|
||||
@ -131,7 +136,10 @@ module decode (
|
||||
is_inc_a ? ALU_OP_INC :
|
||||
is_inc_r ? ALU_OP_INCR :
|
||||
alu_op_t'({1'b0, dec_y});
|
||||
assign reg_write_alu_o = is_inc_r;
|
||||
assign reg_write_alu_o = is_inc_r | is_rot_r;
|
||||
|
||||
assign rot_op_valid_o = is_rot_r;
|
||||
assign rot_op_o = rot_op_t'(instr1_i[5:3]);
|
||||
|
||||
assign op_dest_o = (is_ld_r_r & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY :
|
||||
(is_ld_r_n & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY :
|
||||
@ -149,6 +157,7 @@ module decode (
|
||||
is_inc_r ? OP_DEST_REG8 :
|
||||
is_call_nn ? OP_DEST_MEMORY :
|
||||
is_push_rr ? OP_DEST_MEMORY :
|
||||
is_rot_r ? OP_DEST_REG8 :
|
||||
op_dest_t'('X);
|
||||
|
||||
assign op_src_o = (is_ld_r_r & reg8_src == REG8_A) ? OP_SRC_A :
|
||||
@ -164,6 +173,7 @@ module decode (
|
||||
is_ld_rr_nn ? OP_SRC_OPERAND16 :
|
||||
is_ldd_hl_a ? OP_SRC_REG16 :
|
||||
is_bit_n_r ? OP_SRC_REG8 :
|
||||
is_rot_r ? OP_SRC_REG8 :
|
||||
(is_call_nn & state_i == ST4_EXEC) ? OP_SRC_PC_L :
|
||||
(is_call_nn & state_i == ST5_EXEC) ? OP_SRC_PC_H :
|
||||
(is_push_rr & reg16_src != REG16_SP_AF) ? OP_SRC_REG8 :
|
||||
|
@ -18,6 +18,8 @@ module tb_top ();
|
||||
logic halted;
|
||||
logic [15:0] last_pc;
|
||||
logic [ 7:0] last_opcode;
|
||||
logic [ 7:0] last_op1;
|
||||
logic [ 7:0] last_op2;
|
||||
|
||||
logic we;
|
||||
logic [15:0] address;
|
||||
@ -27,6 +29,8 @@ module tb_top ();
|
||||
assign instr_undef = gb_inst.cpu_inst.control_inst.is_undef;
|
||||
assign last_pc = gb_inst.cpu_inst.control_inst.instr_pc_r;
|
||||
assign last_opcode = gb_inst.cpu_inst.control_inst.instr_r;
|
||||
assign last_op1 = gb_inst.cpu_inst.control_inst.operand0_r;
|
||||
assign last_op2 = gb_inst.cpu_inst.control_inst.operand1_r;
|
||||
|
||||
assign we = gb_inst.we;
|
||||
assign address = gb_inst.address;
|
||||
@ -34,11 +38,12 @@ module tb_top ();
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (nreset && instr_undef & ~halted) begin
|
||||
$display($sformatf("[%t] %X: Undefined opcode %X", $time(), last_pc, last_opcode));
|
||||
$display($sformatf("[%0t] %X: Undefined opcode %X | [%X | %X]", $time(), last_pc, last_opcode, last_op1, last_op2));
|
||||
$fatal(0);
|
||||
$finish();
|
||||
end
|
||||
if (nreset && we) begin
|
||||
$display($sformatf("[%t] Write: [%X] <= %X", $time(), address, wdata));
|
||||
$display($sformatf("[%0t] Write: [%X] <= %X", $time(), address, wdata));
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user