2021-02-17 00:05:46 +01:00
|
|
|
`include "cpu_pkg.svh"
|
|
|
|
|
|
|
|
import cpu_pkg::*;
|
|
|
|
|
|
|
|
module alu (
|
2023-10-02 00:00:56 +02:00
|
|
|
input logic clk,
|
|
|
|
input logic nreset,
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
input alu_ctrl_t alu_ctrl_i,
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
input logic [ 7:0] operand_in_i,
|
|
|
|
output logic [ 7:0] operand_out_o,
|
2022-02-08 17:14:57 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
output logic [ 7:0] reg_a_o,
|
|
|
|
output logic [ 7:0] reg_f_o
|
|
|
|
);
|
2021-02-19 00:22:26 +01:00
|
|
|
|
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
logic [ 7:0] incdec_a;
|
|
|
|
logic [ 7:0] incdec_f;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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);
|
2021-02-20 23:57:15 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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);
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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;
|
2021-02-19 22:53:13 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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);
|
2022-02-08 17:14:57 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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
|
2022-02-08 17:14:57 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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
|
2021-02-20 23:57:15 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
assign xor_a = a_r ^ operand_in_i;
|
|
|
|
assign xor_f = {~(|xor_a), 3'b0, f_r[3:0]};
|
2021-02-19 00:22:26 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
assign cp_a = a_r;
|
|
|
|
assign cp_f = sub_f;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
logic [ 7:0] bit_a;
|
|
|
|
logic [ 7:0] bit_f;
|
2022-02-08 17:14:57 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
assign bsr_a = ({8{alu_ctrl_i.bsr_op.b}} & bit_a);
|
|
|
|
assign bsr_f = ({8{alu_ctrl_i.bsr_op.b}} & bit_f);
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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]};
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
logic [ 7:0] rl_a;
|
|
|
|
logic [ 7:0] rl_f;
|
2021-02-20 23:57:15 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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);
|
2021-02-19 22:53:13 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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]};
|
2022-02-08 17:14:57 +01:00
|
|
|
|
2021-02-20 23:57:15 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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;
|
2021-02-20 23:57:15 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
assign incdec_input = alu_ctrl_i.incdec_op.dst_a ? a_r :
|
|
|
|
operand_in_i;
|
2021-02-19 00:22:26 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
assign incdec_a = ({8{alu_ctrl_i.incdec_op.inc}} & inc_a) |
|
|
|
|
({8{alu_ctrl_i.incdec_op.dec}} & dec_a);
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
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)
|
|
|
|
);
|
2021-02-19 00:22:26 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
endmodule : alu
|