mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-06 17:44:09 +00:00
ice40: Use memory_libmap
pass.
This commit is contained in:
parent
3b2f95953c
commit
d7dc2313b9
4
techlibs/ice40/.gitignore
vendored
4
techlibs/ice40/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
brams_init.mk
|
|
||||||
brams_init1.vh
|
|
||||||
brams_init2.vh
|
|
||||||
brams_init3.vh
|
|
|
@ -3,22 +3,6 @@ OBJS += techlibs/ice40/synth_ice40.o
|
||||||
OBJS += techlibs/ice40/ice40_braminit.o
|
OBJS += techlibs/ice40/ice40_braminit.o
|
||||||
OBJS += techlibs/ice40/ice40_opt.o
|
OBJS += techlibs/ice40/ice40_opt.o
|
||||||
|
|
||||||
GENFILES += techlibs/ice40/brams_init1.vh
|
|
||||||
GENFILES += techlibs/ice40/brams_init2.vh
|
|
||||||
GENFILES += techlibs/ice40/brams_init3.vh
|
|
||||||
|
|
||||||
EXTRA_OBJS += techlibs/ice40/brams_init.mk
|
|
||||||
.SECONDARY: techlibs/ice40/brams_init.mk
|
|
||||||
|
|
||||||
techlibs/ice40/brams_init.mk: techlibs/ice40/brams_init.py
|
|
||||||
$(Q) mkdir -p techlibs/ice40
|
|
||||||
$(P) $(PYTHON_EXECUTABLE) $<
|
|
||||||
$(Q) touch techlibs/ice40/brams_init.mk
|
|
||||||
|
|
||||||
techlibs/ice40/brams_init1.vh: techlibs/ice40/brams_init.mk
|
|
||||||
techlibs/ice40/brams_init2.vh: techlibs/ice40/brams_init.mk
|
|
||||||
techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk
|
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v))
|
||||||
|
@ -26,10 +10,7 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/spram.txt))
|
||||||
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/spram_map.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v))
|
||||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v))
|
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v))
|
||||||
|
|
||||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
|
|
||||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
|
|
||||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init3.vh))
|
|
||||||
|
|
||||||
|
|
|
@ -1,100 +1,23 @@
|
||||||
bram $__ICE40_RAM4K_M0
|
ram block $__ICE40_RAM4K_ {
|
||||||
init 1
|
abits 11;
|
||||||
abits 8
|
widths 2 4 8 16 per_port;
|
||||||
dbits 16
|
cost 64;
|
||||||
groups 2
|
option "HAS_BE" 1 {
|
||||||
ports 1 1
|
byte 1;
|
||||||
wrmode 0 1
|
}
|
||||||
enable 1 16
|
init any;
|
||||||
transp 0 0
|
port sw "W" {
|
||||||
clocks 2 3
|
option "HAS_BE" 0 {
|
||||||
clkpol 2 3
|
width 2 4 8;
|
||||||
endbram
|
}
|
||||||
|
option "HAS_BE" 1 {
|
||||||
bram $__ICE40_RAM4K_M123
|
width 16;
|
||||||
init 1
|
wrbe_separate;
|
||||||
abits 9 @M1
|
}
|
||||||
dbits 8 @M1
|
clock anyedge;
|
||||||
abits 10 @M2
|
}
|
||||||
dbits 4 @M2
|
port sr "R" {
|
||||||
abits 11 @M3
|
clock anyedge;
|
||||||
dbits 2 @M3
|
rden;
|
||||||
groups 2
|
}
|
||||||
ports 1 1
|
}
|
||||||
wrmode 0 1
|
|
||||||
enable 1 1
|
|
||||||
transp 0 0
|
|
||||||
clocks 2 3
|
|
||||||
clkpol 2 3
|
|
||||||
endbram
|
|
||||||
|
|
||||||
# The syn_* attributes are described in:
|
|
||||||
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
|
|
||||||
attr_icase 1
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M0
|
|
||||||
# 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 efficiency 2
|
|
||||||
make_transp
|
|
||||||
or_next_if_better
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M0
|
|
||||||
# explicitly requested RAM
|
|
||||||
attribute syn_ramstyle=block_ram ram_block
|
|
||||||
attribute !syn_romstyle
|
|
||||||
attribute !rom_block
|
|
||||||
attribute !logic_block
|
|
||||||
min wports 1
|
|
||||||
make_transp
|
|
||||||
or_next_if_better
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M0
|
|
||||||
# explicitly requested ROM
|
|
||||||
attribute syn_romstyle=ebr rom_block
|
|
||||||
attribute !syn_ramstyle
|
|
||||||
attribute !ram_block
|
|
||||||
attribute !logic_block
|
|
||||||
max wports 0
|
|
||||||
make_transp
|
|
||||||
or_next_if_better
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M123
|
|
||||||
# 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 efficiency 2
|
|
||||||
make_transp
|
|
||||||
or_next_if_better
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M123
|
|
||||||
# explicitly requested RAM
|
|
||||||
attribute syn_ramstyle=block_ram ram_block
|
|
||||||
attribute !syn_romstyle
|
|
||||||
attribute !rom_block
|
|
||||||
attribute !logic_block
|
|
||||||
min wports 1
|
|
||||||
make_transp
|
|
||||||
or_next_if_better
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match $__ICE40_RAM4K_M123
|
|
||||||
# explicitly requested ROM
|
|
||||||
attribute syn_romstyle=ebr rom_block
|
|
||||||
attribute !syn_ramstyle
|
|
||||||
attribute !ram_block
|
|
||||||
attribute !logic_block
|
|
||||||
max wports 0
|
|
||||||
make_transp
|
|
||||||
endmatch
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
def write_init_vh(filename, initbits):
|
|
||||||
with open(filename, "w") as f:
|
|
||||||
for i in range(16):
|
|
||||||
print("localparam [255:0] INIT_%X = {" % i, file=f)
|
|
||||||
for k in range(32):
|
|
||||||
print(" %s%s" % (", ".join(["INIT[%4d]" % initbits[i*256 + 255 - k*8 - l] for l in range(8)]), "," if k != 31 else ""), file=f)
|
|
||||||
print("};", file=f);
|
|
||||||
|
|
||||||
write_init_vh("techlibs/ice40/brams_init1.vh", [i//2 + 2048*(i%2) for i in range(4096)])
|
|
||||||
write_init_vh("techlibs/ice40/brams_init2.vh", [i//4 + 1024*(i%4) for i in range(4096)])
|
|
||||||
write_init_vh("techlibs/ice40/brams_init3.vh", [i//8 + 512*(i%8) for i in range(4096)])
|
|
||||||
|
|
|
@ -1,318 +1,218 @@
|
||||||
|
module $__ICE40_RAM4K_ (...);
|
||||||
|
|
||||||
module \$__ICE40_RAM4K (
|
parameter INIT = 0;
|
||||||
output [15:0] RDATA,
|
parameter OPTION_HAS_BE = 1;
|
||||||
input RCLK, RCLKE, RE,
|
parameter PORT_R_WIDTH = 16;
|
||||||
input [10:0] RADDR,
|
parameter PORT_W_WIDTH = 16;
|
||||||
input WCLK, WCLKE, WE,
|
parameter PORT_W_WR_BE_WIDTH = 16;
|
||||||
input [10:0] WADDR,
|
parameter PORT_R_CLK_POL = 1;
|
||||||
input [15:0] MASK, WDATA
|
parameter PORT_W_CLK_POL = 1;
|
||||||
);
|
|
||||||
parameter [1:0] READ_MODE = 0;
|
|
||||||
parameter [1:0] WRITE_MODE = 0;
|
|
||||||
parameter [0:0] NEGCLK_R = 0;
|
|
||||||
parameter [0:0] NEGCLK_W = 0;
|
|
||||||
|
|
||||||
parameter [255:0] INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
input PORT_R_CLK;
|
||||||
parameter [255:0] INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
input PORT_R_RD_EN;
|
||||||
parameter [255:0] INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
input [10:0] PORT_R_ADDR;
|
||||||
parameter [255:0] INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;
|
||||||
parameter [255:0] INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
parameter [255:0] INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
|
||||||
|
|
||||||
generate
|
input PORT_W_CLK;
|
||||||
case ({NEGCLK_R, NEGCLK_W})
|
input PORT_W_WR_EN;
|
||||||
2'b00:
|
input [15:0] PORT_W_WR_BE;
|
||||||
SB_RAM40_4K #(
|
input [10:0] PORT_W_ADDR;
|
||||||
.READ_MODE(READ_MODE),
|
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
|
||||||
.WRITE_MODE(WRITE_MODE),
|
|
||||||
.INIT_0(INIT_0),
|
|
||||||
.INIT_1(INIT_1),
|
|
||||||
.INIT_2(INIT_2),
|
|
||||||
.INIT_3(INIT_3),
|
|
||||||
.INIT_4(INIT_4),
|
|
||||||
.INIT_5(INIT_5),
|
|
||||||
.INIT_6(INIT_6),
|
|
||||||
.INIT_7(INIT_7),
|
|
||||||
.INIT_8(INIT_8),
|
|
||||||
.INIT_9(INIT_9),
|
|
||||||
.INIT_A(INIT_A),
|
|
||||||
.INIT_B(INIT_B),
|
|
||||||
.INIT_C(INIT_C),
|
|
||||||
.INIT_D(INIT_D),
|
|
||||||
.INIT_E(INIT_E),
|
|
||||||
.INIT_F(INIT_F)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.RDATA(RDATA),
|
|
||||||
.RCLK (RCLK ),
|
|
||||||
.RCLKE(RCLKE),
|
|
||||||
.RE (RE ),
|
|
||||||
.RADDR(RADDR),
|
|
||||||
.WCLK (WCLK ),
|
|
||||||
.WCLKE(WCLKE),
|
|
||||||
.WE (WE ),
|
|
||||||
.WADDR(WADDR),
|
|
||||||
.MASK (MASK ),
|
|
||||||
.WDATA(WDATA)
|
|
||||||
);
|
|
||||||
2'b01:
|
|
||||||
SB_RAM40_4KNW #(
|
|
||||||
.READ_MODE(READ_MODE),
|
|
||||||
.WRITE_MODE(WRITE_MODE),
|
|
||||||
.INIT_0(INIT_0),
|
|
||||||
.INIT_1(INIT_1),
|
|
||||||
.INIT_2(INIT_2),
|
|
||||||
.INIT_3(INIT_3),
|
|
||||||
.INIT_4(INIT_4),
|
|
||||||
.INIT_5(INIT_5),
|
|
||||||
.INIT_6(INIT_6),
|
|
||||||
.INIT_7(INIT_7),
|
|
||||||
.INIT_8(INIT_8),
|
|
||||||
.INIT_9(INIT_9),
|
|
||||||
.INIT_A(INIT_A),
|
|
||||||
.INIT_B(INIT_B),
|
|
||||||
.INIT_C(INIT_C),
|
|
||||||
.INIT_D(INIT_D),
|
|
||||||
.INIT_E(INIT_E),
|
|
||||||
.INIT_F(INIT_F)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.RDATA(RDATA),
|
|
||||||
.RCLK (RCLK ),
|
|
||||||
.RCLKE(RCLKE),
|
|
||||||
.RE (RE ),
|
|
||||||
.RADDR(RADDR),
|
|
||||||
.WCLKN(WCLK ),
|
|
||||||
.WCLKE(WCLKE),
|
|
||||||
.WE (WE ),
|
|
||||||
.WADDR(WADDR),
|
|
||||||
.MASK (MASK ),
|
|
||||||
.WDATA(WDATA)
|
|
||||||
);
|
|
||||||
2'b10:
|
|
||||||
SB_RAM40_4KNR #(
|
|
||||||
.READ_MODE(READ_MODE),
|
|
||||||
.WRITE_MODE(WRITE_MODE),
|
|
||||||
.INIT_0(INIT_0),
|
|
||||||
.INIT_1(INIT_1),
|
|
||||||
.INIT_2(INIT_2),
|
|
||||||
.INIT_3(INIT_3),
|
|
||||||
.INIT_4(INIT_4),
|
|
||||||
.INIT_5(INIT_5),
|
|
||||||
.INIT_6(INIT_6),
|
|
||||||
.INIT_7(INIT_7),
|
|
||||||
.INIT_8(INIT_8),
|
|
||||||
.INIT_9(INIT_9),
|
|
||||||
.INIT_A(INIT_A),
|
|
||||||
.INIT_B(INIT_B),
|
|
||||||
.INIT_C(INIT_C),
|
|
||||||
.INIT_D(INIT_D),
|
|
||||||
.INIT_E(INIT_E),
|
|
||||||
.INIT_F(INIT_F)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.RDATA(RDATA),
|
|
||||||
.RCLKN(RCLK ),
|
|
||||||
.RCLKE(RCLKE),
|
|
||||||
.RE (RE ),
|
|
||||||
.RADDR(RADDR),
|
|
||||||
.WCLK (WCLK ),
|
|
||||||
.WCLKE(WCLKE),
|
|
||||||
.WE (WE ),
|
|
||||||
.WADDR(WADDR),
|
|
||||||
.MASK (MASK ),
|
|
||||||
.WDATA(WDATA)
|
|
||||||
);
|
|
||||||
2'b11:
|
|
||||||
SB_RAM40_4KNRNW #(
|
|
||||||
.READ_MODE(READ_MODE),
|
|
||||||
.WRITE_MODE(WRITE_MODE),
|
|
||||||
.INIT_0(INIT_0),
|
|
||||||
.INIT_1(INIT_1),
|
|
||||||
.INIT_2(INIT_2),
|
|
||||||
.INIT_3(INIT_3),
|
|
||||||
.INIT_4(INIT_4),
|
|
||||||
.INIT_5(INIT_5),
|
|
||||||
.INIT_6(INIT_6),
|
|
||||||
.INIT_7(INIT_7),
|
|
||||||
.INIT_8(INIT_8),
|
|
||||||
.INIT_9(INIT_9),
|
|
||||||
.INIT_A(INIT_A),
|
|
||||||
.INIT_B(INIT_B),
|
|
||||||
.INIT_C(INIT_C),
|
|
||||||
.INIT_D(INIT_D),
|
|
||||||
.INIT_E(INIT_E),
|
|
||||||
.INIT_F(INIT_F)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.RDATA(RDATA),
|
|
||||||
.RCLKN(RCLK ),
|
|
||||||
.RCLKE(RCLKE),
|
|
||||||
.RE (RE ),
|
|
||||||
.RADDR(RADDR),
|
|
||||||
.WCLKN(WCLK ),
|
|
||||||
.WCLKE(WCLKE),
|
|
||||||
.WE (WE ),
|
|
||||||
.WADDR(WADDR),
|
|
||||||
.MASK (MASK ),
|
|
||||||
.WDATA(WDATA)
|
|
||||||
);
|
|
||||||
endcase
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
|
wire [15:0] RDATA;
|
||||||
|
wire [15:0] WDATA;
|
||||||
|
wire [15:0] MASK;
|
||||||
|
wire [10:0] RADDR = {PORT_R_ADDR[0], PORT_R_ADDR[1], PORT_R_ADDR[2], PORT_R_ADDR[10:3]};
|
||||||
|
wire [10:0] WADDR = {PORT_W_ADDR[0], PORT_W_ADDR[1], PORT_W_ADDR[2], PORT_W_ADDR[10:3]};
|
||||||
|
|
||||||
module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
function [1:0] mode;
|
||||||
parameter [0:0] CLKPOL2 = 1;
|
input integer width;
|
||||||
parameter [0:0] CLKPOL3 = 1;
|
case (width)
|
||||||
|
16: mode = 0;
|
||||||
|
8: mode = 1;
|
||||||
|
4: mode = 2;
|
||||||
|
2: mode = 3;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
parameter [4095:0] INIT = 4096'bx;
|
function [255:0] slice_init;
|
||||||
|
input [3:0] idx;
|
||||||
|
integer i;
|
||||||
|
reg [7:0] ri;
|
||||||
|
reg [11:0] a;
|
||||||
|
for (i = 0; i < 256; i = i + 1) begin
|
||||||
|
ri = i;
|
||||||
|
a = {idx, ri[7:4], ri[0], ri[1], ri[2], ri[3]};
|
||||||
|
slice_init[i] = INIT[a];
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
input CLK2;
|
`define INSTANCE(type, rclk, wclk) \
|
||||||
input CLK3;
|
type #( \
|
||||||
|
.INIT_0(slice_init(0)), \
|
||||||
input [7:0] A1ADDR;
|
.INIT_1(slice_init(1)), \
|
||||||
output [15:0] A1DATA;
|
.INIT_2(slice_init(2)), \
|
||||||
input A1EN;
|
.INIT_3(slice_init(3)), \
|
||||||
|
.INIT_4(slice_init(4)), \
|
||||||
input [7:0] B1ADDR;
|
.INIT_5(slice_init(5)), \
|
||||||
input [15:0] B1DATA;
|
.INIT_6(slice_init(6)), \
|
||||||
input [15:0] B1EN;
|
.INIT_7(slice_init(7)), \
|
||||||
|
.INIT_8(slice_init(8)), \
|
||||||
wire [10:0] A1ADDR_11 = A1ADDR;
|
.INIT_9(slice_init(9)), \
|
||||||
wire [10:0] B1ADDR_11 = B1ADDR;
|
.INIT_A(slice_init(10)), \
|
||||||
|
.INIT_B(slice_init(11)), \
|
||||||
\$__ICE40_RAM4K #(
|
.INIT_C(slice_init(12)), \
|
||||||
.READ_MODE(0),
|
.INIT_D(slice_init(13)), \
|
||||||
.WRITE_MODE(0),
|
.INIT_E(slice_init(14)), \
|
||||||
.NEGCLK_R(!CLKPOL2),
|
.INIT_F(slice_init(15)), \
|
||||||
.NEGCLK_W(!CLKPOL3),
|
.READ_MODE(mode(PORT_R_WIDTH)), \
|
||||||
.INIT_0(INIT[ 0*256 +: 256]),
|
.WRITE_MODE(mode(PORT_W_WIDTH)) \
|
||||||
.INIT_1(INIT[ 1*256 +: 256]),
|
|
||||||
.INIT_2(INIT[ 2*256 +: 256]),
|
|
||||||
.INIT_3(INIT[ 3*256 +: 256]),
|
|
||||||
.INIT_4(INIT[ 4*256 +: 256]),
|
|
||||||
.INIT_5(INIT[ 5*256 +: 256]),
|
|
||||||
.INIT_6(INIT[ 6*256 +: 256]),
|
|
||||||
.INIT_7(INIT[ 7*256 +: 256]),
|
|
||||||
.INIT_8(INIT[ 8*256 +: 256]),
|
|
||||||
.INIT_9(INIT[ 9*256 +: 256]),
|
|
||||||
.INIT_A(INIT[10*256 +: 256]),
|
|
||||||
.INIT_B(INIT[11*256 +: 256]),
|
|
||||||
.INIT_C(INIT[12*256 +: 256]),
|
|
||||||
.INIT_D(INIT[13*256 +: 256]),
|
|
||||||
.INIT_E(INIT[14*256 +: 256]),
|
|
||||||
.INIT_F(INIT[15*256 +: 256])
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.RDATA(A1DATA),
|
|
||||||
.RADDR(A1ADDR_11),
|
|
||||||
.RCLK(CLK2),
|
|
||||||
.RCLKE(A1EN),
|
|
||||||
.RE(1'b1),
|
|
||||||
.WDATA(B1DATA),
|
|
||||||
.WADDR(B1ADDR_11),
|
|
||||||
.MASK(~B1EN),
|
|
||||||
.WCLK(CLK3),
|
|
||||||
.WCLKE(|B1EN),
|
|
||||||
.WE(1'b1)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
|
||||||
parameter CFG_ABITS = 9;
|
|
||||||
parameter CFG_DBITS = 8;
|
|
||||||
|
|
||||||
parameter [0:0] CLKPOL2 = 1;
|
|
||||||
parameter [0:0] CLKPOL3 = 1;
|
|
||||||
|
|
||||||
parameter [4095:0] INIT = 4096'bx;
|
|
||||||
|
|
||||||
localparam MODE =
|
|
||||||
CFG_ABITS == 9 ? 1 :
|
|
||||||
CFG_ABITS == 10 ? 2 :
|
|
||||||
CFG_ABITS == 11 ? 3 : 'bx;
|
|
||||||
|
|
||||||
input CLK2;
|
|
||||||
input CLK3;
|
|
||||||
|
|
||||||
input [CFG_ABITS-1:0] A1ADDR;
|
|
||||||
output [CFG_DBITS-1:0] A1DATA;
|
|
||||||
input A1EN;
|
|
||||||
|
|
||||||
input [CFG_ABITS-1:0] B1ADDR;
|
|
||||||
input [CFG_DBITS-1:0] B1DATA;
|
|
||||||
input B1EN;
|
|
||||||
|
|
||||||
wire [10:0] A1ADDR_11 = A1ADDR;
|
|
||||||
wire [10:0] B1ADDR_11 = B1ADDR;
|
|
||||||
|
|
||||||
wire [15:0] A1DATA_16, B1DATA_16;
|
|
||||||
|
|
||||||
`define INSTANCE \
|
|
||||||
\$__ICE40_RAM4K #( \
|
|
||||||
.READ_MODE(MODE), \
|
|
||||||
.WRITE_MODE(MODE), \
|
|
||||||
.NEGCLK_R(!CLKPOL2), \
|
|
||||||
.NEGCLK_W(!CLKPOL3), \
|
|
||||||
.INIT_0(INIT_0), \
|
|
||||||
.INIT_1(INIT_1), \
|
|
||||||
.INIT_2(INIT_2), \
|
|
||||||
.INIT_3(INIT_3), \
|
|
||||||
.INIT_4(INIT_4), \
|
|
||||||
.INIT_5(INIT_5), \
|
|
||||||
.INIT_6(INIT_6), \
|
|
||||||
.INIT_7(INIT_7), \
|
|
||||||
.INIT_8(INIT_8), \
|
|
||||||
.INIT_9(INIT_9), \
|
|
||||||
.INIT_A(INIT_A), \
|
|
||||||
.INIT_B(INIT_B), \
|
|
||||||
.INIT_C(INIT_C), \
|
|
||||||
.INIT_D(INIT_D), \
|
|
||||||
.INIT_E(INIT_E), \
|
|
||||||
.INIT_F(INIT_F) \
|
|
||||||
) _TECHMAP_REPLACE_ ( \
|
) _TECHMAP_REPLACE_ ( \
|
||||||
.RDATA(A1DATA_16), \
|
.RDATA(RDATA), \
|
||||||
.RADDR(A1ADDR_11), \
|
.rclk(PORT_R_CLK), \
|
||||||
.RCLK(CLK2), \
|
.RCLKE(PORT_R_RD_EN), \
|
||||||
.RCLKE(A1EN), \
|
|
||||||
.RE(1'b1), \
|
.RE(1'b1), \
|
||||||
.WDATA(B1DATA_16), \
|
.RADDR(RADDR), \
|
||||||
.WADDR(B1ADDR_11), \
|
.WDATA(WDATA), \
|
||||||
.WCLK(CLK3), \
|
.wclk(PORT_W_CLK), \
|
||||||
.WCLKE(|B1EN), \
|
.WCLKE(PORT_W_WR_EN), \
|
||||||
.WE(1'b1) \
|
.WE(1'b1), \
|
||||||
|
.WADDR(WADDR), \
|
||||||
|
.MASK(MASK), \
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (MODE == 1) begin
|
|
||||||
assign A1DATA = {A1DATA_16[14], A1DATA_16[12], A1DATA_16[10], A1DATA_16[ 8],
|
|
||||||
A1DATA_16[ 6], A1DATA_16[ 4], A1DATA_16[ 2], A1DATA_16[ 0]};
|
|
||||||
assign {B1DATA_16[14], B1DATA_16[12], B1DATA_16[10], B1DATA_16[ 8],
|
|
||||||
B1DATA_16[ 6], B1DATA_16[ 4], B1DATA_16[ 2], B1DATA_16[ 0]} = B1DATA;
|
|
||||||
`include "brams_init1.vh"
|
|
||||||
`INSTANCE
|
|
||||||
end
|
|
||||||
if (MODE == 2) begin
|
|
||||||
assign A1DATA = {A1DATA_16[13], A1DATA_16[9], A1DATA_16[5], A1DATA_16[1]};
|
|
||||||
assign {B1DATA_16[13], B1DATA_16[9], B1DATA_16[5], B1DATA_16[1]} = B1DATA;
|
|
||||||
`include "brams_init2.vh"
|
|
||||||
`INSTANCE
|
|
||||||
end
|
|
||||||
if (MODE == 3) begin
|
|
||||||
assign A1DATA = {A1DATA_16[11], A1DATA_16[3]};
|
|
||||||
assign {B1DATA_16[11], B1DATA_16[3]} = B1DATA;
|
|
||||||
`include "brams_init3.vh"
|
|
||||||
`INSTANCE
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
`undef INSTANCE
|
case(PORT_R_WIDTH)
|
||||||
|
2: begin
|
||||||
|
assign PORT_R_RD_DATA = {
|
||||||
|
RDATA[11],
|
||||||
|
RDATA[3]
|
||||||
|
};
|
||||||
|
end
|
||||||
|
4: begin
|
||||||
|
assign PORT_R_RD_DATA = {
|
||||||
|
RDATA[13],
|
||||||
|
RDATA[5],
|
||||||
|
RDATA[9],
|
||||||
|
RDATA[1]
|
||||||
|
};
|
||||||
|
end
|
||||||
|
8: begin
|
||||||
|
assign PORT_R_RD_DATA = {
|
||||||
|
RDATA[14],
|
||||||
|
RDATA[6],
|
||||||
|
RDATA[10],
|
||||||
|
RDATA[2],
|
||||||
|
RDATA[12],
|
||||||
|
RDATA[4],
|
||||||
|
RDATA[8],
|
||||||
|
RDATA[0]
|
||||||
|
};
|
||||||
|
end
|
||||||
|
16: begin
|
||||||
|
assign PORT_R_RD_DATA = {
|
||||||
|
RDATA[15],
|
||||||
|
RDATA[7],
|
||||||
|
RDATA[11],
|
||||||
|
RDATA[3],
|
||||||
|
RDATA[13],
|
||||||
|
RDATA[5],
|
||||||
|
RDATA[9],
|
||||||
|
RDATA[1],
|
||||||
|
RDATA[14],
|
||||||
|
RDATA[6],
|
||||||
|
RDATA[10],
|
||||||
|
RDATA[2],
|
||||||
|
RDATA[12],
|
||||||
|
RDATA[4],
|
||||||
|
RDATA[8],
|
||||||
|
RDATA[0]
|
||||||
|
};
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case(PORT_W_WIDTH)
|
||||||
|
2: begin
|
||||||
|
assign {
|
||||||
|
WDATA[11],
|
||||||
|
WDATA[3]
|
||||||
|
} = PORT_W_WR_DATA;
|
||||||
|
end
|
||||||
|
4: begin
|
||||||
|
assign {
|
||||||
|
WDATA[13],
|
||||||
|
WDATA[5],
|
||||||
|
WDATA[9],
|
||||||
|
WDATA[1]
|
||||||
|
} = PORT_W_WR_DATA;
|
||||||
|
end
|
||||||
|
8: begin
|
||||||
|
assign {
|
||||||
|
WDATA[14],
|
||||||
|
WDATA[6],
|
||||||
|
WDATA[10],
|
||||||
|
WDATA[2],
|
||||||
|
WDATA[12],
|
||||||
|
WDATA[4],
|
||||||
|
WDATA[8],
|
||||||
|
WDATA[0]
|
||||||
|
} = PORT_W_WR_DATA;
|
||||||
|
end
|
||||||
|
16: begin
|
||||||
|
assign WDATA = {
|
||||||
|
PORT_W_WR_DATA[15],
|
||||||
|
PORT_W_WR_DATA[7],
|
||||||
|
PORT_W_WR_DATA[11],
|
||||||
|
PORT_W_WR_DATA[3],
|
||||||
|
PORT_W_WR_DATA[13],
|
||||||
|
PORT_W_WR_DATA[5],
|
||||||
|
PORT_W_WR_DATA[9],
|
||||||
|
PORT_W_WR_DATA[1],
|
||||||
|
PORT_W_WR_DATA[14],
|
||||||
|
PORT_W_WR_DATA[6],
|
||||||
|
PORT_W_WR_DATA[10],
|
||||||
|
PORT_W_WR_DATA[2],
|
||||||
|
PORT_W_WR_DATA[12],
|
||||||
|
PORT_W_WR_DATA[4],
|
||||||
|
PORT_W_WR_DATA[8],
|
||||||
|
PORT_W_WR_DATA[0]
|
||||||
|
};
|
||||||
|
assign MASK = ~{
|
||||||
|
PORT_W_WR_BE[15],
|
||||||
|
PORT_W_WR_BE[7],
|
||||||
|
PORT_W_WR_BE[11],
|
||||||
|
PORT_W_WR_BE[3],
|
||||||
|
PORT_W_WR_BE[13],
|
||||||
|
PORT_W_WR_BE[5],
|
||||||
|
PORT_W_WR_BE[9],
|
||||||
|
PORT_W_WR_BE[1],
|
||||||
|
PORT_W_WR_BE[14],
|
||||||
|
PORT_W_WR_BE[6],
|
||||||
|
PORT_W_WR_BE[10],
|
||||||
|
PORT_W_WR_BE[2],
|
||||||
|
PORT_W_WR_BE[12],
|
||||||
|
PORT_W_WR_BE[4],
|
||||||
|
PORT_W_WR_BE[8],
|
||||||
|
PORT_W_WR_BE[0]
|
||||||
|
};
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (PORT_R_CLK_POL) begin
|
||||||
|
if (PORT_W_CLK_POL) begin
|
||||||
|
`INSTANCE(SB_RAM40_4K, RCLK, WCLK)
|
||||||
|
end else begin
|
||||||
|
`INSTANCE(SB_RAM40_4KNW, RCLK, WCLKN)
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
if (PORT_W_CLK_POL) begin
|
||||||
|
`INSTANCE(SB_RAM40_4KNR, RCLKN, WCLK)
|
||||||
|
end else begin
|
||||||
|
`INSTANCE(SB_RAM40_4KNRNW, RCLKN, WCLKN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
12
techlibs/ice40/spram.txt
Normal file
12
techlibs/ice40/spram.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
ram huge $__ICE40_SPRAM_ {
|
||||||
|
abits 14;
|
||||||
|
width 16;
|
||||||
|
cost 2048;
|
||||||
|
byte 4;
|
||||||
|
port srsw "A" {
|
||||||
|
clock posedge;
|
||||||
|
clken;
|
||||||
|
wrbe_separate;
|
||||||
|
rdwr no_change;
|
||||||
|
}
|
||||||
|
}
|
24
techlibs/ice40/spram_map.v
Normal file
24
techlibs/ice40/spram_map.v
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
module $__ICE40_SPRAM_ (...);
|
||||||
|
|
||||||
|
input PORT_A_CLK;
|
||||||
|
input PORT_A_CLK_EN;
|
||||||
|
input PORT_A_WR_EN;
|
||||||
|
input [3:0] PORT_A_WR_BE;
|
||||||
|
input [13:0] PORT_A_ADDR;
|
||||||
|
input [15:0] PORT_A_WR_DATA;
|
||||||
|
output [15:0] PORT_A_RD_DATA;
|
||||||
|
|
||||||
|
SB_SPRAM256KA _TECHMAP_REPLACE_ (
|
||||||
|
.ADDRESS(PORT_A_ADDR),
|
||||||
|
.DATAIN(PORT_A_WR_DATA),
|
||||||
|
.MASKWREN(PORT_A_WR_BE),
|
||||||
|
.WREN(PORT_A_WR_EN),
|
||||||
|
.CHIPSELECT(PORT_A_CLK_EN),
|
||||||
|
.CLOCK(PORT_A_CLK),
|
||||||
|
.STANDBY(1'b0),
|
||||||
|
.SLEEP(1'b0),
|
||||||
|
.POWEROFF(1'b1),
|
||||||
|
.DATAOUT(PORT_A_RD_DATA),
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
|
@ -90,6 +90,9 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
log(" -nobram\n");
|
log(" -nobram\n");
|
||||||
log(" do not use SB_RAM40_4K* cells in output netlist\n");
|
log(" do not use SB_RAM40_4K* cells in output netlist\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -spram\n");
|
||||||
|
log(" enable automatic inference of SB_SPRAM256KA\n");
|
||||||
|
log("\n");
|
||||||
log(" -dsp\n");
|
log(" -dsp\n");
|
||||||
log(" use iCE40 UltraPlus DSP cells for large arithmetic\n");
|
log(" use iCE40 UltraPlus DSP cells for large arithmetic\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -116,7 +119,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, blif_file, edif_file, json_file, device_opt;
|
string top_opt, blif_file, edif_file, json_file, device_opt;
|
||||||
bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap;
|
bool nocarry, nodffe, nobram, spram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap;
|
||||||
int min_ce_use;
|
int min_ce_use;
|
||||||
|
|
||||||
void clear_flags() override
|
void clear_flags() override
|
||||||
|
@ -129,6 +132,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
nodffe = false;
|
nodffe = false;
|
||||||
min_ce_use = -1;
|
min_ce_use = -1;
|
||||||
nobram = false;
|
nobram = false;
|
||||||
|
spram = false;
|
||||||
dsp = false;
|
dsp = false;
|
||||||
flatten = true;
|
flatten = true;
|
||||||
retime = false;
|
retime = false;
|
||||||
|
@ -204,6 +208,10 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
nobram = true;
|
nobram = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-spram") {
|
||||||
|
spram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-dsp") {
|
if (args[argidx] == "-dsp") {
|
||||||
dsp = true;
|
dsp = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -322,19 +330,24 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nobram && check_label("map_bram", "(skip if -nobram)"))
|
if (check_label("map_ram"))
|
||||||
{
|
{
|
||||||
run("memory_bram -rules +/ice40/brams.txt");
|
std::string args = "";
|
||||||
run("techmap -map +/ice40/brams_map.v");
|
if (!spram)
|
||||||
|
args += " -no-auto-huge";
|
||||||
|
if (nobram)
|
||||||
|
args += " -no-auto-block";
|
||||||
|
if (help_mode)
|
||||||
|
args += " [-no-auto-huge] [-no-auto-block]";
|
||||||
|
run("memory_libmap -lib +/ice40/brams.txt -lib +/ice40/spram.txt" + args, "(-no-auto-huge unless -spram, -no-auto-block if -nobram)");
|
||||||
|
run("techmap -map +/ice40/brams_map.v -map +/ice40/spram_map.v");
|
||||||
run("ice40_braminit");
|
run("ice40_braminit");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_ffram"))
|
if (check_label("map_ffram"))
|
||||||
{
|
{
|
||||||
run("opt -fast -mux_undef -undriven -fine");
|
run("opt -fast -mux_undef -undriven -fine");
|
||||||
run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
|
run("memory_map");
|
||||||
"-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
|
|
||||||
"-attr syn_romstyle=auto -attr syn_romstyle=logic");
|
|
||||||
run("opt -undriven -fine");
|
run("opt -undriven -fine");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,34 +71,6 @@ synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
|
||||||
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
|
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
|
||||||
select -assert-min 1 t:SB_DFFE
|
select -assert-min 1 t:SB_DFFE
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockram.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
|
|
||||||
hierarchy -top sync_ram_sdp
|
|
||||||
setattr -set syn_romstyle "ebr" m:memory
|
|
||||||
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockram.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
|
|
||||||
hierarchy -top sync_ram_sdp
|
|
||||||
setattr -set rom_block 1 m:memory
|
|
||||||
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockram.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
|
|
||||||
hierarchy -top sync_ram_sdp
|
|
||||||
setattr -set syn_ramstyle "block_ram" m:memory
|
|
||||||
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockram.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
|
|
||||||
hierarchy -top sync_ram_sdp
|
|
||||||
setattr -set ram_block 1 m:memory
|
|
||||||
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
|
|
||||||
|
|
||||||
# ================================ ROM ================================
|
# ================================ ROM ================================
|
||||||
# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
|
# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
|
||||||
|
|
||||||
|
@ -164,31 +136,3 @@ setattr -set logic_block 1 m:memory
|
||||||
synth_ice40 -top sync_rom; cd sync_rom
|
synth_ice40 -top sync_rom; cd sync_rom
|
||||||
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
|
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
|
||||||
select -assert-min 1 t:SB_LUT4
|
select -assert-min 1 t:SB_LUT4
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockrom.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
|
|
||||||
hierarchy -top sync_rom
|
|
||||||
setattr -set syn_ramstyle "block_ram" m:memory
|
|
||||||
synth_ice40 -top sync_rom; cd sync_rom
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockrom.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
|
|
||||||
hierarchy -top sync_rom
|
|
||||||
setattr -set ram_block 1 m:memory
|
|
||||||
synth_ice40 -top sync_rom; cd sync_rom
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockrom.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
|
|
||||||
hierarchy -top sync_rom
|
|
||||||
setattr -set syn_romstyle "ebr" m:memory
|
|
||||||
synth_ice40 -top sync_rom -nobram; cd sync_rom
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
|
|
||||||
|
|
||||||
design -reset; read_verilog -defer ../common/blockrom.v
|
|
||||||
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
|
|
||||||
hierarchy -top sync_rom
|
|
||||||
setattr -set rom_block 1 m:memory
|
|
||||||
synth_ice40 -top sync_rom -nobram; cd sync_rom
|
|
||||||
select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
|
|
||||||
|
|
Loading…
Reference in a new issue