| /* |
| * 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. |
| * |
| */ |
| |
| // ============================================================================ |
| |
| // Box containing MUXF7.[AB] + MUXF8, |
| // Necessary to make these an atomic unit so that |
| // ABC cannot optimise just one of the MUXF7 away |
| // and expect to save on its delay |
| (* abc9_box_id = 3, lib_whitebox *) |
| module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); |
| assign O = S1 ? (S0 ? I3 : I2) |
| : (S0 ? I1 : I0); |
| endmodule |
| |
| // Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} |
| // Necessary since RAMD* and SRL* have both combinatorial (i.e. |
| // same-cycle read operation) and sequential (write operation |
| // is only committed on the next clock edge). |
| // To model the combinatorial path, such cells have to be split |
| // into comb and seq parts, with this box modelling only the former. |
| (* abc9_box_id=2000 *) |
| module \$__ABC9_LUT6 (input A, input [5:0] S, output Y); |
| endmodule |
| // Box to emulate comb/seq behaviour of RAMD128 |
| (* abc9_box_id=2001 *) |
| module \$__ABC9_LUT7 (input A, input [6:0] S, output Y); |
| endmodule |
| |
| |
| // Modules used to model the comb/seq behaviour of DSP48E1 |
| // With abc9_map.v responsible for splicing the below modules |
| // between the combinatorial DSP48E1 box (e.g. disconnecting |
| // A when AREG, MREG or PREG is enabled and splicing in the |
| // "$__ABC9_DSP48E1_REG" blackbox as "REG" in the diagram below) |
| // this acts to first disables the combinatorial path (as there |
| // is no connectivity through REG), and secondly, since this is |
| // blackbox a new PI will be introduced with an arrival time of |
| // zero. |
| // Note: Since these "$__ABC9_DSP48E1_REG" modules are of a |
| // sequential nature, they are not passed as a box to ABC and |
| // (desirably) represented as PO/PIs. |
| // |
| // At the DSP output, we place a blackbox mux ("M" in the diagram |
| // below) to capture the fact that the critical-path could come |
| // from any one of its inputs. |
| // In contrast to "REG", the "$__ABC9_DSP48E1_*_MUX" modules are |
| // combinatorial blackboxes that do get passed to ABC. |
| // The propagation delay through this box (specified in the box |
| // file) captures the arrival time of the register (i.e. |
| // propagation from AREG to P after clock edge), or zero delay |
| // for the combinatorial path from the DSP. |
| // |
| // Doing so should means that ABC is able to analyse the |
| // worst-case delay through to P, regardless of if it was |
| // through any combinatorial paths (e.g. B, below) or an |
| // internal register (A2REG). |
| // However, the true value of being as complete as this is |
| // questionable since if AREG=1 and BREG=0 (as below) |
| // then the worse-case path would very likely be through B |
| // and very unlikely to be through AREG.Q...? |
| // |
| // In graphical form: |
| // |
| // +-----+ |
| // +------>> REG >>----+ |
| // | +-----+ | |
| // | | |
| // | +---------+ | __ |
| // A >>-+X X-| | +--| \ |
| // | DSP48E1 |P | M |--->> P |
| // | AREG=1 |-------|__/ |
| // B >>------| | |
| // +---------+ |
| // |
| `define ABC9_DSP48E1_MUX(__NAME__) """ |
| module __NAME__ (input Aq, ADq, Bq, Cq, Dq, input [47:0] I, input Mq, input [47:0] P, input Pq, output [47:0] O); |
| endmodule |
| """ |
| (* abc9_box_id=2100 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_P_MUX ) |
| (* abc9_box_id=2101 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_PCOUT_MUX ) |
| (* abc9_box_id=2102 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_P_MUX ) |
| (* abc9_box_id=2103 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX ) |
| (* abc9_box_id=2104 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_P_MUX ) |
| (* abc9_box_id=2105 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_PCOUT_MUX ) |
| |
| `define ABC9_DSP48E1(__NAME__) """ |
| module __NAME__ ( |
| output [29:0] ACOUT, |
| output [17:0] BCOUT, |
| output reg CARRYCASCOUT, |
| output reg [3:0] CARRYOUT, |
| output reg MULTSIGNOUT, |
| output OVERFLOW, |
| output reg signed [47:0] P, |
| output PATTERNBDETECT, |
| output PATTERNDETECT, |
| output [47:0] PCOUT, |
| output UNDERFLOW, |
| input signed [29:0] A, |
| input [29:0] ACIN, |
| input [3:0] ALUMODE, |
| input signed [17:0] B, |
| input [17:0] BCIN, |
| input [47:0] C, |
| input CARRYCASCIN, |
| input CARRYIN, |
| input [2:0] CARRYINSEL, |
| input CEA1, |
| input CEA2, |
| input CEAD, |
| input CEALUMODE, |
| input CEB1, |
| input CEB2, |
| input CEC, |
| input CECARRYIN, |
| input CECTRL, |
| input CED, |
| input CEINMODE, |
| input CEM, |
| input CEP, |
| input CLK, |
| input [24:0] D, |
| input [4:0] INMODE, |
| input MULTSIGNIN, |
| input [6:0] OPMODE, |
| input [47:0] PCIN, |
| input RSTA, |
| input RSTALLCARRYIN, |
| input RSTALUMODE, |
| input RSTB, |
| input RSTC, |
| input RSTCTRL, |
| input RSTD, |
| input RSTINMODE, |
| input RSTM, |
| 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; |
| endmodule |
| """ |
| (* abc9_box_id=3000 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT ) |
| (* abc9_box_id=3001 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT_DPORT ) |
| (* abc9_box_id=3002 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1 ) |