mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #2397 from daveshah1/nexus
synth_nexus: Initial implementation
This commit is contained in:
commit
ac0bd2ffc4
1
Makefile
1
Makefile
|
@ -789,6 +789,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
|
||||||
|
+cd tests/arch/nexus && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/rpc && bash run-test.sh
|
+cd tests/rpc && bash run-test.sh
|
||||||
+cd tests/memfile && bash run-test.sh
|
+cd tests/memfile && bash run-test.sh
|
||||||
+cd tests/verilog && bash run-test.sh
|
+cd tests/verilog && bash run-test.sh
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
OBJS += techlibs/nexus/synth_nexus.o
|
||||||
|
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_map.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/parse_init.vh))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_xtra.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams.txt))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_init.vh))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
|
||||||
|
$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Claire Xen <claire@symbioticeda.com>
|
||||||
|
* Copyright (C) 2018 David Shah <dave@ds0.me>
|
||||||
|
*
|
||||||
|
* 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_nexus_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 <= 4;
|
||||||
|
|
||||||
|
(* 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));
|
||||||
|
|
||||||
|
function integer round_up2;
|
||||||
|
input integer N;
|
||||||
|
begin
|
||||||
|
round_up2 = ((N + 1) / 2) * 2;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
localparam Y_WIDTH2 = round_up2(Y_WIDTH);
|
||||||
|
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH2-1:0] AA = A_buf;
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH2-1:0] BX = B_buf;
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH2+1:0] FCO, Y1;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
// Carry feed-in
|
||||||
|
CCU2 #(
|
||||||
|
.INIT0("0xFFFF"),
|
||||||
|
.INIT1("0x00AA"),
|
||||||
|
.INJECT("NO")
|
||||||
|
) ccu2c_i (
|
||||||
|
.A0(1'b1), .B0(1'b1), .C0(1'b1), .D0(1'b1),
|
||||||
|
.A1(CI), .B1(1'b1), .C1(1'b1), .D1(1'b1),
|
||||||
|
.COUT(FCO[0])
|
||||||
|
);
|
||||||
|
|
||||||
|
generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
|
||||||
|
CCU2 #(
|
||||||
|
.INIT0("0x96AA"),
|
||||||
|
.INIT1("0x96AA"),
|
||||||
|
.INJECT("NO")
|
||||||
|
) ccu2c_i (
|
||||||
|
.CIN(FCO[i]),
|
||||||
|
.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
|
||||||
|
.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
|
||||||
|
.S0(Y[i]), .S1(Y1[i]),
|
||||||
|
.COUT(FCO[i+2])
|
||||||
|
);
|
||||||
|
|
||||||
|
assign CO[i] = (AA[i] && BB[i]) || (((i == 0) ? CI : CO[i-1]) && (AA[i] || BB[i]));
|
||||||
|
if (i+1 < Y_WIDTH) begin
|
||||||
|
assign CO[i+1] = (AA[i+1] && BB[i+1]) || (CO[i] && (AA[i+1] || BB[i+1]));
|
||||||
|
assign Y[i+1] = Y1[i];
|
||||||
|
end
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
assign X = AA ^ BB;
|
||||||
|
endmodule
|
|
@ -0,0 +1,60 @@
|
||||||
|
bram $__NX_PDP16K
|
||||||
|
init 1
|
||||||
|
|
||||||
|
abits 9 @a9d36
|
||||||
|
dbits 36 @a9d36
|
||||||
|
abits 10 @a10d18
|
||||||
|
dbits 18 @a10d18
|
||||||
|
abits 11 @a11d9
|
||||||
|
dbits 9 @a11d9
|
||||||
|
abits 12 @a12d4
|
||||||
|
dbits 4 @a12d4
|
||||||
|
abits 13 @a13d2
|
||||||
|
dbits 2 @a13d2
|
||||||
|
abits 14 @a14d1
|
||||||
|
dbits 1 @a14d1
|
||||||
|
|
||||||
|
groups 2
|
||||||
|
ports 1 1
|
||||||
|
wrmode 1 0
|
||||||
|
enable 4 1 @a9d36
|
||||||
|
enable 2 1 @a10d18
|
||||||
|
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
|
||||||
|
transp 0 0
|
||||||
|
clocks 2 3
|
||||||
|
clkpol 2 3
|
||||||
|
endbram
|
||||||
|
|
||||||
|
match $__NX_PDP16K
|
||||||
|
# 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 2048
|
||||||
|
min efficiency 5
|
||||||
|
shuffle_enable A
|
||||||
|
or_next_if_better
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match $__NX_PDP16K
|
||||||
|
# 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
|
||||||
|
or_next_if_better
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match $__NX_PDP16K
|
||||||
|
# explicitly requested ROM
|
||||||
|
attribute syn_romstyle=ebr rom_block
|
||||||
|
attribute !syn_ramstyle
|
||||||
|
attribute !ram_block
|
||||||
|
attribute !logic_block
|
||||||
|
max wports 0
|
||||||
|
shuffle_enable A
|
||||||
|
endmatch
|
|
@ -0,0 +1,64 @@
|
||||||
|
.INITVAL_00($sformatf("0x%080x", permute_init(INIT[0 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_01($sformatf("0x%080x", permute_init(INIT[1 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_02($sformatf("0x%080x", permute_init(INIT[2 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_03($sformatf("0x%080x", permute_init(INIT[3 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_04($sformatf("0x%080x", permute_init(INIT[4 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_05($sformatf("0x%080x", permute_init(INIT[5 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_06($sformatf("0x%080x", permute_init(INIT[6 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_07($sformatf("0x%080x", permute_init(INIT[7 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_08($sformatf("0x%080x", permute_init(INIT[8 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_09($sformatf("0x%080x", permute_init(INIT[9 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0A($sformatf("0x%080x", permute_init(INIT[10 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0B($sformatf("0x%080x", permute_init(INIT[11 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0C($sformatf("0x%080x", permute_init(INIT[12 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0D($sformatf("0x%080x", permute_init(INIT[13 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0E($sformatf("0x%080x", permute_init(INIT[14 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_0F($sformatf("0x%080x", permute_init(INIT[15 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_10($sformatf("0x%080x", permute_init(INIT[16 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_11($sformatf("0x%080x", permute_init(INIT[17 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_12($sformatf("0x%080x", permute_init(INIT[18 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_13($sformatf("0x%080x", permute_init(INIT[19 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_14($sformatf("0x%080x", permute_init(INIT[20 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_15($sformatf("0x%080x", permute_init(INIT[21 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_16($sformatf("0x%080x", permute_init(INIT[22 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_17($sformatf("0x%080x", permute_init(INIT[23 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_18($sformatf("0x%080x", permute_init(INIT[24 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_19($sformatf("0x%080x", permute_init(INIT[25 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1A($sformatf("0x%080x", permute_init(INIT[26 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1B($sformatf("0x%080x", permute_init(INIT[27 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1C($sformatf("0x%080x", permute_init(INIT[28 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1D($sformatf("0x%080x", permute_init(INIT[29 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1E($sformatf("0x%080x", permute_init(INIT[30 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_1F($sformatf("0x%080x", permute_init(INIT[31 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_20($sformatf("0x%080x", permute_init(INIT[32 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_21($sformatf("0x%080x", permute_init(INIT[33 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_22($sformatf("0x%080x", permute_init(INIT[34 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_23($sformatf("0x%080x", permute_init(INIT[35 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_24($sformatf("0x%080x", permute_init(INIT[36 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_25($sformatf("0x%080x", permute_init(INIT[37 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_26($sformatf("0x%080x", permute_init(INIT[38 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_27($sformatf("0x%080x", permute_init(INIT[39 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_28($sformatf("0x%080x", permute_init(INIT[40 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_29($sformatf("0x%080x", permute_init(INIT[41 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2A($sformatf("0x%080x", permute_init(INIT[42 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2B($sformatf("0x%080x", permute_init(INIT[43 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2C($sformatf("0x%080x", permute_init(INIT[44 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2D($sformatf("0x%080x", permute_init(INIT[45 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2E($sformatf("0x%080x", permute_init(INIT[46 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_2F($sformatf("0x%080x", permute_init(INIT[47 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_30($sformatf("0x%080x", permute_init(INIT[48 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_31($sformatf("0x%080x", permute_init(INIT[49 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_32($sformatf("0x%080x", permute_init(INIT[50 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_33($sformatf("0x%080x", permute_init(INIT[51 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_34($sformatf("0x%080x", permute_init(INIT[52 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_35($sformatf("0x%080x", permute_init(INIT[53 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_36($sformatf("0x%080x", permute_init(INIT[54 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_37($sformatf("0x%080x", permute_init(INIT[55 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_38($sformatf("0x%080x", permute_init(INIT[56 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_39($sformatf("0x%080x", permute_init(INIT[57 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3A($sformatf("0x%080x", permute_init(INIT[58 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3B($sformatf("0x%080x", permute_init(INIT[59 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3C($sformatf("0x%080x", permute_init(INIT[60 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3D($sformatf("0x%080x", permute_init(INIT[61 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3E($sformatf("0x%080x", permute_init(INIT[62 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
|
||||||
|
.INITVAL_3F($sformatf("0x%080x", permute_init(INIT[63 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])))
|
|
@ -0,0 +1,115 @@
|
||||||
|
module \$__NX_PDP16K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
|
parameter CFG_ABITS = 9;
|
||||||
|
parameter CFG_DBITS = 36;
|
||||||
|
parameter CFG_ENABLE_A = 4;
|
||||||
|
|
||||||
|
parameter CLKPOL2 = 1;
|
||||||
|
parameter CLKPOL3 = 1;
|
||||||
|
parameter [18431:0] INIT = 18432'b0;
|
||||||
|
|
||||||
|
parameter _TECHMAP_BITS_CONNMAP_ = 8;
|
||||||
|
parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK2_ = 0;
|
||||||
|
parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK3_ = 0;
|
||||||
|
|
||||||
|
input CLK2;
|
||||||
|
input CLK3;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] A1ADDR;
|
||||||
|
input [CFG_DBITS-1:0] A1DATA;
|
||||||
|
input [CFG_ENABLE_A-1:0] A1EN;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] B1ADDR;
|
||||||
|
output [CFG_DBITS-1:0] B1DATA;
|
||||||
|
input B1EN;
|
||||||
|
|
||||||
|
// Address is left justified, in x18 and above lower bits are byte enables
|
||||||
|
localparam A_SHIFT =
|
||||||
|
(CFG_DBITS == 36) ? 5 :
|
||||||
|
(CFG_DBITS == 18) ? 4 :
|
||||||
|
(CFG_DBITS == 9) ? 3 :
|
||||||
|
(CFG_DBITS == 4) ? 2 :
|
||||||
|
(CFG_DBITS == 2) ? 1 :
|
||||||
|
0;
|
||||||
|
|
||||||
|
// Different primitives needed for single vs dual clock case
|
||||||
|
localparam SINGLE_CLOCK = (_TECHMAP_CONNMAP_CLK2_ == _TECHMAP_CONNMAP_CLK3_);
|
||||||
|
|
||||||
|
localparam WIDTH = $sformatf("X%d", CFG_DBITS);
|
||||||
|
|
||||||
|
wire [13:0] ra, wa;
|
||||||
|
wire [35:0] rd, wd;
|
||||||
|
|
||||||
|
assign ra = {B1ADDR, {A_SHIFT{1'b1}}};
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (CFG_ENABLE_A > 1)
|
||||||
|
assign wa = {A1ADDR, {(A_SHIFT-CFG_ENABLE_A){1'b1}}, A1EN};
|
||||||
|
else
|
||||||
|
assign wa = {A1ADDR, {A_SHIFT{1'b1}}};
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign wd = A1DATA;
|
||||||
|
assign B1DATA = rd[CFG_DBITS-1:0];
|
||||||
|
|
||||||
|
wire wck, rck;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (CLKPOL2)
|
||||||
|
assign wck = CLK2;
|
||||||
|
else
|
||||||
|
INV wck_inv_i (.A(CLK2), .Z(wck));
|
||||||
|
if (CLKPOL3)
|
||||||
|
assign rck = CLK3;
|
||||||
|
else
|
||||||
|
INV wck_inv_i (.A(CLK3), .Z(rck));
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
wire we = |A1EN;
|
||||||
|
|
||||||
|
localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 4) ? 256 : 288;
|
||||||
|
|
||||||
|
function [319:0] permute_init;
|
||||||
|
input [INIT_CHUNK_SIZE-1:0] chunk;
|
||||||
|
integer i;
|
||||||
|
begin
|
||||||
|
if (CFG_DBITS <= 4) begin
|
||||||
|
for (i = 0; i < 32; i = i + 1'b1)
|
||||||
|
permute_init[i * 10 +: 10] = {2'b00, chunk[i * 8 +: 8]};
|
||||||
|
end else begin
|
||||||
|
for (i = 0; i < 32; i = i + 1'b1)
|
||||||
|
permute_init[i * 10 +: 10] = {1'b0, chunk[i * 9 +: 9]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (SINGLE_CLOCK) begin
|
||||||
|
PDPSC16K #(
|
||||||
|
.DATA_WIDTH_W(WIDTH),
|
||||||
|
.DATA_WIDTH_R(WIDTH),
|
||||||
|
.OUTREG("BYPASSED"),
|
||||||
|
.ECC("DISABLED"),
|
||||||
|
.GSR("DISABLED"),
|
||||||
|
`include "brams_init.vh"
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.CLK(wck), .RST(1'b0),
|
||||||
|
.DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
|
||||||
|
.ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
|
||||||
|
);
|
||||||
|
end else begin
|
||||||
|
PDP16K #(
|
||||||
|
.DATA_WIDTH_W(WIDTH),
|
||||||
|
.DATA_WIDTH_R(WIDTH),
|
||||||
|
.OUTREG("BYPASSED"),
|
||||||
|
.ECC("DISABLED"),
|
||||||
|
.GSR("DISABLED"),
|
||||||
|
`include "brams_init.vh"
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.CLKW(wck), .CLKR(rck), .RST(1'b0),
|
||||||
|
.DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
|
||||||
|
.ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Flipflop intermediate map level
|
||||||
|
module \$__FF_NOLSR (input D, C, E, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
generate
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||||
|
FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(1'b0), .Q(Q));
|
||||||
|
else
|
||||||
|
FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(1'b0), .Q(Q));
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__FF_SYNCLSR (input D, C, E, R, output Q);
|
||||||
|
parameter SR_VAL = 1'b0;
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
wire Ci, Ei, Ri, Rg, Dd;
|
||||||
|
generate
|
||||||
|
if (SR_VAL)
|
||||||
|
FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
|
||||||
|
else
|
||||||
|
FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__FF_ASYNCLSR (input D, C, E, R, output Q);
|
||||||
|
parameter SR_VAL = 1'b0;
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = (_TECHMAP_WIREINIT_Q_ === 1'bx || _TECHMAP_WIREINIT_Q_ === SR_VAL);
|
||||||
|
wire Ci, Ei, Ri, Rg, Dd;
|
||||||
|
generate
|
||||||
|
if (SR_VAL)
|
||||||
|
FD1P3BX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
|
||||||
|
else
|
||||||
|
FD1P3DX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module \$_DFF_P_ (input D, C, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(1'b1), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_PP_ (input D, C, E, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(E), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_SDFF_PP0_ (input D, C, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
|
||||||
|
module \$_SDFF_PP1_ (input D, C, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
|
||||||
|
module \$_DFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
|
||||||
|
module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$__NX_TINOUTPAD (input I, OE, output O, inout B);
|
||||||
|
BB _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .B(B));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__NX_TOUTPAD (input I, OE, output O);
|
||||||
|
OBZ _TECHMAP_REPLACE_ (.I(I), .O(), .T(~OE), .O(O));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`ifndef NO_LUT
|
||||||
|
module \$lut (A, Y);
|
||||||
|
parameter WIDTH = 0;
|
||||||
|
parameter LUT = 0;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A;
|
||||||
|
output Y;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (WIDTH == 1) begin
|
||||||
|
if (LUT == 2'b01)
|
||||||
|
INV _TECHMAP_REPLACE_ (.A(A[0]), .Z(Y));
|
||||||
|
else
|
||||||
|
LUT4 #(.INIT($sformatf("0x%04x", {{8{LUT[1]}}, {8{LUT[0]}}}))) _TECHMAP_REPLACE_ (.Z(Y),
|
||||||
|
.D(A[0]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 2) begin
|
||||||
|
localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}};
|
||||||
|
LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
|
||||||
|
.C(A[0]), .D(A[1]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 3) begin
|
||||||
|
localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}};
|
||||||
|
LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
|
||||||
|
.B(A[0]), .C(A[1]), .D(A[2]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 4) begin
|
||||||
|
LUT4 #(.INIT($sformatf("0x%04x", LUT))) _TECHMAP_REPLACE_ (.Z(Y),
|
||||||
|
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 5) begin
|
||||||
|
WIDEFN9 #(
|
||||||
|
.INIT0($sformatf("0x%04x", LUT[15:0 ])),
|
||||||
|
.INIT1($sformatf("0x%04x", LUT[31:16])),
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.A0(A[0]), .B0(A[1]), .C0(A[2]), .D0(A[3]),
|
||||||
|
.A1(A[0]), .B1(A[1]), .C1(A[2]), .D1(A[3]),
|
||||||
|
.SEL(A[4]), .Z(Y)
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
`endif
|
|
@ -0,0 +1,379 @@
|
||||||
|
(* abc9_lut=1, lib_whitebox *)
|
||||||
|
module LUT4(input A, B, C, D, output Z);
|
||||||
|
parameter INIT = "0x0000";
|
||||||
|
`include "parse_init.vh"
|
||||||
|
localparam initp = parse_init(INIT);
|
||||||
|
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
|
||||||
|
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
|
||||||
|
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
|
||||||
|
assign Z = A ? s1[1] : s1[0];
|
||||||
|
|
||||||
|
// Per-input delay differences are considered 'interconnect'
|
||||||
|
// so not known yet
|
||||||
|
specify
|
||||||
|
(A => Z) = 233;
|
||||||
|
(B => Z) = 233;
|
||||||
|
(C => Z) = 233;
|
||||||
|
(D => Z) = 233;
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// This is a placeholder for ABC9 to extract the area/delay
|
||||||
|
// cost of 5-input LUTs and is not intended to be instantiated
|
||||||
|
(* abc9_lut=2 *)
|
||||||
|
module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
|
||||||
|
specify
|
||||||
|
(SEL => Z) = 171;
|
||||||
|
(D => Z) = 303;
|
||||||
|
(C => Z) = 311;
|
||||||
|
(B => Z) = 309;
|
||||||
|
(A => Z) = 306;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Two LUT4s and MUX2
|
||||||
|
module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
|
||||||
|
parameter INIT0 = "0x0000";
|
||||||
|
parameter INIT1 = "0x0000";
|
||||||
|
wire z0, z1;
|
||||||
|
LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
|
||||||
|
LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
|
||||||
|
assign Z = SEL ? z1 : z0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_box, lib_whitebox *)
|
||||||
|
module INV(input A, output Z);
|
||||||
|
assign Z = !A;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(A => Z) = 10;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Bidirectional IO buffer
|
||||||
|
module BB(input T, I, output O,
|
||||||
|
(* iopad_external_pin *) inout B);
|
||||||
|
assign B = T ? 1'bz : O;
|
||||||
|
assign I = B;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Input buffer
|
||||||
|
module IB(
|
||||||
|
(* iopad_external_pin *) input I,
|
||||||
|
output O);
|
||||||
|
assign O = I;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Output buffer
|
||||||
|
module OB(input I,
|
||||||
|
(* iopad_external_pin *) output O);
|
||||||
|
assign O = I;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Output buffer with tristate
|
||||||
|
module OBZ(input I, T,
|
||||||
|
(* iopad_external_pin *) output O);
|
||||||
|
assign O = T ? 1'bz : I;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
module VLO(output Z);
|
||||||
|
assign Z = 1'b0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module VHI(output Z);
|
||||||
|
assign Z = 1'b1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Vendor flipflops
|
||||||
|
// (all have active high clock, enable and set/reset - use INV to invert)
|
||||||
|
|
||||||
|
// Async preset
|
||||||
|
(* abc9_box, lib_whitebox *)
|
||||||
|
module FD1P3BX(input D, CK, SP, PD, output reg Q);
|
||||||
|
parameter GSR = "DISABLED";
|
||||||
|
initial Q = 1'b1;
|
||||||
|
always @(posedge CK or posedge PD)
|
||||||
|
if (PD)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (SP)
|
||||||
|
Q <= D;
|
||||||
|
specify
|
||||||
|
$setup(D, posedge CK, 0);
|
||||||
|
$setup(SP, posedge CK, 212);
|
||||||
|
$setup(PD, posedge CK, 224);
|
||||||
|
`ifndef YOSYS
|
||||||
|
if (PD) (posedge CLK => (Q : 1)) = 0;
|
||||||
|
`else
|
||||||
|
if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
|
||||||
|
// but for facilitating a bypass box, let's pretend it's
|
||||||
|
// a simple path
|
||||||
|
`endif
|
||||||
|
if (!PD && SP) (posedge CK => (Q : D)) = 336;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Async clear
|
||||||
|
(* abc9_box, lib_whitebox *)
|
||||||
|
module FD1P3DX(input D, CK, SP, CD, output reg Q);
|
||||||
|
parameter GSR = "DISABLED";
|
||||||
|
initial Q = 1'b0;
|
||||||
|
always @(posedge CK or posedge CD)
|
||||||
|
if (CD)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (SP)
|
||||||
|
Q <= D;
|
||||||
|
specify
|
||||||
|
$setup(D, posedge CK, 0);
|
||||||
|
$setup(SP, posedge CK, 212);
|
||||||
|
$setup(CD, posedge CK, 224);
|
||||||
|
`ifndef YOSYS
|
||||||
|
if (CD) (posedge CLK => (Q : 0)) = 0;
|
||||||
|
`else
|
||||||
|
if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
|
||||||
|
// but for facilitating a bypass box, let's pretend it's
|
||||||
|
// a simple path
|
||||||
|
`endif
|
||||||
|
if (!CD && SP) (posedge CK => (Q : D)) = 336;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Sync clear
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module FD1P3IX(input D, CK, SP, CD, output reg Q);
|
||||||
|
parameter GSR = "DISABLED";
|
||||||
|
initial Q = 1'b0;
|
||||||
|
always @(posedge CK)
|
||||||
|
if (CD)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (SP)
|
||||||
|
Q <= D;
|
||||||
|
specify
|
||||||
|
$setup(D, posedge CK, 0);
|
||||||
|
$setup(SP, posedge CK, 212);
|
||||||
|
$setup(CD, posedge CK, 224);
|
||||||
|
if (!CD && SP) (posedge CK => (Q : D)) = 336;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Sync preset
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module FD1P3JX(input D, CK, SP, PD, output reg Q);
|
||||||
|
parameter GSR = "DISABLED";
|
||||||
|
initial Q = 1'b1;
|
||||||
|
always @(posedge CK)
|
||||||
|
if (PD)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (SP)
|
||||||
|
Q <= D;
|
||||||
|
specify
|
||||||
|
$setup(D, posedge CK, 0);
|
||||||
|
$setup(SP, posedge CK, 212);
|
||||||
|
$setup(PD, posedge CK, 224);
|
||||||
|
if (!PD && SP) (posedge CK => (Q : D)) = 336;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// LUT4 with LUT3 tap for CCU2 use only
|
||||||
|
(* lib_whitebox *)
|
||||||
|
module LUT4_3(input A, B, C, D, output Z, Z3);
|
||||||
|
parameter INIT = "0x0000";
|
||||||
|
`include "parse_init.vh"
|
||||||
|
localparam initp = parse_init(INIT);
|
||||||
|
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
|
||||||
|
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
|
||||||
|
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
|
||||||
|
assign Z = A ? s1[1] : s1[0];
|
||||||
|
|
||||||
|
wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
|
||||||
|
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
|
||||||
|
assign Z3 = A ? s1_3[1] : s1_3[0];
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Carry primitive (incoporating two LUTs)
|
||||||
|
(* abc9_box, lib_whitebox *)
|
||||||
|
module CCU2(
|
||||||
|
(* abc9_carry *) input CIN,
|
||||||
|
input A1, B1, C1, D1, A0, B0, C0, D0,
|
||||||
|
output S1, S0,
|
||||||
|
(* abc9_carry *) output COUT);
|
||||||
|
parameter INJECT = "YES";
|
||||||
|
parameter INIT0 = "0x0000";
|
||||||
|
parameter INIT1 = "0x1111";
|
||||||
|
|
||||||
|
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
|
||||||
|
|
||||||
|
wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
|
||||||
|
LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
|
||||||
|
LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
|
||||||
|
|
||||||
|
assign S0 = LUT4_0 ^ (CIN & ~inject_p);
|
||||||
|
assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
|
||||||
|
assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
|
||||||
|
assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
|
||||||
|
|
||||||
|
specify
|
||||||
|
(A0 => S0) = 233;
|
||||||
|
(B0 => S0) = 233;
|
||||||
|
(C0 => S0) = 233;
|
||||||
|
(D0 => S0) = 233;
|
||||||
|
(CIN => S0) = 228;
|
||||||
|
(A0 => S1) = 481;
|
||||||
|
(B0 => S1) = 481;
|
||||||
|
(C0 => S1) = 481;
|
||||||
|
(D0 => S1) = 481;
|
||||||
|
(A1 => S1) = 233;
|
||||||
|
(B1 => S1) = 233;
|
||||||
|
(C1 => S1) = 233;
|
||||||
|
(D1 => S1) = 233;
|
||||||
|
(CIN => S1) = 307;
|
||||||
|
(A0 => COUT) = 347;
|
||||||
|
(B0 => COUT) = 347;
|
||||||
|
(C0 => COUT) = 347;
|
||||||
|
(D0 => COUT) = 347;
|
||||||
|
(A1 => COUT) = 347;
|
||||||
|
(B1 => COUT) = 347;
|
||||||
|
(C1 => COUT) = 347;
|
||||||
|
(D1 => COUT) = 347;
|
||||||
|
(CIN => COUT) = 59;
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Packed flipflop
|
||||||
|
module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
parameter [127:0] CEMUX = "1";
|
||||||
|
parameter CLKMUX = "CLK";
|
||||||
|
parameter LSRMUX = "LSR";
|
||||||
|
parameter REGDDR = "DISABLED";
|
||||||
|
parameter SRMODE = "LSR_OVER_CE";
|
||||||
|
parameter REGSET = "RESET";
|
||||||
|
parameter [127:0] LSRMODE = "LSR";
|
||||||
|
|
||||||
|
wire muxce;
|
||||||
|
generate
|
||||||
|
case (CEMUX)
|
||||||
|
"1": assign muxce = 1'b1;
|
||||||
|
"0": assign muxce = 1'b0;
|
||||||
|
"INV": assign muxce = ~CE;
|
||||||
|
default: assign muxce = CE;
|
||||||
|
endcase
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
|
||||||
|
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
|
||||||
|
wire srval;
|
||||||
|
generate
|
||||||
|
if (LSRMODE == "PRLD")
|
||||||
|
assign srval = M;
|
||||||
|
else
|
||||||
|
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
initial Q = srval;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (REGDDR == "ENABLED") begin
|
||||||
|
if (SRMODE == "ASYNC") begin
|
||||||
|
always @(posedge muxclk, negedge muxclk, posedge muxlsr)
|
||||||
|
if (muxlsr)
|
||||||
|
Q <= srval;
|
||||||
|
else if (muxce)
|
||||||
|
Q <= DI;
|
||||||
|
end else begin
|
||||||
|
always @(posedge muxclk, negedge muxclk)
|
||||||
|
if (muxlsr)
|
||||||
|
Q <= srval;
|
||||||
|
else if (muxce)
|
||||||
|
Q <= DI;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
if (SRMODE == "ASYNC") begin
|
||||||
|
always @(posedge muxclk, posedge muxlsr)
|
||||||
|
if (muxlsr)
|
||||||
|
Q <= srval;
|
||||||
|
else if (muxce)
|
||||||
|
Q <= DI;
|
||||||
|
end else begin
|
||||||
|
always @(posedge muxclk)
|
||||||
|
if (muxlsr)
|
||||||
|
Q <= srval;
|
||||||
|
else if (muxce)
|
||||||
|
Q <= DI;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Packed combinational logic (for post-pnr sim)
|
||||||
|
module OXIDE_COMB(
|
||||||
|
input A, B, C, D, // LUT inputs
|
||||||
|
input SEL, // mux select input
|
||||||
|
input F1, // output from LUT 1 for mux
|
||||||
|
input FCI, // carry input
|
||||||
|
input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
|
||||||
|
input WD, // LUTRAM write data input
|
||||||
|
input WCK, WRE, // LUTRAM write clock and enable
|
||||||
|
output F, // LUT/carry output
|
||||||
|
output OFX // mux output
|
||||||
|
);
|
||||||
|
parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
|
||||||
|
parameter [15:0] INIT = 16'h0000;
|
||||||
|
parameter INJECT = "YES";
|
||||||
|
|
||||||
|
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
|
||||||
|
|
||||||
|
reg [15:0] lut = INIT;
|
||||||
|
|
||||||
|
wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
|
||||||
|
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
|
||||||
|
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
|
||||||
|
wire Z = A ? s1[1] : s1[0];
|
||||||
|
|
||||||
|
wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
|
||||||
|
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
|
||||||
|
wire Z3 = A ? s1_3[1] : s1_3[0];
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (MODE == "DPRAM") begin
|
||||||
|
always @(posedge WCK)
|
||||||
|
if (WRE)
|
||||||
|
lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
|
||||||
|
end
|
||||||
|
if (MODE == "CCU2") begin
|
||||||
|
assign F = Z ^ (FCI & ~inject_p);
|
||||||
|
assign FCO = Z ? FCI : (Z3 & ~inject_p);
|
||||||
|
end else begin
|
||||||
|
assign F = Z;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign OFX = SEL ? F1 : F;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// LUTRAM
|
||||||
|
module DPR16X4(
|
||||||
|
input [3:0] RAD, DI, WAD,
|
||||||
|
input WRE, WCK,
|
||||||
|
output [3:0] DO
|
||||||
|
);
|
||||||
|
parameter INITVAL = "0x0000000000000000";
|
||||||
|
`include "parse_init.vh"
|
||||||
|
localparam [63:0] parsed_init = parse_init_64(INITVAL);
|
||||||
|
|
||||||
|
reg [3:0] mem[0:15];
|
||||||
|
integer i;
|
||||||
|
initial begin
|
||||||
|
for (i = 0; i < 15; i++)
|
||||||
|
mem[i] = parsed_init[i * 4 +: 4];
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge WCK)
|
||||||
|
if (WRE)
|
||||||
|
mem[WAD] <= DI;
|
||||||
|
assign DO = mem[RAD];
|
||||||
|
endmodule
|
|
@ -0,0 +1,286 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Based on Xilinx cells_xtra.py; modified for Radiant's structure
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from io import StringIO
|
||||||
|
from enum import Enum, auto
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class Cell:
|
||||||
|
def __init__(self, name, keep=False, port_attrs={}):
|
||||||
|
self.name = name
|
||||||
|
self.keep = keep
|
||||||
|
self.port_attrs = port_attrs
|
||||||
|
self.found = False
|
||||||
|
|
||||||
|
class State(Enum):
|
||||||
|
OUTSIDE = auto()
|
||||||
|
IN_MODULE = auto()
|
||||||
|
IN_OTHER_MODULE = auto()
|
||||||
|
IN_FUNCTION = auto()
|
||||||
|
IN_TASK = auto()
|
||||||
|
|
||||||
|
devices = [
|
||||||
|
("lifcl", [
|
||||||
|
Cell("ACC54"),
|
||||||
|
Cell("ADC"),
|
||||||
|
Cell("ALUREG"),
|
||||||
|
Cell("BB_ADC", keep=True),
|
||||||
|
Cell("BB_CDR", keep=True),
|
||||||
|
Cell("BB_I3C_A", keep=True),
|
||||||
|
Cell("BFD1P3KX"),
|
||||||
|
Cell("BFD1P3LX"),
|
||||||
|
Cell("BNKREF18", keep=True),
|
||||||
|
Cell("CONFIG_LMMI", keep=True),
|
||||||
|
Cell("DCC"),
|
||||||
|
Cell("DCS"),
|
||||||
|
Cell("DDRDLL"),
|
||||||
|
Cell("DELAYA"),
|
||||||
|
Cell("DELAYB"),
|
||||||
|
Cell("DIFFIO18", keep=True),
|
||||||
|
Cell("DLLDEL"),
|
||||||
|
Cell("DP16K_MODE"),
|
||||||
|
Cell("DP16K"),
|
||||||
|
Cell("DPHY", keep=True),
|
||||||
|
Cell("DPSC512K"),
|
||||||
|
Cell("DQSBUF"),
|
||||||
|
Cell("EBR_CORE"),
|
||||||
|
Cell("EBR"),
|
||||||
|
Cell("ECLKDIV"),
|
||||||
|
Cell("ECLKSYNC"),
|
||||||
|
Cell("FBMUX"),
|
||||||
|
Cell("FIFO16K_MODE"),
|
||||||
|
Cell("FIFO16K"),
|
||||||
|
Cell("GSR"),
|
||||||
|
Cell("HSE"),
|
||||||
|
Cell("I2CFIFO"),
|
||||||
|
Cell("IDDR71"),
|
||||||
|
Cell("IDDRX1"),
|
||||||
|
Cell("IDDRX2DQ"),
|
||||||
|
Cell("IDDRX2"),
|
||||||
|
Cell("IDDRX4DQ"),
|
||||||
|
Cell("IDDRX4"),
|
||||||
|
Cell("IDDRX5"),
|
||||||
|
Cell("IFD1P3BX"),
|
||||||
|
Cell("IFD1P3DX"),
|
||||||
|
Cell("IFD1P3IX"),
|
||||||
|
Cell("IFD1P3JX"),
|
||||||
|
Cell("JTAG", keep=True),
|
||||||
|
Cell("LRAM"),
|
||||||
|
Cell("M18X36"),
|
||||||
|
Cell("MIPI"),
|
||||||
|
Cell("MULT18"),
|
||||||
|
Cell("MULT18X18"),
|
||||||
|
Cell("MULT18X36"),
|
||||||
|
Cell("MULT36"),
|
||||||
|
Cell("MULT36X36"),
|
||||||
|
Cell("MULT9"),
|
||||||
|
Cell("MULT9X9"),
|
||||||
|
Cell("MULTADDSUB18X18"),
|
||||||
|
Cell("MULTADDSUB18X18WIDE"),
|
||||||
|
Cell("MULTADDSUB18X36"),
|
||||||
|
Cell("MULTADDSUB36X36"),
|
||||||
|
Cell("MULTADDSUB9X9WIDE"),
|
||||||
|
Cell("MULTIBOOT", keep=True),
|
||||||
|
Cell("MULTPREADD18X18"),
|
||||||
|
Cell("MULTPREADD9X9"),
|
||||||
|
Cell("ODDR71"),
|
||||||
|
Cell("ODDRX1"),
|
||||||
|
Cell("ODDRX2DQS"),
|
||||||
|
Cell("ODDRX2DQ"),
|
||||||
|
Cell("ODDRX2"),
|
||||||
|
Cell("ODDRX4DQS"),
|
||||||
|
Cell("ODDRX4DQ"),
|
||||||
|
Cell("ODDRX4"),
|
||||||
|
Cell("ODDRX5"),
|
||||||
|
Cell("OFD1P3BX"),
|
||||||
|
Cell("OFD1P3DX"),
|
||||||
|
Cell("OFD1P3IX"),
|
||||||
|
Cell("OFD1P3JX"),
|
||||||
|
Cell("OSC"),
|
||||||
|
Cell("OSCA"),
|
||||||
|
Cell("OSHX2"),
|
||||||
|
Cell("OSHX4"),
|
||||||
|
Cell("PCIE"),
|
||||||
|
Cell("PCLKDIV"),
|
||||||
|
Cell("PCLKDIVSP"),
|
||||||
|
Cell("PDP16K_MODE"),
|
||||||
|
Cell("PDP16K"),
|
||||||
|
Cell("PDPSC16K_MODE"),
|
||||||
|
Cell("PDPSC16K"),
|
||||||
|
Cell("PDPSC512K"),
|
||||||
|
Cell("PLL"),
|
||||||
|
Cell("PREADD9"),
|
||||||
|
Cell("PUR", keep=True),
|
||||||
|
Cell("REFMUX"),
|
||||||
|
Cell("REG18"),
|
||||||
|
Cell("SEDC", keep=True),
|
||||||
|
Cell("SEIO18"),
|
||||||
|
Cell("SEIO33"),
|
||||||
|
Cell("SGMIICDR"),
|
||||||
|
Cell("SP16K_MODE"),
|
||||||
|
Cell("SP16K"),
|
||||||
|
Cell("SP512K"),
|
||||||
|
Cell("TSALLA"),
|
||||||
|
Cell("TSHX2DQS"),
|
||||||
|
Cell("TSHX2DQ"),
|
||||||
|
Cell("TSHX4DQS"),
|
||||||
|
Cell("TSHX4DQ"),
|
||||||
|
Cell("WDT", keep=True),
|
||||||
|
|
||||||
|
Cell("ACC54_CORE"),
|
||||||
|
Cell("ADC_CORE"),
|
||||||
|
Cell("ALUREG_CORE"),
|
||||||
|
Cell("BNKREF18_CORE"),
|
||||||
|
Cell("BNKREF33_CORE"),
|
||||||
|
Cell("DIFFIO18_CORE"),
|
||||||
|
Cell("CONFIG_CLKRST_CORE", keep=True),
|
||||||
|
Cell("CONFIG_HSE_CORE", keep=True),
|
||||||
|
Cell("CONFIG_IP_CORE", keep=True),
|
||||||
|
Cell("CONFIG_JTAG_CORE", keep=True),
|
||||||
|
Cell("CONFIG_LMMI_CORE", keep=True),
|
||||||
|
Cell("CONFIG_MULTIBOOT_CORE", keep=True),
|
||||||
|
Cell("CONFIG_SEDC_CORE", keep=True),
|
||||||
|
Cell("CONFIG_WDT_CORE", keep=True),
|
||||||
|
Cell("DDRDLL_CORE"),
|
||||||
|
Cell("DLLDEL_CORE"),
|
||||||
|
Cell("DPHY_CORE"),
|
||||||
|
Cell("DQSBUF_CORE"),
|
||||||
|
Cell("ECLKDIV_CORE"),
|
||||||
|
Cell("ECLKSYNC_CORE"),
|
||||||
|
Cell("FBMUX_CORE"),
|
||||||
|
Cell("GSR_CORE"),
|
||||||
|
Cell("I2CFIFO_CORE"),
|
||||||
|
Cell("LRAM_CORE"),
|
||||||
|
Cell("MULT18_CORE"),
|
||||||
|
Cell("MULT18X36_CORE"),
|
||||||
|
Cell("MULT36_CORE"),
|
||||||
|
Cell("MULT9_CORE"),
|
||||||
|
Cell("OSC_CORE"),
|
||||||
|
Cell("PCIE_CORE"),
|
||||||
|
Cell("PLL_CORE"),
|
||||||
|
Cell("PREADD9_CORE"),
|
||||||
|
Cell("REFMUX_CORE"),
|
||||||
|
Cell("REG18_CORE"),
|
||||||
|
Cell("SEIO18_CORE"),
|
||||||
|
Cell("SEIO33_CORE"),
|
||||||
|
Cell("SGMIICDR_CORE"),
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
def xtract_cells_decl(device, cells, dirs, outf):
|
||||||
|
fname = os.path.join(dir, device + '.v')
|
||||||
|
with open(fname) as f:
|
||||||
|
state = State.OUTSIDE
|
||||||
|
# Probably the most horrible Verilog "parser" ever written.
|
||||||
|
cell = None
|
||||||
|
for l in f:
|
||||||
|
l, _, comment = l.partition('//')
|
||||||
|
l = l.strip()
|
||||||
|
if l.startswith("module "):
|
||||||
|
cell_name = l[7:l.find('(')].strip()
|
||||||
|
cell = None
|
||||||
|
module_ports = []
|
||||||
|
iopad_pin = set()
|
||||||
|
if state != State.OUTSIDE:
|
||||||
|
print('Nested modules in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
for c in cells:
|
||||||
|
if c.name != cell_name:
|
||||||
|
continue
|
||||||
|
cell = c
|
||||||
|
state = State.IN_MODULE
|
||||||
|
if cell.keep:
|
||||||
|
outf.write('(* keep *)\n')
|
||||||
|
outf.write('module {} (...);\n'.format(cell.name))
|
||||||
|
cell.found = True
|
||||||
|
|
||||||
|
m = re.search(r'synthesis .*black_box_pad_pin="([^"]*)"', comment)
|
||||||
|
if m:
|
||||||
|
iopad_pin = set(m.group(1).split(","))
|
||||||
|
|
||||||
|
if cell is None:
|
||||||
|
state = State.IN_OTHER_MODULE
|
||||||
|
elif l.startswith('task '):
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
state = State.IN_TASK
|
||||||
|
elif l.startswith('function '):
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
state = State.IN_FUNCTION
|
||||||
|
elif l == 'endtask':
|
||||||
|
if state == State.IN_TASK:
|
||||||
|
state = State.IN_MODULE
|
||||||
|
elif l == 'endfunction':
|
||||||
|
if state == State.IN_FUNCTION:
|
||||||
|
state = State.IN_MODULE
|
||||||
|
elif l == 'endmodule':
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
for kind, rng, port in module_ports:
|
||||||
|
for attr in cell.port_attrs.get(port, []):
|
||||||
|
outf.write(' (* {} *)\n'.format(attr))
|
||||||
|
if port in iopad_pin:
|
||||||
|
outf.write(' (* iopad_external_pin *)\n')
|
||||||
|
if rng is None:
|
||||||
|
outf.write(' {} {};\n'.format(kind, port))
|
||||||
|
else:
|
||||||
|
outf.write(' {} {} {};\n'.format(kind, rng, port))
|
||||||
|
outf.write(l + '\n')
|
||||||
|
outf.write('\n')
|
||||||
|
elif state != State.IN_OTHER_MODULE:
|
||||||
|
print('endmodule in weird place in {}.'.format(cell.name, fname))
|
||||||
|
sys.exit(1)
|
||||||
|
state = State.OUTSIDE
|
||||||
|
elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
|
||||||
|
if l.endswith((';', ',')):
|
||||||
|
l = l[:-1]
|
||||||
|
if ';' in l:
|
||||||
|
print('Weird port line in {} [{}].'.format(fname, l))
|
||||||
|
sys.exit(1)
|
||||||
|
kind, _, ports = l.partition(' ')
|
||||||
|
for port in ports.split(','):
|
||||||
|
port = port.strip()
|
||||||
|
if port.startswith('['):
|
||||||
|
rng, port = port.split()
|
||||||
|
else:
|
||||||
|
rng = None
|
||||||
|
module_ports.append((kind, rng, port))
|
||||||
|
elif l.startswith('parameter ') and state == State.IN_MODULE:
|
||||||
|
if l.endswith((';', ',')):
|
||||||
|
l = l[:-1]
|
||||||
|
while ' ' in l:
|
||||||
|
l = l.replace(' ', ' ')
|
||||||
|
if ';' in l:
|
||||||
|
print('Weird parameter line in {} [{}].'.format(fname, l))
|
||||||
|
sys.exit(1)
|
||||||
|
outf.write(' {};\n'.format(l))
|
||||||
|
|
||||||
|
if state != State.OUTSIDE:
|
||||||
|
print('endmodule not found in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
for cell in cells:
|
||||||
|
if not cell.found:
|
||||||
|
print('cell {} not found in {}.'.format(cell.name, fname))
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = ArgumentParser(description='Extract Lattice blackbox cell definitions from Radiant.')
|
||||||
|
parser.add_argument('radiant_dir', nargs='?', default='/opt/lscc/radiant/2.0/')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
dirs = [
|
||||||
|
os.path.join(args.radiant_dir, 'cae_library/synthesis/verilog/'),
|
||||||
|
]
|
||||||
|
for dir in dirs:
|
||||||
|
if not os.path.isdir(dir):
|
||||||
|
print('{} is not a directory'.format(dir))
|
||||||
|
|
||||||
|
out = StringIO()
|
||||||
|
for device, cells in devices:
|
||||||
|
xtract_cells_decl(device, cells, dirs, out)
|
||||||
|
|
||||||
|
with open('cells_xtra.v', 'w') as f:
|
||||||
|
f.write('// Created by cells_xtra.py from Lattice models\n')
|
||||||
|
f.write('\n')
|
||||||
|
f.write(out.getvalue())
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
||||||
|
module \$_DLATCH_N_ (E, D, Q);
|
||||||
|
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||||
|
input E, D;
|
||||||
|
output Q = !E ? D : Q;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DLATCH_P_ (E, D, Q);
|
||||||
|
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||||
|
input E, D;
|
||||||
|
output Q = E ? D : Q;
|
||||||
|
endmodule
|
|
@ -0,0 +1,26 @@
|
||||||
|
bram $__NEXUS_DPR16X4
|
||||||
|
init 1
|
||||||
|
abits 4
|
||||||
|
dbits 4
|
||||||
|
groups 2
|
||||||
|
ports 1 1
|
||||||
|
wrmode 0 1
|
||||||
|
enable 0 1
|
||||||
|
transp 0 0
|
||||||
|
clocks 0 1
|
||||||
|
clkpol 0 2
|
||||||
|
endbram
|
||||||
|
|
||||||
|
# The syn_* attributes are described in:
|
||||||
|
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
|
||||||
|
attr_icase 1
|
||||||
|
|
||||||
|
match $__NEXUS_DPR16X4
|
||||||
|
attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed
|
||||||
|
attribute !syn_romstyle syn_romstyle=auto
|
||||||
|
attribute !ram_block
|
||||||
|
attribute !rom_block
|
||||||
|
attribute !logic_block
|
||||||
|
make_outreg
|
||||||
|
min wports 1
|
||||||
|
endmatch
|
|
@ -0,0 +1,34 @@
|
||||||
|
module \$__NEXUS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||||
|
parameter [63:0] INIT = 64'b0;
|
||||||
|
parameter CLKPOL2 = 1;
|
||||||
|
input CLK1;
|
||||||
|
|
||||||
|
input [3:0] A1ADDR;
|
||||||
|
output [3:0] A1DATA;
|
||||||
|
|
||||||
|
input [3:0] B1ADDR;
|
||||||
|
input [3:0] B1DATA;
|
||||||
|
input B1EN;
|
||||||
|
|
||||||
|
|
||||||
|
wire wck;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (CLKPOL2)
|
||||||
|
assign wck = CLK1;
|
||||||
|
else
|
||||||
|
INV wck_inv_i (.A(CLK1), .Z(wck));
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
DPR16X4 #(
|
||||||
|
.INITVAL($sformatf("0x%08x", INIT))
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.RAD(A1ADDR),
|
||||||
|
.DO(A1DATA),
|
||||||
|
|
||||||
|
.WAD(B1ADDR),
|
||||||
|
.DI(B1DATA),
|
||||||
|
.WCK(CLK1),
|
||||||
|
.WRE(B1EN)
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -0,0 +1,33 @@
|
||||||
|
function [15:0] parse_init;
|
||||||
|
input [((2+(16/4))*8)-1:0] init;
|
||||||
|
reg [7:0] c;
|
||||||
|
integer i;
|
||||||
|
begin
|
||||||
|
for (i = 0; i < (16/4); i = i + 1) begin
|
||||||
|
c = init[(i * 8) +: 8];
|
||||||
|
if (c >= "0" && c <= "9")
|
||||||
|
parse_init[(i * 4) +: 4] = (c - "0");
|
||||||
|
else if (c >= "A" && c <= "F")
|
||||||
|
parse_init[(i * 4) +: 4] = (c - "A") + 10;
|
||||||
|
else if (c >= "a" && c <= "f")
|
||||||
|
parse_init[(i * 4) +: 4] = (c - "a") + 10;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function [63:0] parse_init_64;
|
||||||
|
input [((2+(64/4))*8)-1:0] init;
|
||||||
|
reg [7:0] c;
|
||||||
|
integer i;
|
||||||
|
begin
|
||||||
|
for (i = 0; i < (64/4); i = i + 1) begin
|
||||||
|
c = init[(i * 8) +: 8];
|
||||||
|
if (c >= "0" && c <= "9")
|
||||||
|
parse_init_64[(i * 4) +: 4] = (c - "0");
|
||||||
|
else if (c >= "A" && c <= "F")
|
||||||
|
parse_init_64[(i * 4) +: 4] = (c - "A") + 10;
|
||||||
|
else if (c >= "a" && c <= "f")
|
||||||
|
parse_init_64[(i * 4) +: 4] = (c - "a") + 10;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endfunction
|
|
@ -0,0 +1,372 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 David Shah <dave@ds0.me>
|
||||||
|
*
|
||||||
|
* 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 SynthNexusPass : public ScriptPass
|
||||||
|
{
|
||||||
|
SynthNexusPass() : ScriptPass("synth_nexus", "synthesis for Lattice Nexus FPGAs") { }
|
||||||
|
|
||||||
|
void on_register() override
|
||||||
|
{
|
||||||
|
RTLIL::constpad["synth_nexus.abc9.W"] = "300";
|
||||||
|
}
|
||||||
|
|
||||||
|
void help() override
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" synth_nexus [options]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command runs synthesis for Lattice Nexus FPGAs.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -top <module>\n");
|
||||||
|
log(" use the specified module as top module\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -family <device>\n");
|
||||||
|
log(" run synthesis for the specified Nexus device\n");
|
||||||
|
log(" supported values: lifcl, lfd2nx\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -json <file>\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(" -vm <file>\n");
|
||||||
|
log(" write the design to the specified structural Verilog file. writing of\n");
|
||||||
|
log(" an output file is omitted if this parameter is not specified.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -run <from_label>:<to_label>\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(" -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(" -noccu2\n");
|
||||||
|
log(" do not use CCU2 cells in output netlist\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nodffe\n");
|
||||||
|
log(" do not use flipflops with CE in output netlist\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nobram\n");
|
||||||
|
log(" do not use block RAM cells in output netlist\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nolutram\n");
|
||||||
|
log(" do not use LUT RAM cells in output netlist\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nowidelut\n");
|
||||||
|
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noiopad\n");
|
||||||
|
log(" do not insert IO buffers\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -abc9\n");
|
||||||
|
log(" use new ABC9 flow (EXPERIMENTAL)\n");
|
||||||
|
log("\n");
|
||||||
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
help_script();
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string top_opt, json_file, vm_file, family;
|
||||||
|
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, flatten, dff, retime, abc9;
|
||||||
|
|
||||||
|
void clear_flags() override
|
||||||
|
{
|
||||||
|
top_opt = "-auto-top";
|
||||||
|
family = "lifcl";
|
||||||
|
json_file = "";
|
||||||
|
vm_file = "";
|
||||||
|
noccu2 = false;
|
||||||
|
nodffe = false;
|
||||||
|
nobram = false;
|
||||||
|
nolutram = false;
|
||||||
|
nowidelut = false;
|
||||||
|
noiopad = false;
|
||||||
|
flatten = true;
|
||||||
|
dff = false;
|
||||||
|
retime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> 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] == "-json" && argidx+1 < args.size()) {
|
||||||
|
json_file = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-vm" && argidx+1 < args.size()) {
|
||||||
|
vm_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] == "-family") && argidx+1 < args.size()) {
|
||||||
|
family = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-flatten") {
|
||||||
|
flatten = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noflatten") {
|
||||||
|
flatten = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-dff") {
|
||||||
|
dff = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-retime") {
|
||||||
|
retime = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noccu2") {
|
||||||
|
noccu2 = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nodffe") {
|
||||||
|
nodffe = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nobram") {
|
||||||
|
nobram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nolutram") {
|
||||||
|
nolutram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nowidelut") {
|
||||||
|
nowidelut = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noiopad") {
|
||||||
|
noiopad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-abc9") {
|
||||||
|
abc9 = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (!design->full_selection())
|
||||||
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
|
if (abc9 && retime)
|
||||||
|
log_cmd_error("-retime option not currently compatible with -abc9!\n");
|
||||||
|
|
||||||
|
log_header(design, "Executing SYNTH_NEXUS pass.\n");
|
||||||
|
log_push();
|
||||||
|
|
||||||
|
run_script(design, run_from, run_to);
|
||||||
|
|
||||||
|
log_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void script() override
|
||||||
|
{
|
||||||
|
|
||||||
|
if (family != "lifcl" && family != "lfd2nx")
|
||||||
|
log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family.c_str());
|
||||||
|
|
||||||
|
if (check_label("begin"))
|
||||||
|
{
|
||||||
|
run("read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v");
|
||||||
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("coarse"))
|
||||||
|
{
|
||||||
|
run("proc");
|
||||||
|
if (flatten || help_mode)
|
||||||
|
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");
|
||||||
|
|
||||||
|
run("alumacc");
|
||||||
|
run("opt");
|
||||||
|
run("memory -nomap");
|
||||||
|
run("opt_clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nobram && check_label("map_bram", "(skip if -nobram)"))
|
||||||
|
{
|
||||||
|
run("memory_bram -rules +/nexus/brams.txt");
|
||||||
|
run("setundef -zero -params t:$__NX_PDP16K");
|
||||||
|
run("techmap -map +/nexus/brams_map.v");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
|
||||||
|
{
|
||||||
|
run("memory_bram -rules +/nexus/lutrams.txt");
|
||||||
|
run("setundef -zero -params t:$__NEXUS_DPR16X4");
|
||||||
|
run("techmap -map +/nexus/lutrams_map.v");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffram"))
|
||||||
|
{
|
||||||
|
run("opt -fast -mux_undef -undriven -fine");
|
||||||
|
run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
|
||||||
|
"-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
|
||||||
|
"-attr syn_romstyle=auto -attr syn_romstyle=logic");
|
||||||
|
run("opt -undriven -fine");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_gates"))
|
||||||
|
{
|
||||||
|
if (noccu2)
|
||||||
|
run("techmap");
|
||||||
|
else
|
||||||
|
run("techmap -map +/techmap.v -map +/nexus/arith_map.v");
|
||||||
|
if (help_mode || !noiopad)
|
||||||
|
run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad $__NX_TOUTPAD OE:I:O -tinoutpad $__NX_TINOUTPAD OE:O:I:B A:top", "(skip if '-noiopad')");
|
||||||
|
run("opt -fast");
|
||||||
|
if (retime || help_mode)
|
||||||
|
run("abc -dff -D 1", "(only if -retime)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffs"))
|
||||||
|
{
|
||||||
|
run("opt_clean");
|
||||||
|
std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x";
|
||||||
|
if (help_mode) {
|
||||||
|
dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]";
|
||||||
|
} else if (!nodffe) {
|
||||||
|
dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r";
|
||||||
|
}
|
||||||
|
run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)");
|
||||||
|
if ((abc9 && dff) || help_mode)
|
||||||
|
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff");
|
||||||
|
run("techmap -D NO_LUT -map +/nexus/cells_map.v");
|
||||||
|
run("opt_expr -undriven -mux_undef");
|
||||||
|
run("simplemap");
|
||||||
|
run("attrmvcp -copy -attr syn_useioff");
|
||||||
|
run("opt_clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_luts"))
|
||||||
|
{
|
||||||
|
run("techmap -map +/nexus/latches_map.v");
|
||||||
|
|
||||||
|
if (abc9) {
|
||||||
|
std::string abc9_opts;
|
||||||
|
if (nowidelut)
|
||||||
|
abc9_opts += " -maxlut 4";
|
||||||
|
std::string k = "synth_nexus.abc9.W";
|
||||||
|
if (active_design && active_design->scratchpad.count(k))
|
||||||
|
abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
|
||||||
|
else
|
||||||
|
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
|
||||||
|
if (nowidelut)
|
||||||
|
abc9_opts += " -maxlut 4";
|
||||||
|
if (dff)
|
||||||
|
abc9_opts += " -dff";
|
||||||
|
run("abc9" + abc9_opts);
|
||||||
|
} else {
|
||||||
|
std::string abc_args = " -dress";
|
||||||
|
if (nowidelut)
|
||||||
|
abc_args += " -lut 4";
|
||||||
|
else
|
||||||
|
abc_args += " -lut 4:5";
|
||||||
|
if (dff)
|
||||||
|
abc_args += " -dff";
|
||||||
|
run("abc" + abc_args);
|
||||||
|
}
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_cells"))
|
||||||
|
{
|
||||||
|
run("techmap -map +/nexus/cells_map.v");
|
||||||
|
|
||||||
|
// This is needed for Radiant, but perhaps not optimal for nextpnr...
|
||||||
|
run("setundef -zero");
|
||||||
|
|
||||||
|
run("hilomap -singleton -hicell VHI Z -locell VLO Z");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("check"))
|
||||||
|
{
|
||||||
|
run("autoname");
|
||||||
|
run("hierarchy -check");
|
||||||
|
run("stat");
|
||||||
|
run("check -noinit");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("json"))
|
||||||
|
{
|
||||||
|
if (!json_file.empty() || help_mode)
|
||||||
|
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("vm"))
|
||||||
|
{
|
||||||
|
if (!vm_file.empty() || help_mode)
|
||||||
|
run(stringf("write_verilog %s", help_mode ? "<file-name>" : vm_file.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} SynthNexusPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,2 @@
|
||||||
|
/*.log
|
||||||
|
/run-test.mk
|
|
@ -0,0 +1,21 @@
|
||||||
|
read_verilog ../common/add_sub.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
design -save orig
|
||||||
|
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 10 t:LUT4
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:LUT4 %% t:* %D
|
||||||
|
|
||||||
|
design -load orig
|
||||||
|
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 6 t:LUT4
|
||||||
|
select -assert-count 4 t:WIDEFN9
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:LUT4 t:WIDEFN9 %% t:* %D
|
|
@ -0,0 +1,44 @@
|
||||||
|
read_verilog ../common/adffs.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top adff
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 1 t:FD1P3DX
|
||||||
|
select -assert-none t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top adffn
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 1 t:FD1P3DX
|
||||||
|
select -assert-count 1 t:INV
|
||||||
|
select -assert-none t:FD1P3DX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top dffs
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 1 t:FD1P3IX
|
||||||
|
select -assert-count 1 t:LUT4
|
||||||
|
select -assert-none t:FD1P3IX t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top ndffnr
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 1 t:FD1P3IX
|
||||||
|
select -assert-count 2 t:INV
|
||||||
|
select -assert-none t:FD1P3IX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,18 @@
|
||||||
|
read_verilog ../common/blockram.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
# Check that we use the right dual and single clock variants
|
||||||
|
|
||||||
|
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
|
||||||
|
synth_nexus -top sync_ram_sdp
|
||||||
|
cd sync_ram_sdp
|
||||||
|
select -assert-count 1 t:PDPSC16K
|
||||||
|
select -assert-none t:PDPSC16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog blockram_dc.v
|
||||||
|
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp_dc
|
||||||
|
synth_nexus -top sync_ram_sdp_dc
|
||||||
|
cd sync_ram_sdp_dc
|
||||||
|
select -assert-count 1 t:PDP16K
|
||||||
|
select -assert-none t:PDP16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
module sync_ram_sdp_dc #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
|
||||||
|
(input wire clkw, clkr, write_enable,
|
||||||
|
input wire [DATA_WIDTH-1:0] data_in,
|
||||||
|
input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w,
|
||||||
|
output wire [DATA_WIDTH-1:0] data_out);
|
||||||
|
|
||||||
|
localparam WORD = (DATA_WIDTH-1);
|
||||||
|
localparam DEPTH = (2**ADDRESS_WIDTH-1);
|
||||||
|
|
||||||
|
reg [WORD:0] data_out_r;
|
||||||
|
reg [WORD:0] memory [0:DEPTH];
|
||||||
|
|
||||||
|
always @(posedge clkw) begin
|
||||||
|
if (write_enable)
|
||||||
|
memory[address_in_w] <= data_in;
|
||||||
|
end
|
||||||
|
always @(posedge clkr) begin
|
||||||
|
data_out_r <= memory[address_in_r];
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_out = data_out_r;
|
||||||
|
|
||||||
|
endmodule // sync_ram_sdp_dc
|
|
@ -0,0 +1,11 @@
|
||||||
|
read_verilog ../common/counter.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
equiv_opt -assert -multiclock -map +/nexus/cells_sim.v synth_nexus # 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
|
||||||
|
stat
|
||||||
|
select -assert-count 5 t:CCU2
|
||||||
|
select -assert-count 8 t:FD1P3DX
|
||||||
|
select -assert-none t:CCU2 t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,19 @@
|
||||||
|
read_verilog ../common/dffs.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top dff
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
|
||||||
|
select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top dffe
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
|
||||||
|
select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D
|
|
@ -0,0 +1,19 @@
|
||||||
|
read_verilog ../common/fsm.v
|
||||||
|
hierarchy -top fsm
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
|
||||||
|
equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
|
||||||
|
miter -equiv -make_assert -flatten gold gate miter
|
||||||
|
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
|
||||||
|
|
||||||
|
stat
|
||||||
|
|
||||||
|
select -assert-max 1 t:INV
|
||||||
|
select -assert-max 2 t:LUT4
|
||||||
|
select -assert-max 6 t:WIDEFN9
|
||||||
|
select -assert-count 6 t:FD1P3IX
|
||||||
|
select -assert-none t:LUT4 t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,8 @@
|
||||||
|
read_verilog ../common/logic.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:LUT4
|
||||||
|
select -assert-none t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,19 @@
|
||||||
|
read_verilog ../common/lutram.v
|
||||||
|
hierarchy -top lutram_1w1r
|
||||||
|
proc
|
||||||
|
memory -nomap
|
||||||
|
equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
|
||||||
|
memory
|
||||||
|
opt -full
|
||||||
|
|
||||||
|
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||||
|
sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
|
||||||
|
|
||||||
|
design -load postopt
|
||||||
|
cd lutram_1w1r
|
||||||
|
stat
|
||||||
|
select -assert-count 8 t:WIDEFN9
|
||||||
|
select -assert-count 16 t:LUT4
|
||||||
|
select -assert-count 8 t:DPR16X4
|
||||||
|
select -assert-count 36 t:FD1P3IX
|
||||||
|
select -assert-none t:DPR16X4 t:FD1P3IX t:WIDEFN9 t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,28 @@
|
||||||
|
read_verilog ../common/mul.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
|
||||||
|
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 7 t:CCU2
|
||||||
|
select -assert-max 5 t:WIDEFN9
|
||||||
|
select -assert-max 62 t:LUT4
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9
|
||||||
|
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
|
||||||
|
|
||||||
|
stat
|
||||||
|
|
||||||
|
select -assert-count 7 t:CCU2
|
||||||
|
select -assert-max 12 t:WIDEFN9
|
||||||
|
select -assert-max 58 t:LUT4
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
|
|
@ -0,0 +1,43 @@
|
||||||
|
read_verilog ../common/mux.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top mux2
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
|
||||||
|
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||||
|
cd mux2 # Constrain all select calls below inside the top module
|
||||||
|
select -assert-count 1 t:LUT4
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top mux4
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:WIDEFN9
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top mux8
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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 4 t:LUT4
|
||||||
|
select -assert-count 1 t:WIDEFN9
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
hierarchy -top mux16
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
|
||||||
|
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||||
|
cd mux16 # Constrain all select calls below inside the top module
|
||||||
|
select -assert-min 11 t:LUT4
|
||||||
|
select -assert-max 12 t:LUT4
|
||||||
|
select -assert-count 1 t:WIDEFN9
|
||||||
|
|
||||||
|
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
{
|
||||||
|
echo "all::"
|
||||||
|
for x in *.ys; do
|
||||||
|
echo "all:: run-$x"
|
||||||
|
echo "run-$x:"
|
||||||
|
echo " @echo 'Running $x..'"
|
||||||
|
echo " @../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
|
||||||
|
done
|
||||||
|
for s in *.sh; do
|
||||||
|
if [ "$s" != "run-test.sh" ]; then
|
||||||
|
echo "all:: run-$s"
|
||||||
|
echo "run-$s:"
|
||||||
|
echo " @echo 'Running $s..'"
|
||||||
|
echo " @bash $s"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} > run-test.mk
|
||||||
|
exec ${MAKE:-make} -f run-test.mk
|
|
@ -0,0 +1,9 @@
|
||||||
|
read_verilog ../common/shifter.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
|
||||||
|
select -assert-none t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
|
@ -0,0 +1,12 @@
|
||||||
|
read_verilog ../common/tribuf.v
|
||||||
|
hierarchy -top tristate
|
||||||
|
proc
|
||||||
|
tribuf
|
||||||
|
flatten
|
||||||
|
synth
|
||||||
|
equiv_opt -assert -map +/nexus/cells_sim.v -map +/simcells.v synth_nexus # 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 1 t:OBZ
|
||||||
|
select -assert-count 1 t:INV
|
||||||
|
select -assert-none t:OBZ t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
|
Loading…
Reference in New Issue