From 8520b7fbe0b24dda47749aa870881b6b03480d4a Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Mon, 6 Apr 2015 17:07:10 +0200
Subject: [PATCH] Added support for initialized xilinx brams

---
 README                           |   2 +-
 techlibs/xilinx/.gitignore       |   2 +
 techlibs/xilinx/Makefile.inc     |  21 +++
 techlibs/xilinx/brams.txt        |   4 +
 techlibs/xilinx/brams_init.py    |  37 +++++
 techlibs/xilinx/brams_map.v      | 228 +++++++++++++++++++++----------
 techlibs/xilinx/tests/bram1.v    |  17 +++
 techlibs/xilinx/tests/bram1_tb.v |  52 +++++--
 techlibs/xilinx/tests/bram2.sh   |   2 +-
 techlibs/xilinx/tests/bram2.v    |  19 ++-
 techlibs/xilinx/tests/bram2_tb.v |  19 ++-
 11 files changed, 313 insertions(+), 90 deletions(-)
 create mode 100644 techlibs/xilinx/.gitignore
 create mode 100644 techlibs/xilinx/brams_init.py

diff --git a/README b/README
index 856f6079b..af78a31ca 100644
--- a/README
+++ b/README
@@ -56,7 +56,7 @@ For example on Ubuntu Linux 14.04 LTS the following commands will install all
 prerequisites for building yosys:
 
 	$ yosys_deps="build-essential clang bison flex libreadline-dev gawk
-	       tcl-dev libffi-dev git mercurial graphviz xdot pkg-config"
+	       tcl-dev libffi-dev git mercurial graphviz xdot pkg-config python"
 	$ sudo apt-get install $yosys_deps
 
 There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
diff --git a/techlibs/xilinx/.gitignore b/techlibs/xilinx/.gitignore
new file mode 100644
index 000000000..d127107db
--- /dev/null
+++ b/techlibs/xilinx/.gitignore
@@ -0,0 +1,2 @@
+brams_init.mk
+brams_init_*.vh
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 18f6764ea..5253e129d 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -1,10 +1,31 @@
 
 OBJS += techlibs/xilinx/synth_xilinx.o
 
+GENFILES += techlibs/xilinx/brams_init_36.vh
+GENFILES += techlibs/xilinx/brams_init_32.vh
+GENFILES += techlibs/xilinx/brams_init_18.vh
+GENFILES += techlibs/xilinx/brams_init_16.vh
+
+EXTRA_OBJS += techlibs/xilinx/brams_init.mk
+.SECONDARY: techlibs/xilinx/brams_init.mk
+
+techlibs/xilinx/brams_init.mk: techlibs/xilinx/brams_init.py
+	cd techlibs/xilinx && python brams_init.py
+	touch techlibs/xilinx/brams_init.mk
+
+techlibs/xilinx/brams_init_36.vh: techlibs/xilinx/brams_init.mk
+techlibs/xilinx/brams_init_32.vh: techlibs/xilinx/brams_init.mk
+techlibs/xilinx/brams_init_18.vh: techlibs/xilinx/brams_init.mk
+techlibs/xilinx/brams_init_16.vh: techlibs/xilinx/brams_init.mk
+
 $(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/brams_init_36.vh))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_init_18.vh))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_init_16.vh))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
 
diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt
index 84c114578..5e71c468f 100644
--- a/techlibs/xilinx/brams.txt
+++ b/techlibs/xilinx/brams.txt
@@ -1,5 +1,6 @@
 
 bram $__XILINX_RAMB36_SDP
+  init 1
   abits 9
   dbits 72
   groups 2
@@ -12,6 +13,7 @@ bram $__XILINX_RAMB36_SDP
 endbram
 
 bram $__XILINX_RAMB18_SDP
+  init 1
   abits 9
   dbits 36
   groups 2
@@ -24,6 +26,7 @@ bram $__XILINX_RAMB18_SDP
 endbram
 
 bram $__XILINX_RAMB36_TDP
+  init 1
   abits 10     @a10d36
   dbits 36     @a10d36
   abits 11     @a11d18
@@ -48,6 +51,7 @@ bram $__XILINX_RAMB36_TDP
 endbram
 
 bram $__XILINX_RAMB18_TDP
+  init 1
   abits 10     @a10d18
   dbits 18     @a10d18
   abits 11     @a11d9
diff --git a/techlibs/xilinx/brams_init.py b/techlibs/xilinx/brams_init.py
new file mode 100644
index 000000000..be61d3f6a
--- /dev/null
+++ b/techlibs/xilinx/brams_init.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+from __future__ import division
+from __future__ import print_function
+
+with open("brams_init_18.vh", "w") as f:
+    for i in range(8):
+        init_snippets = ["INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+        for k in range(4, 256, 4):
+            init_snippets[k] = "\n           " + init_snippets[k]
+        print(".INITP_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+    for i in range(64):
+        init_snippets = ["INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+        for k in range(4, 32, 4):
+            init_snippets[k] = "\n          " + init_snippets[k]
+        print(".INIT_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+
+with open("brams_init_36.vh", "w") as f:
+    for i in range(16):
+        init_snippets = ["INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+        for k in range(4, 256, 4):
+            init_snippets[k] = "\n           " + init_snippets[k]
+        print(".INITP_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+    for i in range(128):
+        init_snippets = ["INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+        for k in range(4, 32, 4):
+            init_snippets[k] = "\n          " + init_snippets[k]
+        print(".INIT_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+
+with open("brams_init_16.vh", "w") as f:
+    for i in range(64):
+        print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
+
+with open("brams_init_32.vh", "w") as f:
+    for i in range(128):
+        print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
+
diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/brams_map.v
index 2e9bba9a9..cbfd4e1eb 100644
--- a/techlibs/xilinx/brams_map.v
+++ b/techlibs/xilinx/brams_map.v
@@ -1,6 +1,7 @@
 module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 	parameter CLKPOL2 = 1;
 	parameter CLKPOL3 = 1;
+	parameter [36863:0] INIT = 36864'bx;
 
 	input CLK2;
 	input CLK3;
@@ -32,6 +33,7 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 		.WRITE_MODE_B("READ_FIRST"),
 		.IS_CLKARDCLK_INVERTED(!CLKPOL2),
 		.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+		`include "brams_init_36.vh"
 		.SIM_DEVICE("7SERIES")
 	) _TECHMAP_REPLACE_ (
 		.DOBDO(DO[63:32]),
@@ -66,6 +68,7 @@ endmodule
 module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 	parameter CLKPOL2 = 1;
 	parameter CLKPOL3 = 1;
+	parameter [18431:0] INIT = 18432'bx;
 
 	input CLK2;
 	input CLK3;
@@ -94,6 +97,7 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 		.WRITE_MODE_B("READ_FIRST"),
 		.IS_CLKARDCLK_INVERTED(!CLKPOL2),
 		.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
+		`include "brams_init_18.vh"
 		.SIM_DEVICE("7SERIES")
 	) _TECHMAP_REPLACE_ (
 		.DOBDO(DO[31:16]),
@@ -132,6 +136,7 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 
 	parameter CLKPOL2 = 1;
 	parameter CLKPOL3 = 1;
+	parameter [36863:0] INIT = 36864'bx;
 
 	input CLK2;
 	input CLK3;
@@ -156,42 +161,83 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 	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),
+	generate if (CFG_DBITS > 8) begin
+		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),
+			`include "brams_init_36.vh"
+			.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)
-	);
+			.DIBDI(DI),
+			.DIPBDIP(DIP),
+			.DOBDO(DOBDO),
+			.DOPBDOP(DOPBDOP),
+			.ADDRBWRADDR(B1ADDR_16),
+			.CLKBWRCLK(CLK3),
+			.ENBWREN(|1),
+			.REGCEB(|0),
+			.RSTRAMB(|0),
+			.RSTREGB(|0),
+			.WEBWE(B1EN_8)
+		);
+	end else begin
+		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),
+			`include "brams_init_32.vh"
+			.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)
+		);
+	end endgenerate
 endmodule
 
 // ------------------------------------------------------------------------
@@ -203,6 +249,7 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 
 	parameter CLKPOL2 = 1;
 	parameter CLKPOL3 = 1;
+	parameter [18431:0] INIT = 18432'bx;
 
 	input CLK2;
 	input CLK3;
@@ -227,41 +274,82 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
 	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),
+	generate if (CFG_DBITS > 8) begin
+		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),
+			`include "brams_init_18.vh"
+			.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)
-	);
+			.DIBDI(DI),
+			.DIPBDIP(DIP),
+			.DOBDO(DOBDO),
+			.DOPBDOP(DOPBDOP),
+			.ADDRBWRADDR(B1ADDR_14),
+			.CLKBWRCLK(CLK3),
+			.ENBWREN(|1),
+			.REGCEB(|0),
+			.RSTRAMB(|0),
+			.RSTREGB(|0),
+			.WEBWE(B1EN_4)
+		);
+	end else begin
+		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),
+			`include "brams_init_16.vh"
+			.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)
+		);
+	end endgenerate
 endmodule
 
diff --git a/techlibs/xilinx/tests/bram1.v b/techlibs/xilinx/tests/bram1.v
index 034cc18e9..ac7140a04 100644
--- a/techlibs/xilinx/tests/bram1.v
+++ b/techlibs/xilinx/tests/bram1.v
@@ -10,10 +10,27 @@ module bram1 #(
 	input [ABITS-1:0] RD_ADDR,
 	output [DBITS-1:0] RD_DATA
 );
+	localparam [ABITS-1:0] INIT_ADDR_0 = 1234;
+	localparam [ABITS-1:0] INIT_ADDR_1 = 4321;
+	localparam [ABITS-1:0] INIT_ADDR_2 = 2**ABITS-1;
+	localparam [ABITS-1:0] INIT_ADDR_3 = (2**ABITS-1) / 2;
+
+	localparam [DBITS-1:0] INIT_DATA_0 = 128'h 51e152a7300e309ccb8cd06d34558f49;
+	localparam [DBITS-1:0] INIT_DATA_1 = 128'h 07b1fe94a530ddf3027520f9d23ab43e;
+	localparam [DBITS-1:0] INIT_DATA_2 = 128'h 3cedc6de43ef3f607af3193658d0eb0b;
+	localparam [DBITS-1:0] INIT_DATA_3 = 128'h f6bc5514a8abf1e2810df966bcc13b46;
+
 	reg [DBITS-1:0] memory [0:2**ABITS-1];
 	reg [ABITS-1:0] RD_ADDR_BUF;
 	reg [DBITS-1:0] RD_DATA_BUF;
 
+	initial begin
+		memory[INIT_ADDR_0] <= INIT_DATA_0;
+		memory[INIT_ADDR_1] <= INIT_DATA_1;
+		memory[INIT_ADDR_2] <= INIT_DATA_2;
+		memory[INIT_ADDR_3] <= INIT_DATA_3;
+	end
+
 	always @(posedge clk) begin
 		if (WR_EN) memory[WR_ADDR] <= WR_DATA;
 		RD_ADDR_BUF <= RD_ADDR;
diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v
index 8f854b749..e75dfe31d 100644
--- a/techlibs/xilinx/tests/bram1_tb.v
+++ b/techlibs/xilinx/tests/bram1_tb.v
@@ -8,6 +8,16 @@ module bram1_tb #(
 	reg [ABITS-1:0] RD_ADDR;
 	wire [DBITS-1:0] RD_DATA;
 
+	localparam [ABITS-1:0] INIT_ADDR_0 = 1234;
+	localparam [ABITS-1:0] INIT_ADDR_1 = 4321;
+	localparam [ABITS-1:0] INIT_ADDR_2 = 2**ABITS-1;
+	localparam [ABITS-1:0] INIT_ADDR_3 = (2**ABITS-1) / 2;
+
+	localparam [DBITS-1:0] INIT_DATA_0 = 128'h 51e152a7300e309ccb8cd06d34558f49;
+	localparam [DBITS-1:0] INIT_DATA_1 = 128'h 07b1fe94a530ddf3027520f9d23ab43e;
+	localparam [DBITS-1:0] INIT_DATA_2 = 128'h 3cedc6de43ef3f607af3193658d0eb0b;
+	localparam [DBITS-1:0] INIT_DATA_3 = 128'h f6bc5514a8abf1e2810df966bcc13b46;
+
 	bram1 #(
 		// .ABITS(ABITS),
 		// .DBITS(DBITS),
@@ -68,6 +78,11 @@ module bram1_tb #(
 		// $dumpfile("testbench.vcd");
 		// $dumpvars(0, bram1_tb);
 
+		memory[INIT_ADDR_0] = INIT_DATA_0;
+		memory[INIT_ADDR_1] = INIT_DATA_1;
+		memory[INIT_ADDR_2] = INIT_DATA_2;
+		memory[INIT_ADDR_3] = INIT_DATA_3;
+
 		xorshift64_next;
 		xorshift64_next;
 		xorshift64_next;
@@ -84,16 +99,33 @@ module bram1_tb #(
 
 		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;
+			if (i == 0) begin
+				WR_EN <= 0;
+				RD_ADDR <= INIT_ADDR_0;
+			end else
+			if (i == 1) begin
+				WR_EN <= 0;
+				RD_ADDR <= INIT_ADDR_1;
+			end else
+			if (i == 2) begin
+				WR_EN <= 0;
+				RD_ADDR <= INIT_ADDR_2;
+			end else
+			if (i == 3) begin
+				WR_EN <= 0;
+				RD_ADDR <= INIT_ADDR_3;
+			end else 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;
+			end
 
 			#1; clk <= 1;
 			#1; clk <= 0;
diff --git a/techlibs/xilinx/tests/bram2.sh b/techlibs/xilinx/tests/bram2.sh
index d8d8ed305..5d9c84dac 100644
--- a/techlibs/xilinx/tests/bram2.sh
+++ b/techlibs/xilinx/tests/bram2.sh
@@ -3,6 +3,6 @@
 set -ex
 unisims=/opt/Xilinx/Vivado/2014.4/data/verilog/src/unisims
 ../../../yosys -v2 -l bram2.log -p synth_xilinx -o bram2_syn.v bram2.v
-iverilog -o bram2_tb bram2_tb.v bram2_syn.v -y $unisims $unisims/../glbl.v
+iverilog -T typ -o bram2_tb bram2_tb.v bram2_syn.v -y $unisims $unisims/../glbl.v
 vvp -N bram2_tb
 
diff --git a/techlibs/xilinx/tests/bram2.v b/techlibs/xilinx/tests/bram2.v
index 9444fb172..0a6013ca6 100644
--- a/techlibs/xilinx/tests/bram2.v
+++ b/techlibs/xilinx/tests/bram2.v
@@ -1,18 +1,29 @@
 module myram(
 	input		  rd_clk,
 	input	   [ 7:0] rd_addr,
-	output reg [15:0] rd_data,
+	output reg [17:0] rd_data,
 	input		  wr_clk,
 	input		  wr_enable,
 	input	   [ 7:0] wr_addr,
-	input	   [15:0] wr_data
+	input	   [17:0] wr_data
 );
-	reg [15:0] memory [0:255];
+	reg [17:0] memory [0:255];
 	integer i;
 
+	function [17:0] hash(input [7:0] k);
+		reg [31:0] x;
+		begin
+			x = {k, ~k, k, ~k};
+			x = x ^ (x << 13);
+			x = x ^ (x >> 17);
+			x = x ^ (x << 5);
+			hash = x;
+		end
+	endfunction
+
 	initial begin
 		for (i = 0; i < 256; i = i+1)
-			memory[i] = i;
+			memory[i] = hash(i);
 	end
 
 	always @(posedge rd_clk)
diff --git a/techlibs/xilinx/tests/bram2_tb.v b/techlibs/xilinx/tests/bram2_tb.v
index 3a43b655d..0fe4137c6 100644
--- a/techlibs/xilinx/tests/bram2_tb.v
+++ b/techlibs/xilinx/tests/bram2_tb.v
@@ -3,12 +3,23 @@
 module testbench;
 	reg         rd_clk;
 	reg  [ 7:0] rd_addr;
-	wire [15:0] rd_data;
+	wire [17:0] rd_data;
 
 	wire        wr_clk    = 0;
 	wire        wr_enable = 0;
 	wire [ 7:0] wr_addr   = 0;
-	wire [15:0] wr_data   = 0;
+	wire [17:0] wr_data   = 0;
+
+	function [17:0] hash(input [7:0] k);
+		reg [31:0] x;
+		begin
+			x = {k, ~k, k, ~k};
+			x = x ^ (x << 13);
+			x = x ^ (x >> 17);
+			x = x ^ (x << 5);
+			hash = x;
+		end
+	endfunction
 
 	myram uut (
 		.rd_clk   (rd_clk   ),
@@ -34,8 +45,8 @@ module testbench;
 			rd_addr <= rd_addr + 1;
 			@(posedge rd_clk);
 			// $display("%3d %3d", i, rd_data);
-			if (i != rd_data) begin
-				$display("[%1t] ERROR: addr=%3d, data=%3d", $time, i, rd_data);
+			if (hash(i) !== rd_data) begin
+				$display("[%1t] ERROR: addr=%3d, data_mem=%18b, data_ref=%18b", $time, i, rd_data, hash(i));
 				$stop;
 			end
 		end