Merge remote-tracking branch 'origin/xaig' into xc7mux
[yosys.git] / techlibs / xilinx / cells_map.v
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * 2019 Eddie Hung <eddie@fpgeh.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 // Convert negative-polarity reset to positive-polarity
22 (* techmap_celltype = "$_DFF_NN0_" *)
23 module _90_dff_nn0_to_np0(input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
24 (* techmap_celltype = "$_DFF_PN0_" *)
25 module _90_dff_pn0_to_pp0(input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
26
27 (* techmap_celltype = "$_DFF_NN1_" *)
28 module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
29 (* techmap_celltype = "$_DFF_PN1_" *)
30 module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
31
32
33 module \$__SHREG_ (input C, input D, input E, output Q);
34 parameter DEPTH = 0;
35 parameter [DEPTH-1:0] INIT = 0;
36 parameter CLKPOL = 1;
37 parameter ENPOL = 2;
38
39 \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q));
40 endmodule
41
42 module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO);
43 parameter DEPTH = 0;
44 parameter [DEPTH-1:0] INIT = 0;
45 parameter CLKPOL = 1;
46 parameter ENPOL = 2;
47
48 // shregmap's INIT parameter shifts out LSB first;
49 // however Xilinx expects MSB first
50 function [DEPTH-1:0] brev;
51 input [DEPTH-1:0] din;
52 integer i;
53 begin
54 for (i = 0; i < DEPTH; i=i+1)
55 brev[i] = din[DEPTH-1-i];
56 end
57 endfunction
58 localparam [DEPTH-1:0] INIT_R = brev(INIT);
59
60 parameter _TECHMAP_CONSTMSK_L_ = 0;
61 parameter _TECHMAP_CONSTVAL_L_ = 0;
62
63 wire CE;
64 generate
65 if (ENPOL == 0)
66 assign CE = ~E;
67 else if (ENPOL == 1)
68 assign CE = E;
69 else
70 assign CE = 1'b1;
71 if (DEPTH == 1) begin
72 if (CLKPOL)
73 FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
74 else
75 FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
76 end else
77 if (DEPTH <= 16) begin
78 SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q));
79 end else
80 if (DEPTH > 17 && DEPTH <= 32) begin
81 SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q));
82 end else
83 if (DEPTH > 33 && DEPTH <= 64) begin
84 wire T0, T1, T2;
85 SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
86 \$__XILINX_SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2));
87 if (&_TECHMAP_CONSTMSK_L_)
88 assign Q = T2;
89 else
90 MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5]));
91 end else
92 if (DEPTH > 65 && DEPTH <= 96) begin
93 wire T0, T1, T2, T3, T4, T5, T6;
94 SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
95 SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
96 \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4));
97 if (&_TECHMAP_CONSTMSK_L_)
98 assign Q = T4;
99 else begin
100 MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5]));
101 MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5]));
102 MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6]));
103 end
104 end else
105 if (DEPTH > 97 && DEPTH < 128) begin
106 wire T0, T1, T2, T3, T4, T5, T6, T7, T8;
107 SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
108 SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
109 SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
110 \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6));
111 if (&_TECHMAP_CONSTMSK_L_)
112 assign Q = T6;
113 else begin
114 MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
115 MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
116 MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
117 end
118 end
119 else if (DEPTH == 128) begin
120 wire T0, T1, T2, T3, T4, T5, T6;
121 SRLC32E #(.INIT(INIT_R[ 32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
122 SRLC32E #(.INIT(INIT_R[ 64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
123 SRLC32E #(.INIT(INIT_R[ 96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
124 SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO));
125 if (&_TECHMAP_CONSTMSK_L_)
126 assign Q = T6;
127 else begin
128 wire T7, T8;
129 MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
130 MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
131 MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
132 end
133 end
134 else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin
135 // Handle cases where fixed-length depth is
136 // just 1 over a convenient value
137 \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q));
138 end
139 else begin
140 localparam lower_clog2 = $clog2((DEPTH+1)/2);
141 localparam lower_depth = 2 ** lower_clog2;
142 wire T0, T1, T2, T3;
143 if (&_TECHMAP_CONSTMSK_L_) begin
144 \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0));
145 \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3));
146 end
147 else begin
148 \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1));
149 \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3));
150 assign Q = L[lower_clog2] ? T2 : T0;
151 end
152 if (DEPTH == 2 * lower_depth)
153 assign SO = T3;
154 end
155 endgenerate
156 endmodule
157
158 module \$__XILINX_SHIFTX (A, B, Y);
159 parameter A_SIGNED = 0;
160 parameter B_SIGNED = 0;
161 parameter A_WIDTH = 1;
162 parameter B_WIDTH = 1;
163 parameter Y_WIDTH = 1;
164
165 input [A_WIDTH-1:0] A;
166 input [B_WIDTH-1:0] B;
167 output [Y_WIDTH-1:0] Y;
168
169 parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0;
170 parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0;
171 parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
172 parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
173
174 function integer compute_num_leading_X_in_A;
175 integer i, c;
176 begin
177 compute_num_leading_X_in_A = 0;
178 c = 1;
179 for (i = A_WIDTH-1; i >= 0; i=i-1) begin
180 if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx)
181 c = 0;
182 compute_num_leading_X_in_A = compute_num_leading_X_in_A + c;
183 end
184 end
185 endfunction
186 localparam num_leading_X_in_A = compute_num_leading_X_in_A();
187
188 generate
189 genvar i, j;
190 // Bit-blast
191 if (Y_WIDTH > 1) begin
192 for (i = 0; i < Y_WIDTH; i++)
193 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i]));
194 end
195 // If the LSB of B is constant zero (and Y_WIDTH is 1) then
196 // we can optimise by removing every other entry from A
197 // and popping the constant zero from B
198 else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin
199 wire [(A_WIDTH+1)/2-1:0] A_i;
200 for (i = 0; i < (A_WIDTH+1)/2; i++)
201 assign A_i[i] = A[i*2];
202 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y));
203 end
204 // Trim off any leading 1'bx -es in A, and resize B accordingly
205 else if (num_leading_X_in_A > 0) begin
206 localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A;
207 localparam B_WIDTH_new = $clog2(A_WIDTH_new);
208 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y));
209 end
210 else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
211 \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
212 end
213 else if (B_WIDTH == 3) begin
214 localparam a_width0 = 2 ** 2;
215 localparam a_widthN = A_WIDTH - a_width0;
216 wire T0, T1;
217 \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0));
218 if (a_widthN > 1)
219 \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1));
220 else
221 assign T1 = A[A_WIDTH-1];
222 MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y));
223 end
224 else if (B_WIDTH == 4) begin
225 localparam a_width0 = 2 ** 2;
226 localparam num_mux8 = A_WIDTH / a_width0;
227 localparam a_widthN = A_WIDTH - num_mux8*a_width0;
228 wire [4-1:0] T;
229 for (i = 0; i < 4; i++)
230 if (i < num_mux8)
231 \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i]));
232 else if (i == num_mux8 && a_widthN > 0) begin
233 if (a_widthN > 1)
234 \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
235 else
236 assign T[i] = A[A_WIDTH-1];
237 end
238 else
239 assign T[i] = 1'bx;
240 \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y));
241 end
242 else begin
243 localparam a_width0 = 2 ** 4;
244 localparam num_mux16 = A_WIDTH / a_width0;
245 localparam a_widthN = A_WIDTH - num_mux16*a_width0;
246 wire [(2**(B_WIDTH-4))-1:0] T;
247 for (i = 0; i < 2 ** (B_WIDTH-4); i++)
248 if (i < num_mux16)
249 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i]));
250 else if (i == num_mux16 && a_widthN > 0) begin
251 if (a_widthN > 1)
252 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
253 else
254 assign T[i] = A[A_WIDTH-1];
255 end
256 else
257 assign T[i] = 1'bx;
258 \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y));
259 end
260 endgenerate
261 endmodule
262
263 module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
264 input A, B, C, D, E, F, G, H, S, T, U;
265 output Y;
266 \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y));
267 endmodule
268
269 module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
270 input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
271 output Y;
272 \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y));
273 endmodule
274
275 `ifndef _ABC
276 module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
277 output O;
278 input I0, I1, I2, I3, S0, S1;
279 wire T0, T1;
280 MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0));
281 MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1));
282 MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));
283 endmodule
284 `endif