mirror of
https://github.com/olofk/serv.git
synced 2025-04-19 19:37:06 -04:00
112 lines
2.6 KiB
Verilog
112 lines
2.6 KiB
Verilog
`default_nettype none
|
|
module serv_alu
|
|
(
|
|
input wire clk,
|
|
input wire i_rst,
|
|
input wire i_en,
|
|
input wire i_cnt0,
|
|
input wire i_rs1,
|
|
input wire i_rs2,
|
|
input wire i_imm,
|
|
input wire i_op_b_rs2,
|
|
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 [3:0] i_rd_sel,
|
|
output wire o_rd);
|
|
|
|
wire result_add;
|
|
wire result_eq;
|
|
wire result_lt;
|
|
wire result_sh;
|
|
|
|
reg result_lt_r;
|
|
|
|
wire [4:0] shamt;
|
|
reg shamt_msb;
|
|
|
|
wire shamt_ser;
|
|
wire plus_1;
|
|
|
|
wire add_cy;
|
|
reg add_cy_r;
|
|
|
|
wire b_inv_plus_1;
|
|
wire b_inv_plus_1_cy;
|
|
reg b_inv_plus_1_cy_r;
|
|
|
|
wire op_b = i_op_b_rs2 ? i_rs2 : i_imm;
|
|
assign shamt_ser = i_sh_right ? 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 add_b = i_sub ? b_inv_plus_1 : op_b;
|
|
assign {add_cy,result_add} = i_rs1+add_b+add_cy_r;
|
|
assign {b_inv_plus_1_cy,b_inv_plus_1} = {1'b0,~op_b}+plus_1+b_inv_plus_1_cy_r;
|
|
|
|
reg lt_r;
|
|
|
|
reg eq_r;
|
|
|
|
wire lt_sign = i_cnt_done & !i_cmp_uns;
|
|
|
|
wire eq = (i_rs1 == op_b);
|
|
|
|
assign result_eq = eq & eq_r;
|
|
assign result_lt = eq ? lt_r : op_b^lt_sign;
|
|
|
|
assign plus_1 = i_cnt0;
|
|
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, op_b}];
|
|
|
|
assign o_rd = (i_rd_sel[0] & result_add) |
|
|
(i_rd_sel[1] & result_sh) |
|
|
(i_rd_sel[2] & result_lt_r & plus_1) |
|
|
(i_rd_sel[3] & result_bool);
|
|
|
|
|
|
always @(posedge clk) begin
|
|
add_cy_r <= i_en & add_cy;
|
|
b_inv_plus_1_cy_r <= i_en & b_inv_plus_1_cy;
|
|
|
|
lt_r <= result_lt & i_en;
|
|
|
|
if (i_en) begin
|
|
result_lt_r <= result_lt;
|
|
end
|
|
eq_r <= result_eq | ~i_en;
|
|
|
|
if (i_shamt_en)
|
|
shamt_msb <= b_inv_plus_1_cy;
|
|
end
|
|
|
|
endmodule
|