/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf * 2019 Eddie Hung * * 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. * */ // 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. `ifdef DFF_MODE // 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. // 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: // // ++===================================++ // || Sim model || // || /\/\/\/\ || // D -->>-----< > +------+ || // R -->>-----< Comb. > |$_DFF_| || // CE -->>-----< logic >-----| [NP]_|---+---->>-- Q // || +--< > +------+ | || // || | \/\/\/\/ | || // || | | || // || +----------------------------+ || // || || // ++===================================++ // // is transformed into: // // ++==================++ // || Comb box || // || || // || /\/\/\/\ || // D -->>-----< > || // R -->>-----< Comb. > || +----------+ // CE -->>-----< logic >--->>-- $Q --|$__ABC_FF_|--+-->> Q // $abc9_currQ +-->>-----< > || +----------+ | // | || \/\/\/\/ || | // | || || | // | ++==================++ | // | | // +----------------------------------------------+ // // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to // capture asynchronous behaviour // (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock // domain and polarity (used when partitioning the module so that `abc9' only // performs sequential synthesis (with reachability analysis) correctly on // one domain at a time) and also used to infer the optional delay target // from the (* abc9_clock_period = %d *) attribute attached to any wire // within // (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 // 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, $Q; 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($Q), .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($Q), .C(C), .CE(CE), .R(R) ); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_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, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDSE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) ); end else begin assign Q = QQ; FDRE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .R(R) ); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule module FDSE (output Q, input C, CE, D, S); 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, $Q; 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($Q), .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($Q), .C(C), .CE(CE), .S(S) ); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_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); parameter [0:0] INIT = 1'b1; wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDRE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) ); end else begin assign Q = QQ; FDSE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .S(S) ); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_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, $Q, $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($Q), .C(C), .CE(CE), .PRE(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); // Since this is an async flop, async behaviour is dealt with here $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); 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($Q), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); // Since this is an async flop, async behaviour is dealt with here $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_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; wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end else begin assign Q = QQ; FDCE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_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, $Q, $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($Q), .C(C), .CE(CE), .CLR(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); 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($Q), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_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, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDCE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end else begin assign Q = QQ; FDPE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule `endif // Attach a (combinatorial) black-box onto the output // of thes LUTRAM primitives to capture their // asynchronous read behaviour 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 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); $__ABC9_LUT6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); 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 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); $__ABC9_LUT6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); endmodule 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 spo (.A($SPO), .S(A), .Y(SPO)); $__ABC9_LUT7 dpo (.A($DPO), .S(DPRA), .Y(DPO)); endmodule module RAM32M ( output [1:0] DOA, output [1:0] DOB, output [1:0] DOC, output [1:0] DOD, (* techmap_autopurge *) input [4:0] ADDRA, (* techmap_autopurge *) input [4:0] ADDRB, (* techmap_autopurge *) input [4:0] ADDRC, (* techmap_autopurge *) input [4:0] ADDRD, (* techmap_autopurge *) input [1:0] DIA, (* techmap_autopurge *) input [1:0] DIB, (* techmap_autopurge *) input [1:0] DIC, (* techmap_autopurge *) input [1:0] DID, (* techmap_autopurge *) input WCLK, (* techmap_autopurge *) input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; parameter [63:0] INIT_C = 64'h0000000000000000; parameter [63:0] INIT_D = 64'h0000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; wire [1:0] $DOA, $DOB, $DOC, $DOD; RAM32M #( .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), .WCLK(WCLK), .WE(WE), .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) ); $__ABC9_LUT6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0])); $__ABC9_LUT6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1])); $__ABC9_LUT6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0])); $__ABC9_LUT6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1])); $__ABC9_LUT6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0])); $__ABC9_LUT6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1])); $__ABC9_LUT6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0])); $__ABC9_LUT6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1])); endmodule module RAM64M ( output DOA, output DOB, output DOC, output DOD, (* techmap_autopurge *) input [5:0] ADDRA, (* techmap_autopurge *) input [5:0] ADDRB, (* techmap_autopurge *) input [5:0] ADDRC, (* techmap_autopurge *) input [5:0] ADDRD, (* techmap_autopurge *) input DIA, (* techmap_autopurge *) input DIB, (* techmap_autopurge *) input DIC, (* techmap_autopurge *) input DID, (* techmap_autopurge *) input WCLK, (* techmap_autopurge *) input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; parameter [63:0] INIT_C = 64'h0000000000000000; parameter [63:0] INIT_D = 64'h0000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; wire $DOA, $DOB, $DOC, $DOD; RAM64M #( .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), .WCLK(WCLK), .WE(WE), .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) ); $__ABC9_LUT6 doa (.A($DOA), .S(ADDRA), .Y(DOA)); $__ABC9_LUT6 dob (.A($DOB), .S(ADDRB), .Y(DOB)); $__ABC9_LUT6 doc (.A($DOC), .S(ADDRC), .Y(DOC)); $__ABC9_LUT6 dod (.A($DOD), .S(ADDRD), .Y(DOD)); endmodule module SRL16E ( output Q, (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D ); parameter [15:0] INIT = 16'h0000; parameter [0:0] IS_CLK_INVERTED = 1'b0; wire $Q; SRL16E #( .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, A3, A2, A1, A0, 1'b1}), .Y(Q)); endmodule module SRLC32E ( output Q, output Q31, (* techmap_autopurge *) input [4:0] A, (* techmap_autopurge *) input CE, CLK, D ); parameter [31:0] INIT = 32'h00000000; parameter [0:0] IS_CLK_INVERTED = 1'b0; wire $Q; SRLC32E #( .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 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 ); 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_ = ""; localparam techmap_guard = (_TECHMAP_CELLTYPE_ != ""); `define DSP48E1_INST(__CELL__) """ __CELL__ #( .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) ); """ wire [29:0] iA; wire [17:0] iB; wire [47:0] iC; wire [24:0] iD; wire pA, pB, pC, pD, pAD, pM, pP; wire [47:0] oP, mP; wire [47:0] oPCOUT, mPCOUT; generate if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; else if (techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); assign pD = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); assign pAD = 1'bx; if (PREG == 0) begin if (MREG == 1) $__ABC9_REG rM (.Q(pM)); else assign pM = 1'bx; assign pP = 1'bx; end else begin assign pM = 1'bx; $__ABC9_REG rP (.Q(pP)); end 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) ); `DSP48E1_INST($__ABC9_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0 && ADREG == 0) assign iD = D, pD = 1'bx; else $__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); if (PREG == 0) begin if (MREG == 1) begin assign pAD = 1'bx; $__ABC9_REG rM (.Q(pM)); end else begin if (ADREG == 1) $__ABC9_REG rAD (.Q(pAD)); else assign pAD = 1'bx; assign pM = 1'bx; end assign pP = 1'bx; end else begin assign pAD = 1'bx, pM = 1'bx; $__ABC9_REG rP (.Q(pP)); end 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) ); $__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) ); `DSP48E1_INST($__ABC9_DSP48E1_MULT_DPORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); assign pD = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); assign pAD = 1'bx; 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)); else assign pP = 1'bx; 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) ); $__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) ); `DSP48E1_INST($__ABC9_DSP48E1 ) end else $error("Invalid DSP48E1 configuration"); endgenerate `undef DSP48E1_INST endmodule