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