diff --git a/techlibs/ice40/.gitignore b/techlibs/ice40/.gitignore deleted file mode 100644 index 6bf3b6717..000000000 --- a/techlibs/ice40/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -brams_init.mk -brams_init1.vh -brams_init2.vh -brams_init3.vh diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 8ce3cb024..4bf8e4e86 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -3,22 +3,6 @@ OBJS += techlibs/ice40/synth_ice40.o OBJS += techlibs/ice40/ice40_braminit.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/cells_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/brams.txt)) $(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/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)) - diff --git a/techlibs/ice40/brams.txt b/techlibs/ice40/brams.txt index 36dfddab2..518972c2a 100644 --- a/techlibs/ice40/brams.txt +++ b/techlibs/ice40/brams.txt @@ -1,100 +1,23 @@ -bram $__ICE40_RAM4K_M0 - init 1 - abits 8 - dbits 16 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 16 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -bram $__ICE40_RAM4K_M123 - init 1 - abits 9 @M1 - dbits 8 @M1 - abits 10 @M2 - dbits 4 @M2 - abits 11 @M3 - dbits 2 @M3 - 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 +ram block $__ICE40_RAM4K_ { + abits 11; + widths 2 4 8 16 per_port; + cost 64; + option "HAS_BE" 1 { + byte 1; + } + init any; + port sw "W" { + option "HAS_BE" 0 { + width 2 4 8; + } + option "HAS_BE" 1 { + width 16; + wrbe_separate; + } + clock anyedge; + } + port sr "R" { + clock anyedge; + rden; + } +} diff --git a/techlibs/ice40/brams_init.py b/techlibs/ice40/brams_init.py deleted file mode 100644 index 4a1485110..000000000 --- a/techlibs/ice40/brams_init.py +++ /dev/null @@ -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)]) - diff --git a/techlibs/ice40/brams_map.v b/techlibs/ice40/brams_map.v index db9f5d8ce..9d7b793e1 100644 --- a/techlibs/ice40/brams_map.v +++ b/techlibs/ice40/brams_map.v @@ -1,318 +1,218 @@ +module $__ICE40_RAM4K_ (...); -module \$__ICE40_RAM4K ( - output [15:0] RDATA, - input RCLK, RCLKE, RE, - input [10:0] RADDR, - input WCLK, WCLKE, WE, - input [10:0] WADDR, - input [15:0] MASK, WDATA -); - 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 INIT = 0; +parameter OPTION_HAS_BE = 1; +parameter PORT_R_WIDTH = 16; +parameter PORT_W_WIDTH = 16; +parameter PORT_W_WR_BE_WIDTH = 16; +parameter PORT_R_CLK_POL = 1; +parameter PORT_W_CLK_POL = 1; - parameter [255:0] INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter [255:0] INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter [255:0] INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter [255:0] INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - 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; +input PORT_R_CLK; +input PORT_R_RD_EN; +input [10:0] PORT_R_ADDR; +output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA; - generate - case ({NEGCLK_R, NEGCLK_W}) - 2'b00: - SB_RAM40_4K #( - .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), - .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 +input PORT_W_CLK; +input PORT_W_WR_EN; +input [15:0] PORT_W_WR_BE; +input [10:0] PORT_W_ADDR; +input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA; +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); - parameter [0:0] CLKPOL2 = 1; - parameter [0:0] CLKPOL3 = 1; +function [1:0] mode; + input integer width; + 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; - input CLK3; - - input [7:0] A1ADDR; - output [15:0] A1DATA; - input A1EN; - - input [7:0] B1ADDR; - input [15:0] B1DATA; - input [15:0] B1EN; - - wire [10:0] A1ADDR_11 = A1ADDR; - wire [10:0] B1ADDR_11 = B1ADDR; - - \$__ICE40_RAM4K #( - .READ_MODE(0), - .WRITE_MODE(0), - .NEGCLK_R(!CLKPOL2), - .NEGCLK_W(!CLKPOL3), - .INIT_0(INIT[ 0*256 +: 256]), - .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) \ +`define INSTANCE(type, rclk, wclk) \ + type #( \ + .INIT_0(slice_init(0)), \ + .INIT_1(slice_init(1)), \ + .INIT_2(slice_init(2)), \ + .INIT_3(slice_init(3)), \ + .INIT_4(slice_init(4)), \ + .INIT_5(slice_init(5)), \ + .INIT_6(slice_init(6)), \ + .INIT_7(slice_init(7)), \ + .INIT_8(slice_init(8)), \ + .INIT_9(slice_init(9)), \ + .INIT_A(slice_init(10)), \ + .INIT_B(slice_init(11)), \ + .INIT_C(slice_init(12)), \ + .INIT_D(slice_init(13)), \ + .INIT_E(slice_init(14)), \ + .INIT_F(slice_init(15)), \ + .READ_MODE(mode(PORT_R_WIDTH)), \ + .WRITE_MODE(mode(PORT_W_WIDTH)) \ ) _TECHMAP_REPLACE_ ( \ - .RDATA(A1DATA_16), \ - .RADDR(A1ADDR_11), \ - .RCLK(CLK2), \ - .RCLKE(A1EN), \ + .RDATA(RDATA), \ + .rclk(PORT_R_CLK), \ + .RCLKE(PORT_R_RD_EN), \ .RE(1'b1), \ - .WDATA(B1DATA_16), \ - .WADDR(B1ADDR_11), \ - .WCLK(CLK3), \ - .WCLKE(|B1EN), \ - .WE(1'b1) \ + .RADDR(RADDR), \ + .WDATA(WDATA), \ + .wclk(PORT_W_CLK), \ + .WCLKE(PORT_W_WR_EN), \ + .WE(1'b1), \ + .WADDR(WADDR), \ + .MASK(MASK), \ ); - 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 +generate -`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 - diff --git a/techlibs/ice40/spram.txt b/techlibs/ice40/spram.txt new file mode 100644 index 000000000..ed0699f7d --- /dev/null +++ b/techlibs/ice40/spram.txt @@ -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; + } +} diff --git a/techlibs/ice40/spram_map.v b/techlibs/ice40/spram_map.v new file mode 100644 index 000000000..ae8919505 --- /dev/null +++ b/techlibs/ice40/spram_map.v @@ -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 diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 421ec3b4e..c10b7003e 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -90,6 +90,9 @@ struct SynthIce40Pass : public ScriptPass log(" -nobram\n"); log(" do not use SB_RAM40_4K* cells in output netlist\n"); log("\n"); + log(" -spram\n"); + log(" enable automatic inference of SB_SPRAM256KA\n"); + log("\n"); log(" -dsp\n"); log(" use iCE40 UltraPlus DSP cells for large arithmetic\n"); log("\n"); @@ -116,7 +119,7 @@ struct SynthIce40Pass : public ScriptPass } 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; void clear_flags() override @@ -129,6 +132,7 @@ struct SynthIce40Pass : public ScriptPass nodffe = false; min_ce_use = -1; nobram = false; + spram = false; dsp = false; flatten = true; retime = false; @@ -204,6 +208,10 @@ struct SynthIce40Pass : public ScriptPass nobram = true; continue; } + if (args[argidx] == "-spram") { + spram = true; + continue; + } if (args[argidx] == "-dsp") { dsp = true; continue; @@ -322,19 +330,24 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); } - if (!nobram && check_label("map_bram", "(skip if -nobram)")) + if (check_label("map_ram")) { - run("memory_bram -rules +/ice40/brams.txt"); - run("techmap -map +/ice40/brams_map.v"); + std::string args = ""; + 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"); } 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("memory_map"); run("opt -undriven -fine"); } diff --git a/tests/arch/ice40/memories.ys b/tests/arch/ice40/memories.ys index 4920a45e3..d480a3abe 100644 --- a/tests/arch/ice40/memories.ys +++ b/tests/arch/ice40/memories.ys @@ -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-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 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 select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly 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