| `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 |