yosys/techlibs/xilinx/abc9_map.v

809 lines
29 KiB
Coq
Raw Normal View History

2019-06-16 00:41:29 -05:00
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
2019-09-30 17:39:24 -05:00
// The following techmapping rules are intended to be run (with -max_iter 1)
// before invoking the `abc9` pass in order to transform the design into
// a format that it understands.
//
// For example, (complex) flip-flops are expected to be described as an
// combinatorial box (containing all control logic such as clock enable
// or synchronous resets) followed by a basic D-Q flop.
2019-10-07 14:54:45 -05:00
// Yosys will automatically analyse the simulation model (described in
// cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in
// order to extract the combinatorial control logic left behind.
// Specifically, a simulation model similar to the one below:
//
2019-10-07 17:31:43 -05:00
// ++===================================++
// || Sim model ||
// || /\/\/\/\ ||
// D -->>-----< > +------+ ||
// R -->>-----< Comb. > |$_DFF_| ||
// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q
// || +--< > +------+ | ||
// || | \/\/\/\/ | ||
// || | | ||
// || +----------------------------+ ||
// || ||
// ++===================================++
2019-10-07 14:54:45 -05:00
//
// is transformed into:
//
2019-10-07 17:31:43 -05:00
// ++==================++
// || Comb box ||
// || ||
// || /\/\/\/\ ||
// D -->>-----< > || +------+
2019-10-07 17:58:55 -05:00
// R -->>-----< Comb. > || |$__ABC|
// CE -->>-----< logic >--->>-- $nextQ --| _FF_ |--+-->> Q
2019-10-07 17:31:43 -05:00
// $abc9_currQ +-->>-----< > || +------+ |
// | || \/\/\/\/ || |
// | || || |
// | ++==================++ |
// | |
// +----------------------------------------------+
2019-10-07 14:54:45 -05:00
//
// The purpose of the following FD* rules are to wrap the flop with:
2019-10-04 19:21:14 -05:00
// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
2019-10-03 12:11:25 -05:00
// the connectivity of its basic D-Q flop
// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock
// domain (used when partitioning the module so that `abc9' only
// performs sequential synthesis (with reachability analysis) correctly on
// one domain at a time) and used to infert the delay target
// (c) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control
2019-10-07 14:54:45 -05:00
// domain (which, combined with this cell type, encodes to `abc9' which
// flops may be merged together)
// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial
// state
// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback
2019-09-30 18:33:40 -05:00
// into the (combinatorial) FD* cell to facilitate clock-enable behaviour
//
// In order to perform sequential synthesis, `abc9' also requires that
// the initial value of all flops be zero.
module FDRE (output Q, input C, CE, D, R);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_R_INVERTED = 1'b0;
wire QQ, $nextQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDSE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_S_INVERTED(IS_R_INVERTED)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R)
);
end
else begin
assign Q = QQ;
FDRE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_R_INVERTED(IS_R_INVERTED)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
);
end
endgenerate
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module FDRE_1 (output Q, input C, CE, D, R);
parameter [0:0] INIT = 1'b0;
wire QQ, $nextQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDSE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R)
);
end
else begin
assign Q = QQ;
FDRE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
);
end
endgenerate
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module FDCE (output Q, input C, CE, D, CLR);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_CLR_INVERTED = 1'b0;
wire QQ, $nextQ, $abc9_currQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDPE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_PRE_INVERTED(IS_CLR_INVERTED)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end
else begin
assign Q = QQ;
FDCE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_CLR_INVERTED(IS_CLR_INVERTED)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end endgenerate
2019-10-07 17:31:43 -05:00
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
// Since this is an async flop, async behaviour is also dealt with
// using the $_ABC9_ASYNC box by abc9_map.v
\$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDCE_1 (output Q, input C, CE, D, CLR);
parameter [0:0] INIT = 1'b0;
2019-12-05 01:04:40 -06:00
wire QQ, $nextQ, $abc9_currQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDPE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end
else begin
assign Q = QQ;
FDCE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end endgenerate
2019-10-07 17:31:43 -05:00
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
\$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDPE (output Q, input C, CE, D, PRE);
parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_PRE_INVERTED = 1'b0;
wire QQ, $nextQ, $abc9_currQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDCE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_CLR_INVERTED(IS_PRE_INVERTED),
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end
else begin
assign Q = QQ;
FDPE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_PRE_INVERTED(IS_PRE_INVERTED),
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end endgenerate
2019-10-07 17:31:43 -05:00
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
\$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDPE_1 (output Q, input C, CE, D, PRE);
parameter [0:0] INIT = 1'b1;
wire QQ, $nextQ, $abc9_currQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDCE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end
else begin
assign Q = QQ;
FDPE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
// ^^^ Note that async
// control is not directly
// supported by abc9 but its
// behaviour is captured by
// $__ABC9_ASYNC below
);
end endgenerate
2019-10-07 17:31:43 -05:00
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
\$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDSE (output Q, input C, CE, D, S);
2019-11-20 13:26:59 -06:00
parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_S_INVERTED = 1'b0;
wire QQ, $nextQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDRE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_R_INVERTED(IS_S_INVERTED)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S)
);
end
else begin
assign Q = QQ;
FDSE #(
.INIT(1'b0),
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_S_INVERTED(IS_S_INVERTED)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
);
end endgenerate
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module FDSE_1 (output Q, input C, CE, D, S);
2019-11-20 13:26:59 -06:00
parameter [0:0] INIT = 1'b1;
wire QQ, $nextQ;
generate if (INIT == 1'b1) begin
assign Q = ~QQ;
FDRE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S)
);
end
else begin
assign Q = QQ;
FDSE_1 #(
.INIT(1'b0)
) _TECHMAP_REPLACE_ (
.D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
);
end endgenerate
\$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));
2019-10-07 14:54:45 -05:00
// Special signals
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */};
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module RAM32X1D (
output DPO, SPO,
(* techmap_autopurge *) input D,
(* techmap_autopurge *) input WCLK,
(* techmap_autopurge *) input WE,
(* techmap_autopurge *) input A0, A1, A2, A3, A4,
(* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
);
parameter INIT = 32'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM32X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
);
\$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
\$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
endmodule
module RAM64X1D (
output DPO, SPO,
(* techmap_autopurge *) input D,
(* techmap_autopurge *) input WCLK,
(* techmap_autopurge *) input WE,
(* techmap_autopurge *) input A0, A1, A2, A3, A4, A5,
(* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
);
parameter INIT = 64'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM64X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
);
\$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
\$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
endmodule
2019-08-20 19:51:50 -05:00
module RAM128X1D (
output DPO, SPO,
(* techmap_autopurge *) input D,
(* techmap_autopurge *) input WCLK,
(* techmap_autopurge *) input WE,
(* techmap_autopurge *) input [6:0] A, DPRA
);
parameter INIT = 128'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM128X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.A(A),
.DPRA(DPRA)
);
\$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
\$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
2019-08-20 17:09:38 -05:00
endmodule
2019-08-20 17:09:38 -05:00
module SRL16E (
output Q,
(* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
2019-08-20 17:09:38 -05:00
);
parameter [15:0] INIT = 16'h0000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
wire \$Q ;
SRL16E #(
2019-08-20 17:09:38 -05:00
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
) _TECHMAP_REPLACE_ (
.Q(\$Q ),
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
);
\$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
2019-08-20 17:09:38 -05:00
endmodule
module SRLC32E (
2019-08-20 19:52:27 -05:00
output Q,
output Q31,
(* techmap_autopurge *) input [4:0] A,
(* techmap_autopurge *) input CE, CLK, D
2019-08-20 17:09:38 -05:00
);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
wire \$Q ;
SRLC32E #(
2019-08-20 17:09:38 -05:00
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
) _TECHMAP_REPLACE_ (
.Q(\$Q ), .Q31(Q31),
.A(A), .CE(CE), .CLK(CLK), .D(D)
);
\$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
endmodule
2019-09-12 19:11:01 -05:00
module DSP48E1 (
(* techmap_autopurge *) output [29:0] ACOUT,
(* techmap_autopurge *) output [17:0] BCOUT,
(* techmap_autopurge *) output reg CARRYCASCOUT,
(* techmap_autopurge *) output reg [3:0] CARRYOUT,
(* techmap_autopurge *) output reg MULTSIGNOUT,
(* techmap_autopurge *) output OVERFLOW,
(* techmap_autopurge *) output reg signed [47:0] P,
(* techmap_autopurge *) output PATTERNBDETECT,
(* techmap_autopurge *) output PATTERNDETECT,
(* techmap_autopurge *) output [47:0] PCOUT,
(* techmap_autopurge *) output UNDERFLOW,
(* techmap_autopurge *) input signed [29:0] A,
(* techmap_autopurge *) input [29:0] ACIN,
(* techmap_autopurge *) input [3:0] ALUMODE,
(* techmap_autopurge *) input signed [17:0] B,
(* techmap_autopurge *) input [17:0] BCIN,
(* techmap_autopurge *) input [47:0] C,
(* techmap_autopurge *) input CARRYCASCIN,
(* techmap_autopurge *) input CARRYIN,
(* techmap_autopurge *) input [2:0] CARRYINSEL,
(* techmap_autopurge *) input CEA1,
(* techmap_autopurge *) input CEA2,
(* techmap_autopurge *) input CEAD,
(* techmap_autopurge *) input CEALUMODE,
(* techmap_autopurge *) input CEB1,
(* techmap_autopurge *) input CEB2,
(* techmap_autopurge *) input CEC,
(* techmap_autopurge *) input CECARRYIN,
(* techmap_autopurge *) input CECTRL,
(* techmap_autopurge *) input CED,
(* techmap_autopurge *) input CEINMODE,
(* techmap_autopurge *) input CEM,
(* techmap_autopurge *) input CEP,
(* techmap_autopurge *) input CLK,
(* techmap_autopurge *) input [24:0] D,
(* techmap_autopurge *) input [4:0] INMODE,
(* techmap_autopurge *) input MULTSIGNIN,
(* techmap_autopurge *) input [6:0] OPMODE,
(* techmap_autopurge *) input [47:0] PCIN,
(* techmap_autopurge *) input RSTA,
(* techmap_autopurge *) input RSTALLCARRYIN,
(* techmap_autopurge *) input RSTALUMODE,
(* techmap_autopurge *) input RSTB,
(* techmap_autopurge *) input RSTC,
(* techmap_autopurge *) input RSTCTRL,
(* techmap_autopurge *) input RSTD,
(* techmap_autopurge *) input RSTINMODE,
(* techmap_autopurge *) input RSTM,
(* techmap_autopurge *) input RSTP
2019-09-12 19:11:01 -05:00
);
parameter integer ACASCREG = 1;
parameter integer ADREG = 1;
parameter integer ALUMODEREG = 1;
parameter integer AREG = 1;
parameter AUTORESET_PATDET = "NO_RESET";
parameter A_INPUT = "DIRECT";
parameter integer BCASCREG = 1;
parameter integer BREG = 1;
parameter B_INPUT = "DIRECT";
parameter integer CARRYINREG = 1;
parameter integer CARRYINSELREG = 1;
parameter integer CREG = 1;
parameter integer DREG = 1;
parameter integer INMODEREG = 1;
parameter integer MREG = 1;
parameter integer OPMODEREG = 1;
parameter integer PREG = 1;
parameter SEL_MASK = "MASK";
parameter SEL_PATTERN = "PATTERN";
parameter USE_DPORT = "FALSE";
parameter USE_MULT = "MULTIPLY";
parameter USE_PATTERN_DETECT = "NO_PATDET";
parameter USE_SIMD = "ONE48";
parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
parameter [47:0] PATTERN = 48'h000000000000;
parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
parameter [4:0] IS_INMODE_INVERTED = 5'b0;
parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
parameter _TECHMAP_CELLTYPE_ = "";
2019-09-12 19:45:02 -05:00
localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");
2019-09-12 19:11:01 -05:00
2019-09-13 19:07:18 -05:00
`define DSP48E1_INST(__CELL__) """
2019-09-13 14:05:14 -05:00
__CELL__ #(
2019-09-12 19:11:01 -05:00
.ACASCREG(ACASCREG),
.ADREG(ADREG),
.ALUMODEREG(ALUMODEREG),
.AREG(AREG),
.AUTORESET_PATDET(AUTORESET_PATDET),
.A_INPUT(A_INPUT),
.BCASCREG(BCASCREG),
.BREG(BREG),
.B_INPUT(B_INPUT),
.CARRYINREG(CARRYINREG),
.CARRYINSELREG(CARRYINSELREG),
.CREG(CREG),
.DREG(DREG),
.INMODEREG(INMODEREG),
.MREG(MREG),
.OPMODEREG(OPMODEREG),
.PREG(PREG),
.SEL_MASK(SEL_MASK),
.SEL_PATTERN(SEL_PATTERN),
.USE_DPORT(USE_DPORT),
.USE_MULT(USE_MULT),
.USE_PATTERN_DETECT(USE_PATTERN_DETECT),
.USE_SIMD(USE_SIMD),
.MASK(MASK),
.PATTERN(PATTERN),
.IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
.IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
.IS_CLK_INVERTED(IS_CLK_INVERTED),
.IS_INMODE_INVERTED(IS_INMODE_INVERTED),
.IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
) _TECHMAP_REPLACE_ (
.ACOUT(ACOUT),
.BCOUT(BCOUT),
.CARRYCASCOUT(CARRYCASCOUT),
.CARRYOUT(CARRYOUT),
.MULTSIGNOUT(MULTSIGNOUT),
.OVERFLOW(OVERFLOW),
.P(oP),
.PATTERNBDETECT(PATTERNBDETECT),
.PATTERNDETECT(PATTERNDETECT),
.PCOUT(oPCOUT),
.UNDERFLOW(UNDERFLOW),
.A(iA),
.ACIN(ACIN),
.ALUMODE(ALUMODE),
.B(iB),
.BCIN(BCIN),
.C(iC),
.CARRYCASCIN(CARRYCASCIN),
.CARRYIN(CARRYIN),
.CARRYINSEL(CARRYINSEL),
.CEA1(CEA1),
.CEA2(CEA2),
.CEAD(CEAD),
.CEALUMODE(CEALUMODE),
.CEB1(CEB1),
.CEB2(CEB2),
.CEC(CEC),
.CECARRYIN(CECARRYIN),
.CECTRL(CECTRL),
.CED(CED),
.CEINMODE(CEINMODE),
.CEM(CEM),
.CEP(CEP),
.CLK(CLK),
.D(iD),
.INMODE(INMODE),
.MULTSIGNIN(MULTSIGNIN),
.OPMODE(OPMODE),
.PCIN(PCIN),
.RSTA(RSTA),
.RSTALLCARRYIN(RSTALLCARRYIN),
.RSTALUMODE(RSTALUMODE),
.RSTB(RSTB),
.RSTC(RSTC),
.RSTCTRL(RSTCTRL),
.RSTD(RSTD),
.RSTINMODE(RSTINMODE),
.RSTM(RSTM),
.RSTP(RSTP)
);
2019-09-13 14:05:14 -05:00
"""
wire [29:0] iA;
wire [17:0] iB;
wire [47:0] iC;
wire [24:0] iD;
2019-09-13 14:05:14 -05:00
wire pA, pB, pC, pD, pAD, pM, pP;
wire [47:0] oP, mP;
wire [47:0] oPCOUT, mPCOUT;
2019-09-13 14:05:14 -05:00
generate
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin
2019-09-19 22:04:52 -05:00
// Disconnect the A-input if MREG is enabled, since
// combinatorial path is broken
2019-09-13 14:05:14 -05:00
if (AREG == 0 && MREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
2019-09-13 14:05:14 -05:00
if (BREG == 0 && MREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
2019-09-13 14:05:14 -05:00
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
2019-09-13 14:05:14 -05:00
if (DREG == 0)
assign iD = D;
else if (techmap_guard)
2019-09-19 22:04:52 -05:00
$error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
assign pD = 1'bx;
2019-09-13 14:05:14 -05:00
if (ADREG == 1 && techmap_guard)
2019-09-19 18:27:14 -05:00
$error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
assign pAD = 1'bx;
2019-09-19 22:04:52 -05:00
if (PREG == 0) begin
if (MREG == 1)
\$__ABC9_REG rM (.Q(pM));
2019-09-19 22:04:52 -05:00
else
assign pM = 1'bx;
assign pP = 1'bx;
end else begin
assign pM = 1'bx;
\$__ABC9_REG rP (.Q(pP));
2019-09-19 18:27:14 -05:00
end
2019-09-13 14:05:14 -05:00
if (MREG == 0 && PREG == 0)
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
\$__ABC9_DSP48E1_MULT_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
);
\$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
);
2019-09-13 14:05:14 -05:00
`DSP48E1_INST(\$__ABC9_DSP48E1_MULT )
2019-09-12 19:11:01 -05:00
end
2019-09-13 13:45:55 -05:00
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
2019-09-19 22:04:52 -05:00
// Disconnect the A-input if MREG is enabled, since
// combinatorial path is broken
2019-09-13 14:05:14 -05:00
if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
2019-09-13 13:45:55 -05:00
else
\$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
2019-09-13 13:45:55 -05:00
if (BREG == 0 && MREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
2019-09-13 13:45:55 -05:00
else
\$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
2019-09-13 13:45:55 -05:00
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
2019-09-13 13:45:55 -05:00
else
\$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
2019-09-13 13:45:55 -05:00
if (DREG == 0 && ADREG == 0)
assign iD = D, pD = 1'bx;
2019-09-13 13:45:55 -05:00
else
\$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
2019-09-19 22:04:52 -05:00
if (PREG == 0) begin
if (MREG == 1) begin
assign pAD = 1'bx;
\$__ABC9_REG rM (.Q(pM));
2019-09-19 22:04:52 -05:00
end else begin
2019-09-19 18:27:14 -05:00
if (ADREG == 1)
\$__ABC9_REG rAD (.Q(pAD));
2019-09-19 18:27:14 -05:00
else
assign pAD = 1'bx;
2019-09-19 22:04:52 -05:00
assign pM = 1'bx;
end
assign pP = 1'bx;
end else begin
assign pAD = 1'bx, pM = 1'bx;
\$__ABC9_REG rP (.Q(pP));
2019-09-19 22:04:52 -05:00
end
2019-09-13 13:45:55 -05:00
if (MREG == 0 && PREG == 0)
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
\$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
2019-09-13 13:45:55 -05:00
);
\$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
2019-09-13 13:45:55 -05:00
);
`DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT )
2019-09-13 14:05:14 -05:00
end
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
2019-09-19 22:04:52 -05:00
// Disconnect the A-input if MREG is enabled, since
// combinatorial path is broken
2019-09-13 14:05:14 -05:00
if (AREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
2019-09-13 14:05:14 -05:00
if (BREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
2019-09-13 14:05:14 -05:00
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
2019-09-13 14:05:14 -05:00
else
\$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
2019-09-13 14:05:14 -05:00
if (DREG == 1 && techmap_guard)
2019-09-19 22:04:52 -05:00
$error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
assign pD = 1'bx;
2019-09-13 14:05:14 -05:00
if (ADREG == 1 && techmap_guard)
2019-09-19 22:04:52 -05:00
$error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
assign pAD = 1'bx;
2019-09-19 22:04:52 -05:00
if (MREG == 1 && techmap_guard)
$error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
assign pM = 1'bx;
if (PREG == 1)
\$__ABC9_REG rP (.Q(pP));
2019-09-19 18:27:14 -05:00
else
assign pP = 1'bx;
2019-09-13 14:05:14 -05:00
if (MREG == 0 && PREG == 0)
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
\$__ABC9_DSP48E1_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
2019-09-13 13:45:55 -05:00
);
\$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
2019-09-13 14:05:14 -05:00
);
`DSP48E1_INST(\$__ABC9_DSP48E1 )
2019-09-13 13:45:55 -05:00
end
2019-09-12 19:11:01 -05:00
else
2019-09-13 13:45:55 -05:00
$error("Invalid DSP48E1 configuration");
2019-09-19 22:04:52 -05:00
endgenerate
`undef DSP48E1_INST
2019-09-12 19:11:01 -05:00
endmodule