svgb/rtl/cpu/alu.sv

170 lines
4.9 KiB
Systemverilog

`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[7:0]) |
({8{alu_ctrl_i.alu_op == ALU_OP_SUB}} & sub_a[7:0]) |
({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