`include "cpu_pkg.svh" import cpu_pkg::*; module alu ( input logic clk, input logic nreset, input alu_ctrl_t alu_ctrl_i, input logic [ 7:0] operand_in_i, output logic [ 7:0] operand_out_o, output logic [ 7:0] reg_a_o, output logic [ 7:0] reg_f_o ); logic nop_valid; 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; always_ff @(posedge clk or negedge nreset) begin if (!nreset) a_r <= '0; else if (a_we) a_r <= a_next; end 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] incdec_input; logic [ 7:0] inc_a; logic [ 7:0] inc_f; logic [ 7:0] dec_a; logic [ 7:0] dec_f; assign incdec_input = alu_ctrl_i.incdec_op.dst_a ? a_r : operand_in_i; assign incdec_a = ({8{alu_ctrl_i.incdec_op.inc}} & inc_a) | ({8{alu_ctrl_i.incdec_op.dec}} & dec_a); assign incdec_f = ({8{alu_ctrl_i.incdec_op.inc}} & inc_f) | ({8{alu_ctrl_i.incdec_op.dec}} & dec_f); 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 dec_a = incdec_input - 8'h01; assign dec_f = {~(|dec_a), 1'b1, dec_a[4], f_r[4], 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); `include "sva_common.svh" `SVA_DEF_CLK(clk); `SVA_DEF_NRESET(nreset); `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) ); `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) ); endmodule : alu