`include "cpu_pkg.svh" import cpu_pkg::*; module control ( input logic clk_i, input logic nreset_i, input logic [ 7:0] rdata_i, input logic [ 7:0] f_i, output state_t state_o, output logic [15:0] pc_o, output logic [15:0] sp_o, output logic instr_valid_o, output logic instr_undef_o, output logic [ 7:0] operand8_o, output logic [15:0] operand16_o, 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, output reg8_t reg8_src_o, output alu16_op_t alu16_op_o, output reg16_t reg16_src_o, output reg16_t reg16_dest_o, output logic memory_we_o, output adr_src_t adr_src_o ); logic nreset_r; logic halted_r; logic state_we; state_t state_r; state_t state_next; logic pc_we; logic [15:0] pc_r; logic [15:0] pc_next; logic sp_we; logic [15:0] sp_r; logic [15:0] sp_next; logic instr_pc_we; logic [15:0] instr_pc_r; logic [15:0] instr_pc_next; logic instr_we; logic [ 7:0] instr_r; logic [ 7:0] instr_next; logic operand0_we; logic [ 7:0] operand0_r; logic [ 7:0] operand0_next; logic operand1_we; logic [ 7:0] operand1_r; logic [ 7:0] operand1_next; logic [ 7:0] decoder_instr0_selected; logic [ 7:0] decoder_instr1_selected; logic [ 7:0] decoder_instr2_selected; logic decoder_need_instr1; logic decoder_need_instr2; 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; logic is_undef; logic pc_incr; logic instr_valid; logic branch_taken; logic branch_cc_true; logic branch_always; sp_src_t sp_src; pc_src_t pc_src; cc_t cc; always_ff @(posedge clk_i) begin nreset_r <= nreset_i; end always_ff @(posedge clk_i or negedge nreset_i) begin if (~nreset_i) halted_r <= 1'b0; else if (is_undef) halted_r <= halted_r | is_undef; end `DEF_FF(state_r, state_next, state_we, ST0_ADDR); `DEF_FF(pc_r, pc_next, pc_we, '0); `DEF_FF(sp_r, sp_next, sp_we, '0); `DEF_FF(instr_pc_r, instr_pc_next, instr_pc_we, '0); `DEF_FF(instr_r, instr_next, instr_we, '0); `DEF_FF(operand0_r, operand0_next, operand0_we, '0); `DEF_FF(operand1_r, operand1_next, operand1_we, '0); assign pc_we = (nreset_r & ~is_undef & ~halted_r) & (pc_incr | branch_taken); assign pc_next = (branch_taken & pc_src == PC_SRC_OPERAND8) ? (pc_r + {{8{operand0_r[7]}}, operand0_r}) : (branch_taken & pc_src == PC_SRC_OPERAND16) ? {operand1_r, operand0_r} : (pc_r + 16'b1); assign sp_we = instr_valid & decoder_sp_we; assign sp_next = (sp_src == SP_SRC_OPERAND16) ? {operand1_r, operand0_r} : (sp_src == SP_SRC_INC) ? (sp_r + 16'h01) : (sp_src == SP_SRC_DEC) ? (sp_r + 16'hFFFF) : '0; assign instr_we = (state_r == ST1_DEC); assign instr_next = rdata_i; assign instr_pc_we = (state_r == ST0_ADDR); assign instr_pc_next = pc_r; assign operand0_we = (state_r == ST2_DEC); assign operand0_next = rdata_i; assign operand1_we = (state_r == ST3_DEC); assign operand1_next = rdata_i; assign state_we = nreset_r & ~is_undef & ~halted_r; always_comb begin case (state_r) ST0_ADDR: state_next = ST1_DEC; ST1_DEC: state_next = decoder_need_instr1 ? ST2_DEC : ST2_EXEC; ST2_EXEC: state_next = decoder_is_multicycle ? ST3_EXEC : ST0_ADDR; ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST3_EXEC; ST3_DEC: state_next = ST4_EXEC; ST3_EXEC: state_next = ST0_ADDR; ST4_EXEC: state_next = decoder_is_multicycle ? ST5_EXEC : ST0_ADDR; ST5_EXEC: state_next = ST0_ADDR; endcase end decode decode_inst ( .instr0_i (decoder_instr0_selected), .instr1_i (decoder_instr1_selected), .instr2_i (decoder_instr2_selected), .state_i (state_r), .need_instr1_o (decoder_need_instr1), .need_instr2_o (decoder_need_instr2), .is_multicycle_o(decoder_is_multicycle), .undef_o (decoder_is_undef), .sp_we_o (decoder_sp_we), .sp_src_o (sp_src), .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), .reg8_dest_o (reg8_dest_o), .reg8_src_o (reg8_src_o), .alu16_op_o (alu16_op_o), .reg16_src_o (reg16_src_o), .reg16_dest_o (reg16_dest_o), .memory_we_o (decoder_memory_we), .adr_src_o (decoder_adr_src), .branch_always_o(branch_always), .cc_o (cc), .pc_src_o (pc_src) ); assign decoder_instr0_selected = (state_r == ST1_DEC) ? rdata_i : instr_r; assign decoder_instr1_selected = (state_r == ST2_DEC) ? rdata_i : operand0_r; assign decoder_instr2_selected = (state_r == ST3_DEC) ? rdata_i : operand1_r; 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); assign branch_taken = instr_valid & (pc_src != PC_SRC_SEQ) & (branch_cc_true | branch_always); assign branch_cc_true = ((cc == CC_NZ) & ~f_i[7]) | ((cc == CC_Z) & f_i[7]) | ((cc == CC_NC) & ~f_i[4]) | ((cc == CC_C) & f_i[4]); assign state_o = state_r; assign pc_o = pc_r; assign sp_o = sp_r; assign instr_valid_o = instr_valid; assign instr_undef_o = is_undef; assign operand8_o = operand0_r; assign operand16_o = {operand1_r, operand0_r}; assign memory_we_o = instr_valid & decoder_memory_we; assign adr_src_o = instr_valid ? decoder_adr_src : ADR_SRC_PC; endmodule : control