`include "cpu_pkg.svh" import cpu_pkg::*; module control ( input logic clk_i, input logic nreset_i, input logic [ 7:0] rdata_i, output state_t state_o, output logic [15:0] pc_o, output logic instr_valid_o, output logic instr_undef_o, output logic [ 7:0] operand8_o, output logic [15:0] operand16_o ); logic nreset_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 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_undef; logic is_undef; logic pc_incr; logic instr_valid; `define DEF_FF(register, next, we, rst_value) \ always_ff @(posedge clk_i or negedge nreset_i) begin \ if (~nreset_i) begin \ register <= (rst_value); \ end else if ((we)) begin \ register <= (next); \ end \ end always_ff @(posedge clk_i) begin nreset_r <= nreset_i; end `DEF_FF(state_r, state_next, state_we, ST0_ADDR); `DEF_FF(pc_r, pc_next, pc_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 & pc_incr & ~is_undef; assign pc_next = (pc_r + 16'b1); 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; 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 = ST0_ADDR; ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST0_ADDR; ST3_DEC: state_next = ST4_EXEC; ST4_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), .need_instr1_o(decoder_need_instr1), .need_instr2_o(decoder_need_instr2), .undef_o (decoder_is_undef) ); 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 = (state_r != ST0_ADDR & decoder_is_undef); assign instr_valid = (state_r == ST4_EXEC); assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2); assign state_o = state_r; assign pc_o = pc_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}; endmodule : control