aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r--techlibs/xilinx/Makefile.inc10
-rw-r--r--techlibs/xilinx/arith_map.v91
-rw-r--r--techlibs/xilinx/brams.txt101
-rw-r--r--techlibs/xilinx/brams_map.v267
-rw-r--r--techlibs/xilinx/cells.v53
-rw-r--r--techlibs/xilinx/cells_map.v84
-rw-r--r--techlibs/xilinx/cells_sim.v158
-rw-r--r--techlibs/xilinx/example_basys3/README16
-rw-r--r--techlibs/xilinx/example_basys3/example.v21
-rw-r--r--techlibs/xilinx/example_basys3/example.xdc21
-rw-r--r--techlibs/xilinx/example_basys3/run.sh4
-rw-r--r--techlibs/xilinx/example_basys3/run_prog.tcl4
-rw-r--r--techlibs/xilinx/example_basys3/run_vivado.tcl9
-rw-r--r--techlibs/xilinx/example_basys3/run_yosys.ys2
-rw-r--r--techlibs/xilinx/example_mojo_counter/README10
-rw-r--r--techlibs/xilinx/example_mojo_counter/example.sh18
-rw-r--r--techlibs/xilinx/example_mojo_counter/example.ucf14
-rw-r--r--techlibs/xilinx/example_mojo_counter/example.v14
-rw-r--r--techlibs/xilinx/example_sim_counter/counter.v12
-rw-r--r--techlibs/xilinx/example_sim_counter/counter_tb.v61
-rw-r--r--techlibs/xilinx/example_sim_counter/run_sim.sh23
-rw-r--r--techlibs/xilinx/example_zed_counter/README10
-rw-r--r--techlibs/xilinx/example_zed_counter/example.sh18
-rw-r--r--techlibs/xilinx/example_zed_counter/example.ucf14
-rw-r--r--techlibs/xilinx/example_zed_counter/example.v14
-rw-r--r--techlibs/xilinx/synth_xilinx.cc132
-rw-r--r--techlibs/xilinx/tests/.gitignore3
-rw-r--r--techlibs/xilinx/tests/bram1.sh63
-rw-r--r--techlibs/xilinx/tests/bram1.v24
-rw-r--r--techlibs/xilinx/tests/bram1_tb.v116
30 files changed, 1060 insertions, 327 deletions
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index cd19f10e7..9af7b58f3 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -1,9 +1,9 @@
OBJS += techlibs/xilinx/synth_xilinx.o
-EXTRA_TARGETS += share/xilinx/cells.v
-
-share/xilinx/cells.v: techlibs/xilinx/cells.v
- $(P) mkdir -p share/xilinx
- $(Q) cp techlibs/xilinx/cells.v share/xilinx/cells.v
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.txt))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
new file mode 100644
index 000000000..a154f7740
--- /dev/null
+++ b/techlibs/xilinx/arith_map.v
@@ -0,0 +1,91 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+(* techmap_celltype = "$lcu" *)
+module _80_xilinx_lcu (P, G, CI, CO);
+ parameter WIDTH = 2;
+
+ input [WIDTH-1:0] P, G;
+ input CI;
+
+ output [WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = WIDTH <= 2;
+
+ wire [WIDTH-1:0] C = {CO, CI};
+ wire [WIDTH-1:0] S = P & ~G;
+
+ genvar i;
+ generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
+ MUXCY muxcy (
+ .CI(C[i]),
+ .DI(G[i]),
+ .S(S[i]),
+ .O(CO[i])
+ );
+ end endgenerate
+endmodule
+
+(* techmap_celltype = "$alu" *)
+module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ input [A_WIDTH-1:0] A;
+ input [B_WIDTH-1:0] B;
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ output [Y_WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ wire [Y_WIDTH-1:0] A_buf, B_buf;
+ \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+ \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+ wire [Y_WIDTH-1:0] AA = A_buf;
+ wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+
+ wire [Y_WIDTH-1:0] P = AA ^ BB;
+ wire [Y_WIDTH-1:0] G = AA & BB;
+ wire [Y_WIDTH-1:0] C = {CO, CI};
+ wire [Y_WIDTH-1:0] S = P & ~G;
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
+ MUXCY muxcy (
+ .CI(C[i]),
+ .DI(G[i]),
+ .S(S[i]),
+ .O(CO[i])
+ );
+ XORCY xorcy (
+ .CI(C[i]),
+ .LI(S[i]),
+ .O(Y[i])
+ );
+ end endgenerate
+
+ assign X = P;
+endmodule
+
diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt
new file mode 100644
index 000000000..84c114578
--- /dev/null
+++ b/techlibs/xilinx/brams.txt
@@ -0,0 +1,101 @@
+
+bram $__XILINX_RAMB36_SDP
+ abits 9
+ dbits 72
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 8
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__XILINX_RAMB18_SDP
+ abits 9
+ dbits 36
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 4
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__XILINX_RAMB36_TDP
+ abits 10 @a10d36
+ dbits 36 @a10d36
+ abits 11 @a11d18
+ dbits 18 @a11d18
+ abits 12 @a12d9
+ dbits 9 @a12d9
+ abits 13 @a13d4
+ dbits 4 @a13d4
+ abits 14 @a14d2
+ dbits 2 @a14d2
+ abits 15 @a15d1
+ dbits 1 @a15d1
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 4 @a10d36
+ enable 0 2 @a11d18
+ enable 0 1 @a12d9 @a13d4 @a14d2 @a15d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__XILINX_RAMB18_TDP
+ abits 10 @a10d18
+ dbits 18 @a10d18
+ abits 11 @a11d9
+ dbits 9 @a11d9
+ abits 12 @a12d4
+ dbits 4 @a12d4
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 2 @a10d18
+ enable 0 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__XILINX_RAMB36_SDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__XILINX_RAMB18_SDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__XILINX_RAMB36_TDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__XILINX_RAMB18_TDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+endmatch
+
diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/brams_map.v
new file mode 100644
index 000000000..2e9bba9a9
--- /dev/null
+++ b/techlibs/xilinx/brams_map.v
@@ -0,0 +1,267 @@
+module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [8:0] A1ADDR;
+ output [71:0] A1DATA;
+
+ input [8:0] B1ADDR;
+ input [71:0] B1DATA;
+ input [7:0] B1EN;
+
+ wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0};
+ wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0};
+
+ wire [7:0] DIP, DOP;
+ wire [63:0] DI, DO;
+
+ assign A1DATA = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32],
+ DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+
+ assign { DIP[7], DI[63:56], DIP[6], DI[55:48], DIP[5], DI[47:40], DIP[4], DI[39:32],
+ DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ RAMB36E1 #(
+ .RAM_MODE("SDP"),
+ .READ_WIDTH_A(72),
+ .WRITE_WIDTH_B(72),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ .IS_CLKARDCLK_INVERTED(!CLKPOL2),
+ .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+ .SIM_DEVICE("7SERIES")
+ ) _TECHMAP_REPLACE_ (
+ .DOBDO(DO[63:32]),
+ .DOADO(DO[31:0]),
+ .DOPBDOP(DOP[7:4]),
+ .DOPADOP(DOP[3:0]),
+ .DIBDI(DI[63:32]),
+ .DIADI(DI[31:0]),
+ .DIPBDIP(DIP[7:4]),
+ .DIPADIP(DIP[3:0]),
+
+ .ADDRARDADDR(A1ADDR_16),
+ .CLKARDCLK(CLK2),
+ .ENARDEN(|1),
+ .REGCEAREGCE(|1),
+ .RSTRAMARSTRAM(|0),
+ .RSTREGARSTREG(|0),
+ .WEA(4'b0),
+
+ .ADDRBWRADDR(B1ADDR_16),
+ .CLKBWRCLK(CLK3),
+ .ENBWREN(|1),
+ .REGCEB(|0),
+ .RSTRAMB(|0),
+ .RSTREGB(|0),
+ .WEBWE(B1EN)
+ );
+endmodule
+
+// ------------------------------------------------------------------------
+
+module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [8:0] A1ADDR;
+ output [35:0] A1DATA;
+
+ input [8:0] B1ADDR;
+ input [35:0] B1DATA;
+ input [3:0] B1EN;
+
+ wire [13:0] A1ADDR_14 = {A1ADDR, 5'b0};
+ wire [13:0] B1ADDR_14 = {B1ADDR, 5'b0};
+
+ wire [3:0] DIP, DOP;
+ wire [31:0] DI, DO;
+
+ assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ RAMB18E1 #(
+ .RAM_MODE("SDP"),
+ .READ_WIDTH_A(36),
+ .WRITE_WIDTH_B(36),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ .IS_CLKARDCLK_INVERTED(!CLKPOL2),
+ .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+ .SIM_DEVICE("7SERIES")
+ ) _TECHMAP_REPLACE_ (
+ .DOBDO(DO[31:16]),
+ .DOADO(DO[15:0]),
+ .DOPBDOP(DOP[3:2]),
+ .DOPADOP(DOP[1:0]),
+ .DIBDI(DI[31:16]),
+ .DIADI(DI[15:0]),
+ .DIPBDIP(DIP[3:2]),
+ .DIPADIP(DIP[1:0]),
+
+ .ADDRARDADDR(A1ADDR_14),
+ .CLKARDCLK(CLK2),
+ .ENARDEN(|1),
+ .REGCEAREGCE(|1),
+ .RSTRAMARSTRAM(|0),
+ .RSTREGARSTREG(|0),
+ .WEA(2'b0),
+
+ .ADDRBWRADDR(B1ADDR_14),
+ .CLKBWRCLK(CLK3),
+ .ENBWREN(|1),
+ .REGCEB(|0),
+ .RSTRAMB(|0),
+ .RSTREGB(|0),
+ .WEBWE(B1EN)
+ );
+endmodule
+
+// ------------------------------------------------------------------------
+
+module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 36;
+ parameter CFG_ENABLE_B = 4;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input [CFG_ENABLE_B-1:0] B1EN;
+
+ wire [15:0] A1ADDR_16 = A1ADDR << (15 - CFG_ABITS);
+ wire [15:0] B1ADDR_16 = B1ADDR << (15 - CFG_ABITS);
+ wire [7:0] B1EN_8 = B1EN;
+
+ wire [3:0] DIP, DOP;
+ wire [31:0] DI, DO;
+
+ wire [31:0] DOBDO;
+ wire [3:0] DOPBDOP;
+
+ assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ RAMB36E1 #(
+ .RAM_MODE("TDP"),
+ .READ_WIDTH_A(CFG_DBITS),
+ .READ_WIDTH_B(CFG_DBITS),
+ .WRITE_WIDTH_A(CFG_DBITS),
+ .WRITE_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ .IS_CLKARDCLK_INVERTED(!CLKPOL2),
+ .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+ .SIM_DEVICE("7SERIES")
+ ) _TECHMAP_REPLACE_ (
+ .DIADI(32'd0),
+ .DIPADIP(4'd0),
+ .DOADO(DO[31:0]),
+ .DOPADOP(DOP[3:0]),
+ .ADDRARDADDR(A1ADDR_16),
+ .CLKARDCLK(CLK2),
+ .ENARDEN(|1),
+ .REGCEAREGCE(|1),
+ .RSTRAMARSTRAM(|0),
+ .RSTREGARSTREG(|0),
+ .WEA(4'b0),
+
+ .DIBDI(DI),
+ .DIPBDIP(DIP),
+ .DOBDO(DOBDO),
+ .DOPBDOP(DOPBDOP),
+ .ADDRBWRADDR(B1ADDR_16),
+ .CLKBWRCLK(CLK3),
+ .ENBWREN(|1),
+ .REGCEB(|0),
+ .RSTRAMB(|0),
+ .RSTREGB(|0),
+ .WEBWE(B1EN_8)
+ );
+endmodule
+
+// ------------------------------------------------------------------------
+
+module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 18;
+ parameter CFG_ENABLE_B = 2;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input [CFG_ENABLE_B-1:0] B1EN;
+
+ wire [13:0] A1ADDR_14 = A1ADDR << (14 - CFG_ABITS);
+ wire [13:0] B1ADDR_14 = B1ADDR << (14 - CFG_ABITS);
+ wire [3:0] B1EN_4 = B1EN;
+
+ wire [1:0] DIP, DOP;
+ wire [15:0] DI, DO;
+
+ wire [15:0] DOBDO;
+ wire [1:0] DOPBDOP;
+
+ assign A1DATA = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ RAMB18E1 #(
+ .RAM_MODE("TDP"),
+ .READ_WIDTH_A(CFG_DBITS),
+ .READ_WIDTH_B(CFG_DBITS),
+ .WRITE_WIDTH_A(CFG_DBITS),
+ .WRITE_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ .IS_CLKARDCLK_INVERTED(!CLKPOL2),
+ .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+ .SIM_DEVICE("7SERIES")
+ ) _TECHMAP_REPLACE_ (
+ .DIADI(16'b0),
+ .DIPADIP(2'b0),
+ .DOADO(DO),
+ .DOPADOP(DOP),
+ .ADDRARDADDR(A1ADDR_14),
+ .CLKARDCLK(CLK2),
+ .ENARDEN(|1),
+ .REGCEAREGCE(|1),
+ .RSTRAMARSTRAM(|0),
+ .RSTREGARSTREG(|0),
+ .WEA(2'b0),
+
+ .DIBDI(DI),
+ .DIPBDIP(DIP),
+ .DOBDO(DOBDO),
+ .DOPBDOP(DOPBDOP),
+ .ADDRBWRADDR(B1ADDR_14),
+ .CLKBWRCLK(CLK3),
+ .ENBWREN(|1),
+ .REGCEB(|0),
+ .RSTRAMB(|0),
+ .RSTREGB(|0),
+ .WEBWE(B1EN_4)
+ );
+endmodule
+
diff --git a/techlibs/xilinx/cells.v b/techlibs/xilinx/cells.v
deleted file mode 100644
index d19be0db7..000000000
--- a/techlibs/xilinx/cells.v
+++ /dev/null
@@ -1,53 +0,0 @@
-module \$_DFF_P_ (D, C, Q);
-
- input D, C;
- output Q;
-
- FDRE fpga_dff (
- .D(D), .Q(Q), .C(C),
- .CE(1'b1), .R(1'b0)
- );
-
-endmodule
-
-module \$lut (A, Y);
-
- parameter WIDTH = 0;
- parameter LUT = 0;
-
- input [WIDTH-1:0] A;
- output Y;
-
- generate
- if (WIDTH == 1) begin:lut1
- LUT1 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]));
- end else
- if (WIDTH == 2) begin:lut2
- LUT2 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]), .I1(A[1]));
- end else
- if (WIDTH == 3) begin:lut3
- LUT3 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]));
- end else
- if (WIDTH == 4) begin:lut4
- LUT4 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]));
- end else
- if (WIDTH == 5) begin:lut5
- LUT5 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]));
- end else
- if (WIDTH == 6) begin:lut6
- LUT6 #(.INIT(LUT)) fpga_lut (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- end else begin:error
- wire _TECHMAP_FAIL_ = 1;
- end
- endgenerate
-
-endmodule
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
new file mode 100644
index 000000000..8e5a83ce5
--- /dev/null
+++ b/techlibs/xilinx/cells_map.v
@@ -0,0 +1,84 @@
+
+module \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
+module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
+module \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
+
+module \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]));
+ end else
+ if (WIDTH == 6) begin
+ LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ end else
+ if (WIDTH == 7) begin
+ wire T0, T1;
+ LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
+ end else
+ if (WIDTH == 8) begin
+ wire T0, T1, T2, T3, T4, T5;
+ LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
+ MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
+ MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
new file mode 100644
index 000000000..1f114a22c
--- /dev/null
+++ b/techlibs/xilinx/cells_sim.v
@@ -0,0 +1,158 @@
+
+// See Xilinx UG953 and UG474 for a description of the cell types below.
+// http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
+// http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_4/ug953-vivado-7series-libraries.pdf
+
+module VCC(output P);
+ assign P = 1;
+endmodule
+
+module GND(output G);
+ assign G = 0;
+endmodule
+
+module IBUF(output O, input I);
+ assign O = I;
+endmodule
+
+module OBUF(output O, input I);
+ assign O = I;
+endmodule
+
+module BUFG(output O, input I);
+ assign O = I;
+endmodule
+
+// module OBUFT(output O, input I, T);
+// assign O = T ? 1'bz : I;
+// endmodule
+
+// module IOBUF(inout IO, output O, input I, T);
+// assign O = IO, IO = T ? 1'bz : I;
+// endmodule
+
+module INV(output O, input I);
+ assign O = !I;
+endmodule
+
+module LUT1(output O, input I0);
+ parameter [1:0] INIT = 0;
+ assign O = I0 ? INIT[1] : INIT[0];
+endmodule
+
+module LUT2(output O, input I0, I1);
+ parameter [3:0] INIT = 0;
+ wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+module LUT3(output O, input I0, I1, I2);
+ parameter [7:0] INIT = 0;
+ wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+module LUT4(output O, input I0, I1, I2, I3);
+ parameter [15:0] INIT = 0;
+ wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
+ wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+module LUT5(output O, input I0, I1, I2, I3, I4);
+ parameter [31:0] INIT = 0;
+ wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
+ wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
+ wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+module LUT6(output O, input I0, I1, I2, I3, I4, I5);
+ parameter [63:0] INIT = 0;
+ wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
+ wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
+ wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
+ wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+module MUXCY(output O, input CI, DI, S);
+ assign O = S ? CI : DI;
+endmodule
+
+module MUXF7(output O, input I0, I1, S);
+ assign O = S ? I1 : I0;
+endmodule
+
+module MUXF8(output O, input I0, I1, S);
+ assign O = S ? I1 : I0;
+endmodule
+
+module XORCY(output O, input CI, LI);
+ assign O = CI ^ LI;
+endmodule
+
+module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
+ assign O = S ^ {CO[2:0], CI | CYINIT};
+ assign CO[0] = S[0] ? CI | CYINIT : DI[0];
+ assign CO[1] = S[1] ? CO[0] : DI[1];
+ assign CO[2] = S[2] ? CO[1] : DI[2];
+ assign CO[3] = S[3] ? CO[2] : DI[3];
+endmodule
+
+module FDRE (output reg 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;
+ initial Q <= INIT;
+ generate case (|IS_C_INVERTED)
+ 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ endcase endgenerate
+endmodule
+
+module FDSE (output reg Q, input C, CE, D, S);
+ 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_S_INVERTED = 1'b0;
+ initial Q <= INIT;
+ generate case (|IS_C_INVERTED)
+ 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ endcase endgenerate
+endmodule
+
+module FDCE (output reg 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;
+ initial Q <= INIT;
+ generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED})
+ 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
+ endcase endgenerate
+endmodule
+
+module FDPE (output reg Q, input C, CE, D, PRE);
+ 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_PRE_INVERTED = 1'b0;
+ initial Q <= INIT;
+ generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED})
+ 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
+ endcase endgenerate
+endmodule
+
diff --git a/techlibs/xilinx/example_basys3/README b/techlibs/xilinx/example_basys3/README
new file mode 100644
index 000000000..85b6eab10
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/README
@@ -0,0 +1,16 @@
+
+A simple example design, based on the Digilent BASYS3 board
+===========================================================
+
+Running Yosys:
+ yosys run_yosys.ys
+
+Running Vivado:
+ vivado -nolog -nojournal -mode batch -source run_vivado.tcl
+
+Programming board:
+ vivado -nolog -nojournal -mode batch -source run_prog.tcl
+
+All of the above:
+ bash run.sh
+
diff --git a/techlibs/xilinx/example_basys3/example.v b/techlibs/xilinx/example_basys3/example.v
new file mode 100644
index 000000000..2b01a22a8
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/example.v
@@ -0,0 +1,21 @@
+module example(CLK, LD);
+ input CLK;
+ output [15:0] LD;
+
+ wire clock;
+ reg [15:0] leds;
+
+ BUFG CLK_BUF (.I(CLK), .O(clock));
+ OBUF LD_BUF[15:0] (.I(leds), .O(LD));
+
+ parameter COUNTBITS = 26;
+ reg [COUNTBITS-1:0] counter;
+
+ always @(posedge CLK) begin
+ counter <= counter + 1;
+ if (counter[COUNTBITS-1])
+ leds <= 16'h8000 >> counter[COUNTBITS-2:COUNTBITS-5];
+ else
+ leds <= 16'h0001 << counter[COUNTBITS-2:COUNTBITS-5];
+ end
+endmodule
diff --git a/techlibs/xilinx/example_basys3/example.xdc b/techlibs/xilinx/example_basys3/example.xdc
new file mode 100644
index 000000000..c1fd0e925
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/example.xdc
@@ -0,0 +1,21 @@
+
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W5 } [get_ports CLK]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U16 } [get_ports {LD[0]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN E19 } [get_ports {LD[1]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U19 } [get_ports {LD[2]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V19 } [get_ports {LD[3]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W18 } [get_ports {LD[4]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U15 } [get_ports {LD[5]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U14 } [get_ports {LD[6]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V14 } [get_ports {LD[7]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V13 } [get_ports {LD[8]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V3 } [get_ports {LD[9]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W3 } [get_ports {LD[10]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U3 } [get_ports {LD[11]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN P3 } [get_ports {LD[12]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN N3 } [get_ports {LD[13]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN P1 } [get_ports {LD[14]}]
+set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN L1 } [get_ports {LD[15]}]
+
+create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK]
+
diff --git a/techlibs/xilinx/example_basys3/run.sh b/techlibs/xilinx/example_basys3/run.sh
new file mode 100644
index 000000000..10f059103
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/run.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+yosys run_yosys.ys
+vivado -nolog -nojournal -mode batch -source run_vivado.tcl
+vivado -nolog -nojournal -mode batch -source run_prog.tcl
diff --git a/techlibs/xilinx/example_basys3/run_prog.tcl b/techlibs/xilinx/example_basys3/run_prog.tcl
new file mode 100644
index 000000000..d711af840
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/run_prog.tcl
@@ -0,0 +1,4 @@
+connect_hw_server
+open_hw_target [lindex [get_hw_targets] 0]
+set_property PROGRAM.FILE example.bit [lindex [get_hw_devices] 0]
+program_hw_devices [lindex [get_hw_devices] 0]
diff --git a/techlibs/xilinx/example_basys3/run_vivado.tcl b/techlibs/xilinx/example_basys3/run_vivado.tcl
new file mode 100644
index 000000000..c3b6a610e
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/run_vivado.tcl
@@ -0,0 +1,9 @@
+read_xdc example.xdc
+read_edif example.edif
+link_design -part xc7a35tcpg236-1 -top example
+opt_design
+place_design
+route_design
+report_utilization
+report_timing
+write_bitstream -force example.bit
diff --git a/techlibs/xilinx/example_basys3/run_yosys.ys b/techlibs/xilinx/example_basys3/run_yosys.ys
new file mode 100644
index 000000000..4541826d3
--- /dev/null
+++ b/techlibs/xilinx/example_basys3/run_yosys.ys
@@ -0,0 +1,2 @@
+read_verilog example.v
+synth_xilinx -edif example.edif -top example
diff --git a/techlibs/xilinx/example_mojo_counter/README b/techlibs/xilinx/example_mojo_counter/README
deleted file mode 100644
index 690a9d843..000000000
--- a/techlibs/xilinx/example_mojo_counter/README
+++ /dev/null
@@ -1,10 +0,0 @@
-
-This is a simple example for Yosys synthesis targeting the Mojo FPGA
-development board [1, 2]. Simple script for xst-based synthesis (incl.
-generation of reference edif files) and uploading to the board can be
-found here [3].
-
-[1] http://embeddedmicro.com/tutorials/mojo
-[2] https://www.sparkfun.com/products/11953
-[3] http://svn.clifford.at/handicraft/2013/mojo/
-
diff --git a/techlibs/xilinx/example_mojo_counter/example.sh b/techlibs/xilinx/example_mojo_counter/example.sh
deleted file mode 100644
index 74a0c117f..000000000
--- a/techlibs/xilinx/example_mojo_counter/example.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-XILINX_DIR=/opt/Xilinx/14.5/ISE_DS/ISE
-XILINX_PART=xc6slx9-2-tqg144
-
-../../../yosys - <<- EOT
- read_verilog example.v
- synth_xilinx -edif synth.edif
-EOT
-
-$XILINX_DIR/bin/lin64/edif2ngd -a synth.edif synth.ngo
-$XILINX_DIR/bin/lin64/ngdbuild -p $XILINX_PART -uc example.ucf synth.ngo synth.ngd
-$XILINX_DIR/bin/lin64/map -p $XILINX_PART -w -o mapped.ncd synth.ngd constraints.pcf
-$XILINX_DIR/bin/lin64/par -w mapped.ncd placed.ncd constraints.pcf
-$XILINX_DIR/bin/lin64/bitgen -w placed.ncd example.bit constraints.pcf
-
diff --git a/techlibs/xilinx/example_mojo_counter/example.ucf b/techlibs/xilinx/example_mojo_counter/example.ucf
deleted file mode 100644
index 93d97b4dc..000000000
--- a/techlibs/xilinx/example_mojo_counter/example.ucf
+++ /dev/null
@@ -1,14 +0,0 @@
-NET "clk" TNM_NET = clk;
-TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
-
-NET "clk" LOC = P56;
-NET "ctrl" LOC = P1;
-
-NET "led_0" LOC = P134;
-NET "led_1" LOC = P133;
-NET "led_2" LOC = P132;
-NET "led_3" LOC = P131;
-NET "led_4" LOC = P127;
-NET "led_5" LOC = P126;
-NET "led_6" LOC = P124;
-NET "led_7" LOC = P123;
diff --git a/techlibs/xilinx/example_mojo_counter/example.v b/techlibs/xilinx/example_mojo_counter/example.v
deleted file mode 100644
index cb98cc1b2..000000000
--- a/techlibs/xilinx/example_mojo_counter/example.v
+++ /dev/null
@@ -1,14 +0,0 @@
-module top(clk, ctrl, led_7, led_6, led_5, led_4, led_3, led_2, led_1, led_0);
-
-input clk, ctrl;
-output led_7, led_6, led_5, led_4;
-output led_3, led_2, led_1, led_0;
-
-reg [31:0] counter;
-
-always @(posedge clk)
- counter <= counter + (ctrl ? 4 : 1);
-
-assign {led_7, led_6, led_5, led_4, led_3, led_2, led_1, led_0} = counter >> 24;
-
-endmodule
diff --git a/techlibs/xilinx/example_sim_counter/counter.v b/techlibs/xilinx/example_sim_counter/counter.v
deleted file mode 100644
index 72208bd80..000000000
--- a/techlibs/xilinx/example_sim_counter/counter.v
+++ /dev/null
@@ -1,12 +0,0 @@
-module counter (clk, rst, en, count);
-
- input clk, rst, en;
- output reg [3:0] count;
-
- always @(posedge clk)
- if (rst)
- count <= 4'd0;
- else if (en)
- count <= count + 4'd1;
-
-endmodule
diff --git a/techlibs/xilinx/example_sim_counter/counter_tb.v b/techlibs/xilinx/example_sim_counter/counter_tb.v
deleted file mode 100644
index b6b64269e..000000000
--- a/techlibs/xilinx/example_sim_counter/counter_tb.v
+++ /dev/null
@@ -1,61 +0,0 @@
-`timescale 1 ns / 1 ps
-
-module testbench;
-
-reg clk, en, rst;
-wire [3:0] count;
-
-counter uut_counter(
- .clk(clk),
- .count(count),
- .en(en),
- .rst(rst)
-);
-
-initial begin
- clk <= 0;
- forever begin
- #50;
- clk <= ~clk;
- end
-end
-
-initial begin
- @(posedge clk);
- forever begin
- @(posedge clk);
- $display("%d", count);
- end
-end
-
-initial begin
- rst <= 1; en <= 0; @(posedge clk);
- rst <= 1; en <= 0; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 1; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 1; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- rst <= 0; en <= 1; @(posedge clk);
- rst <= 0; en <= 0; @(posedge clk);
- $finish;
-end
-
-endmodule
diff --git a/techlibs/xilinx/example_sim_counter/run_sim.sh b/techlibs/xilinx/example_sim_counter/run_sim.sh
deleted file mode 100644
index b8354c002..000000000
--- a/techlibs/xilinx/example_sim_counter/run_sim.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-XILINX_DIR=/opt/Xilinx/14.5/ISE_DS/ISE
-
-../../../yosys -p 'synth_xilinx -top counter; write_verilog -noattr testbench_synth.v' counter.v
-
-iverilog -o testbench_gold counter_tb.v counter.v
-iverilog -o testbench_gate counter_tb.v testbench_synth.v \
- $XILINX_DIR/verilog/src/{glbl,unisims/{FDRE,LUT1,LUT2,LUT3,LUT4,LUT5,LUT6,BUFGP,IBUF}}.v
-
-./testbench_gold > testbench_gold.txt
-./testbench_gate > testbench_gate.txt
-
-if diff -u testbench_gold.txt testbench_gate.txt; then
- set +x; echo; echo; banner " PASS "
-else
- exit 1
-fi
-
-rm -f testbench_{synth,gold,gate,mapped}*
-
diff --git a/techlibs/xilinx/example_zed_counter/README b/techlibs/xilinx/example_zed_counter/README
deleted file mode 100644
index 539f24e73..000000000
--- a/techlibs/xilinx/example_zed_counter/README
+++ /dev/null
@@ -1,10 +0,0 @@
-
-This is a simple example for Yosys synthesis targeting the ZED FPGA
-development board [1, 2]. Simple script for xst-based synthesis (incl.
-generation of reference edif files) and uploading to the board can be
-found here [3].
-
-[1] http://www.zedboard.org/
-[2] https://www.xilinx.com/zynq/
-[3] http://verilog.james.walms.co.uk/
-
diff --git a/techlibs/xilinx/example_zed_counter/example.sh b/techlibs/xilinx/example_zed_counter/example.sh
deleted file mode 100644
index d0fcd8322..000000000
--- a/techlibs/xilinx/example_zed_counter/example.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-XILINX_DIR=/opt/Xilinx/14.7/ISE_DS/ISE
-XILINX_PART=xc7z020clg484-1
-
-yosys - <<- EOT
- read_verilog example.v
- synth_xilinx -edif synth.edif
-EOT
-
-$XILINX_DIR/bin/lin64/edif2ngd -a synth.edif synth.ngo
-$XILINX_DIR/bin/lin64/ngdbuild -p $XILINX_PART -uc example.ucf synth.ngo synth.ngd
-$XILINX_DIR/bin/lin64/map -p $XILINX_PART -w -o mapped.ncd synth.ngd constraints.pcf
-$XILINX_DIR/bin/lin64/par -w mapped.ncd placed.ncd constraints.pcf
-$XILINX_DIR/bin/lin64/bitgen -w placed.ncd example.bit constraints.pcf
-$XILINX_DIR/bin/lin64/promgen -w -b -p bin -o example.bin -u 0 example.bit -data_width 32
diff --git a/techlibs/xilinx/example_zed_counter/example.ucf b/techlibs/xilinx/example_zed_counter/example.ucf
deleted file mode 100644
index dadc8373c..000000000
--- a/techlibs/xilinx/example_zed_counter/example.ucf
+++ /dev/null
@@ -1,14 +0,0 @@
-NET "clk" TNM_NET = clk;
-TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
-
-NET "clk" LOC = Y9 | IOSTANDARD=LVCMOS33; # "GCLK"
-NET "ctrl" LOC = P16 | IOSTANDARD=LVCMOS18; # "BTNC"
-
-NET "led_0" LOC = T22 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_1" LOC = T21 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_2" LOC = U22 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_3" LOC = U21 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_4" LOC = V22 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_5" LOC = W22 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_6" LOC = U19 | IOSTANDARD=LVCMOS33; # "LD0"
-NET "led_7" LOC = U14 | IOSTANDARD=LVCMOS33; # "LD0"
diff --git a/techlibs/xilinx/example_zed_counter/example.v b/techlibs/xilinx/example_zed_counter/example.v
deleted file mode 100644
index cb98cc1b2..000000000
--- a/techlibs/xilinx/example_zed_counter/example.v
+++ /dev/null
@@ -1,14 +0,0 @@
-module top(clk, ctrl, led_7, led_6, led_5, led_4, led_3, led_2, led_1, led_0);
-
-input clk, ctrl;
-output led_7, led_6, led_5, led_4;
-output led_3, led_2, led_1, led_0;
-
-reg [31:0] counter;
-
-always @(posedge clk)
- counter <= counter + (ctrl ? 4 : 1);
-
-assign {led_7, led_6, led_5, led_4, led_3, led_2, led_1, led_0} = counter >> 24;
-
-endmodule
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index ff906db8f..836ba9add 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -22,7 +22,10 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
-static bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
{
if (label == run_from)
active = true;
@@ -40,16 +43,12 @@ struct SynthXilinxPass : public Pass {
log(" synth_xilinx [options]\n");
log("\n");
log("This command runs synthesis for Xilinx FPGAs. This command does not operate on\n");
- log("partly selected designs.\n");
+ log("partly selected designs. At the moment this command creates netlists that are\n");
+ log("compatible with 7-Series Xilinx devices.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n");
log("\n");
- log(" -arch <arch>\n");
- log(" select architecture. the following architectures are supported:\n");
- log(" spartan6 (default), artix7, kintex7, virtex7, zynq7000\n");
- log(" (this parameter is not used by the command at the moment)\n");
- log("\n");
log(" -edif <file>\n");
log(" write the design to the specified edif file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
@@ -59,39 +58,50 @@ struct SynthXilinxPass : public Pass {
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
+ log(" -flatten\n");
+ log(" flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
log("\n");
log(" begin:\n");
+ log(" read_verilog -lib +/xilinx/cells_sim.v\n");
log(" hierarchy -check -top <top>\n");
log("\n");
- log(" coarse:\n");
+ log(" flatten: (only if -flatten)\n");
log(" proc\n");
- log(" opt\n");
- log(" memory\n");
- log(" clean\n");
- log(" fsm\n");
- log(" opt\n");
+ log(" flatten\n");
+ log("\n");
+ log(" coarse:\n");
+ log(" synth -run coarse\n");
+ log(" dff2dffe\n");
+ log("\n");
+ log(" bram:\n");
+ log(" memory_bram -rules +/xilinx/brams.txt\n");
+ log(" techmap -map +/xilinx/brams_map.v\n");
log("\n");
log(" fine:\n");
- log(" techmap\n");
- log(" opt\n");
+ log(" opt -fast -full\n");
+ log(" memory_map\n");
+ log(" opt -full\n");
+ log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
+ log(" opt -fast\n");
log("\n");
log(" map_luts:\n");
- log(" abc -lut 6\n");
+ log(" abc -lut 5:8 [-dff]\n");
log(" clean\n");
log("\n");
log(" map_cells:\n");
- log(" techmap -share_map xilinx/cells.v\n");
+ log(" techmap -map +/xilinx/cells_map.v\n");
log(" clean\n");
log("\n");
- log(" clkbuf:\n");
- log(" select -set xilinx_clocks <top>/t:FDRE %%x:+FDRE[C] <top>/t:FDRE %%d\n");
- log(" iopadmap -inpad BUFGP O:I @xilinx_clocks\n");
- log("\n");
- log(" iobuf:\n");
- log(" select -set xilinx_nonclocks <top>/w:* <top>/t:BUFGP %%x:+BUFGP[I] %%d\n");
- log(" iopadmap -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks\n");
+ log(" check:\n");
+ log(" hierarchy -check\n");
+ log(" stat\n");
+ log(" check -noinit\n");
log("\n");
log(" edif:\n");
log(" write_edif synth.edif\n");
@@ -103,6 +113,8 @@ struct SynthXilinxPass : public Pass {
std::string arch_name = "spartan6";
std::string edif_file;
std::string run_from, run_to;
+ bool flatten = false;
+ bool retime = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -111,10 +123,6 @@ struct SynthXilinxPass : public Pass {
top_module = args[++argidx];
continue;
}
- if (args[argidx] == "-arch" && argidx+1 < args.size()) {
- arch_name = args[++argidx];
- continue;
- }
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
edif_file = args[++argidx];
continue;
@@ -127,6 +135,14 @@ struct SynthXilinxPass : public Pass {
run_to = args[argidx].substr(pos+1);
continue;
}
+ if (args[argidx] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -134,20 +150,6 @@ struct SynthXilinxPass : public Pass {
if (!design->full_selection())
log_cmd_error("This comannd only operates on fully selected designs!\n");
- if (arch_name == "spartan6") {
- /* set flags */
- } else
- if (arch_name == "artix7") {
- /* set flags */
- } else
- if (arch_name == "kintex7") {
- /* set flags */
- } else
- if (arch_name == "zynq7000") {
- /* set flags */
- } else
- log_cmd_error("Architecture '%s' is not supported!\n", arch_name.c_str());
-
bool active = run_from.empty();
log_header("Executing SYNTH_XILINX pass.\n");
@@ -155,47 +157,54 @@ struct SynthXilinxPass : public Pass {
if (check_label(active, run_from, run_to, "begin"))
{
+ Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str()));
}
- if (check_label(active, run_from, run_to, "coarse"))
+ if (flatten && check_label(active, run_from, run_to, "flatten"))
{
Pass::call(design, "proc");
- Pass::call(design, "opt");
- Pass::call(design, "memory");
- Pass::call(design, "clean");
- Pass::call(design, "fsm");
- Pass::call(design, "opt");
+ Pass::call(design, "flatten");
+ }
+
+ if (check_label(active, run_from, run_to, "coarse"))
+ {
+ Pass::call(design, "synth -run coarse");
+ Pass::call(design, "dff2dffe");
+ }
+
+ if (check_label(active, run_from, run_to, "bram"))
+ {
+ Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
+ Pass::call(design, "techmap -map +/xilinx/brams_map.v");
}
if (check_label(active, run_from, run_to, "fine"))
{
- Pass::call(design, "techmap");
- Pass::call(design, "opt");
+ Pass::call(design, "opt -fast -full");
+ Pass::call(design, "memory_map");
+ Pass::call(design, "opt -full");
+ Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
+ Pass::call(design, "opt -fast");
}
if (check_label(active, run_from, run_to, "map_luts"))
{
- Pass::call(design, "abc -lut 6");
+ Pass::call(design, "abc -lut 5:8" + string(retime ? " -dff" : ""));
Pass::call(design, "clean");
}
if (check_label(active, run_from, run_to, "map_cells"))
{
- Pass::call(design, "techmap -share_map xilinx/cells.v");
+ Pass::call(design, "techmap -map +/xilinx/cells_map.v");
Pass::call(design, "clean");
}
- if (check_label(active, run_from, run_to, "clkbuf"))
- {
- Pass::call(design, stringf("select -set xilinx_clocks %s/t:FDRE %%x:+FDRE[C] %s/t:FDRE %%d", top_module.c_str(), top_module.c_str()));
- Pass::call(design, "iopadmap -inpad BUFGP O:I @xilinx_clocks");
- }
-
- if (check_label(active, run_from, run_to, "iobuf"))
+ if (check_label(active, run_from, run_to, "check"))
{
- Pass::call(design, stringf("select -set xilinx_nonclocks %s/w:* %s/t:BUFGP %%x:+BUFGP[I] %%d", top_module.c_str(), top_module.c_str()));
- Pass::call(design, "iopadmap -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks");
+ Pass::call(design, "hierarchy -check");
+ Pass::call(design, "stat");
+ Pass::call(design, "check -noinit");
}
if (check_label(active, run_from, run_to, "edif"))
@@ -208,3 +217,4 @@ struct SynthXilinxPass : public Pass {
}
} SynthXilinxPass;
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore
new file mode 100644
index 000000000..bc2f8babf
--- /dev/null
+++ b/techlibs/xilinx/tests/.gitignore
@@ -0,0 +1,3 @@
+bram1_cmp
+bram1.mk
+bram1_[0-9]*/
diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh
new file mode 100644
index 000000000..1f0359ac9
--- /dev/null
+++ b/techlibs/xilinx/tests/bram1.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+set -e
+
+transp_list="0 1"
+abits_list="1 2 4 8 10 16 20"
+dbits_list="1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80"
+
+use_xsim=false
+unisims=/opt/Xilinx/Vivado/2014.4/data/verilog/src/unisims
+
+echo "all: all_list" > bram1.mk
+all_list=""
+
+for transp in $transp_list; do
+for abits in $abits_list; do
+for dbits in $dbits_list; do
+ if [ $(( (1 << $abits) * $dbits )) -gt 1000000 ]; then continue; fi
+ id=`printf "%d%02d%02d" $transp $abits $dbits`
+ echo "Creating bram1_$id.."
+ rm -rf bram1_$id
+ mkdir -p bram1_$id
+ cp bram1.v bram1_tb.v bram1_$id/
+ sed -i "/parameter/ s,ABITS *= *[0-9]*,ABITS = $abits," bram1_$id/*.v
+ sed -i "/parameter/ s,DBITS *= *[0-9]*,DBITS = $dbits," bram1_$id/*.v
+ sed -i "/parameter/ s,TRANSP *= *[0-9]*,TRANSP = $transp," bram1_$id/*.v
+ {
+ echo "set -e"
+ echo "../../../../yosys -q -lsynth.log -p 'synth_xilinx -top bram1; write_verilog synth.v' bram1.v"
+ if $use_xsim; then
+ echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt"
+ echo "xvlog --work gate bram1_tb.v synth.v > gate.txt"
+ echo "xelab -R gold.bram1_tb >> gold.txt"
+ echo "xelab -L unisim -R gate.bram1_tb >> gate.txt"
+ else
+ echo "iverilog -o bram1_tb_gold bram1_tb.v bram1.v > gold.txt 2>&1"
+ echo "iverilog -o bram1_tb_gate bram1_tb.v synth.v -y $unisims $unisims/../glbl.v > gate.txt 2>&1"
+ echo "./bram1_tb_gold >> gold.txt"
+ echo "./bram1_tb_gate >> gate.txt"
+ fi
+ echo "../bram1_cmp <( grep '#OUT#' gold.txt; ) <( grep '#OUT#' gate.txt; )"
+ } > bram1_$id/run.sh
+ {
+ echo "bram1_$id/ok:"
+ echo " @cd bram1_$id && bash run.sh"
+ echo " @echo -n '[$id]'"
+ echo " @touch \$@"
+ } >> bram1.mk
+ all_list="$all_list bram1_$id/ok"
+done; done; done
+
+cc -o bram1_cmp ../../../tests/tools/cmp_tbdata.c
+echo all_list: $(echo $all_list | tr ' ' '\n' | sort -R) >> bram1.mk
+
+echo "Testing..."
+${MAKE:-make} -f bram1.mk
+echo
+
+echo "Used rules:" $(grep -h 'Selected rule.*with efficiency' bram1_*/synth.log | gawk '{ print $3; }' | sort -u)
+
+echo "Cleaning up..."
+rm -rf bram1_cmp bram1.mk bram1_[0-9]*/
+
diff --git a/techlibs/xilinx/tests/bram1.v b/techlibs/xilinx/tests/bram1.v
new file mode 100644
index 000000000..034cc18e9
--- /dev/null
+++ b/techlibs/xilinx/tests/bram1.v
@@ -0,0 +1,24 @@
+module bram1 #(
+ parameter ABITS = 8, DBITS = 8, TRANSP = 0
+) (
+ input clk,
+
+ input [ABITS-1:0] WR_ADDR,
+ input [DBITS-1:0] WR_DATA,
+ input WR_EN,
+
+ input [ABITS-1:0] RD_ADDR,
+ output [DBITS-1:0] RD_DATA
+);
+ reg [DBITS-1:0] memory [0:2**ABITS-1];
+ reg [ABITS-1:0] RD_ADDR_BUF;
+ reg [DBITS-1:0] RD_DATA_BUF;
+
+ always @(posedge clk) begin
+ if (WR_EN) memory[WR_ADDR] <= WR_DATA;
+ RD_ADDR_BUF <= RD_ADDR;
+ RD_DATA_BUF <= memory[RD_ADDR];
+ end
+
+ assign RD_DATA = TRANSP ? memory[RD_ADDR_BUF] : RD_DATA_BUF;
+endmodule
diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v
new file mode 100644
index 000000000..8f854b749
--- /dev/null
+++ b/techlibs/xilinx/tests/bram1_tb.v
@@ -0,0 +1,116 @@
+module bram1_tb #(
+ parameter ABITS = 8, DBITS = 8, TRANSP = 0
+);
+ reg clk;
+ reg [ABITS-1:0] WR_ADDR;
+ reg [DBITS-1:0] WR_DATA;
+ reg WR_EN;
+ reg [ABITS-1:0] RD_ADDR;
+ wire [DBITS-1:0] RD_DATA;
+
+ bram1 #(
+ // .ABITS(ABITS),
+ // .DBITS(DBITS),
+ // .TRANSP(TRANSP)
+ ) uut (
+ .clk (clk ),
+ .WR_ADDR(WR_ADDR),
+ .WR_DATA(WR_DATA),
+ .WR_EN (WR_EN ),
+ .RD_ADDR(RD_ADDR),
+ .RD_DATA(RD_DATA)
+ );
+
+ reg [63:0] xorshift64_state = 64'd88172645463325252 ^ (ABITS << 24) ^ (DBITS << 16) ^ (TRANSP << 8);
+
+ task xorshift64_next;
+ begin
+ // see page 4 of Marsaglia, George (July 2003). "Xorshift RNGs". Journal of Statistical Software 8 (14).
+ xorshift64_state = xorshift64_state ^ (xorshift64_state << 13);
+ xorshift64_state = xorshift64_state ^ (xorshift64_state >> 7);
+ xorshift64_state = xorshift64_state ^ (xorshift64_state << 17);
+ end
+ endtask
+
+ reg [ABITS-1:0] randaddr1;
+ reg [ABITS-1:0] randaddr2;
+ reg [ABITS-1:0] randaddr3;
+
+ function [31:0] getaddr(input [3:0] n);
+ begin
+ case (n)
+ 0: getaddr = 0;
+ 1: getaddr = 2**ABITS-1;
+ 2: getaddr = 'b101 << (ABITS / 3);
+ 3: getaddr = 'b101 << (2*ABITS / 3);
+ 4: getaddr = 'b11011 << (ABITS / 4);
+ 5: getaddr = 'b11011 << (2*ABITS / 4);
+ 6: getaddr = 'b11011 << (3*ABITS / 4);
+ 7: getaddr = randaddr1;
+ 8: getaddr = randaddr2;
+ 9: getaddr = randaddr3;
+ default: begin
+ getaddr = 1 << (2*n-16);
+ if (!getaddr) getaddr = xorshift64_state;
+ end
+ endcase
+ end
+ endfunction
+
+ reg [DBITS-1:0] memory [0:2**ABITS-1];
+ reg [DBITS-1:0] expected_rd, expected_rd_masked;
+
+ event error;
+ reg error_ind = 0;
+
+ integer i, j;
+ initial begin
+ // $dumpfile("testbench.vcd");
+ // $dumpvars(0, bram1_tb);
+
+ xorshift64_next;
+ xorshift64_next;
+ xorshift64_next;
+ xorshift64_next;
+
+ randaddr1 = xorshift64_state;
+ xorshift64_next;
+
+ randaddr2 = xorshift64_state;
+ xorshift64_next;
+
+ randaddr3 = xorshift64_state;
+ xorshift64_next;
+
+ clk <= 0;
+ for (i = 0; i < 512; i = i+1) begin
+ if (DBITS > 64)
+ WR_DATA <= (xorshift64_state << (DBITS-64)) ^ xorshift64_state;
+ else
+ WR_DATA <= xorshift64_state;
+ xorshift64_next;
+ WR_ADDR <= getaddr(i < 256 ? i[7:4] : xorshift64_state[63:60]);
+ xorshift64_next;
+ RD_ADDR <= getaddr(i < 256 ? i[3:0] : xorshift64_state[59:56]);
+ WR_EN <= xorshift64_state[55];
+ xorshift64_next;
+
+ #1; clk <= 1;
+ #1; clk <= 0;
+
+ if (TRANSP) begin
+ if (WR_EN) memory[WR_ADDR] = WR_DATA;
+ expected_rd = memory[RD_ADDR];
+ end else begin
+ expected_rd = memory[RD_ADDR];
+ if (WR_EN) memory[WR_ADDR] = WR_DATA;
+ end
+
+ for (j = 0; j < DBITS; j = j+1)
+ expected_rd_masked[j] = expected_rd[j] !== 1'bx ? expected_rd[j] : RD_DATA[j];
+
+ $display("#OUT# %3d | WA=%x WD=%x WE=%x | RA=%x RD=%x (%x) | %s", i, WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd, expected_rd_masked === RD_DATA ? "ok" : "ERROR");
+ if (expected_rd_masked !== RD_DATA) begin -> error; error_ind = ~error_ind; end
+ end
+ end
+endmodule