// Certain arithmetic operations between a signal of width n and a constant can be directly mapped // to a single k-LUT (where n <= k). This is preferable to normal alumacc techmapping process // because for many targets, arithmetic techmapping creates hard logic (such as carry cells) which often // cannot be optimized further. // // TODO: Currently, only comparisons with 1-bit output are mapped. Potentially, all arithmetic cells // with n <= k inputs should be techmapped in this way, because this shortens the critical path // from n to 1 by avoiding carry chains. (* techmap_celltype = "$eq $ne $lt $le $gt $ge" *) module _90_lut_cmp_ (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; parameter _TECHMAP_CONSTMSK_A_ = 0; parameter _TECHMAP_CONSTVAL_A_ = 0; parameter _TECHMAP_CONSTMSK_B_ = 0; parameter _TECHMAP_CONSTVAL_B_ = 0; function automatic integer gen_lut; input integer width; input integer operation; input integer swap; input integer sign; input integer operand; integer n, i_var, i_cst, lhs, rhs, o_bit; begin gen_lut = width'b0; for (n = 0; n < (1 << width); n++) begin if (sign) i_var = n[width-1:0]; else i_var = n; i_cst = operand; if (swap) begin lhs = i_cst; rhs = i_var; end else begin lhs = i_var; rhs = i_cst; end if (operation == 0) o_bit = (lhs < rhs); if (operation == 1) o_bit = (lhs <= rhs); if (operation == 2) o_bit = (lhs > rhs); if (operation == 3) o_bit = (lhs >= rhs); if (operation == 4) o_bit = (lhs == rhs); if (operation == 5) o_bit = (lhs != rhs); gen_lut = gen_lut | (o_bit << n); end end endfunction generate if (_TECHMAP_CELLTYPE_ == "$lt") localparam operation = 0; if (_TECHMAP_CELLTYPE_ == "$le") localparam operation = 1; if (_TECHMAP_CELLTYPE_ == "$gt") localparam operation = 2; if (_TECHMAP_CELLTYPE_ == "$ge") localparam operation = 3; if (_TECHMAP_CELLTYPE_ == "$eq") localparam operation = 4; if (_TECHMAP_CELLTYPE_ == "$ne") localparam operation = 5; if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) wire _TECHMAP_FAIL_ = 1; else if (&_TECHMAP_CONSTMSK_B_) \$lut #( .WIDTH(A_WIDTH), .LUT({ gen_lut(A_WIDTH, operation, 0, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_B_) }) ) _TECHMAP_REPLACE_ ( .A(A), .Y(Y) ); else if (&_TECHMAP_CONSTMSK_A_) \$lut #( .WIDTH(B_WIDTH), .LUT({ gen_lut(B_WIDTH, operation, 1, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_A_) }) ) _TECHMAP_REPLACE_ ( .A(B), .Y(Y) ); else wire _TECHMAP_FAIL_ = 1; endgenerate endmodule