aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/xilinx/cells_map.v126
-rw-r--r--techlibs/xilinx/cells_sim.v39
-rw-r--r--techlibs/xilinx/cells_xtra.sh4
-rw-r--r--techlibs/xilinx/cells_xtra.v16
-rw-r--r--techlibs/xilinx/synth_xilinx.cc19
5 files changed, 183 insertions, 21 deletions
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index d5801c0fc..4173814fd 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -17,4 +17,128 @@
*
*/
-// Empty for now
+module \$__SHREG_ (input C, input D, input E, output Q);
+ parameter DEPTH = 0;
+ parameter [DEPTH-1:0] INIT = 0;
+ parameter CLKPOL = 1;
+ parameter ENPOL = 2;
+
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q));
+endmodule
+
+module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO);
+ parameter DEPTH = 0;
+ parameter [DEPTH-1:0] INIT = 0;
+ parameter CLKPOL = 1;
+ parameter ENPOL = 2;
+
+ // shregmap's INIT parameter shifts out LSB first;
+ // however Xilinx expects MSB first
+ function [DEPTH-1:0] brev;
+ input [DEPTH-1:0] din;
+ integer i;
+ begin
+ for (i = 0; i < DEPTH; i=i+1)
+ brev[i] = din[DEPTH-1-i];
+ end
+ endfunction
+ localparam [DEPTH-1:0] INIT_R = brev(INIT);
+
+ parameter _TECHMAP_CONSTMSK_L_ = 0;
+ parameter _TECHMAP_CONSTVAL_L_ = 0;
+
+ wire CE;
+ generate
+ if (ENPOL == 0)
+ assign CE = ~E;
+ else if (ENPOL == 1)
+ assign CE = E;
+ else
+ assign CE = 1'b1;
+ if (DEPTH == 1) begin
+ if (CLKPOL)
+ FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
+ else
+ FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
+ end else
+ if (DEPTH <= 16) begin
+ 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));
+ end else
+ if (DEPTH > 17 && DEPTH <= 32) begin
+ SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q));
+ end else
+ if (DEPTH > 33 && DEPTH <= 64) begin
+ wire T0, T1, T2;
+ 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));
+ \$__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));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T2;
+ else
+ MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5]));
+ end else
+ if (DEPTH > 65 && DEPTH <= 96) begin
+ wire T0, T1, T2, T3, T4, T5, T6;
+ 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));
+ 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));
+ \$__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));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T4;
+ else begin
+ MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6]));
+ end
+ end else
+ if (DEPTH > 97 && DEPTH < 128) begin
+ wire T0, T1, T2, T3, T4, T5, T6, T7, T8;
+ 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));
+ 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));
+ 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));
+ \$__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));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T6;
+ else begin
+ MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
+ end
+ end
+ else if (DEPTH == 128) begin
+ wire T0, T1, T2, T3, T4, T5, T6;
+ 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));
+ 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));
+ 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));
+ 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));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T6;
+ else begin
+ wire T7, T8;
+ MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
+ end
+ end
+ else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin
+ // Handle cases where fixed-length depth is
+ // just 1 over a convenient value
+ \$__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));
+ end
+ else begin
+ localparam lower_clog2 = $clog2((DEPTH+1)/2);
+ localparam lower_depth = 2 ** lower_clog2;
+ wire T0, T1, T2, T3;
+ if (&_TECHMAP_CONSTMSK_L_) begin
+ \$__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));
+ \$__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));
+ end
+ else begin
+ \$__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));
+ \$__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));
+ wire [1023:0] _TECHMAP_DO_ = "techmap -map +/techmap.v";
+ assign Q = L[lower_clog2] ? T2 : T0;
+ end
+ if (DEPTH == 2 * lower_depth)
+ assign SO = T3;
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index ff5ff0726..c756115f6 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -251,3 +251,42 @@ module RAM128X1D (
wire clk = WCLK ^ IS_WCLK_INVERTED;
always @(posedge clk) if (WE) mem[A] <= D;
endmodule
+
+module SRL16E (
+ output Q,
+ input A0, A1, A2, A3, CE, CLK, D
+);
+ parameter [15:0] INIT = 16'h0000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+
+ reg [15:0] r = INIT;
+ assign Q = r[{A3,A2,A1,A0}];
+ generate
+ if (IS_CLK_INVERTED) begin
+ always @(negedge CLK) if (CE) r <= { r[14:0], D };
+ end
+ else
+ always @(posedge CLK) if (CE) r <= { r[14:0], D };
+ endgenerate
+endmodule
+
+module SRLC32E (
+ output Q,
+ output Q31,
+ input [4:0] A,
+ input CE, CLK, D
+);
+ parameter [31:0] INIT = 32'h00000000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+
+ reg [31:0] r = INIT;
+ assign Q31 = r[31];
+ assign Q = r[A];
+ generate
+ if (IS_CLK_INVERTED) begin
+ always @(negedge CLK) if (CE) r <= { r[30:0], D };
+ end
+ else
+ always @(posedge CLK) if (CE) r <= { r[30:0], D };
+ endgenerate
+endmodule
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
index 56520ea10..c23e67029 100644
--- a/techlibs/xilinx/cells_xtra.sh
+++ b/techlibs/xilinx/cells_xtra.sh
@@ -135,8 +135,8 @@ function xtract_cell_decl()
xtract_cell_decl ROM256X1
xtract_cell_decl ROM32X1
xtract_cell_decl ROM64X1
- xtract_cell_decl SRL16E
- xtract_cell_decl SRLC32E
+ #xtract_cell_decl SRL16E
+ #xtract_cell_decl SRLC32E
xtract_cell_decl STARTUPE2 "(* keep *)"
xtract_cell_decl USR_ACCESSE2
xtract_cell_decl XADC
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 497518d35..06c868080 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -3847,22 +3847,6 @@ module ROM64X1 (...);
input A0, A1, A2, A3, A4, A5;
endmodule
-module SRL16E (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- output Q;
- input A0, A1, A2, A3, CE, CLK, D;
-endmodule
-
-module SRLC32E (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- output Q;
- output Q31;
- input [4:0] A;
- input CE, CLK, D;
-endmodule
-
(* keep *)
module STARTUPE2 (...);
parameter PROG_USR = "FALSE";
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index b82ab9337..326684daf 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -64,10 +64,13 @@ struct SynthXilinxPass : public Pass
log(" (this feature is experimental and incomplete)\n");
log("\n");
log(" -nobram\n");
- log(" disable infering of block rams\n");
+ log(" disable inference of block rams\n");
log("\n");
log(" -nodram\n");
- log(" disable infering of distributed rams\n");
+ log(" disable inference of distributed rams\n");
+ log("\n");
+ log(" -nosrl\n");
+ log(" disable inference of shift registers\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
@@ -110,6 +113,8 @@ struct SynthXilinxPass : public Pass
log(" dffsr2dff\n");
log(" dff2dffe\n");
log(" opt -full\n");
+ log(" simplemap t:$dff t:$dffe (without -nosrl and without -retime only)\n");
+ log(" shregmap -tech xilinx -minlen 3 (without -nosrl and without -retime only)\n");
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n");
log(" opt -fast\n");
log("\n");
@@ -148,6 +153,7 @@ struct SynthXilinxPass : public Pass
bool vpr = false;
bool nobram = false;
bool nodram = false;
+ bool nosrl = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -192,6 +198,10 @@ struct SynthXilinxPass : public Pass
nodram = true;
continue;
}
+ if (args[argidx] == "-nosrl") {
+ nosrl = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -256,6 +266,11 @@ struct SynthXilinxPass : public Pass
Pass::call(design, "dff2dffe");
Pass::call(design, "opt -full");
+ if (!nosrl && !retime) {
+ Pass::call(design, "simplemap t:$dff t:$dffe");
+ Pass::call(design, "shregmap -tech xilinx -minlen 3");
+ }
+
if (vpr) {
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY");
} else {