synth_gatemate: Initial implementation
authorPatrick Urban <patrick.urban@web.de>
Mon, 13 Sep 2021 15:16:15 +0000 (17:16 +0200)
committerMarcelina Koƛcielnicka <mwk@0x04.net>
Sat, 13 Nov 2021 20:53:25 +0000 (21:53 +0100)
Signed-off-by: Patrick Urban <patrick.urban@web.de>
29 files changed:
techlibs/gatemate/Makefile.inc [new file with mode: 0644]
techlibs/gatemate/arith_map.v [new file with mode: 0644]
techlibs/gatemate/brams.txt [new file with mode: 0644]
techlibs/gatemate/brams_init_20.vh [new file with mode: 0644]
techlibs/gatemate/brams_init_40.vh [new file with mode: 0644]
techlibs/gatemate/brams_map.v [new file with mode: 0644]
techlibs/gatemate/cells_bb.v [new file with mode: 0644]
techlibs/gatemate/cells_sim.v [new file with mode: 0644]
techlibs/gatemate/gatemate_bramopt.cc [new file with mode: 0644]
techlibs/gatemate/iob_map.v [new file with mode: 0644]
techlibs/gatemate/lut_map.v [new file with mode: 0644]
techlibs/gatemate/mul_map.v [new file with mode: 0644]
techlibs/gatemate/mux_map.v [new file with mode: 0644]
techlibs/gatemate/reg_map.v [new file with mode: 0644]
techlibs/gatemate/synth_gatemate.cc [new file with mode: 0644]
tests/arch/gatemate/add_sub.ys [new file with mode: 0644]
tests/arch/gatemate/adffs.ys [new file with mode: 0644]
tests/arch/gatemate/counter.ys [new file with mode: 0644]
tests/arch/gatemate/dffs.ys [new file with mode: 0644]
tests/arch/gatemate/fsm.ys [new file with mode: 0644]
tests/arch/gatemate/latches.ys [new file with mode: 0644]
tests/arch/gatemate/logic.ys [new file with mode: 0644]
tests/arch/gatemate/memory.ys [new file with mode: 0644]
tests/arch/gatemate/mul.v [new file with mode: 0644]
tests/arch/gatemate/mul.ys [new file with mode: 0644]
tests/arch/gatemate/mux.ys [new file with mode: 0644]
tests/arch/gatemate/run-test.sh [new file with mode: 0755]
tests/arch/gatemate/shifter.ys [new file with mode: 0644]
tests/arch/gatemate/tribuf.ys [new file with mode: 0644]

diff --git a/techlibs/gatemate/Makefile.inc b/techlibs/gatemate/Makefile.inc
new file mode 100644 (file)
index 0000000..bd18ce8
--- /dev/null
@@ -0,0 +1,16 @@
+\r
+OBJS += techlibs/gatemate/synth_gatemate.o\r
+OBJS += techlibs/gatemate/gatemate_bramopt.o\r
+\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/iob_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/lut_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mul_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/arith_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/cells_sim.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/cells_bb.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_map.v))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams.txt))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_20.vh))\r
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_40.vh))\r
diff --git a/techlibs/gatemate/arith_map.v b/techlibs/gatemate/arith_map.v
new file mode 100644 (file)
index 0000000..a3ab9c1
--- /dev/null
@@ -0,0 +1,69 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+(* techmap_celltype = "$alu" *)\r
+module _80_gatemate_alu(A, B, CI, BI, X, Y, CO);\r
+       parameter A_SIGNED = 0;\r
+       parameter B_SIGNED = 0;\r
+       parameter A_WIDTH = 1;\r
+       parameter B_WIDTH = 1;\r
+       parameter Y_WIDTH = 1;\r
+\r
+       (* force_downto *)\r
+       input [A_WIDTH-1:0] A;\r
+       (* force_downto *)\r
+       input [B_WIDTH-1:0] B;\r
+       (* force_downto *)\r
+       output [Y_WIDTH-1:0] X, Y;\r
+\r
+       input CI, BI;\r
+       (* force_downto *)\r
+       output [Y_WIDTH-1:0] CO;\r
+\r
+       wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;\r
+\r
+       (* force_downto *)\r
+       wire [Y_WIDTH-1:0] A_buf, B_buf;\r
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));\r
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));\r
+\r
+       (* force_downto *)\r
+       wire [Y_WIDTH-1:0] AA = A_buf;\r
+       (* force_downto *)\r
+       wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;\r
+       (* force_downto *)\r
+       wire [Y_WIDTH-1:0] C = {CO, CI};\r
+\r
+       genvar i;\r
+       generate\r
+               for (i = 0; i < Y_WIDTH; i = i + 1)\r
+               begin: slice\r
+                       CC_ADDF addf_i (\r
+                               .A(AA[i]),\r
+                               .B(BB[i]),\r
+                               .CI(C[i]),\r
+                               .CO(CO[i]),\r
+                               .S(Y[i])\r
+                       );\r
+               end\r
+       endgenerate\r
+\r
+       assign X = AA ^ BB;\r
+\r
+endmodule\r
diff --git a/techlibs/gatemate/brams.txt b/techlibs/gatemate/brams.txt
new file mode 100644 (file)
index 0000000..9e0bebb
--- /dev/null
@@ -0,0 +1,280 @@
+bram $__CC_BRAM_CASCADE
+  init 1
+  abits 16 @a16d1
+  dbits 1  @a16d1
+  groups 2
+  ports 1 1
+  wrmode 1 0
+  enable 1 1 @a16d1
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+bram $__CC_BRAM_40K_SDP
+  init 1
+  abits 9  @a9d80
+  dbits 80 @a9d80
+  groups 2
+  ports 1 1
+  wrmode 1 0
+  enable 80 1 @a9d80
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+bram $__CC_BRAM_20K_SDP
+  init 1
+  abits 9  @a9d40
+  dbits 40 @a9d40
+  groups 2
+  ports 1 1
+  wrmode 1 0
+  enable 40 1 @a9d40
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+bram $__CC_BRAM_40K_TDP
+  init 1
+  abits 10 @a10d40
+  dbits 40 @a10d40
+  abits 11 @a11d20
+  dbits 20 @a11d20
+  abits 12 @a12d10
+  dbits 10 @a12d10
+  abits 13 @a13d5
+  dbits 5  @a13d5
+  abits 14 @a14d2
+  dbits 2  @a14d2
+  abits 15 @a15d1
+  dbits 1  @a15d1
+  groups 2
+  ports 1 1
+  wrmode 1 0
+  enable 40 1 @a10d40
+  enable 20 1 @a11d20
+  enable 10 1 @a12d10
+  enable 5 1  @a13d5
+  enable 2 1  @a14d2
+  enable 1 1  @a15d1
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+bram $__CC_BRAM_20K_TDP
+  init 1
+  abits 10 @a10d20
+  dbits 20 @a10d20
+  abits 11 @a11d10
+  dbits 10 @a11d10
+  abits 12 @a12d5
+  dbits 5  @a12d5
+  abits 13 @a13d2
+  dbits 2  @a13d2
+  abits 14 @a14d1
+  dbits 1  @a14d1
+  groups 2
+  ports 1 1
+  wrmode 1 0
+  enable 20 1 @a10d20
+  enable 10 1 @a11d10
+  enable 5 1  @a12d5
+  enable 2 1  @a13d2
+  enable 1 1  @a14d1
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+match $__CC_BRAM_CASCADE
+  # implicitly requested RAM or ROM
+  attribute !syn_ramstyle syn_ramstyle=auto
+  attribute !syn_romstyle syn_romstyle=auto
+  attribute !ram_block
+  attribute !rom_block
+  attribute !logic_block
+  min bits 512
+  min efficiency 5
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_CASCADE
+  # explicitly requested RAM
+  attribute syn_ramstyle=block_ram ram_block
+  attribute !syn_romstyle
+  attribute !rom_block
+  attribute !logic_block
+  min wports 1
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_CASCADE
+  # explicitly requested ROM
+  attribute syn_romstyle=ebr rom_block
+  attribute !syn_ramstyle
+  attribute !ram_block
+  attribute !logic_block
+  max wports 0
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+  # implicitly requested RAM or ROM
+  attribute !syn_ramstyle syn_ramstyle=auto
+  attribute !syn_romstyle syn_romstyle=auto
+  attribute !ram_block
+  attribute !rom_block
+  attribute !logic_block
+  min bits 512
+  min efficiency 5
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+  # explicitly requested RAM
+  attribute syn_ramstyle=block_ram ram_block
+  attribute !syn_romstyle
+  attribute !rom_block
+  attribute !logic_block
+  min wports 1
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+  # explicitly requested ROM
+  attribute syn_romstyle=ebr rom_block
+  attribute !syn_ramstyle
+  attribute !ram_block
+  attribute !logic_block
+  max wports 0
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+  # implicitly requested RAM or ROM
+  attribute !syn_ramstyle syn_ramstyle=auto
+  attribute !syn_romstyle syn_romstyle=auto
+  attribute !ram_block
+  attribute !rom_block
+  attribute !logic_block
+  min bits 512
+  min efficiency 5
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+  # explicitly requested RAM
+  attribute syn_ramstyle=block_ram ram_block
+  attribute !syn_romstyle
+  attribute !rom_block
+  attribute !logic_block
+  min wports 1
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+  # explicitly requested ROM
+  attribute syn_romstyle=ebr rom_block
+  attribute !syn_ramstyle
+  attribute !ram_block
+  attribute !logic_block
+  max wports 0
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+  # implicitly requested RAM or ROM
+  attribute !syn_ramstyle syn_ramstyle=auto
+  attribute !syn_romstyle syn_romstyle=auto
+  attribute !ram_block
+  attribute !rom_block
+  attribute !logic_block
+  min bits 512
+  min efficiency 5
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+  # explicitly requested RAM
+  attribute syn_ramstyle=block_ram ram_block
+  attribute !syn_romstyle
+  attribute !rom_block
+  attribute !logic_block
+  min wports 1
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+  # explicitly requested ROM
+  attribute syn_romstyle=ebr rom_block
+  attribute !syn_ramstyle
+  attribute !ram_block
+  attribute !logic_block
+  max wports 0
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+  # implicitly requested RAM or ROM
+  attribute !syn_ramstyle syn_ramstyle=auto
+  attribute !syn_romstyle syn_romstyle=auto
+  attribute !ram_block
+  attribute !rom_block
+  attribute !logic_block
+  min bits 512
+  min efficiency 5
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+  # explicitly requested RAM
+  attribute syn_ramstyle=block_ram ram_block
+  attribute !syn_romstyle
+  attribute !rom_block
+  attribute !logic_block
+  min wports 1
+  shuffle_enable A
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+  # explicitly requested ROM
+  attribute syn_romstyle=ebr rom_block
+  attribute !syn_ramstyle
+  attribute !ram_block
+  attribute !logic_block
+  max wports 0
+  shuffle_enable A
+  make_transp
+endmatch
diff --git a/techlibs/gatemate/brams_init_20.vh b/techlibs/gatemate/brams_init_20.vh
new file mode 100644 (file)
index 0000000..d0764ed
--- /dev/null
@@ -0,0 +1,64 @@
+.INIT_00(permute_init(INIT[  0*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_01(permute_init(INIT[  1*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_02(permute_init(INIT[  2*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_03(permute_init(INIT[  3*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_04(permute_init(INIT[  4*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_05(permute_init(INIT[  5*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_06(permute_init(INIT[  6*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_07(permute_init(INIT[  7*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_08(permute_init(INIT[  8*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_09(permute_init(INIT[  9*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0A(permute_init(INIT[ 10*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0B(permute_init(INIT[ 11*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0C(permute_init(INIT[ 12*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0D(permute_init(INIT[ 13*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0E(permute_init(INIT[ 14*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0F(permute_init(INIT[ 15*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_10(permute_init(INIT[ 16*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_11(permute_init(INIT[ 17*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_12(permute_init(INIT[ 18*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_13(permute_init(INIT[ 19*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_14(permute_init(INIT[ 20*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_15(permute_init(INIT[ 21*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_16(permute_init(INIT[ 22*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_17(permute_init(INIT[ 23*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_18(permute_init(INIT[ 24*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_19(permute_init(INIT[ 25*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1A(permute_init(INIT[ 26*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1B(permute_init(INIT[ 27*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1C(permute_init(INIT[ 28*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1D(permute_init(INIT[ 29*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1E(permute_init(INIT[ 30*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1F(permute_init(INIT[ 31*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_20(permute_init(INIT[ 32*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_21(permute_init(INIT[ 33*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_22(permute_init(INIT[ 34*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_23(permute_init(INIT[ 35*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_24(permute_init(INIT[ 36*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_25(permute_init(INIT[ 37*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_26(permute_init(INIT[ 38*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_27(permute_init(INIT[ 39*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_28(permute_init(INIT[ 40*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_29(permute_init(INIT[ 41*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2A(permute_init(INIT[ 42*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2B(permute_init(INIT[ 43*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2C(permute_init(INIT[ 44*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2D(permute_init(INIT[ 45*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2E(permute_init(INIT[ 46*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2F(permute_init(INIT[ 47*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_30(permute_init(INIT[ 48*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_31(permute_init(INIT[ 49*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_32(permute_init(INIT[ 50*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_33(permute_init(INIT[ 51*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_34(permute_init(INIT[ 52*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_35(permute_init(INIT[ 53*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_36(permute_init(INIT[ 54*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_37(permute_init(INIT[ 55*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_38(permute_init(INIT[ 56*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_39(permute_init(INIT[ 57*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3A(permute_init(INIT[ 58*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3B(permute_init(INIT[ 59*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3C(permute_init(INIT[ 60*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3D(permute_init(INIT[ 61*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3E(permute_init(INIT[ 62*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3F(permute_init(INIT[ 63*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
diff --git a/techlibs/gatemate/brams_init_40.vh b/techlibs/gatemate/brams_init_40.vh
new file mode 100644 (file)
index 0000000..ccf14bc
--- /dev/null
@@ -0,0 +1,128 @@
+.INIT_00(permute_init(INIT[  0*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_01(permute_init(INIT[  1*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_02(permute_init(INIT[  2*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_03(permute_init(INIT[  3*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_04(permute_init(INIT[  4*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_05(permute_init(INIT[  5*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_06(permute_init(INIT[  6*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_07(permute_init(INIT[  7*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_08(permute_init(INIT[  8*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_09(permute_init(INIT[  9*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0A(permute_init(INIT[ 10*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0B(permute_init(INIT[ 11*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0C(permute_init(INIT[ 12*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0D(permute_init(INIT[ 13*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0E(permute_init(INIT[ 14*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0F(permute_init(INIT[ 15*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_10(permute_init(INIT[ 16*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_11(permute_init(INIT[ 17*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_12(permute_init(INIT[ 18*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_13(permute_init(INIT[ 19*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_14(permute_init(INIT[ 20*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_15(permute_init(INIT[ 21*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_16(permute_init(INIT[ 22*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_17(permute_init(INIT[ 23*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_18(permute_init(INIT[ 24*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_19(permute_init(INIT[ 25*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1A(permute_init(INIT[ 26*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1B(permute_init(INIT[ 27*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1C(permute_init(INIT[ 28*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1D(permute_init(INIT[ 29*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1E(permute_init(INIT[ 30*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1F(permute_init(INIT[ 31*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_20(permute_init(INIT[ 32*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_21(permute_init(INIT[ 33*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_22(permute_init(INIT[ 34*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_23(permute_init(INIT[ 35*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_24(permute_init(INIT[ 36*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_25(permute_init(INIT[ 37*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_26(permute_init(INIT[ 38*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_27(permute_init(INIT[ 39*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_28(permute_init(INIT[ 40*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_29(permute_init(INIT[ 41*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2A(permute_init(INIT[ 42*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2B(permute_init(INIT[ 43*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2C(permute_init(INIT[ 44*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2D(permute_init(INIT[ 45*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2E(permute_init(INIT[ 46*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2F(permute_init(INIT[ 47*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_30(permute_init(INIT[ 48*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_31(permute_init(INIT[ 49*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_32(permute_init(INIT[ 50*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_33(permute_init(INIT[ 51*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_34(permute_init(INIT[ 52*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_35(permute_init(INIT[ 53*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_36(permute_init(INIT[ 54*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_37(permute_init(INIT[ 55*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_38(permute_init(INIT[ 56*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_39(permute_init(INIT[ 57*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3A(permute_init(INIT[ 58*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3B(permute_init(INIT[ 59*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3C(permute_init(INIT[ 60*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3D(permute_init(INIT[ 61*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3E(permute_init(INIT[ 62*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3F(permute_init(INIT[ 63*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_40(permute_init(INIT[ 64*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_41(permute_init(INIT[ 65*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_42(permute_init(INIT[ 66*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_43(permute_init(INIT[ 67*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_44(permute_init(INIT[ 68*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_45(permute_init(INIT[ 69*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_46(permute_init(INIT[ 70*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_47(permute_init(INIT[ 71*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_48(permute_init(INIT[ 72*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_49(permute_init(INIT[ 73*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4A(permute_init(INIT[ 74*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4B(permute_init(INIT[ 75*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4C(permute_init(INIT[ 76*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4D(permute_init(INIT[ 77*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4E(permute_init(INIT[ 78*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4F(permute_init(INIT[ 79*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_50(permute_init(INIT[ 80*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_51(permute_init(INIT[ 81*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_52(permute_init(INIT[ 82*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_53(permute_init(INIT[ 83*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_54(permute_init(INIT[ 84*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_55(permute_init(INIT[ 85*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_56(permute_init(INIT[ 86*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_57(permute_init(INIT[ 87*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_58(permute_init(INIT[ 88*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_59(permute_init(INIT[ 89*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5A(permute_init(INIT[ 90*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5B(permute_init(INIT[ 91*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5C(permute_init(INIT[ 92*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5D(permute_init(INIT[ 93*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5E(permute_init(INIT[ 94*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5F(permute_init(INIT[ 95*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_60(permute_init(INIT[ 96*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_61(permute_init(INIT[ 97*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_62(permute_init(INIT[ 98*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_63(permute_init(INIT[ 99*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_64(permute_init(INIT[100*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_65(permute_init(INIT[101*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_66(permute_init(INIT[102*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_67(permute_init(INIT[103*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_68(permute_init(INIT[104*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_69(permute_init(INIT[105*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6A(permute_init(INIT[106*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6B(permute_init(INIT[107*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6C(permute_init(INIT[108*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6D(permute_init(INIT[109*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6E(permute_init(INIT[110*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6F(permute_init(INIT[111*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_70(permute_init(INIT[112*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_71(permute_init(INIT[113*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_72(permute_init(INIT[114*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_73(permute_init(INIT[115*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_74(permute_init(INIT[116*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_75(permute_init(INIT[117*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_76(permute_init(INIT[118*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_77(permute_init(INIT[119*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_78(permute_init(INIT[120*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_79(permute_init(INIT[121*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7A(permute_init(INIT[122*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7B(permute_init(INIT[123*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7C(permute_init(INIT[124*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7D(permute_init(INIT[125*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7E(permute_init(INIT[126*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7F(permute_init(INIT[127*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
diff --git a/techlibs/gatemate/brams_map.v b/techlibs/gatemate/brams_map.v
new file mode 100644 (file)
index 0000000..eaaf146
--- /dev/null
@@ -0,0 +1,539 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+module \$__CC_BRAM_20K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);\r
+\r
+       parameter CFG_ABITS = 14;\r
+       parameter CFG_DBITS = 40;\r
+       parameter CFG_ENABLE_A = 1;\r
+       parameter CFG_ENABLE_B = 1;\r
+\r
+       parameter CLKPOL2 = 1;\r
+       parameter CLKPOL3 = 1;\r
+\r
+       // 512 x 40 bit\r
+       parameter [20479:0] INIT = 20480'b0;\r
+\r
+       input CLK2;\r
+       input CLK3;\r
+\r
+       // write side of the memory\r
+       input [15:0] A1ADDR;\r
+       input [39:0] A1DATA;\r
+       input [39:0] A1EN;\r
+\r
+       // read side of the memory\r
+       input [15:0] B1ADDR;\r
+       output [39:0] B1DATA;\r
+       input [0:0] B1EN;\r
+\r
+       // unconnected signals\r
+       wire ECC_1B_ERR, ECC_2B_ERR;\r
+\r
+       // internal signals\r
+       wire [15:0] ADDRA = {A1ADDR, 7'b0};\r
+       wire [15:0] ADDRB = {B1ADDR, 7'b0};\r
+\r
+       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+\r
+       function [319:0] permute_init;\r
+               input [INIT_CHUNK_SIZE-1:0] chunk;\r
+               integer i;\r
+               begin\r
+                       if (CFG_DBITS <= 2) begin\r
+                               for (i = 0; i < 64; i = i + 1) begin\r
+                                       if (^chunk[i * 4 +: 4] === 1'bx) begin\r
+                                               permute_init[i * 5 +: 5] = 5'b0;\r
+                                       end\r
+                                       else begin\r
+                                               permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};\r
+                                       end\r
+                               end\r
+                       end else begin\r
+                               permute_init = chunk;\r
+                       end\r
+               end\r
+       endfunction\r
+\r
+       CC_BRAM_20K #(\r
+               `include "brams_init_20.vh"\r
+               .LOC("UNPLACED"),\r
+               .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+               .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+               .RAM_MODE("SDP"),\r
+               .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+               .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+               .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+               .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+               .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+               .ECC_EN(1'b0)\r
+       ) _TECHMAP_REPLACE_ (\r
+               .A_DO(B1DATA[19:0]),\r
+               .B_DO(B1DATA[39:20]),\r
+               .ECC_1B_ERR(ECC_1B_ERR),\r
+               .ECC_2B_ERR(ECC_2B_ERR),\r
+               .A_CLK(CLK2),\r
+               .B_CLK(CLK3),\r
+               .A_EN(1'b1),\r
+               .B_EN(B1EN),\r
+               .A_WE(1'b1),\r
+               .B_WE(1'b0),\r
+               .A_ADDR(ADDRA),\r
+               .B_ADDR(ADDRB),\r
+               .A_DI(A1DATA[19:0]),\r
+               .B_DI(A1DATA[39:20]),\r
+               .A_BM(A1EN[19:0]),\r
+               .B_BM(A1EN[39:20])\r
+       );\r
+\r
+endmodule\r
+\r
+\r
+module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);\r
+\r
+       parameter CFG_ABITS = 15;\r
+       parameter CFG_DBITS = 80;\r
+       parameter CFG_ENABLE_A = 1;\r
+       parameter CFG_ENABLE_B = 1;\r
+\r
+       parameter CLKPOL2 = 1;\r
+       parameter CLKPOL3 = 1;\r
+\r
+       // 512 x 80 bit\r
+       parameter [40959:0] INIT = 40960'b0;\r
+\r
+       input CLK2;\r
+       input CLK3;\r
+\r
+       // write side of the memory\r
+       input [15:0] A1ADDR;\r
+       input [79:0] A1DATA;\r
+       input [79:0] A1EN;\r
+\r
+       // read side of the memory\r
+       input [15:0] B1ADDR;\r
+       output [79:0] B1DATA;\r
+       input [0:0] B1EN;\r
+\r
+       // unconnected signals\r
+       wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;\r
+\r
+       // internal signals\r
+       wire [15:0] ADDRA = {A1ADDR, 7'b0};\r
+       wire [15:0] ADDRB = {B1ADDR, 7'b0};\r
+\r
+       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+\r
+       function [319:0] permute_init;\r
+               input [INIT_CHUNK_SIZE-1:0] chunk;\r
+               integer i;\r
+               begin\r
+                       if (CFG_DBITS <= 2) begin\r
+                               for (i = 0; i < 64; i = i + 1) begin\r
+                                       if (^chunk[i * 4 +: 4] === 1'bx) begin\r
+                                               permute_init[i * 5 +: 5] = 5'b0;\r
+                                       end\r
+                                       else begin\r
+                                               permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};\r
+                                       end\r
+                               end\r
+                       end else begin\r
+                               permute_init = chunk;\r
+                       end\r
+               end\r
+       endfunction\r
+\r
+       CC_BRAM_40K #(\r
+               `include "brams_init_40.vh"\r
+               .LOC("UNPLACED"),\r
+               .CAS("NONE"),\r
+               .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+               .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+               .RAM_MODE("SDP"),\r
+               .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+               .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+               .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+               .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+               .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+               .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)\r
+       ) _TECHMAP_REPLACE_ (\r
+               .A_DO(B1DATA[39:0]),\r
+               .B_DO(B1DATA[79:40]),\r
+               .A_ECC_1B_ERR(A_ECC_1B_ERR),\r
+               .B_ECC_1B_ERR(B_ECC_1B_ERR),\r
+               .A_ECC_2B_ERR(A_ECC_2B_ERR),\r
+               .B_ECC_2B_ERR(B_ECC_2B_ERR),\r
+               .A_CLK(CLK2),\r
+               .B_CLK(CLK3),\r
+               .A_EN(1'b1),\r
+               .B_EN(B1EN),\r
+               .A_WE(1'b1),\r
+               .B_WE(1'b0),\r
+               .A_ADDR(ADDRA),\r
+               .B_ADDR(ADDRB),\r
+               .A_DI(A1DATA[39:0]),\r
+               .B_DI(A1DATA[79:40]),\r
+               .A_BM(A1EN[39:0]),\r
+               .B_BM(A1EN[79:40])\r
+       );\r
+\r
+endmodule\r
+\r
+\r
+module \$__CC_BRAM_20K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);\r
+\r
+       parameter CFG_ABITS = 14;\r
+       parameter CFG_DBITS = 20;\r
+       parameter CFG_ENABLE_A = 1;\r
+       parameter CFG_ENABLE_B = 1;\r
+\r
+       parameter CLKPOL2 = 1;\r
+       parameter CLKPOL3 = 1;\r
+\r
+       // 512 x 40 bit\r
+       parameter [20479:0] INIT = 20480'b0;\r
+\r
+       input CLK2;\r
+       input CLK3;\r
+\r
+       // write side of the memory\r
+       input [15:0] A1ADDR;\r
+       input [19:0] A1DATA;\r
+       input [19:0] A1EN;\r
+\r
+       // read side of the memory\r
+       input [15:0] B1ADDR;\r
+       output [19:0] B1DATA;\r
+       input [0:0] B1EN;\r
+\r
+       // unconnected signals\r
+       wire [19:0] A_DO;\r
+       wire ECC_1B_ERR, ECC_2B_ERR;\r
+\r
+       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+\r
+       function [319:0] permute_init;\r
+               input [INIT_CHUNK_SIZE-1:0] chunk;\r
+               integer i;\r
+               begin\r
+                       if (CFG_DBITS <= 2) begin\r
+                               for (i = 0; i < 64; i = i + 1) begin\r
+                                       if (^chunk[i * 4 +: 4] === 1'bx) begin\r
+                                               permute_init[i * 5 +: 5] = 5'b0;\r
+                                       end\r
+                                       else begin\r
+                                               permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};\r
+                                       end\r
+                               end\r
+                       end else begin\r
+                               permute_init = chunk;\r
+                       end\r
+               end\r
+       endfunction\r
+\r
+       // internal signals\r
+       generate\r
+               wire [15:0] ADDRA;\r
+               wire [15:0] ADDRB;\r
+\r
+               if (CFG_DBITS == 1) begin: blk\r
+                       assign ADDRA = {A1ADDR[13:5], 1'b0, A1ADDR[4:0], 1'b0};\r
+                       assign ADDRB = {B1ADDR[13:5], 1'b0, B1ADDR[4:0], 1'b0};\r
+               end\r
+               else if (CFG_DBITS == 2) begin: blk\r
+                       assign ADDRA = {A1ADDR[12:4], 1'b0, A1ADDR[3:0], 2'b0};\r
+                       assign ADDRB = {B1ADDR[12:4], 1'b0, B1ADDR[3:0], 2'b0};\r
+               end\r
+               else if (CFG_DBITS == 5) begin: blk\r
+                       assign ADDRA = {A1ADDR[11:3], 1'b0, A1ADDR[2:0], 3'b0};\r
+                       assign ADDRB = {B1ADDR[11:3], 1'b0, B1ADDR[2:0], 3'b0};\r
+               end\r
+               else if (CFG_DBITS == 10) begin: blk\r
+                       assign ADDRA = {A1ADDR[10:2], 1'b0, A1ADDR[1:0], 4'b0};\r
+                       assign ADDRB = {B1ADDR[10:2], 1'b0, B1ADDR[1:0], 4'b0};\r
+               end\r
+               else if (CFG_DBITS == 20) begin: blk\r
+                       assign ADDRA = {A1ADDR[9:1], 1'b0, A1ADDR[0], 5'b0};\r
+                       assign ADDRB = {B1ADDR[9:1], 1'b0, B1ADDR[0], 5'b0};\r
+               end\r
+\r
+               CC_BRAM_20K #(\r
+                       `include "brams_init_20.vh"\r
+                       .LOC("UNPLACED"),\r
+                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+                       .RAM_MODE("TDP"),\r
+                       .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+                       .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+                       .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+                       .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+                       .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+                       .ECC_EN(1'b0)\r
+               ) _TECHMAP_REPLACE_ (\r
+                       .A_DO(A_DO),\r
+                       .B_DO(B1DATA),\r
+                       .ECC_1B_ERR(ECC_1B_ERR),\r
+                       .ECC_2B_ERR(ECC_2B_ERR),\r
+                       .A_CLK(CLK2),\r
+                       .B_CLK(CLK3),\r
+                       .A_EN(1'b1),\r
+                       .B_EN(B1EN),\r
+                       .A_WE(1'b1),\r
+                       .B_WE(1'b0),\r
+                       .A_ADDR(ADDRA),\r
+                       .B_ADDR(ADDRB),\r
+                       .A_DI(A1DATA),\r
+                       .B_DI(20'b0),\r
+                       .A_BM(A1EN),\r
+                       .B_BM(20'b0)\r
+               );\r
+       endgenerate\r
+\r
+endmodule\r
+\r
+\r
+module \$__CC_BRAM_40K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);\r
+\r
+       parameter CFG_ABITS = 15;\r
+       parameter CFG_DBITS = 40;\r
+       parameter CFG_ENABLE_A = 1;\r
+       parameter CFG_ENABLE_B = 1;\r
+\r
+       parameter CLKPOL2 = 1;\r
+       parameter CLKPOL3 = 1;\r
+\r
+       // 512 x 80 bit\r
+       parameter [40959:0] INIT = 40960'b0;\r
+\r
+       input CLK2;\r
+       input CLK3;\r
+\r
+       // write side of the memory\r
+       input [15:0] A1ADDR;\r
+       input [39:0] A1DATA;\r
+       input [39:0] A1EN;\r
+\r
+       // read side of the memory\r
+       input [15:0] B1ADDR;\r
+       output [39:0] B1DATA;\r
+       input [0:0] B1EN;\r
+\r
+       // unconnected signals\r
+       wire [39:0] A_DO;\r
+       wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;\r
+\r
+       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+\r
+       function [319:0] permute_init;\r
+               input [INIT_CHUNK_SIZE-1:0] chunk;\r
+               integer i;\r
+               begin\r
+                       if (CFG_DBITS <= 2) begin\r
+                               for (i = 0; i < 64; i = i + 1) begin\r
+                                       permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]} & 5'b11111;\r
+                               end\r
+                       end else begin\r
+                               permute_init = chunk;\r
+                       end\r
+               end\r
+       endfunction\r
+\r
+       generate\r
+               wire [15:0] ADDRA;\r
+               wire [15:0] ADDRB;\r
+\r
+               if (CFG_DBITS == 1) begin\r
+                       assign ADDRA = {A1ADDR, 1'b0};\r
+                       assign ADDRB = {B1ADDR, 1'b0};\r
+               end\r
+               else if (CFG_DBITS == 2) begin\r
+                       assign ADDRA = {A1ADDR, 2'b0};\r
+                       assign ADDRB = {B1ADDR, 2'b0};\r
+               end\r
+               else if (CFG_DBITS == 5) begin\r
+                       assign ADDRA = {A1ADDR, 3'b0};\r
+                       assign ADDRB = {B1ADDR, 3'b0};\r
+               end\r
+               else if (CFG_DBITS == 10) begin\r
+                       assign ADDRA = {A1ADDR, 4'b0};\r
+                       assign ADDRB = {B1ADDR, 4'b0};\r
+               end\r
+               else if (CFG_DBITS == 20) begin\r
+                       assign ADDRA = {A1ADDR, 5'b0};\r
+                       assign ADDRB = {B1ADDR, 5'b0};\r
+               end\r
+               else if (CFG_DBITS == 40) begin\r
+                       assign ADDRA = {A1ADDR, 6'b0};\r
+                       assign ADDRB = {B1ADDR, 6'b0};\r
+               end\r
+\r
+               CC_BRAM_40K #(\r
+                       `include "brams_init_40.vh"\r
+                       .LOC("UNPLACED"),\r
+                       .CAS("NONE"),\r
+                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+                       .RAM_MODE("TDP"),\r
+                       .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+                       .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+                       .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+                       .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+                       .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+                       .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)\r
+               ) _TECHMAP_REPLACE_ (\r
+                       .A_DO(A_DO),\r
+                       .B_DO(B1DATA),\r
+                       .A_ECC_1B_ERR(A_ECC_1B_ERR),\r
+                       .B_ECC_1B_ERR(B_ECC_1B_ERR),\r
+                       .A_ECC_2B_ERR(A_ECC_2B_ERR),\r
+                       .B_ECC_2B_ERR(B_ECC_2B_ERR),\r
+                       .A_CLK(CLK2),\r
+                       .B_CLK(CLK3),\r
+                       .A_EN(1'b1),\r
+                       .B_EN(B1EN),\r
+                       .A_WE(1'b1),\r
+                       .B_WE(1'b0),\r
+                       .A_ADDR(ADDRA),\r
+                       .B_ADDR(ADDRB),\r
+                       .A_DI(A1DATA),\r
+                       .B_DI(40'b0),\r
+                       .A_BM(A1EN),\r
+                       .B_BM(40'b0)\r
+               );\r
+       endgenerate\r
+\r
+endmodule\r
+\r
+\r
+module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);\r
+\r
+       parameter CFG_ABITS = 16;\r
+       parameter CFG_DBITS = 1;\r
+       parameter CFG_ENABLE_A = 1;\r
+       parameter CFG_ENABLE_B = 1;\r
+\r
+       parameter CLKPOL2 = 1;\r
+       parameter CLKPOL3 = 1;\r
+\r
+       // 64K x 1\r
+       parameter [65535:0] INIT = 65535'b0;\r
+\r
+       input CLK2;\r
+       input CLK3;\r
+\r
+       // write side of the memory\r
+       input [15:0] A1ADDR;\r
+       input [39:0] A1DATA;\r
+       input [39:0] A1EN;\r
+\r
+       // read side of the memory\r
+       input [15:0] B1ADDR;\r
+       output [39:0] B1DATA;\r
+       input [0:0] B1EN;\r
+\r
+       // cascade signals\r
+       wire A_CAS, B_CAS;\r
+\r
+       // unconnected signals\r
+       wire [39:0] A_UP_DO, A_LO_DO, B_LO_DO;\r
+       wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;\r
+\r
+       localparam INIT_CHUNK_SIZE = 256;\r
+\r
+       function [319:0] permute_init;\r
+               input [INIT_CHUNK_SIZE-1:0] chunk;\r
+               integer i;\r
+               begin\r
+                       for (i = 0; i < 64; i = i + 1) begin\r
+                               permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]} & 5'b11111;\r
+                       end\r
+               end\r
+       endfunction\r
+\r
+       generate\r
+               CC_BRAM_40K #(\r
+                       `include "brams_init_40.vh"\r
+                       .LOC("UNPLACED"),\r
+                       .CAS("UPPER"),\r
+                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+                       .RAM_MODE("TDP"),\r
+                       .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+                       .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+                       .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+                       .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+                       .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+                       .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)\r
+               ) upper_cell (\r
+                       .A_CI(A_CAS),\r
+                       .B_CI(B_CAS),\r
+                       .A_DO(A_UP_DO),\r
+                       .B_DO(B1DATA),\r
+                       .A_ECC_1B_ERR(A_ECC_1B_ERR),\r
+                       .B_ECC_1B_ERR(B_ECC_1B_ERR),\r
+                       .A_ECC_2B_ERR(A_ECC_2B_ERR),\r
+                       .B_ECC_2B_ERR(B_ECC_2B_ERR),\r
+                       .A_CLK(CLK2),\r
+                       .B_CLK(CLK3),\r
+                       .A_EN(1'b1),\r
+                       .B_EN(B1EN),\r
+                       .A_WE(1'b1),\r
+                       .B_WE(1'b0),\r
+                       .A_ADDR(A1ADDR),\r
+                       .B_ADDR(B1ADDR),\r
+                       .A_DI(A1DATA),\r
+                       .B_DI(40'b0),\r
+                       .A_BM(A1EN),\r
+                       .B_BM(40'b0)\r
+               );\r
+\r
+               CC_BRAM_40K #(\r
+                       `include "brams_init_40.vh"\r
+                       .LOC("UNPLACED"),\r
+                       .CAS("LOWER"),\r
+                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
+                       .RAM_MODE("TDP"),\r
+                       .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
+                       .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),\r
+                       .A_EN_INV(1'b0), .B_EN_INV(1'b0),\r
+                       .A_WE_INV(1'b0), .B_WE_INV(1'b0),\r
+                       .A_DO_REG(1'b0), .B_DO_REG(1'b0),\r
+                       .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)\r
+               ) lower_cell (\r
+                       .A_CI(1'b1),\r
+                       .B_CI(),\r
+                       .A_CO(A_CAS),\r
+                       .B_CO(B_CAS),\r
+                       .A_CLK(CLK2),\r
+                       .B_CLK(CLK3),\r
+                       .A_EN(1'b1),\r
+                       .B_EN(B1EN),\r
+                       .A_WE(1'b1),\r
+                       .B_WE(1'b0),\r
+                       .A_ADDR(A1ADDR),\r
+                       .B_ADDR(B1ADDR),\r
+                       .A_DI(A1DATA),\r
+                       .B_DI(40'b0),\r
+                       .A_BM(A1EN),\r
+                       .B_BM(40'b0)\r
+               );\r
+       endgenerate\r
+\r
+endmodule\r
diff --git a/techlibs/gatemate/cells_bb.v b/techlibs/gatemate/cells_bb.v
new file mode 100644 (file)
index 0000000..3a1fcd5
--- /dev/null
@@ -0,0 +1,124 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+(* blackbox *)\r
+module CC_PLL #(\r
+       parameter REF_CLK = "", // e.g. "10.0"\r
+       parameter OUT_CLK = "", // e.g. "50.0"\r
+       parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED\r
+       parameter LOW_JITTER = 1,\r
+       parameter CI_FILTER_CONST = 2,\r
+       parameter CP_FILTER_CONST = 4\r
+)(\r
+       input  CLK_REF, CLK_FEEDBACK, USR_CLK_REF,\r
+       input  USR_LOCKED_STDY_RST,\r
+       output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED,\r
+       output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT\r
+);\r
+endmodule\r
+\r
+(* blackbox *)\r
+module CC_PLL_ADV #(\r
+       parameter [95:0] PLL_CFG_A = 96'bx,\r
+       parameter [95:0] PLL_CFG_B = 96'bx\r
+)(\r
+       input  CLK_REF, CLK_FEEDBACK, USR_CLK_REF,\r
+       input  USR_LOCKED_STDY_RST, USR_SEL_A_B,\r
+       output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED,\r
+       output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT\r
+);\r
+endmodule\r
+\r
+(* blackbox *)\r
+module CC_SERDES #(\r
+       parameter SERDES_CFG = ""\r
+)(\r
+       input [63:0] TX_DATA_I,\r
+       input TX_RESET_I,\r
+       input TX_PCS_RESET_I,\r
+       input TX_PMA_RESET_I,\r
+       input PLL_RESET_I,\r
+       input TX_POWERDOWN_N_I,\r
+       input TX_POLARITY_I,\r
+       input [2:0] TX_PRBS_SEL_I,\r
+       input TX_PRBS_FORCE_ERR_I,\r
+       input TX_8B10B_EN_I,\r
+       input [7:0] TX_8B10B_BYPASS_I,\r
+       input [7:0] TX_CHAR_IS_K_I,\r
+       input [7:0] TX_CHAR_DISPMODE_I,\r
+       input [7:0] TX_CHAR_DISPVAL_I,\r
+       input TX_ELEC_IDLE_I,\r
+       input TX_DETECT_RX_I,\r
+       input [2:0] LOOPBACK_I,\r
+       input CLK_CORE_TX_I,\r
+       input CLK_CORE_RX_I,\r
+       input RX_RESET_I,\r
+       input RX_PMA_RESET_I,\r
+       input RX_EQA_RESET_I,\r
+       input RX_CDR_RESET_I,\r
+       input RX_PCS_RESET_I,\r
+       input RX_BUF_RESET_I,\r
+       input RX_POWERDOWN_N_I,\r
+       input RX_POLARITY_I,\r
+       input [2:0] RX_PRBS_SEL_I,\r
+       input RX_PRBS_CNT_RESET_I,\r
+       input RX_8B10B_EN_I,\r
+       input [7:0] RX_8B10B_BYPASS_I,\r
+       input RX_EN_EI_DETECTOR_I,\r
+       input RX_COMMA_DETECT_EN_I,\r
+       input RX_SLIDE_I,\r
+       input RX_MCOMMA_ALIGN_I,\r
+       input RX_PCOMMA_ALIGN_I,\r
+       input CLK_REG_I,\r
+       input REGFILE_WE_I,\r
+       input REGFILE_EN_I,\r
+       input [7:0] REGFILE_ADDR_I,\r
+       input [15:0] REGFILE_DI_I,\r
+       input [15:0] REGFILE_MASK_I,\r
+       output [63:0] RX_DATA_O,\r
+       output [7:0] RX_NOT_IN_TABLE_O,\r
+       output [7:0] RX_CHAR_IS_COMMA_O,\r
+       output [7:0] RX_CHAR_IS_K_O,\r
+       output [7:0] RX_DISP_ERR_O,\r
+       output RX_DETECT_DONE_O,\r
+       output RX_PRESENT_O,\r
+       output TX_BUF_ERR_O,\r
+       output TX_RESETDONE_O,\r
+       output RX_PRBS_ERR_O,\r
+       output RX_BUF_ERR_O,\r
+       output RX_BYTE_IS_ALIGNED_O,\r
+       output RX_BYTE_REALIGN_O,\r
+       output RX_RESETDONE_O,\r
+       output RX_EI_EN_O,\r
+       output CLK_CORE_RX_O,\r
+       output CLK_CORE_PLL_O,\r
+       output [15:0] REGFILE_DO_O,\r
+       output REGFILE_RDY_O\r
+);\r
+endmodule\r
+\r
+(* blackbox *) (* keep *)\r
+module CC_CFG_CTRL(\r
+       input [7:0] DATA,\r
+       input CLK,\r
+       input EN,\r
+       input RECFG,\r
+       input VALID\r
+);\r
+endmodule\r
diff --git a/techlibs/gatemate/cells_sim.v b/techlibs/gatemate/cells_sim.v
new file mode 100644 (file)
index 0000000..0d24101
--- /dev/null
@@ -0,0 +1,1574 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+`timescale 1ps/1ps\r
+\r
+module CC_IBUF #(\r
+       parameter PIN_NAME = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter [0:0] PULLUP = 1'bx,\r
+       parameter [0:0] PULLDOWN = 1'bx,\r
+       parameter [0:0] KEEPER = 1'bx,\r
+       parameter [0:0] SCHMITT_TRIGGER = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_IBF = 1'bx,\r
+       parameter [0:0] FF_IBF = 1'bx\r
+)(\r
+       (* iopad_external_pin *)\r
+       input  I,\r
+       output Y\r
+);\r
+       assign Y = I;\r
+\r
+       specify\r
+               (I => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_OBUF #(\r
+       parameter PIN_NAME = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter DRIVE = "UNDEFINED",\r
+       parameter SLEW = "UNDEFINED",\r
+       // IOSEL\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A,\r
+       (* iopad_external_pin *)\r
+       output O\r
+);\r
+       assign O = A;\r
+\r
+       specify\r
+               (A => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_TOBUF #(\r
+       parameter PIN_NAME = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter DRIVE = "UNDEFINED",\r
+       parameter SLEW = "UNDEFINED",\r
+       parameter [0:0] PULLUP = 1'bx,\r
+       parameter [0:0] PULLDOWN = 1'bx,\r
+       parameter [0:0] KEEPER = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A, T,\r
+       (* iopad_external_pin *)\r
+       output O\r
+);\r
+       assign O = T ? 1'bz : A;\r
+\r
+       specify\r
+               (A => O) = (0:0:0, 0:0:0);\r
+               (T => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_IOBUF #(\r
+       parameter PIN_NAME = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter DRIVE = "UNDEFINED",\r
+       parameter SLEW = "UNDEFINED",\r
+       parameter [0:0] PULLUP = 1'bx,\r
+       parameter [0:0] PULLDOWN = 1'bx,\r
+       parameter [0:0] KEEPER = 1'bx,\r
+       parameter [0:0] SCHMITT_TRIGGER = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_IBF = 1'bx,\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_IBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A, T,\r
+       output Y,\r
+       (* iopad_external_pin *)\r
+       inout  IO\r
+);\r
+       assign IO = T ? 1'bz : A;\r
+       assign Y = IO;\r
+\r
+       specify\r
+               (A => Y) = (0:0:0, 0:0:0);\r
+               (T => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LVDS_IBUF #(\r
+       parameter PIN_NAME_P = "UNPLACED",\r
+       parameter PIN_NAME_N = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter [0:0] LVDS_RTERM = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_IBF = 1'bx,\r
+       parameter [0:0] FF_IBF = 1'bx\r
+)(\r
+       (* iopad_external_pin *)\r
+       input  IP, IN,\r
+       output Y\r
+);\r
+       assign Y = IP;\r
+\r
+       specify\r
+               (IP => Y) = (0:0:0, 0:0:0);\r
+               (IN => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LVDS_OBUF #(\r
+       parameter PIN_NAME_P = "UNPLACED",\r
+       parameter PIN_NAME_N = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter [0:0] LVDS_BOOST = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A,\r
+       (* iopad_external_pin *)\r
+       output OP, ON\r
+);\r
+       assign OP = A;\r
+       assign ON = ~A;\r
+\r
+       specify\r
+               (A => OP) = (0:0:0, 0:0:0);\r
+               (A => ON) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LVDS_TOBUF #(\r
+       parameter PIN_NAME_P = "UNPLACED",\r
+       parameter PIN_NAME_N = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter [0:0] LVDS_BOOST = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A, T,\r
+       (* iopad_external_pin *)\r
+       output OP, ON\r
+);\r
+       assign OP = T ? 1'bz :  A;\r
+       assign ON = T ? 1'bz : ~A;\r
+\r
+       specify\r
+               (A => OP) = (0:0:0, 0:0:0);\r
+               (A => OP) = (0:0:0, 0:0:0);\r
+               (A => ON) = (0:0:0, 0:0:0);\r
+               (A => ON) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LVDS_IOBUF #(\r
+       parameter PIN_NAME_P = "UNPLACED",\r
+       parameter PIN_NAME_N = "UNPLACED",\r
+       parameter V_IO = "UNDEFINED",\r
+       parameter [0:0] LVDS_RTERM = 1'bx,\r
+       parameter [0:0] LVDS_BOOST = 1'bx,\r
+       // IOSEL\r
+       parameter [3:0] DELAY_IBF = 1'bx,\r
+       parameter [3:0] DELAY_OBF = 1'bx,\r
+       parameter [0:0] FF_IBF = 1'bx,\r
+       parameter [0:0] FF_OBF = 1'bx\r
+)(\r
+       input  A, T,\r
+       (* iopad_external_pin *)\r
+       inout  IOP, ION,\r
+       output Y\r
+);\r
+       assign IOP = T ? 1'bz :  A;\r
+       assign ION = T ? 1'bz : ~A;\r
+       assign Y = IOP;\r
+\r
+       specify\r
+               (A => Y)   = (0:0:0, 0:0:0);\r
+               (A => IOP) = (0:0:0, 0:0:0);\r
+               (A => ION) = (0:0:0, 0:0:0);\r
+               (T => Y)   = (0:0:0, 0:0:0);\r
+               (T => IOP) = (0:0:0, 0:0:0);\r
+               (T => ION) = (0:0:0, 0:0:0);\r
+               (IOP => Y) = (0:0:0, 0:0:0);\r
+               (ION => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_IDDR #(\r
+       parameter [0:0] CLK_INV = 1'b0\r
+)(\r
+       input D,\r
+       (* clkbuf_sink *)\r
+       input CLK,\r
+       output reg Q0, Q1\r
+);\r
+       wire clk;\r
+       assign clk = (CLK_INV) ? ~CLK : CLK;\r
+\r
+       always @(posedge clk)\r
+       begin\r
+               Q0 <= D;\r
+       end\r
+\r
+       always @(negedge clk)\r
+       begin\r
+               Q1 <= D;\r
+       end\r
+\r
+endmodule\r
+\r
+\r
+module CC_ODDR #(\r
+       parameter [0:0] CLK_INV = 1'b0\r
+)(\r
+       input D0,\r
+       input D1,\r
+       (* clkbuf_sink *)\r
+       input CLK,\r
+       (* clkbuf_sink *)\r
+       input DDR,\r
+       output Q\r
+);\r
+       wire clk;\r
+       assign clk = (CLK_INV) ? ~CLK : CLK;\r
+\r
+       reg q0, q1;\r
+       assign Q = (DDR) ? q0 : q1;\r
+\r
+       always @(posedge clk)\r
+       begin\r
+               q0 <= D0;\r
+       end\r
+\r
+       always @(negedge clk)\r
+       begin\r
+               q1 <= D1;\r
+       end\r
+\r
+endmodule\r
+\r
+\r
+module CC_DFF #(\r
+       parameter [0:0] CLK_INV = 1'b0,\r
+       parameter [0:0] EN_INV  = 1'b0,\r
+       parameter [0:0] SR_INV  = 1'b0,\r
+       parameter [0:0] SR_VAL  = 1'b0\r
+)(\r
+       input D,\r
+       (* clkbuf_sink *)\r
+       input CLK,\r
+       input EN,\r
+       input SR,\r
+       output reg Q\r
+);\r
+       wire clk, en, sr;\r
+       assign clk = (CLK_INV) ? ~CLK : CLK;\r
+       assign en  = (EN_INV)  ?  ~EN :  EN;\r
+       assign sr  = (SR_INV)  ?  ~SR :  SR;\r
+\r
+       initial Q = 0;\r
+\r
+       always @(posedge clk or posedge sr)\r
+       begin\r
+               if (sr) begin\r
+                       Q <= SR_VAL;\r
+               end\r
+               else if (en) begin\r
+                       Q <= D;\r
+               end\r
+       end\r
+\r
+endmodule\r
+\r
+\r
+module CC_DLT #(\r
+       parameter [0:0] G_INV = 1'b0,\r
+       parameter [0:0] SR_INV = 1'b0,\r
+       parameter [0:0] SR_VAL = 1'b0\r
+)(\r
+       input D,\r
+       input G,\r
+       input SR,\r
+       output reg Q\r
+);\r
+       wire en, sr;\r
+       assign en  = (G_INV) ? ~G : G;\r
+       assign sr  = (SR_INV) ? ~SR : SR;\r
+\r
+       initial Q = 0;\r
+\r
+       always @(*)\r
+       begin\r
+               if (sr) begin\r
+                       Q <= SR_VAL;\r
+               end\r
+               else if (en) begin\r
+                       Q <= D;\r
+               end\r
+       end\r
+\r
+endmodule\r
+\r
+\r
+module CC_LUT1 (\r
+       output O,\r
+       input  I0\r
+);\r
+       parameter [1:0] INIT = 0;\r
+\r
+       assign O = I0 ? INIT[1] : INIT[0];\r
+\r
+       specify\r
+               (I0 => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LUT2 (\r
+       output O,\r
+       input  I0, I1\r
+);\r
+       parameter [3:0] INIT = 0;\r
+\r
+       wire [1:0] s1 = I1 ? INIT[3:2] : INIT[1:0];\r
+       assign O = I0 ? s1[1] : s1[0];\r
+\r
+       specify\r
+               (I0 => O) = (0:0:0, 0:0:0);\r
+               (I1 => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LUT3 (\r
+       output O,\r
+       input  I0, I1, I2\r
+);\r
+       parameter [7:0] INIT = 0;\r
+\r
+       wire [3:0] s2 = I2 ? INIT[7:4] : INIT[3:0];\r
+       wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];\r
+       assign O = I0 ? s1[1] : s1[0];\r
+\r
+       specify\r
+               (I0 => O) = (0:0:0, 0:0:0);\r
+               (I1 => O) = (0:0:0, 0:0:0);\r
+               (I2 => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_LUT4 (\r
+       output O,\r
+       input  I0, I1, I2, I3\r
+);\r
+       parameter [15:0] INIT = 0;\r
+\r
+       wire [7:0] s3 = I3 ? INIT[15:8] : INIT[7:0];\r
+       wire [3:0] s2 = I2 ? s3[7:4] : s3[3:0];\r
+       wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];\r
+       assign O = I0 ? s1[1] : s1[0];\r
+\r
+       specify\r
+               (I0 => O) = (0:0:0, 0:0:0);\r
+               (I1 => O) = (0:0:0, 0:0:0);\r
+               (I2 => O) = (0:0:0, 0:0:0);\r
+               (I3 => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_MX2 (\r
+       input  D0, D1,\r
+       input  S0,\r
+       output reg Y\r
+);\r
+       always @(*) begin\r
+               case (S0)\r
+                       1'b0: Y <= D0;\r
+                       1'b1: Y <= D1;\r
+               endcase\r
+       end\r
+\r
+       specify\r
+               (D0 => Y) = (0:0:0, 0:0:0);\r
+               (D1 => Y) = (0:0:0, 0:0:0);\r
+               (S0 => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_MX4 (\r
+       input  D0, D1, D2, D3,\r
+       input  S0, S1,\r
+       output reg Y\r
+);\r
+       always @(*) begin\r
+               case ({S1, S0})\r
+                       2'b00: Y <= D0;\r
+                       2'b01: Y <= D1;\r
+                       2'b10: Y <= D2;\r
+                       2'b11: Y <= D3;\r
+               endcase\r
+       end\r
+\r
+       specify\r
+               (D0 => Y) = (0:0:0, 0:0:0);\r
+               (D1 => Y) = (0:0:0, 0:0:0);\r
+               (D2 => Y) = (0:0:0, 0:0:0);\r
+               (D3 => Y) = (0:0:0, 0:0:0);\r
+               (S0 => Y) = (0:0:0, 0:0:0);\r
+               (S1 => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_MX8 (\r
+       input  D0, D1, D2, D3,\r
+       input  D4, D5, D6, D7,\r
+       input  S0, S1, S2,\r
+       output reg Y\r
+);\r
+       always @(*) begin\r
+               case ({S2, S1, S0})\r
+                       3'b000: Y <= D0;\r
+                       3'b001: Y <= D1;\r
+                       3'b010: Y <= D2;\r
+                       3'b011: Y <= D3;\r
+                       3'b100: Y <= D4;\r
+                       3'b101: Y <= D5;\r
+                       3'b110: Y <= D6;\r
+                       3'b111: Y <= D7;\r
+               endcase\r
+       end\r
+\r
+       specify\r
+               (D0 => Y) = (0:0:0, 0:0:0);\r
+               (D1 => Y) = (0:0:0, 0:0:0);\r
+               (D2 => Y) = (0:0:0, 0:0:0);\r
+               (D3 => Y) = (0:0:0, 0:0:0);\r
+               (D4 => Y) = (0:0:0, 0:0:0);\r
+               (D5 => Y) = (0:0:0, 0:0:0);\r
+               (D6 => Y) = (0:0:0, 0:0:0);\r
+               (D7 => Y) = (0:0:0, 0:0:0);\r
+               (S0 => Y) = (0:0:0, 0:0:0);\r
+               (S1 => Y) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_ADDF (\r
+       input  A, B, CI,\r
+       output CO, S\r
+);\r
+       assign {CO, S} = A + B + CI;\r
+\r
+       specify\r
+               (A => S)   = (0:0:0, 0:0:0);\r
+               (B => S)   = (0:0:0, 0:0:0);\r
+               (CI => S)  = (0:0:0, 0:0:0);\r
+               (A => CO)  = (0:0:0, 0:0:0);\r
+               (B => CO)  = (0:0:0, 0:0:0);\r
+               (CI => CO) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+module CC_MULT #(\r
+       parameter A_WIDTH = 0,\r
+       parameter B_WIDTH = 0,\r
+       parameter P_WIDTH = 0\r
+)(\r
+       input signed [A_WIDTH-1:0] A,\r
+       input signed [B_WIDTH-1:0] B,\r
+       output reg signed [P_WIDTH-1:0] P\r
+);\r
+       always @(*)\r
+       begin\r
+               P <= A * B;\r
+       end\r
+endmodule\r
+\r
+\r
+module CC_BUFG (\r
+       input  I,\r
+       (* clkbuf_driver *)\r
+       output O\r
+);\r
+       assign O = I;\r
+\r
+       specify\r
+               (I => O) = (0:0:0, 0:0:0);\r
+       endspecify\r
+endmodule\r
+\r
+\r
+(* blackbox *)\r
+module CC_BRAM_20K (\r
+       output [19:0] A_DO,\r
+       output [19:0] B_DO,\r
+       output ECC_1B_ERR,\r
+       output ECC_2B_ERR,\r
+       (* clkbuf_sink *)\r
+       input A_CLK,\r
+       (* clkbuf_sink *)\r
+       input B_CLK,\r
+       input A_EN,\r
+       input B_EN,\r
+       input A_WE,\r
+       input B_WE,\r
+       input [15:0] A_ADDR,\r
+       input [15:0] B_ADDR,\r
+       input [19:0] A_DI,\r
+       input [19:0] B_DI,\r
+       input [19:0] A_BM,\r
+       input [19:0] B_BM\r
+);\r
+       // Location format: D(0..N-1)(0..N-1)X(0..3)Y(0..7)Z(0..1) or UNPLACED\r
+       parameter LOC = "UNPLACED";\r
+\r
+       // Port Widths\r
+       parameter A_RD_WIDTH = 0;\r
+       parameter B_RD_WIDTH = 0;\r
+       parameter A_WR_WIDTH = 0;\r
+       parameter B_WR_WIDTH = 0;\r
+\r
+       // RAM and Write Modes\r
+       parameter RAM_MODE = "SDP";\r
+       parameter A_WR_MODE = "NO_CHANGE";\r
+       parameter B_WR_MODE = "NO_CHANGE";\r
+\r
+       // Inverting Control Pins\r
+       parameter A_CLK_INV = 1'b0;\r
+       parameter B_CLK_INV = 1'b0;\r
+       parameter A_EN_INV = 1'b0;\r
+       parameter B_EN_INV = 1'b0;\r
+       parameter A_WE_INV = 1'b0;\r
+       parameter B_WE_INV = 1'b0;\r
+\r
+       // Output Register\r
+       parameter A_DO_REG = 1'b0;\r
+       parameter B_DO_REG = 1'b0;\r
+\r
+       // Error Checking and Correction\r
+       parameter ECC_EN = 1'b0;\r
+\r
+       // RAM Contents\r
+       parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+\r
+       localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH;\r
+       localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH;\r
+\r
+       integer i, k;\r
+\r
+       // 512 x 40 bit\r
+       reg [20479:0] memory = 20480'b0;\r
+\r
+       initial begin\r
+               // Check parameters\r
+               if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin\r
+                       $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin\r
+                       $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin\r
+                       $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if (ECC_EN != 1'b0) begin\r
+                       $display("WARNING: ECC feature not supported in simulation.");\r
+               end\r
+               if ((ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin\r
+                       $display("ERROR: Illegal ECC Port configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A);\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_A == 40) && (RAM_MODE == "TDP")) begin\r
+                       $display("ERROR: Port A width of 40 bits is only supported in SDP mode.");\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_B == 40) && (RAM_MODE == "TDP")) begin\r
+                       $display("ERROR: Port B width of 40 bits is only supported in SDP mode.");\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) &&\r
+                       (WIDTH_MODE_A != 5)  && (WIDTH_MODE_A != 2)  && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin\r
+                       $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A);\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) &&\r
+                       (WIDTH_MODE_B != 5)  && (WIDTH_MODE_B != 2)  && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin\r
+                       $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B);\r
+                       $finish();\r
+               end\r
+               // RAM initialization\r
+               for (i=0; i < 320; i=i+1) begin\r
+                       memory[320*0+i]  = INIT_00[i];\r
+                       memory[320*1+i]  = INIT_01[i];\r
+                       memory[320*2+i]  = INIT_02[i];\r
+                       memory[320*3+i]  = INIT_03[i];\r
+                       memory[320*4+i]  = INIT_04[i];\r
+                       memory[320*5+i]  = INIT_05[i];\r
+                       memory[320*6+i]  = INIT_06[i];\r
+                       memory[320*7+i]  = INIT_07[i];\r
+                       memory[320*8+i]  = INIT_08[i];\r
+                       memory[320*9+i]  = INIT_09[i];\r
+                       memory[320*10+i] = INIT_0A[i];\r
+                       memory[320*11+i] = INIT_0B[i];\r
+                       memory[320*12+i] = INIT_0C[i];\r
+                       memory[320*13+i] = INIT_0D[i];\r
+                       memory[320*14+i] = INIT_0E[i];\r
+                       memory[320*15+i] = INIT_0F[i];\r
+                       memory[320*16+i] = INIT_10[i];\r
+                       memory[320*17+i] = INIT_11[i];\r
+                       memory[320*18+i] = INIT_12[i];\r
+                       memory[320*19+i] = INIT_13[i];\r
+                       memory[320*20+i] = INIT_14[i];\r
+                       memory[320*21+i] = INIT_15[i];\r
+                       memory[320*22+i] = INIT_16[i];\r
+                       memory[320*23+i] = INIT_17[i];\r
+                       memory[320*24+i] = INIT_18[i];\r
+                       memory[320*25+i] = INIT_19[i];\r
+                       memory[320*26+i] = INIT_1A[i];\r
+                       memory[320*27+i] = INIT_1B[i];\r
+                       memory[320*28+i] = INIT_1C[i];\r
+                       memory[320*29+i] = INIT_1D[i];\r
+                       memory[320*30+i] = INIT_1E[i];\r
+                       memory[320*31+i] = INIT_1F[i];\r
+                       memory[320*32+i] = INIT_20[i];\r
+                       memory[320*33+i] = INIT_21[i];\r
+                       memory[320*34+i] = INIT_22[i];\r
+                       memory[320*35+i] = INIT_23[i];\r
+                       memory[320*36+i] = INIT_24[i];\r
+                       memory[320*37+i] = INIT_25[i];\r
+                       memory[320*38+i] = INIT_26[i];\r
+                       memory[320*39+i] = INIT_27[i];\r
+                       memory[320*30+i] = INIT_28[i];\r
+                       memory[320*41+i] = INIT_29[i];\r
+                       memory[320*42+i] = INIT_2A[i];\r
+                       memory[320*43+i] = INIT_2B[i];\r
+                       memory[320*44+i] = INIT_2C[i];\r
+                       memory[320*45+i] = INIT_2D[i];\r
+                       memory[320*46+i] = INIT_2E[i];\r
+                       memory[320*47+i] = INIT_2F[i];\r
+                       memory[320*48+i] = INIT_30[i];\r
+                       memory[320*49+i] = INIT_31[i];\r
+                       memory[320*50+i] = INIT_32[i];\r
+                       memory[320*51+i] = INIT_33[i];\r
+                       memory[320*52+i] = INIT_34[i];\r
+                       memory[320*53+i] = INIT_35[i];\r
+                       memory[320*54+i] = INIT_36[i];\r
+                       memory[320*55+i] = INIT_37[i];\r
+                       memory[320*56+i] = INIT_38[i];\r
+                       memory[320*57+i] = INIT_39[i];\r
+                       memory[320*58+i] = INIT_3A[i];\r
+                       memory[320*59+i] = INIT_3B[i];\r
+                       memory[320*60+i] = INIT_3C[i];\r
+                       memory[320*61+i] = INIT_3D[i];\r
+                       memory[320*62+i] = INIT_3E[i];\r
+                       memory[320*63+i] = INIT_3F[i];\r
+               end\r
+       end\r
+\r
+       // Signal inversion\r
+       wire clka = A_CLK_INV ^ A_CLK;\r
+       wire clkb = B_CLK_INV ^ B_CLK;\r
+       wire ena  = A_EN_INV ^ A_EN;\r
+       wire enb  = B_EN_INV ^ B_EN;\r
+       wire wea  = A_WE_INV ^ A_WE;\r
+       wire web  = B_WE_INV ^ B_WE;\r
+\r
+       // Internal signals\r
+       wire [15:0] addra;\r
+       wire [15:0] addrb;\r
+       reg  [19:0] A_DO_out = 0, A_DO_reg = 0;\r
+       reg  [19:0] B_DO_out = 0, B_DO_reg = 0;\r
+\r
+       generate\r
+               if (RAM_MODE == "SDP") begin\r
+                       // Port A (write)\r
+                       if (WIDTH_MODE_A <= 1) begin\r
+                               assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4);\r
+                       end\r
+                       if (WIDTH_MODE_A <= 2) begin\r
+                               assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 5) begin\r
+                               assign addra = A_ADDR[15:7]*5;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 10) begin\r
+                               assign addra = A_ADDR[15:7]*10;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 20) begin\r
+                               assign addra = A_ADDR[15:7]*20;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 40) begin\r
+                               assign addra = A_ADDR[15:7]*40;\r
+                       end\r
+                       // Port B (read)\r
+                       if (WIDTH_MODE_B <= 1) begin\r
+                               assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 2) begin\r
+                               assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 5) begin\r
+                               assign addrb = B_ADDR[15:7]*5;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 10) begin\r
+                               assign addrb = B_ADDR[15:7]*10;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 20) begin\r
+                               assign addrb = B_ADDR[15:7]*20;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 40) begin\r
+                               assign addrb = B_ADDR[15:7]*40;\r
+                       end\r
+               end\r
+               else if (RAM_MODE == "TDP") begin\r
+                       // Port A\r
+                       if (WIDTH_MODE_A <= 1) begin\r
+                               wire [15:0] tmpa = {2'b0, A_ADDR[15:7], A_ADDR[5:1]};\r
+                               assign addra = tmpa + (tmpa/4);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 2) begin\r
+                               wire [15:0] tmpa = {3'b0, A_ADDR[15:7], A_ADDR[5:2]};\r
+                               assign addra = tmpa*2 + (tmpa/2);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 5) begin\r
+                               assign addra = {4'b0, A_ADDR[15:7], A_ADDR[5:3]}*5;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 10) begin\r
+                               assign addra = {5'b0, A_ADDR[15:7], A_ADDR[5:4]}*10;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 20) begin\r
+                               assign addra = {6'b0, A_ADDR[15:7], A_ADDR[5]}*20;\r
+                       end\r
+                       // Port B\r
+                       if (WIDTH_MODE_B <= 1) begin\r
+                               wire [15:0] tmpb = {2'b0, B_ADDR[15:7], B_ADDR[5:1]};\r
+                               assign addrb = tmpb + (tmpb/4);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 2) begin\r
+                               wire [15:0] tmpb = {3'b0, B_ADDR[15:7], B_ADDR[5:2]};\r
+                               assign addrb = tmpb*2 + (tmpb/2);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 5) begin\r
+                               assign addrb = {4'b0, B_ADDR[15:7], B_ADDR[5:3]}*5;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 10) begin\r
+                               assign addrb = {5'b0, B_ADDR[15:7], B_ADDR[5:4]}*10;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 20) begin\r
+                               assign addrb = {6'b0, B_ADDR[15:7], B_ADDR[5]}*20;\r
+                       end\r
+               end\r
+       endgenerate\r
+\r
+       generate\r
+               if (RAM_MODE == "SDP") begin\r
+                       // SDP write port\r
+                       always @(posedge clka)\r
+                       begin\r
+                               for (k=0; k < WIDTH_MODE_A; k=k+1) begin\r
+                                       if (k < 20) begin\r
+                                               if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k];\r
+                                       end\r
+                                       else begin // use both ports\r
+                                               if (ena && wea && B_BM[k-20]) memory[addra+k] <= B_DI[k-20];\r
+                                       end\r
+                               end\r
+                       end\r
+                       // SDP read port\r
+                       always @(posedge clkb)\r
+                       begin\r
+                               for (k=0; k < WIDTH_MODE_B; k=k+1) begin\r
+                                       if (k < 20) begin\r
+                                               if (enb) A_DO_out[k] <= memory[addrb+k];\r
+                                       end\r
+                                       else begin // use both ports\r
+                                               if (enb) B_DO_out[k-20] <= memory[addrb+k];\r
+                                       end\r
+                               end\r
+                       end\r
+               end\r
+               else if (RAM_MODE == "TDP") begin\r
+                       // TDP port A\r
+                       always @(posedge clka)\r
+                       begin\r
+                               for (i=0; i < WIDTH_MODE_A; i=i+1) begin\r
+                                       if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i];\r
+\r
+                                       if (A_WR_MODE == "NO_CHANGE") begin\r
+                                               if (ena) A_DO_out[i] <= memory[addra+i];\r
+                                       end\r
+                                       else if (A_WR_MODE == "WRITE_THROUGH") begin\r
+                                               if (ena) A_DO_out[i] <= A_DI[i];\r
+                                       end\r
+                               end\r
+                       end\r
+                       // TDP port B\r
+                       always @(posedge clkb)\r
+                       begin\r
+                               for (i=0; i < WIDTH_MODE_B; i=i+1) begin\r
+                                       if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i];\r
+\r
+                                       if (B_WR_MODE == "NO_CHANGE") begin\r
+                                               if (enb) B_DO_out[i] <= memory[addrb+i];\r
+                                       end\r
+                                       else if (B_WR_MODE == "WRITE_THROUGH") begin\r
+                                               if (enb) B_DO_out[i] <= B_DI[i];\r
+                                       end\r
+                               end\r
+                       end\r
+               end\r
+       endgenerate\r
+\r
+       // Optional output register\r
+       generate\r
+               if (A_DO_REG) begin\r
+                       always @(posedge clka) begin\r
+                               A_DO_reg <= A_DO_out;\r
+                       end\r
+                       assign A_DO = A_DO_reg;\r
+               end\r
+               else begin\r
+                       assign A_DO = A_DO_out;\r
+               end\r
+               if (B_DO_REG) begin\r
+                       always @(posedge clkb) begin\r
+                               B_DO_reg <= B_DO_out;\r
+                       end\r
+                       assign B_DO = B_DO_reg;\r
+               end\r
+               else begin\r
+                       assign B_DO = B_DO_out;\r
+               end\r
+       endgenerate\r
+endmodule\r
+\r
+\r
+(* blackbox *)\r
+module CC_BRAM_40K (\r
+       output [39:0] A_DO,\r
+       output [39:0] B_DO,\r
+       output A_ECC_1B_ERR,\r
+       output B_ECC_1B_ERR,\r
+       output A_ECC_2B_ERR,\r
+       output B_ECC_2B_ERR,\r
+       output A_CO,\r
+       output B_CO,\r
+       (* clkbuf_sink *)\r
+       input A_CLK,\r
+       (* clkbuf_sink *)\r
+       input B_CLK,\r
+       input A_EN,\r
+       input B_EN,\r
+       input A_WE,\r
+       input B_WE,\r
+       input [15:0] A_ADDR,\r
+       input [15:0] B_ADDR,\r
+       input [39:0] A_DI,\r
+       input [39:0] B_DI,\r
+       input [39:0] A_BM,\r
+       input [39:0] B_BM,\r
+       input A_CI,\r
+       input B_CI\r
+);\r
+       // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED\r
+       parameter LOC = "UNPLACED";\r
+       parameter CAS = "NONE"; // NONE, UPPER, LOWER\r
+\r
+       // Port Widths\r
+       parameter A_RD_WIDTH = 0;\r
+       parameter B_RD_WIDTH = 0;\r
+       parameter A_WR_WIDTH = 0;\r
+       parameter B_WR_WIDTH = 0;\r
+\r
+       // RAM and Write Modes\r
+       parameter RAM_MODE = "SDP";\r
+       parameter A_WR_MODE = "NO_CHANGE";\r
+       parameter B_WR_MODE = "NO_CHANGE";\r
+\r
+       // Inverting Control Pins\r
+       parameter A_CLK_INV = 1'b0;\r
+       parameter B_CLK_INV = 1'b0;\r
+       parameter A_EN_INV = 1'b0;\r
+       parameter B_EN_INV = 1'b0;\r
+       parameter A_WE_INV = 1'b0;\r
+       parameter B_WE_INV = 1'b0;\r
+\r
+       // Output Register\r
+       parameter A_DO_REG = 1'b0;\r
+       parameter B_DO_REG = 1'b0;\r
+\r
+       // Error Checking and Correction\r
+       parameter A_ECC_EN  = 1'b0;\r
+       parameter B_ECC_EN  = 1'b0;\r
+\r
+       parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_40 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_41 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_42 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_43 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_44 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_45 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_46 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_47 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_48 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_49 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_4F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_50 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_51 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_52 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_53 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_54 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_55 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_56 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_57 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_58 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_59 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_5F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_60 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_61 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_62 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_63 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_64 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_65 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_66 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_67 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_68 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_69 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_6F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_70 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_71 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_72 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_73 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_74 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_75 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_76 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_77 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_78 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_79 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+       parameter INIT_7F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\r
+\r
+       localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH;\r
+       localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH;\r
+\r
+       integer i, k;\r
+\r
+       // 512 x 80 bit\r
+       reg [40959:0] memory = 40960'b0;\r
+\r
+       initial begin\r
+               // Check parameters\r
+               if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin\r
+                       $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin\r
+                       $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin\r
+                       $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE);\r
+                       $finish();\r
+               end\r
+               if ((A_ECC_EN != 1'b0) || (B_ECC_EN != 1'b0)) begin\r
+                       $display("WARNING: ECC feature not supported in simulation.");\r
+               end\r
+               if ((A_ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin\r
+                       $display("ERROR: Illegal ECC Port A configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A);\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_A == 80) && (RAM_MODE == "TDP")) begin\r
+                       $display("ERROR: Port A width of 80 bits is only supported in SDP mode.");\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_B == 80) && (RAM_MODE == "TDP")) begin\r
+                       $display("ERROR: Port B width of 80 bits is only supported in SDP mode.");\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_A != 80) && (WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) &&\r
+                       (WIDTH_MODE_A != 5)  && (WIDTH_MODE_A != 2)  && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin\r
+                       $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A);\r
+                       $finish();\r
+               end\r
+               if ((WIDTH_MODE_B != 80) && (WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) &&\r
+                       (WIDTH_MODE_B != 5)  && (WIDTH_MODE_B != 2)  && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin\r
+                       $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B);\r
+                       $finish();\r
+               end\r
+               if ((CAS != "NONE") && ((WIDTH_MODE_A > 1) || (WIDTH_MODE_B > 1))) begin\r
+                       $display("ERROR: Cascade feature only supported in 1 bit data width mode.");\r
+                       $finish();\r
+               end\r
+               if ((CAS != "NONE") && (RAM_MODE != "TDP")) begin\r
+                       $display("ERROR: Cascade feature only supported in TDP mode.");\r
+                       $finish();\r
+               end\r
+               // RAM initialization\r
+               for (i=0; i < 320; i=i+1) begin\r
+                       memory[320*0+i]   = INIT_00[i];\r
+                       memory[320*1+i]   = INIT_01[i];\r
+                       memory[320*2+i]   = INIT_02[i];\r
+                       memory[320*3+i]   = INIT_03[i];\r
+                       memory[320*4+i]   = INIT_04[i];\r
+                       memory[320*5+i]   = INIT_05[i];\r
+                       memory[320*6+i]   = INIT_06[i];\r
+                       memory[320*7+i]   = INIT_07[i];\r
+                       memory[320*8+i]   = INIT_08[i];\r
+                       memory[320*9+i]   = INIT_09[i];\r
+                       memory[320*10+i]  = INIT_0A[i];\r
+                       memory[320*11+i]  = INIT_0B[i];\r
+                       memory[320*12+i]  = INIT_0C[i];\r
+                       memory[320*13+i]  = INIT_0D[i];\r
+                       memory[320*14+i]  = INIT_0E[i];\r
+                       memory[320*15+i]  = INIT_0F[i];\r
+                       memory[320*16+i]  = INIT_10[i];\r
+                       memory[320*17+i]  = INIT_11[i];\r
+                       memory[320*18+i]  = INIT_12[i];\r
+                       memory[320*19+i]  = INIT_13[i];\r
+                       memory[320*20+i]  = INIT_14[i];\r
+                       memory[320*21+i]  = INIT_15[i];\r
+                       memory[320*22+i]  = INIT_16[i];\r
+                       memory[320*23+i]  = INIT_17[i];\r
+                       memory[320*24+i]  = INIT_18[i];\r
+                       memory[320*25+i]  = INIT_19[i];\r
+                       memory[320*26+i]  = INIT_1A[i];\r
+                       memory[320*27+i]  = INIT_1B[i];\r
+                       memory[320*28+i]  = INIT_1C[i];\r
+                       memory[320*29+i]  = INIT_1D[i];\r
+                       memory[320*30+i]  = INIT_1E[i];\r
+                       memory[320*31+i]  = INIT_1F[i];\r
+                       memory[320*32+i]  = INIT_20[i];\r
+                       memory[320*33+i]  = INIT_21[i];\r
+                       memory[320*34+i]  = INIT_22[i];\r
+                       memory[320*35+i]  = INIT_23[i];\r
+                       memory[320*36+i]  = INIT_24[i];\r
+                       memory[320*37+i]  = INIT_25[i];\r
+                       memory[320*38+i]  = INIT_26[i];\r
+                       memory[320*39+i]  = INIT_27[i];\r
+                       memory[320*30+i]  = INIT_28[i];\r
+                       memory[320*41+i]  = INIT_29[i];\r
+                       memory[320*42+i]  = INIT_2A[i];\r
+                       memory[320*43+i]  = INIT_2B[i];\r
+                       memory[320*44+i]  = INIT_2C[i];\r
+                       memory[320*45+i]  = INIT_2D[i];\r
+                       memory[320*46+i]  = INIT_2E[i];\r
+                       memory[320*47+i]  = INIT_2F[i];\r
+                       memory[320*48+i]  = INIT_30[i];\r
+                       memory[320*49+i]  = INIT_31[i];\r
+                       memory[320*50+i]  = INIT_32[i];\r
+                       memory[320*51+i]  = INIT_33[i];\r
+                       memory[320*52+i]  = INIT_34[i];\r
+                       memory[320*53+i]  = INIT_35[i];\r
+                       memory[320*54+i]  = INIT_36[i];\r
+                       memory[320*55+i]  = INIT_37[i];\r
+                       memory[320*56+i]  = INIT_38[i];\r
+                       memory[320*57+i]  = INIT_39[i];\r
+                       memory[320*58+i]  = INIT_3A[i];\r
+                       memory[320*59+i]  = INIT_3B[i];\r
+                       memory[320*60+i]  = INIT_3C[i];\r
+                       memory[320*61+i]  = INIT_3D[i];\r
+                       memory[320*62+i]  = INIT_3E[i];\r
+                       memory[320*63+i]  = INIT_3F[i];\r
+                       memory[320*64+i]  = INIT_40[i];\r
+                       memory[320*65+i]  = INIT_41[i];\r
+                       memory[320*66+i]  = INIT_42[i];\r
+                       memory[320*67+i]  = INIT_43[i];\r
+                       memory[320*68+i]  = INIT_44[i];\r
+                       memory[320*69+i]  = INIT_45[i];\r
+                       memory[320*70+i]  = INIT_46[i];\r
+                       memory[320*71+i]  = INIT_47[i];\r
+                       memory[320*72+i]  = INIT_48[i];\r
+                       memory[320*73+i]  = INIT_49[i];\r
+                       memory[320*74+i]  = INIT_4A[i];\r
+                       memory[320*75+i]  = INIT_4B[i];\r
+                       memory[320*76+i]  = INIT_4C[i];\r
+                       memory[320*77+i]  = INIT_4D[i];\r
+                       memory[320*78+i]  = INIT_4E[i];\r
+                       memory[320*79+i]  = INIT_4F[i];\r
+                       memory[320*80+i]  = INIT_50[i];\r
+                       memory[320*81+i]  = INIT_51[i];\r
+                       memory[320*82+i]  = INIT_52[i];\r
+                       memory[320*83+i]  = INIT_53[i];\r
+                       memory[320*84+i]  = INIT_54[i];\r
+                       memory[320*85+i]  = INIT_55[i];\r
+                       memory[320*86+i]  = INIT_56[i];\r
+                       memory[320*87+i]  = INIT_57[i];\r
+                       memory[320*88+i]  = INIT_58[i];\r
+                       memory[320*89+i]  = INIT_59[i];\r
+                       memory[320*90+i]  = INIT_5A[i];\r
+                       memory[320*91+i]  = INIT_5B[i];\r
+                       memory[320*92+i]  = INIT_5C[i];\r
+                       memory[320*93+i]  = INIT_5D[i];\r
+                       memory[320*94+i]  = INIT_5E[i];\r
+                       memory[320*95+i]  = INIT_5F[i];\r
+                       memory[320*96+i]  = INIT_60[i];\r
+                       memory[320*97+i]  = INIT_61[i];\r
+                       memory[320*98+i]  = INIT_62[i];\r
+                       memory[320*99+i]  = INIT_63[i];\r
+                       memory[320*100+i] = INIT_64[i];\r
+                       memory[320*101+i] = INIT_65[i];\r
+                       memory[320*102+i] = INIT_66[i];\r
+                       memory[320*103+i] = INIT_67[i];\r
+                       memory[320*104+i] = INIT_68[i];\r
+                       memory[320*105+i] = INIT_69[i];\r
+                       memory[320*106+i] = INIT_6A[i];\r
+                       memory[320*107+i] = INIT_6B[i];\r
+                       memory[320*108+i] = INIT_6C[i];\r
+                       memory[320*109+i] = INIT_6D[i];\r
+                       memory[320*110+i] = INIT_6E[i];\r
+                       memory[320*111+i] = INIT_6F[i];\r
+                       memory[320*112+i] = INIT_70[i];\r
+                       memory[320*113+i] = INIT_71[i];\r
+                       memory[320*114+i] = INIT_72[i];\r
+                       memory[320*115+i] = INIT_73[i];\r
+                       memory[320*116+i] = INIT_74[i];\r
+                       memory[320*117+i] = INIT_75[i];\r
+                       memory[320*118+i] = INIT_76[i];\r
+                       memory[320*119+i] = INIT_77[i];\r
+                       memory[320*120+i] = INIT_78[i];\r
+                       memory[320*121+i] = INIT_79[i];\r
+                       memory[320*122+i] = INIT_7A[i];\r
+                       memory[320*123+i] = INIT_7B[i];\r
+                       memory[320*124+i] = INIT_7C[i];\r
+                       memory[320*125+i] = INIT_7D[i];\r
+                       memory[320*126+i] = INIT_7E[i];\r
+                       memory[320*127+i] = INIT_7F[i];\r
+               end\r
+       end\r
+\r
+       // Signal inversion\r
+       wire clka = A_CLK_INV ^ A_CLK;\r
+       wire clkb = B_CLK_INV ^ B_CLK;\r
+       wire ena  = A_EN_INV ^ A_EN;\r
+       wire enb  = B_EN_INV ^ B_EN;\r
+       wire wea  = A_WE_INV ^ A_WE;\r
+       wire web  = B_WE_INV ^ B_WE;\r
+\r
+       // Internal signals\r
+       wire [15:0] addra;\r
+       wire [15:0] addrb;\r
+       reg  [39:0] A_DO_out = 0, A_DO_reg = 0;\r
+       reg  [39:0] B_DO_out = 0, B_DO_reg = 0;\r
+\r
+       generate\r
+               if (RAM_MODE == "SDP") begin\r
+                       // Port A (write)\r
+                       if (WIDTH_MODE_A <= 1) begin\r
+                               assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4);\r
+                       end\r
+                       if (WIDTH_MODE_A <= 2) begin\r
+                               assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 5) begin\r
+                               assign addra = A_ADDR[15:7]*5;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 10) begin\r
+                               assign addra = A_ADDR[15:7]*10;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 20) begin\r
+                               assign addra = A_ADDR[15:7]*20;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 40) begin\r
+                               assign addra = A_ADDR[15:7]*40;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 80) begin\r
+                               assign addra = A_ADDR[15:7]*80;\r
+                       end\r
+                       // Port B (read)\r
+                       if (WIDTH_MODE_B <= 1) begin\r
+                               assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 2) begin\r
+                               assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 5) begin\r
+                               assign addrb = B_ADDR[15:7]*5;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 10) begin\r
+                               assign addrb = B_ADDR[15:7]*10;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 20) begin\r
+                               assign addrb = B_ADDR[15:7]*20;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 40) begin\r
+                               assign addrb = B_ADDR[15:7]*40;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 80) begin\r
+                               assign addrb = B_ADDR[15:7]*80;\r
+                       end\r
+               end\r
+               else if (RAM_MODE == "TDP") begin\r
+                       // Port A\r
+                       if (WIDTH_MODE_A <= 1) begin\r
+                               wire [15:0] tmpa = {1'b0, A_ADDR[15:1]};\r
+                               assign addra = tmpa + (tmpa/4);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 2) begin\r
+                               wire [15:0] tmpa = {2'b0, A_ADDR[15:2]};\r
+                               assign addra = tmpa*2 + (tmpa/2);\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 5) begin\r
+                               assign addra = {3'b0, A_ADDR[15:3]}*5;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 10) begin\r
+                               assign addra = {4'b0, A_ADDR[15:4]}*10;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 20) begin\r
+                               assign addra = {5'b0, A_ADDR[15:5]}*20;\r
+                       end\r
+                       else if (WIDTH_MODE_A <= 40) begin\r
+                               assign addra = {6'b0, A_ADDR[15:6]}*40;\r
+                       end\r
+                       // Port B\r
+                       if (WIDTH_MODE_B <= 1) begin\r
+                               wire [15:0] tmpb = {1'b0, B_ADDR[15:1]};\r
+                               assign addrb = tmpb + (tmpb/4);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 2) begin\r
+                               wire [15:0] tmpb = {2'b0, B_ADDR[15:2]};\r
+                               assign addrb = tmpb*2 + (tmpb/2);\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 5) begin\r
+                               assign addrb = {3'b0, B_ADDR[15:3]}*5;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 10) begin\r
+                               assign addrb = {4'b0, B_ADDR[15:4]}*10;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 20) begin\r
+                               assign addrb = {5'b0, B_ADDR[15:5]}*20;\r
+                       end\r
+                       else if (WIDTH_MODE_B <= 40) begin\r
+                               assign addrb = {6'b0, B_ADDR[15:6]}*40;\r
+                       end\r
+               end\r
+       endgenerate\r
+\r
+       generate\r
+               if (RAM_MODE == "SDP") begin\r
+                       // SDP write port\r
+                       always @(posedge clka)\r
+                       begin\r
+                               for (k=0; k < WIDTH_MODE_A; k=k+1) begin\r
+                                       if (k < 40) begin\r
+                                               if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k];\r
+                                       end\r
+                                       else begin // use both ports\r
+                                               if (ena && wea && B_BM[k-40]) memory[addra+k] <= B_DI[k-40];\r
+                                       end\r
+                               end\r
+                       end\r
+                       // SDP read port\r
+                       always @(posedge clkb)\r
+                       begin\r
+                               for (k=0; k < WIDTH_MODE_B; k=k+1) begin\r
+                                       if (k < 40) begin\r
+                                               if (enb) A_DO_out[k] <= memory[addrb+k];\r
+                                       end\r
+                                       else begin // use both ports\r
+                                               if (enb) B_DO_out[k-40] <= memory[addrb+k];\r
+                                       end\r
+                               end\r
+                       end\r
+               end\r
+               else if (RAM_MODE == "TDP") begin\r
+                       // TDP port A\r
+                       always @(posedge clka)\r
+                       begin\r
+                               for (i=0; i < WIDTH_MODE_A; i=i+1) begin\r
+                                       if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i];\r
+\r
+                                       if (A_WR_MODE == "NO_CHANGE") begin\r
+                                               if (ena) A_DO_out[i] <= memory[addra+i];\r
+                                       end\r
+                                       else if (A_WR_MODE == "WRITE_THROUGH") begin\r
+                                               if (ena) A_DO_out[i] <= A_DI[i];\r
+                                       end\r
+                               end\r
+                       end\r
+                       // TDP port B\r
+                       always @(posedge clkb)\r
+                       begin\r
+                               for (i=0; i < WIDTH_MODE_B; i=i+1) begin\r
+                                       if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i];\r
+\r
+                                       if (B_WR_MODE == "NO_CHANGE") begin\r
+                                               if (enb) B_DO_out[i] <= memory[addrb+i];\r
+                                       end\r
+                                       else if (B_WR_MODE == "WRITE_THROUGH") begin\r
+                                               if (enb) B_DO_out[i] <= B_DI[i];\r
+                                       end\r
+                               end\r
+                       end\r
+               end\r
+       endgenerate\r
+\r
+       // Optional output register\r
+       generate\r
+               if (A_DO_REG) begin\r
+                       always @(posedge clka) begin\r
+                               A_DO_reg <= A_DO_out;\r
+                       end\r
+                       assign A_DO = A_DO_reg;\r
+               end\r
+               else begin\r
+                       assign A_DO = A_DO_out;\r
+               end\r
+               if (B_DO_REG) begin\r
+                       always @(posedge clkb) begin\r
+                               B_DO_reg <= B_DO_out;\r
+                       end\r
+                       assign B_DO = B_DO_reg;\r
+               end\r
+               else begin\r
+                       assign B_DO = B_DO_out;\r
+               end\r
+   endgenerate\r
+endmodule\r
+\r
+\r
+(* blackbox *)\r
+module CC_FIFO_40K (\r
+       output A_ECC_1B_ERR,\r
+       output B_ECC_1B_ERR,\r
+       output A_ECC_2B_ERR,\r
+       output B_ECC_2B_ERR,\r
+       // FIFO pop port\r
+       output [39:0] A_DO,\r
+       output [39:0] B_DO,\r
+       (* clkbuf_sink *)\r
+       input  A_CLK,\r
+       input  A_EN,\r
+       // FIFO push port\r
+       input  [39:0] A_DI,\r
+       input  [39:0] B_DI,\r
+       input  [39:0] A_BM,\r
+       input  [39:0] B_BM,\r
+       (* clkbuf_sink *)\r
+       input  B_CLK,\r
+       input  B_EN,\r
+       input  B_WE,\r
+       // FIFO control\r
+       input  F_RST_N,\r
+       input  [12:0] F_ALMOST_FULL_OFFSET,\r
+       input  [12:0] F_ALMOST_EMPTY_OFFSET,\r
+       // FIFO status signals\r
+       output F_FULL,\r
+       output F_EMPTY,\r
+       output F_ALMOST_FULL,\r
+       output F_ALMOST_EMPTY,\r
+       output F_RD_ERROR,\r
+       output F_WR_ERROR,\r
+       output [15:0] F_RD_PTR,\r
+       output [15:0] F_WR_PTR\r
+);\r
+       // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED\r
+       parameter LOC = "UNPLACED";\r
+\r
+       // Offset configuration\r
+       parameter [12:0] ALMOST_FULL_OFFSET = 12'b0;\r
+       parameter [12:0] ALMOST_EMPTY_OFFSET = 12'b0;\r
+\r
+       // Port Widths\r
+       parameter A_WIDTH = 0;\r
+       parameter B_WIDTH = 0;\r
+\r
+       // RAM and Write Modes\r
+       parameter RAM_MODE = "SDP"; // "TPD" or "SDP"\r
+       parameter FIFO_MODE = "SYNC"; // "ASYNC" or "SYNC"\r
+\r
+       // Inverting Control Pins\r
+       parameter A_CLK_INV = 1'b0;\r
+       parameter B_CLK_INV = 1'b0;\r
+       parameter A_EN_INV = 1'b0;\r
+       parameter B_EN_INV = 1'b0;\r
+       parameter A_WE_INV = 1'b0;\r
+       parameter B_WE_INV = 1'b0;\r
+\r
+       // Output Register\r
+       parameter A_DO_REG = 1'b0;\r
+       parameter B_DO_REG = 1'b0;\r
+\r
+       // Error Checking and Correction\r
+       parameter A_ECC_EN  = 1'b0;\r
+       parameter B_ECC_EN  = 1'b0;\r
+endmodule\r
diff --git a/techlibs/gatemate/gatemate_bramopt.cc b/techlibs/gatemate/gatemate_bramopt.cc
new file mode 100644 (file)
index 0000000..9454f47
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>
+ *
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+bool binary_pred(SigBit s1, SigBit s2)
+{
+       return s1 == s2;
+}
+
+static void proc_glwren(Module *module)
+{
+       std::vector<Cell*> ram_cells;
+
+       // Gather RAM cells
+       for (auto cell : module->cells())
+       {
+               if (cell->type.in(ID(CC_DPSRAM_20K), ID(CC_DPSRAM_40K))) {
+                       ram_cells.push_back(cell);
+               }
+       }
+
+       // Convert bitmask signals
+       for (auto cell : ram_cells)
+       {
+               std::vector<SigBit> mska = cell->getPort(ID(A_BM)).to_sigbit_vector();
+               std::vector<SigBit> mskb = cell->getPort(ID(B_BM)).to_sigbit_vector();
+
+               // Remove State::S0 from vectors
+               mska.erase(std::remove_if(mska.begin(), mska.end(), [](const SigBit & sb){return (sb == State::S0);}), mska.end());
+               mskb.erase(std::remove_if(mskb.begin(), mskb.end(), [](const SigBit & sb){return (sb == State::S0);}), mskb.end());
+
+               if (mska.size() + mskb.size() == 0) {
+                       break;
+               }
+
+               if (cell->getParam(ID(RAM_MODE)).decode_string() == "SDP")
+               {
+                       std::vector<SigBit> msk;
+                       msk.insert(msk.end(), mska.begin(), mska.end());
+                       msk.insert(msk.end(), mskb.begin(), mskb.end());
+
+                       if (std::equal(msk.begin() + 1, msk.end(), msk.begin(), binary_pred))
+                       {
+                               if ((cell->getPort(ID(A_WE)) == State::S1) && (cell->getPort(ID(B_WE)) == State::S0))
+                               {
+                                       cell->setPort(ID(A_WE), msk[0]);
+                                       cell->setPort(ID(B_WE), Const(0, 1));
+                                       // Set bitmask bits to _1_
+                                       cell->setPort(ID(A_BM), Const(State::S1, mska.size()));
+                                       cell->setPort(ID(B_BM), Const(State::S1, mskb.size()));
+                               }
+                       }
+               }
+               else // RAM_MODE == "TDP"
+               {
+                       if (std::equal(mska.begin() + 1, mska.end(), mska.begin(), binary_pred))
+                       {
+                               if (cell->getPort(ID(A_WE)) == State::S1)
+                               {
+                                       // Signals are all equal
+                                       cell->setPort(ID(A_WE), mska[0]);
+                                       cell->setPort(ID(A_BM), Const(State::S1, mska.size()));
+                               }
+                       }
+                       if (std::equal(mskb.begin() + 1, mskb.end(), mskb.begin(), binary_pred))
+                       {
+                               if (cell->getPort(ID(B_WE)) == State::S1)
+                               {
+                                       cell->setPort(ID(B_WE), mskb[0]);
+                                       // Set bitmask bits to _1_
+                                       cell->setPort(ID(B_BM), Const(State::S1, mskb.size()));
+                               }
+                       }
+               }
+       }
+}
+
+struct GateMateBramOptPass : public Pass {
+       GateMateBramOptPass() : Pass("gatemate_bramopt", "GateMate: optimize block RAM cells") { }
+       void help() override
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    gatemate_bramopt [options] [selection]\n");
+               log("\n");
+               log("This pass processes all CC_BRAM_20K and CC_BRAM_40K cells and tries to");
+               log("convert its enable bitmask wires to a single global enable signal.");
+               log("\n");
+               log("    -noglwren\n");
+               log("        do not convert bitmasks to single global write enable signals.\n");
+               log("\n");
+       }
+
+       bool noglwren;
+
+       void clear_flags() override
+       {
+               noglwren = false;
+       }
+
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override
+       {
+               log_header(design, "Executing GATEMATE_BRAMOPT pass (optimize block RAM).\n");
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       if (args[argidx] == "-noglwren") {
+                               noglwren = true;
+                               continue;
+                       }
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               Module *module = design->top_module();
+
+               if (module == nullptr)
+               {
+                       log_cmd_error("No top module found.\n");
+               }
+
+               if (!noglwren) {
+                       proc_glwren(module);
+               }
+       }
+} GateMateBramOptPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gatemate/iob_map.v b/techlibs/gatemate/iob_map.v
new file mode 100644 (file)
index 0000000..b73b4b9
--- /dev/null
@@ -0,0 +1,88 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+module \$__inpad (input I, output Y);\r
+       CC_IBUF /*#(\r
+               .PIN_NAME("UNPLACED"),\r
+               .V_IO("UNDEFINED"),\r
+               .PULLUP(1'bx),\r
+               .PULLDOWN(1'bx),\r
+               .KEEPER(1'bx),\r
+               .SCHMITT_TRIGGER(1'bx),\r
+               .DELAY_IBF(4'bx),\r
+               .FF_IBF(1'bx)\r
+       )*/ _TECHMAP_REPLACE_ (\r
+               .I(I),\r
+               .Y(Y)\r
+       );\r
+endmodule\r
+\r
+module \$__outpad (input A, output O);\r
+       CC_OBUF /*#(\r
+               .PIN_NAME("UNPLACED"),\r
+               .V_IO("UNDEFINED"),\r
+               .SLEW("UNDEFINED"),\r
+               .DRIVE(1'bx),\r
+               .DELAY_OBF(4'bx),\r
+               .FF_OBF(1'bx)\r
+       )*/ _TECHMAP_REPLACE_ (\r
+               .A(A),\r
+               .O(O)\r
+       );\r
+endmodule\r
+\r
+module \$__toutpad (input A, input OE, output O);\r
+       CC_TOBUF /*#(\r
+               .PIN_NAME("UNPLACED"),\r
+               .V_IO("UNDEFINED"),\r
+               .SLEW("UNDEFINED"),\r
+               .DRIVE(1'bx),\r
+               .PULLUP(1'bx),\r
+               .PULLDOWN(1'bx),\r
+               .KEEPER(1'bx),\r
+               .DELAY_OBF(4'bx),\r
+               .FF_OBF(1'bx)\r
+       )*/ _TECHMAP_REPLACE_ (\r
+               .A(A),\r
+               .T(~OE),\r
+               .O(O)\r
+       );\r
+endmodule\r
+\r
+module \$__tinoutpad (input A, input OE, inout IO, output Y);\r
+       CC_IOBUF /*#(\r
+               .PIN_NAME("UNPLACED"),\r
+               .V_IO("UNDEFINED"),\r
+               .SLEW("UNDEFINED"),\r
+               .DRIVE(1'bx),\r
+               .PULLUP(1'bx),\r
+               .PULLDOWN(1'bx),\r
+               .KEEPER(1'bx),\r
+               .SCHMITT_TRIGGER(1'bx),\r
+               .DELAY_IBF(4'bx),\r
+               .DELAY_OBF(4'bx),\r
+               .FF_IBF(1'bx),\r
+               .FF_OBF(1'bx)\r
+       )*/ _TECHMAP_REPLACE_ (\r
+               .A(A),\r
+               .T(~OE),\r
+               .IO(IO),\r
+               .Y(Y)\r
+       );\r
+endmodule\r
diff --git a/techlibs/gatemate/lut_map.v b/techlibs/gatemate/lut_map.v
new file mode 100644 (file)
index 0000000..1e5d497
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+module \$lut (A, Y);\r
+       parameter WIDTH = 0;\r
+       parameter LUT = 0;\r
+\r
+       (* force_downto *)\r
+       input [WIDTH-1:0] A;\r
+       output Y;\r
+\r
+       generate\r
+               if (WIDTH == 1) begin\r
+                       CC_LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]));\r
+               end\r
+               else if (WIDTH == 2) begin\r
+                       CC_LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]));\r
+               end\r
+               else if (WIDTH == 3) begin\r
+                       CC_LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]));\r
+               end\r
+               else if (WIDTH == 4) begin\r
+                       CC_LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));\r
+               end\r
+               else begin\r
+                       wire _TECHMAP_FAIL_ = 1;\r
+               end\r
+       endgenerate\r
+endmodule\r
diff --git a/techlibs/gatemate/mul_map.v b/techlibs/gatemate/mul_map.v
new file mode 100644 (file)
index 0000000..8ab5228
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>
+ *
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+`define MAX(a,b) (a > b ? a : b)
+`define MIN(a,b) (a < b ? a : b)
+
+(* techmap_celltype = "$mul $__mul" *)
+module \$__MULMXN (A, B, Y);
+
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       (* force_downto *)
+       input [A_WIDTH-1:0] A;
+       (* force_downto *)
+       input [B_WIDTH-1:0] B;
+       (* force_downto *)
+       output [Y_WIDTH-1:0] Y;
+
+       localparam MAXWIDTH = `MAX(A_WIDTH, B_WIDTH) + ((A_SIGNED || B_SIGNED) ? 0 : 1);
+
+       generate
+               if (A_SIGNED) begin: blkA
+                       wire signed [MAXWIDTH-1:0] Aext = $signed(A);
+               end
+               else begin: blkA
+                       wire [MAXWIDTH-1:0] Aext = A;
+               end
+               if (B_SIGNED) begin: blkB
+                       wire signed [MAXWIDTH-1:0] Bext = $signed(B);
+               end
+               else begin: blkB
+                       wire [MAXWIDTH-1:0] Bext = B;
+               end
+
+               if (A_WIDTH >= B_WIDTH) begin
+                       CC_MULT #(
+                               .A_WIDTH(MAXWIDTH),
+                               .B_WIDTH(MAXWIDTH),
+                               .P_WIDTH(`MIN(Y_WIDTH,MAXWIDTH+MAXWIDTH)),
+                       ) _TECHMAP_REPLACE_ (
+                               .A(blkA.Aext),
+                               .B(blkB.Bext),
+                               .P(Y)
+                       );
+               end
+               else begin // swap A,B
+                       CC_MULT #(
+                               .A_WIDTH(MAXWIDTH),
+                               .B_WIDTH(MAXWIDTH),
+                               .P_WIDTH(`MIN(Y_WIDTH,MAXWIDTH+MAXWIDTH)),
+                       ) _TECHMAP_REPLACE_ (
+                               .A(blkB.Bext),
+                               .B(blkA.Aext),
+                               .P(Y)
+                       );
+               end
+       endgenerate
+
+endmodule
diff --git a/techlibs/gatemate/mux_map.v b/techlibs/gatemate/mux_map.v
new file mode 100644 (file)
index 0000000..13c1972
--- /dev/null
@@ -0,0 +1,56 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);\r
+       input  A, B, C, D, E, F, G, H, S, T, U;\r
+       output Y;\r
+\r
+       CC_MX8 _TECHMAP_REPLACE_ (\r
+               .D0(A), .D1(B), .D2(C), .D3(D),\r
+               .D4(E), .D5(F), .D6(G), .D7(H),\r
+               .S0(S), .S1(T), .S2(U),\r
+               .Y(Y)\r
+       );\r
+\r
+endmodule\r
+\r
+module \$_MUX4_ (A, B, C, D, S, T, Y);\r
+       input  A, B, C, D, S, T;\r
+       output Y;\r
+\r
+       CC_MX4 _TECHMAP_REPLACE_ (\r
+               .D0(A), .D1(B), .D2(C), .D3(D),\r
+               .S0(S), .S1(T),\r
+               .Y(Y)\r
+       );\r
+\r
+endmodule\r
+\r
+/*\r
+module \$_MUX_ (A, B, S, Y);\r
+       input  A, B, S;\r
+       output Y;\r
+\r
+       CC_MX2 _TECHMAP_REPLACE_ (\r
+               .D0(A), .D1(B), .S0(S),\r
+               .Y(Y)\r
+       );\r
+\r
+endmodule\r
+*/\r
diff --git a/techlibs/gatemate/reg_map.v b/techlibs/gatemate/reg_map.v
new file mode 100644 (file)
index 0000000..5075adf
--- /dev/null
@@ -0,0 +1,108 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+(* techmap_celltype = "$_DFF_[NP]_" *)\r
+module \$_DFF_x_ (input D, C, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DFF #(\r
+               .CLK_INV((_TECHMAP_CELLTYPE_[15:8] == "N")),\r
+               .EN_INV(1'b0),\r
+               .SR_INV(1'b0),\r
+               .SR_VAL(1'b0)\r
+       ) _TECHMAP_REPLACE_ (.D(D), .EN(1'b1), .CLK(C), .SR(1'b0), .Q(Q));\r
+\r
+       wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;\r
+\r
+endmodule\r
+\r
+(* techmap_celltype = "$_DFF_[NP][NP][01]_" *)\r
+module \$_DFF_xxx_ (input D, C, R, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DFF #(\r
+               .CLK_INV(_TECHMAP_CELLTYPE_[31:24] == "N"),\r
+               .EN_INV(1'b0),\r
+               .SR_INV(_TECHMAP_CELLTYPE_[23:16] == "N"),\r
+               .SR_VAL(_TECHMAP_CELLTYPE_[15:8] == "1")\r
+       ) _TECHMAP_REPLACE_ (.D(D), .EN(1'b1), .CLK(C), .SR(R), .Q(Q));\r
+\r
+       wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;\r
+\r
+endmodule\r
+\r
+(* techmap_celltype = "$_DFFE_[NP][NP]_" *)\r
+module \$_DFFE_xx_ (input D, C, E, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DFF #(\r
+               .CLK_INV(_TECHMAP_CELLTYPE_[23:16] == "N"),\r
+               .EN_INV(_TECHMAP_CELLTYPE_[15:8] == "N"),\r
+               .SR_INV(1'b0),\r
+               .SR_VAL(1'b0)\r
+       ) _TECHMAP_REPLACE_ (.D(D), .EN(E), .CLK(C), .SR(1'b0), .Q(Q));\r
+\r
+       wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;\r
+\r
+endmodule\r
+\r
+(* techmap_celltype = "$_DFFE_[NP][NP][01][NP]_" *)\r
+module \$_DFFE_xxxx_ (input D, C, R, E, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DFF #(\r
+               .CLK_INV(_TECHMAP_CELLTYPE_[39:32] == "N"),\r
+               .EN_INV(_TECHMAP_CELLTYPE_[15:8] == "N"),\r
+               .SR_INV(_TECHMAP_CELLTYPE_[31:24] == "N"),\r
+               .SR_VAL(_TECHMAP_CELLTYPE_[23:16] == "1")\r
+       ) _TECHMAP_REPLACE_ (.D(D), .EN(E), .CLK(C), .SR(R), .Q(Q));\r
+\r
+       wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;\r
+\r
+endmodule\r
+\r
+(* techmap_celltype = "$_DLATCH_[NP]_" *)\r
+module \$_DLATCH_x_ (input E, D, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DLT #(\r
+               .G_INV(_TECHMAP_CELLTYPE_[15:8] == "N"),\r
+               .SR_INV(1'b0),\r
+               .SR_VAL(1'b0)\r
+       ) _TECHMAP_REPLACE_ (.D(D), .G(E), .SR(1'b0), .Q(Q));\r
+\r
+endmodule\r
+\r
+(* techmap_celltype = "$_DLATCH_[NP][NP][01]_" *)\r
+module \$_DLATCH_xxx_ (input E, R, D, output Q);\r
+\r
+       parameter _TECHMAP_CELLTYPE_ = "";\r
+\r
+       CC_DLT #(\r
+               .G_INV(_TECHMAP_CELLTYPE_[31:24] == "N"),\r
+               .SR_INV(_TECHMAP_CELLTYPE_[23:16] == "N"),\r
+               .SR_VAL(_TECHMAP_CELLTYPE_[15:8] == "1")\r
+       ) _TECHMAP_REPLACE_ (.D(D), .G(E), .SR(R), .Q(Q));\r
+\r
+endmodule\r
diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc
new file mode 100644 (file)
index 0000000..424d48b
--- /dev/null
@@ -0,0 +1,396 @@
+/*\r
+ *  yosys -- Yosys Open SYnthesis Suite\r
+ *\r
+ *  Copyright (C) 2021  Cologne Chip AG <support@colognechip.com>\r
+ *\r
+ *  Permission to use, copy, modify, and/or distribute this software for any\r
+ *  purpose with or without fee is hereby granted, provided that the above\r
+ *  copyright notice and this permission notice appear in all copies.\r
+ *\r
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\r
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\r
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\r
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+ *\r
+ */\r
+\r
+#include "kernel/register.h"\r
+#include "kernel/celltypes.h"\r
+#include "kernel/rtlil.h"\r
+#include "kernel/log.h"\r
+\r
+USING_YOSYS_NAMESPACE\r
+PRIVATE_NAMESPACE_BEGIN\r
+\r
+struct SynthGateMatePass : public ScriptPass\r
+{\r
+       SynthGateMatePass() : ScriptPass("synth_gatemate", "synthesis for Cologne Chip GateMate FPGAs") { }\r
+\r
+       void help() override\r
+       {\r
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|\r
+               log("\n");\r
+               log("    synth_gatemate [options]\n");\r
+               log("\n");\r
+               log("This command runs synthesis for Cologne Chip AG GateMate FPGAs.\n");\r
+               log("\n");\r
+               log("    -top <module>\n");\r
+               log("        use the specified module as top module.\n");\r
+               log("\n");\r
+               log("    -vlog <file>\n");\r
+               log("        write the design to the specified verilog file. Writing of an output\n");\r
+               log("        file is omitted if this parameter is not specified.\n");\r
+               log("\n");\r
+               log("    -blif <file>\n");\r
+               log("        write the design to the specified BLIF file. Writing of an output file\n");\r
+               log("        is omitted if this parameter is not specified.\n");\r
+               log("\n");\r
+               log("    -edif <file>\n");\r
+               log("        write the design to the specified EDIF file. Writing of an output file\n");\r
+               log("        is omitted if this parameter is not specified.\n");\r
+               log("\n");\r
+               log("    -json <file>\n");\r
+               log("        write the design to the specified JSON file. Writing of an output file\n");\r
+               log("        is omitted if this parameter is not specified.\n");\r
+               log("\n");\r
+               log("    -run <from_label>:<to_label>\n");\r
+               log("        only run the commands between the labels (see below). An empty\n");\r
+               log("        from label is synonymous to 'begin', and empty to label is\n");\r
+               log("        synonymous to the end of the command list.\n");\r
+               log("\n");\r
+               log("    -noflatten\n");\r
+               log("        do not flatten design before synthesis.\n");\r
+               log("\n");\r
+               log("    -nobram\n");\r
+               log("        do not use CC_BRAM_20K or CC_BRAM_40K cells in output netlist.\n");\r
+               log("\n");\r
+               log("    -noaddf\n");\r
+               log("        do not use CC_ADDF full adder cells in output netlist.\n");\r
+               log("\n");\r
+               log("    -nomult\n");\r
+               log("        do not use CC_MULT multiplier cells in output netlist.\n");\r
+               log("\n");\r
+               log("    -nomx8, -nomx4\n");\r
+               log("        do not use CC_MX{8,4} multiplexer cells in output netlist.\n");\r
+               log("\n");;\r
+               log("    -dff\n");\r
+               log("        run 'abc'/'abc9' with -dff option\n");\r
+               log("\n");\r
+               log("    -retime\n");\r
+               log("        run 'abc' with '-dff -D 1' options\n");\r
+               log("\n");\r
+               log("    -noiopad\n");\r
+               log("        disable I/O buffer insertion (useful for hierarchical or \n");\r
+               log("        out-of-context flows).\n");\r
+               log("\n");\r
+               log("    -noclkbuf\n");\r
+               log("        disable automatic clock buffer insertion.\n");\r
+               log("\n");\r
+               log("The following commands are executed by this synthesis command:\n");\r
+               help_script();\r
+               log("\n");\r
+       }\r
+\r
+       string top_opt, vlog_file, blif_file, edif_file, json_file;\r
+       bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, dff, retime, noiopad, noclkbuf;\r
+\r
+       void clear_flags() override\r
+       {\r
+               top_opt = "-auto-top";\r
+               vlog_file = "";\r
+               blif_file = "";\r
+               edif_file = "";\r
+               json_file = "";\r
+               noflatten = false;\r
+               nobram = false;\r
+               noaddf = false;\r
+               nomult = false;\r
+               nomx4 = false;\r
+               nomx8 = false;\r
+               dff = false;\r
+               retime = false;\r
+               noiopad = false;\r
+               noclkbuf = false;\r
+       }\r
+\r
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override\r
+       {\r
+               string run_from, run_to;\r
+               clear_flags();\r
+\r
+               size_t argidx;\r
+               for (argidx = 1; argidx < args.size(); argidx++)\r
+               {\r
+                       if (args[argidx] == "-top" && argidx+1 < args.size()) {\r
+                               top_opt = "-top " + args[++argidx];\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-vlog" && argidx+1 < args.size()) {\r
+                               vlog_file = args[++argidx];\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-blif" && argidx+1 < args.size()) {\r
+                               blif_file = args[++argidx];\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-edif" && argidx+1 < args.size()) {\r
+                               edif_file = args[++argidx];\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-json" && argidx+1 < args.size()) {\r
+                               json_file = args[++argidx];\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-run" && argidx+1 < args.size()) {\r
+                               size_t pos = args[argidx+1].find(':');\r
+                               if (pos == std::string::npos)\r
+                                       break;\r
+                               run_from = args[++argidx].substr(0, pos);\r
+                               run_to = args[argidx].substr(pos+1);\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-noflatten") {\r
+                               noflatten = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-nobram") {\r
+                               nobram = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-noaddf") {\r
+                               noaddf = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-nomult") {\r
+                               nomult = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-nomx4") {\r
+                               nomx4 = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-nomx8") {\r
+                               nomx8 = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-dff") {\r
+                               dff = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-retime") {\r
+                               retime = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-noiopad") {\r
+                               noiopad = true;\r
+                               continue;\r
+                       }\r
+                       if (args[argidx] == "-noclkbuf") {\r
+                               noclkbuf = true;\r
+                               continue;\r
+                       }\r
+                       break;\r
+               }\r
+               extra_args(args, argidx, design);\r
+\r
+               if (!design->full_selection()) {\r
+                       log_cmd_error("This command only operates on fully selected designs!\n");\r
+               }\r
+\r
+               log_header(design, "Executing SYNTH_GATEMATE pass.\n");\r
+               log_push();\r
+\r
+               run_script(design, run_from, run_to);\r
+\r
+               log_pop();\r
+       }\r
+\r
+       void script() override\r
+       {\r
+               if (check_label("begin"))\r
+               {\r
+                       run("read_verilog -lib -specify +/gatemate/cells_sim.v +/gatemate/cells_bb.v");\r
+                       run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));\r
+               }\r
+\r
+               if (check_label("prepare"))\r
+               {\r
+                       run("proc");\r
+                       if (!noflatten) {\r
+                               run("flatten");\r
+                       }\r
+                       run("tribuf -logic");\r
+                       run("deminout");\r
+                       run("opt_expr");\r
+                       run("opt_clean");\r
+                       run("check");\r
+                       run("opt -nodffe -nosdff");\r
+                       run("fsm");\r
+                       run("opt");\r
+                       run("wreduce");\r
+                       run("peepopt");\r
+                       run("opt_clean");\r
+                       run("share");\r
+                       run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");\r
+                       run("opt_expr");\r
+                       run("opt_clean");\r
+               }\r
+\r
+               if (check_label("map_mult", "(skip if '-nomult')"))\r
+               {\r
+                       if (!nomult) {\r
+                               run("techmap -map +/gatemate/mul_map.v");\r
+                       }\r
+               }\r
+\r
+               if (check_label("coarse"))\r
+               {\r
+                       run("alumacc");\r
+                       run("opt");\r
+                       run("memory -nomap");\r
+                       run("opt_clean");\r
+               }\r
+\r
+               if (check_label("map_bram", "(skip if '-nobram')"))\r
+               {\r
+                       if (!nobram) {\r
+                               run("memory_bram -rules +/gatemate/brams.txt");\r
+                               run("setundef -zero -params "\r
+                                       "t:$__CC_BRAM_CASCADE "\r
+                                       "t:$__CC_BRAM_40K_SDP t:$__CC_BRAM_20K_SDP "\r
+                                       "t:$__CC_BRAM_20K_TDP t:$__CC_BRAM_40K_TDP "\r
+                               );\r
+                               run("techmap -map +/gatemate/brams_map.v");\r
+                               run("gatemate_bramopt");\r
+                       }\r
+               }\r
+\r
+               if (check_label("map_ffram"))\r
+               {\r
+                       run("opt -fast -mux_undef -undriven -fine");\r
+                       run("memory_map");\r
+                       run("opt -undriven -fine");\r
+               }\r
+\r
+               if (check_label("map_addf", "(skip if '-noaddf')"))\r
+               {\r
+                       std::string techmap_args = "";\r
+                       if (!noaddf) {\r
+                               techmap_args += " -map +/gatemate/arith_map.v";\r
+                       }\r
+                       run("techmap -map +/techmap.v " + techmap_args);\r
+                       run("opt -fast");\r
+                       if (retime) {\r
+                               run("abc -dff -D 1", "(only if -retime)");\r
+                       }\r
+               }\r
+\r
+               if (check_label("map_io", "(skip if '-noiopad')"))\r
+               {\r
+                       if (!noiopad) {\r
+                               run("iopadmap -bits "\r
+                                       "-inpad $__inpad Y:I "\r
+                                       "-outpad $__outpad A:O "\r
+                                       "-toutpad $__toutpad OE:A:O "\r
+                                       "-tinoutpad $__tinoutpad OE:Y:A:IO"\r
+                               );\r
+                               run("techmap -map +/gatemate/iob_map.v");\r
+                               run("clean");\r
+                       }\r
+               }\r
+\r
+               if (check_label("map_regs"))\r
+               {\r
+                       run("opt_clean");\r
+                       run("dfflegalize -cell $_DFF_?_ 0 -cell $_DFF_???_ 0 "\r
+                               "-cell $_DFFE_??_ 0 -cell $_DFFE_????_ 0 "\r
+                               "-cell $_DLATCH_?_ x -cell $_DLATCH_???_ x"\r
+                       );\r
+                       run("techmap -map +/gatemate/reg_map.v");\r
+                       run("opt_expr -mux_undef");\r
+                       run("simplemap");\r
+                       run("opt_clean");\r
+               }\r
+\r
+               if (check_label("map_muxs"))\r
+               {\r
+                       run("abc -g simple"); // optimize design before muxcover\r
+                       std::string muxcover_args;\r
+                       if (!nomx4) {\r
+                               muxcover_args += stringf(" -mux4");\r
+                       }\r
+                       if (!nomx8) {\r
+                               muxcover_args += stringf(" -mux8");\r
+                       }\r
+                       run("muxcover " + muxcover_args);\r
+                       run("opt -full");\r
+                       run("techmap -map +/gatemate/mux_map.v");\r
+               }\r
+\r
+               if (check_label("map_luts"))\r
+               {\r
+                       std::string abc_args = " -dress -lut 4";\r
+                       if (dff) {\r
+                               abc_args += " -dff";\r
+                       }\r
+                       run("abc " + abc_args);\r
+                       run("clean");\r
+               }\r
+\r
+               if (check_label("map_cells"))\r
+               {\r
+                       run("techmap -map +/gatemate/lut_map.v");\r
+                       run("clean");\r
+               }\r
+\r
+               if (check_label("map_bufg", "(skip if '-noclkbuf')"))\r
+               {\r
+                       if (!noclkbuf) {\r
+                               run("clkbufmap -buf CC_BUFG O:I");\r
+                               run("clean");\r
+                       }\r
+               }\r
+\r
+               if (check_label("check"))\r
+               {\r
+                       run("hierarchy -check");\r
+                       run("stat -width");\r
+                       run("check -noinit");\r
+                       run("blackbox =A:whitebox");\r
+               }\r
+\r
+               if (check_label("vlog"))\r
+               {\r
+                       run("opt_clean -purge");\r
+                       if (!vlog_file.empty() || help_mode) {\r
+                               run(stringf("write_verilog -noattr %s", help_mode ? "<file-name>" : vlog_file.c_str()));\r
+                       }\r
+               }\r
+\r
+               if (check_label("edif"))\r
+               {\r
+                       if (!edif_file.empty() || help_mode) {\r
+                               run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));\r
+                       }\r
+               }\r
+\r
+               if (check_label("json"))\r
+               {\r
+                       if (!json_file.empty() || help_mode) {\r
+                               run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));\r
+                       }\r
+               }\r
+\r
+               if (check_label("blif"))\r
+               {\r
+                       if (!blif_file.empty() || help_mode) {\r
+                               run(stringf("write_blif %s", edif_file.c_str()));\r
+                       }\r
+               }\r
+       }\r
+} SynthGateMatePass;\r
+\r
+PRIVATE_NAMESPACE_END\r
diff --git a/tests/arch/gatemate/add_sub.ys b/tests/arch/gatemate/add_sub.ys
new file mode 100644 (file)
index 0000000..c0055e5
--- /dev/null
@@ -0,0 +1,9 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 8 t:CC_ADDF
+select -assert-count 4 t:CC_LUT1
+select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D
diff --git a/tests/arch/gatemate/adffs.ys b/tests/arch/gatemate/adffs.ys
new file mode 100644 (file)
index 0000000..7bba699
--- /dev/null
@@ -0,0 +1,43 @@
+read_verilog ../common/adffs.v
+design -save read
+
+hierarchy -top adff
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adff # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top adffn
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adffn # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top dffs
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffs # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-count 1 t:CC_LUT2
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D
+
+design -load read
+hierarchy -top ndffnr
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd ndffnr # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-count 1 t:CC_LUT2
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D
diff --git a/tests/arch/gatemate/counter.ys b/tests/arch/gatemate/counter.ys
new file mode 100644 (file)
index 0000000..77ed858
--- /dev/null
@@ -0,0 +1,12 @@
+read_verilog ../common/counter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 8 t:CC_ADDF
+select -assert-count 1 t:CC_BUFG
+select -assert-count 8 t:CC_DFF
+select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/dffs.ys b/tests/arch/gatemate/dffs.ys
new file mode 100644 (file)
index 0000000..0a3944e
--- /dev/null
@@ -0,0 +1,21 @@
+read_verilog ../common/dffs.v
+design -save read
+
+hierarchy -top dff
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dff # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top dffe
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffe # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/fsm.ys b/tests/arch/gatemate/fsm.ys
new file mode 100644 (file)
index 0000000..39b74c9
--- /dev/null
@@ -0,0 +1,20 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad
+async2sync
+miter -equiv -make_assert -flatten gold gate miter
+stat
+sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
+
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd fsm # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:CC_BUFG
+select -assert-count 6 t:CC_DFF
+select -assert-count 3 t:CC_LUT2
+select -assert-count 4 t:CC_LUT3
+select -assert-count 8 t:CC_LUT4
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_LUT3 t:CC_LUT4 %% t:* %D
diff --git a/tests/arch/gatemate/latches.ys b/tests/arch/gatemate/latches.ys
new file mode 100644 (file)
index 0000000..807650b
--- /dev/null
@@ -0,0 +1,29 @@
+read_verilog ../common/latches.v
+design -save read
+
+hierarchy -top latchp
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchp # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-none t:CC_DLT %% t:* %D
+
+design -load read
+hierarchy -top latchn
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchn # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-none t:CC_DLT %% t:* %D
+
+design -load read
+hierarchy -top latchsr
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchsr # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-count 2 t:CC_LUT3
+select -assert-none t:CC_DLT t:CC_LUT3 %% t:* %D
diff --git a/tests/arch/gatemate/logic.ys b/tests/arch/gatemate/logic.ys
new file mode 100644 (file)
index 0000000..2718375
--- /dev/null
@@ -0,0 +1,10 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_LUT1
+select -assert-count 6 t:CC_LUT2
+select -assert-count 2 t:CC_LUT4
+select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_LUT4 %% t:* %D
diff --git a/tests/arch/gatemate/memory.ys b/tests/arch/gatemate/memory.ys
new file mode 100644 (file)
index 0000000..e919920
--- /dev/null
@@ -0,0 +1,34 @@
+# 512 x 40 bit -> CC_BRAM_20K SDP RAM
+read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 40 sync_ram_sdp
+synth_gatemate -top sync_ram_sdp -noiopad
+cd sync_ram_sdp
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_20K
+
+# 512 x 80 bit -> CC_BRAM_40K SDP RAM
+design -reset
+read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 80 sync_ram_sdp
+synth_gatemate -top sync_ram_sdp -noiopad
+cd sync_ram_sdp
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_40K
+
+# 512 x 40 bit -> CC_BRAM_20K SDP ROM
+design -reset
+read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 40 sync_rom
+synth_gatemate -top sync_rom -noiopad
+cd sync_rom
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_20K
+
+# 512 x 80 bit -> CC_BRAM_40K SDP ROM
+design -reset
+read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 80 sync_rom
+synth_gatemate -top sync_rom -noiopad
+cd sync_rom
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_40K
diff --git a/tests/arch/gatemate/mul.v b/tests/arch/gatemate/mul.v
new file mode 100644 (file)
index 0000000..55e8f90
--- /dev/null
@@ -0,0 +1,79 @@
+
+module mul_plain(a, b, p);
+
+    parameter M = 6;
+    parameter N = 6;
+
+    input wire [M-1:0] a;
+    input wire [N-1:0] b;
+    output wire [M+N-1:0] p;
+
+    assign p = a * b;
+
+endmodule
+
+module mul_signed_async (clk, rst, en, a, b, p);
+
+    parameter M = 8;
+    parameter N = 6;
+
+    input wire signed clk, rst, en;
+    input wire signed [M-1:0] a;
+    input wire signed [N-1:0] b;
+    output reg signed [M+N-1:0] p;
+
+    reg signed [M-1:0] a_reg;
+    reg signed [N-1:0] b_reg;
+
+    // signed M*N multiplier with
+    // - input and output pipeline registers
+    // - asynchronous reset (active high)
+    // - clock enable (active high)
+    always @(posedge clk or posedge rst)
+    begin
+        if (rst) begin
+            a_reg <= 0;
+            b_reg <= 0;
+            p <= 0;
+        end
+        else if (en) begin
+            a_reg <= a;
+            b_reg <= b;
+            p <= a_reg * b_reg;
+        end
+    end
+
+endmodule
+
+module mul_unsigned_sync (clk, rst, en, a, b, p);
+
+    parameter M = 6;
+    parameter N = 3;
+
+    input wire clk, rst, en;
+    input wire [M-1:0] a;
+    input wire [N-1:0] b;
+    output reg [M+N-1:0] p;
+
+    reg [M-1:0] a_reg;
+    reg [N-1:0] b_reg;
+
+    // unsigned M*N multiplier with
+    // - input and output pipeline registers
+    // - synchronous reset (active high)
+    // - clock enable (active high)
+    always @(posedge clk)
+    begin
+        if (rst) begin
+            a_reg <= 0;
+            b_reg <= 0;
+            p <= 0;
+        end
+        else if (en) begin
+            a_reg <= a;
+            b_reg <= b;
+            p <= a_reg * b_reg;
+        end
+    end
+
+endmodule
diff --git a/tests/arch/gatemate/mul.ys b/tests/arch/gatemate/mul.ys
new file mode 100644 (file)
index 0000000..d10d07f
--- /dev/null
@@ -0,0 +1,33 @@
+read_verilog mul.v
+design -save read
+
+hierarchy -top mul_plain
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_plain # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-none t:CC_MULT %% t:* %D
+
+design -load read
+hierarchy -top mul_signed_async
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_signed_async # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-count 1 t:CC_BUFG
+select -assert-count 28 t:CC_DFF
+select -assert-none t:CC_MULT t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top mul_unsigned_sync
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_unsigned_sync # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-count 1 t:CC_BUFG
+select -assert-count 18 t:CC_LUT4
+select -assert-count 18 t:CC_DFF
+select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT4 t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/mux.ys b/tests/arch/gatemate/mux.ys
new file mode 100644 (file)
index 0000000..2839648
--- /dev/null
@@ -0,0 +1,20 @@
+read_verilog ../common/mux.v
+design -save read
+
+design -load read
+hierarchy -top mux4
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux4 # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MX4
+select -assert-none t:CC_MX4 %% t:* %D
+
+design -load read
+hierarchy -top mux8
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux8 # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MX8
+select -assert-none t:CC_MX8 %% t:* %D
diff --git a/tests/arch/gatemate/run-test.sh b/tests/arch/gatemate/run-test.sh
new file mode 100755 (executable)
index 0000000..4be4b70
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+set -eu
+source ../../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"
diff --git a/tests/arch/gatemate/shifter.ys b/tests/arch/gatemate/shifter.ys
new file mode 100644 (file)
index 0000000..03df36e
--- /dev/null
@@ -0,0 +1,10 @@
+read_verilog ../common/shifter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 8 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/tribuf.ys b/tests/arch/gatemate/tribuf.ys
new file mode 100644 (file)
index 0000000..96cb05b
--- /dev/null
@@ -0,0 +1,13 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+equiv_opt -assert -map +/gatemate/cells_sim.v -map +/simcells.v synth_gatemate # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd tristate # Constrain all select calls below inside the top module
+select -assert-count 2 t:CC_IBUF
+select -assert-count 1 t:CC_LUT1
+select -assert-count 1 t:CC_TOBUF
+select -assert-none t:CC_IBUF t:CC_LUT1 t:CC_TOBUF %% t:* %D