blob: 842c9a20593c1327a64831c328b544866677c419 [file] [log] [blame] [edit]
`default_nettype none
module serv_alu
(
input wire clk,
input wire i_rst,
input wire i_en,
input wire i_rs1,
input wire i_op_b,
input wire i_buf,
input wire i_init,
input wire i_cnt_done,
input wire i_sub,
input wire [1:0] i_bool_op,
input wire i_cmp_eq,
input wire i_cmp_uns,
output wire o_cmp,
input wire i_shamt_en,
input wire i_sh_right,
input wire i_sh_signed,
output wire o_sh_done,
input wire [1:0] i_rd_sel,
output wire o_rd);
`include "serv_params.vh"
wire result_add;
wire result_eq;
wire result_lt;
wire result_sh;
reg result_lt_r;
wire [4:0] shamt;
reg shamt_msb;
reg en_r;
wire shamt_ser;
wire plus_1;
wire b_inv_plus_1;
assign shamt_ser = i_sh_right ? i_op_b : b_inv_plus_1;
shift_reg #(.LEN (5)) shamt_reg
(.clk (clk),
.i_rst (i_rst),
.i_en (i_shamt_en),
.i_d (shamt_ser),
.o_q (shamt[0]),
.o_par (shamt[4:1]));
ser_shift shift
(
.i_clk (clk),
.i_load (i_init),
.i_shamt (shamt),
.i_shamt_msb (shamt_msb),
.i_signbit (i_sh_signed & i_rs1),
.i_right (i_sh_right),
.o_done (o_sh_done),
.i_d (i_buf),
.o_q (result_sh));
wire b_inv_plus_1_cy;
always @(posedge clk)
if (i_shamt_en)
shamt_msb <= b_inv_plus_1_cy;
ser_add ser_add_inv_plus_1
(
.clk (clk),
.rst (i_rst),
.a (~i_op_b),
.b (plus_1),
.clr (!i_en),
.q (b_inv_plus_1),
.o_v (b_inv_plus_1_cy));
wire add_b = i_sub ? b_inv_plus_1 : i_op_b;
ser_add ser_add
(
.clk (clk),
.rst (i_rst),
.a (i_rs1),
.b (add_b),
.clr (!i_en),
.q (result_add),
.o_v ());
ser_lt ser_lt
(
.i_clk (clk),
.i_a (i_rs1),
.i_b (i_op_b),
.i_clr (!i_init),
.i_sign (i_cnt_done & !i_cmp_uns),
.o_q (result_lt));
assign plus_1 = i_en & !en_r;
assign o_cmp = i_cmp_eq ? result_eq : result_lt;
localparam [15:0] BOOL_LUT = 16'h8E96;//And, Or, =, xor
wire result_bool = BOOL_LUT[{i_bool_op, i_rs1, i_op_b}];
assign o_rd = (i_rd_sel == ALU_RESULT_ADD) ? result_add :
(i_rd_sel == ALU_RESULT_SR) ? result_sh :
(i_rd_sel == ALU_RESULT_LT) ? result_lt_r & plus_1:
(i_rd_sel == ALU_RESULT_BOOL) ? result_bool : 1'bx;
reg eq_r;
always @(posedge clk) begin
if (i_init) begin
result_lt_r <= result_lt;
eq_r <= result_eq;
end else begin
eq_r <= 1'b1;
end
en_r <= i_en;
end
assign result_eq = eq_r & (i_rs1 == i_op_b);
endmodule