Memory Usage Guide For Ice 40 Devices

Download as pdf or txt
Download as pdf or txt
You are on page 1of 22

Memory Usage Guide for

iCE40 Devices
June 2016 Technical Note TN1250

Introduction
This technical note discusses memory usage for the iCE40™ device family (iCE40 LP/HX, iCE40LM, iCE40 Ultra™,
iCE40 UltraLite™, iCE40 UltraPlus™). It is intended to be used as a guide to the high-speed synchronous RAM
Blocks and the iCE40 sysMEM™ Embedded Block RAM (EBR). The EBR is the embedded block RAM of the device,
each 4 Kbit in size.

The iCE40 device architecture provides resources for memory-intensive applications. Single-Port RAM, Dual-Port
RAM and FIFO can be constructed using the EBRs. The EBRs can be utilized by instantiating software primitives
as described later in this document. Apart from primitive instantiation, the iCECube2™ design software infers
generic codes as EBRs.

Memories in iCE40 Devices


iCE40 devices contain an array of EBRs.

Figure 1 shows the placement of EBRs in a typical iCE40 device (does not represent true numbers of design ele-
ments).

Figure 1. Typical Layout of an iCE40 Device

sysMEM
Embedded Block
RAM (EBR)

PIOs Arranged into


sysIO Banks
Programmable
Logic Block
(PLB)

sysCLOCK PLL

© 2016 Lattice Semiconductor Corp. All Lattice trademarks, registered trademarks, patents, and disclaimers are as listed at www.latticesemi.com/legal. All other brand
or product names are trademarks or registered trademarks of their respective holders. The specifications and information herein are subject to change without notice.

www.latticesemi.com 1 TN1250_1.5
Memory Usage Guide
for iCE40 Devices

iCE40 sysMEM Embedded Block RAM


Each iCE40 device includes multiple high-speed synchronous EBRs, each 4Kbit in size. A single iCE40 device
integrates between eight and 32 such blocks. Each EBR is a 256-word deep by 16-bit wide, two-port register file,
as illustrated in Figure 2. The input and output connections to and from an EBR feed into the programmable inter-
connect resources.

Figure 2. sysMEM Embedded Block RAM

WRITE Port READ Port

WDATA[15:0] RDATA[15:0]

MASK[15:0]

WADDR[7:0] RADDR[7:0]
iCE40 sysMEM
Embedded Block RAM
WE RE
(256x16)

WCLKE RCLKE

WCLK RCLK

Using programmable logic resources, an EBR implements a variety of logic functions, each with configurable input
and output data widths.

• Random-access memory (RAM)


— Single-port RAM with a common address, enable, and clock control lines
— Two-port RAM with separate read and write control lines, address inputs, and enable
• Register file and scratchpad RAM
• First-In, First-Out (FIFO) memory for data buffering applications
• 256-deep by 16-wide ROM with registered outputs; contents loaded during configuration
• Counters, sequencers

As shown in Figure 2, an EBR has separate write and read ports, each with independent control signals. Table 1
lists the signals for both ports. Additionally, the write port has an active-low bit-line write-enable control; optionally
mask write operations on individual bits. By default, input and output data is 16 bits wide, although the data width is
configurable using programmable logic and, if needed, multiple EBRs.

The WCLK and RCLK inputs optionally connect to one of the following clock sources:

• The output from any one of the eight Global Buffers, or


• A connection from the general-purpose interconnect fabric

2
Memory Usage Guide
for iCE40 Devices

Signals
Table 1 lists the signal names, direction, and function of each connection to the EBR block.

Table 1. EBR Signal Descriptions


Signal Name Direction Description
WDATA[15:0] Input Write Data input.
Masks write operations for individual data bit-lines.
MASK[15:0] Input
0 = write bit; 1 = don’t write bit
WADDR[7:0] Input Write Address input. Selects one of 256 possible RAM locations.
WE Input Write Enable input.
WCLKE Input Write Clock Enable input.
WCLK Input Write Clock input. Default rising-edge, but with falling-edge option.
RDATA[15:0] Output Read Data output.
RADDR[7:0] Input Read Address input. Selects one of 256 possible RAM locations.
1
RE Input Read Enable input. Only available for SB_RAM256x16 configurations.
RCLKE Input Read Clock Enable input.
RCLK Input Read Clock input. Default rising-edge, but with falling-edge option.
1. Read Enable (RE) is available only for SB_RAM256x16 configuration. For other configurations (x2/ x4/ x8), RDATA output of
SB_RAM40_4K can change, even if RE is active low. To use the RE functionality for other configurations, you can gate the Read Address
RADDR with the RE signal when generating the ADDR signals.

3
Memory Usage Guide
for iCE40 Devices

Timing Diagram
Figure 3 shows the timing diagram for the EBR memory module.

Figure 3. EBR Module Timing Diagram1

WCLK

WE

tSUWE_EBR tHWE_EBR

WCLKE

tSUWCLKE_EBR tHWCLKE_EBR

WADDR ADD_0 ADD_1

tSUADDR_EBR tHADDR_EBR

WDATA DATA_0 DATA_1

tSUDATA_EBR tHDATA_EBR

RCLK

RE

tSURE_EBR tHRE_EBR

RCLKE

tSURCLKE_EBR tHRCLKE_EBR

RADDR ADD_0 ADD_1

tSUADDR_EBR tHADDR_EBR

RDATA INVALID DATA DATA_0 DATA_1

tCO_EBR

1. Internal timing values are considered in the iCEcube2 software’s place and route.

4
Memory Usage Guide
for iCE40 Devices

Memory Initialization
sysMEM memories can be initialized as needed. The initialization can be achieved through HDL (Verilog or VHDL)
by specifying the initial values or through an initialization file (.mem file).

Refer to the iCEcube2 User Guide (under the Help menu) for more information on initializing memories. The Initial-
izing Inferred RAM section covers the process of initializing memory by providing initial values or using mem file.
the Memory Initializer section provides the DOS commands that can be used to initialize various memories using
.mem files.

Write Operations
By default, all EBR write operations are synchronized to the rising edge of WCLK although the clock is invertible as
shown in Figure 2.When the WCLKE signal is low, the clock to the EBR block is disabled, keeping the EBR in its
lowest power mode.

To write data into the EBR block, perform the following operations:

• Supply a valid address on the WADDR[7:0] address input port


• Supply valid data on the WDATA[15:0] data input port
• To write or mask selected data bits, set the associated MASK input port accordingly. For example, write opera-
tions on data bit D[i] are controlled by the associated MASK[i] input.
— MASK[i] = 0: Write operations are enabled for data line WDATA[i]
— MASK[i] = 1: Mask write operations are disabled for data line WDATA[i]
• Enable the EBR write port (WE = 1)
• Enable the EBR write clock (WCLKE = 1)
• Apply a rising clock edge on WCLK (assuming that the clock is not inverted)

Read Operations
By default, all EBR read operations are synchronized to the rising edge of RCLK although the clock is invertible as
shown in Figure 2.

To read data from the EBR block, perform the following operations:

• Supply a valid address on the RADDR[7:0] address input port


• Enable the EBR read port (RE = 1)
• Enable the EBR read clock (RCLKE = 1)
• Apply a rising clock edge on RCLK
• After the clock edge, the EBR contents located at the specified address (RADDR) appear on the RDATA output
port

5
Memory Usage Guide
for iCE40 Devices

EBR Considerations
Read Data Register Undefined Immediately After Configuration
Unlike the flip-flops in the Programmable Logic Blocks and Programmable I/O pins, the RDATA port is not automat-
ically reset after configuration. Consequently, immediately following configuration and before the first valid Read
Data operation, the initial RDATA read value is undefined.

Pre-loading EBR Data


The data contents for an EBR block can be optionally pre-loaded during iCE40 configuration. If not pre-loaded dur-
ing configuration, then the EBR contents must be initialized by the iCE40 application before the EBR contents are
valid. EBR initialization data can be done in the RTL code. Pre-loading the EBR data in the configuration bitstream
increases the size of the configuration image accordingly.

EBR Contents Preserved During Configuration


EBR contents are preserved (write protected) during configuration, assuming that voltage supplies are maintained
throughout. Consequently, data can be passed between multiple iCE40 configurations by leaving it in an EBR block
and then skipping pre-loading during the subsequent reconfiguration.

Low-Power Setting
To place an EBR block in its lowest power mode, keep WCLKE = 0 and RCLKE = 0. In other words, when not
actively using an EBR block, disable the clock inputs.

iCE40 sysMEM Embedded Block RAM Memory Primitives


This section lists the iCE40 sysMEM EBR software primitives that can be instantiated in the RTL. Different EBRs
are used in different configurations. Each EBR has separate write and read ports, each with independent control
signals. Each EBR can be configured into a RAM block of size 256x16, 512x8, 1024x4 or 2048x2. The data con-
tents of the EBR can optionally be pre-loaded during iCE40 device configuration by specifying the initialization data
in the primitive instantiation.

Table 2 lists the supported dual port synchronous RAM configurations, each of 4Kbits in size. The RAM blocks can
be directly instantiated in the top module and taken through the iCube2 software flow.

Table 2. EBR Configurations and Primitive Names

Block RAM
Block RAM Configuration WADDR Port WDATA Port RADDR Port RDATA Port MASK Port
Configuration and Size Size (Bits) Size (Bits) Size (Bits) Size (Bits) Size (Bits)
SB_RAM256x16
SB_RAM256x16NR
256 x 16 (4K) 8 [7:0] 16 [15:0] 8 [7:0] 16 [15:0] 16 [15:0]
SB_RAM256x16NW
SB_RAM256x16NRNW
SB_RAM512x8
SB_RAM512x8NR
512 x 8 (4K) 9 [8:0] 8 [7:0] 9 [8:0] 8 [7:0] No Mask Port
SB_RAM512x8NW
SB_RAM512x8NRNW
SB_RAM1024x4
SB_RAM1024x4NR
1024 x 4 (4K) 10 [9:0] 4 [3:0] 10 [9:0] 4 [3:0] No Mask Port
SB_RAM1024x4NW
SB_RAM1024x4NRNW
SB_RAM2048x2
SB_RAM2048x2NR
2048 x 2 (4K) 11 [10:0] 2 [1:0] 11 [10:0] 2 [1:0] No Mask Port
SB_RAM2048x2NW
SB_RAM2048x2NRNW

For iCE40 EBR primitives with a negative-edged read or write clock, the base primitive name is appended with a ‘N’
and a ‘R’ or ‘W’ depending on the clock that is affected (see Table 3 for the 256x16 RAM block configuration).

6
Memory Usage Guide
for iCE40 Devices

Table 3. Naming Convention for RAM Primitives


RAM Primitive Name Description
SB_RAM256x16 Positive-edged read clock, positive-edged write clock
SB_RAM256x16NR Negative-edged read clock, positive-edged write clock
SB_RAM256x16NW Positive-edged read clock, negative-edged write clock
SB_RAM256x16NRNW Negative-edged read clock, negative-edged write clock

SB_RAM256x16
Figure 4. SB_RAM256x16 Primitive

SB_RAM256x16

WDATA[15:0] RDATA[15:0]

MASK[15:0]

WADDR[7:0] RADDR[7:0]

WE RE

WCLKE RCLKE

WCLK RCLK

Verilog Instantiation
SB_RAM256x16 ram256x16_inst (
.RDATA(RDATA_c[15:0]),
.RADDR(RADDR_c[7:0]),
.RCLK(RCLK_c),
.RCLKE(RCLKE_c),
.RE(RE_c),
.WADDR(WADDR_c[7:0]),
.WCLK(WCLK_c),
.WCLKE(WCLKE_c),
.WDATA(WDATA_c[15:0]),
.WE(WE_c),
.MASK(MASK_c[15:0])
);

defparam ram256x16_inst.INIT_0 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_1 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_2 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_3 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_4 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_5 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_6 =
256'h0000000000000000000000000000000000000000000000000000000000000000;

7
Memory Usage Guide
for iCE40 Devices

defparam ram256x16_inst.INIT_7 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_8 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_9 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_A =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_B =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_C =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_D =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_E =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram256x16_inst.INIT_F =
256'h0000000000000000000000000000000000000000000000000000000000000000;

VHDL Instantiation
ram256x16_inst : SB_RAM256x16
generic map (
INIT_0 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_4 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_5 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_6 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_7 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_8 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_9 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_F => X"0000000000000000000000000000000000000000000000000000000000000000"
)

port map (
RDATA => RDATA_c,
RADDR => RADDR_c,
RCLK => RCLK_c,
RCLKE => RCLKE_c,
RE => RE_c,
WADDR => WADDR_c,
WCLK=> WCLK_c,
WCLKE => WCLKE_c,
WDATA => WDATA_c,
MASK => MASK_c,
WE => WE_c
);

8
Memory Usage Guide
for iCE40 Devices

Table 4 is a complete list of SB_RAM256x16 based primitives.

Table 4. SB_RAM256x16 Based Primitives


Primitive Description
SB_RAM256x16 //Positive edged clock RCLK WCLK
SB_RAM256x16
(RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM256x16NR // Negative edged Read Clock – i.e. RCLKN
SB_RAM256x16NR
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM256x16NW // Negative edged Write Clock – i.e. WCLKN
SB_RAM256x16NW
(RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM256x16NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN
SB_RAM256x16NRNW
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);

SB_RAM512x8
Figure 5. SB_RAM512x8 Primitive

SB_RAM512x8

WDATA[7:0] RDATA[7:0]

WADDR[8:0] RADDR[8:0]

WE RE

WCLKE RCLKE

WCLK RCLK

Verilog Instantiation
SB_RAM512x8 ram512X8_inst (
.RDATA(RDATA_c[7:0]),
.RADDR(RADDR_c[8:0]),
.RCLK(RCLK_c),
.RCLKE(RCLKE_c),
.RE(RE_c),
.WADDR(WADDR_c[8:0]),
.WCLK(WCLK_c),
.WCLKE(WCLKE_c),
.WDATA(WDATA_c[7:0]),
.WE(WE_c)
);

defparam ram512x8_inst.INIT_0 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_1 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_2 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_3 =
256'h0000000000000000000000000000000000000000000000000000000000000000;

9
Memory Usage Guide
for iCE40 Devices

defparam ram512x8_inst.INIT_4 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_5 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_6 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_7 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_8 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_9 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_A =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_B =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_C =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_D =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_E =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram512x8_inst.INIT_F =
256'h0000000000000000000000000000000000000000000000000000000000000000;

VHDL Instantiation
ram512x8_inst : SB_RAM512x8
generic map (
INIT_0 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_4 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_5 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_6 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_7 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_8 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_9 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_F => X"0000000000000000000000000000000000000000000000000000000000000000"
)

port map (
RDATA => RDATA_c,
RADDR => RADDR_c,
RCLK => RCLK_c,
RCLKE => RCLKE_c,
RE => RE_c,
WADDR => WADDR_c,
WCLK=> WCLK_c,

10
Memory Usage Guide
for iCE40 Devices

WCLKE => WCLKE_c,


WDATA => WDATA_c,
WE => WE_c
);
WE => WE_c
);

Table 5 is a complete list of SB_RAM512x8 based primitives.

Table 5. SB_RAM512x8 Based Primitives


Primitive Description
SB_RAM512x8 //Positive edged clock RCLK WCLK
SB_RAM512x8
(RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM512x8NR // Negative edged Read Clock – i.e. RCLKN
SB_RAM512x8NR
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM512x8NW // Negative edged Write Clock – i.e. WCLKN
SB_RAM512x8NW
(RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM512x8NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN
SB_RAM512x8NRNW
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);

SB_RAM1024x4
Figure 6. SB_RAM1024x4 Primitive

SB_RAM1024x4

WDATA[3:0] RDATA[3:0]

WADDR[9:0] RADDR[9:0]

WE RE

WCLKE RCLKE

WCLK RCLK

Verilog Instantiation
SB_RAM1024x4 ram1024x4_inst (
.RDATA(RDATA_c[3:0]), 
.RADDR(RADDR_c[9:0]), 
.RCLK(RCLK_c), 
.RCLKE(RCLKE_c), 
.RE(RE_c), 
.WADDR(WADDR_c[9:0]), 
.WCLK(WCLK_c), 
.WCLKE(WCLKE_c), 
.WDATA(WDATA_c[3:0]), 
.WE(WE_c) 
);

defparam ram1024x4_inst.INIT_0 =
256'h0000000000000000000000000000000000000000000000000000000000000000;

11
Memory Usage Guide
for iCE40 Devices

defparam ram1024x4_inst.INIT_1 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_2 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_3 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_4 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_5 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_6 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_7 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_8 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_9 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_A =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_B =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_C =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_D =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_E =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram1024x4_inst.INIT_F =
256'h0000000000000000000000000000000000000000000000000000000000000000;

VHDL Instantiation
Ram1024X4_inst : SB_RAM1024x4
generic map (
INIT_0 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_4 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_5 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_6 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_7 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_8 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_9 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_F => X"0000000000000000000000000000000000000000000000000000000000000000"
)

port map (
RDATA => RDATA_c,

12
Memory Usage Guide
for iCE40 Devices

RADDR => RADDR_c,


RCLK => RCLK_c,
RCLKE => RCLKE_c,
RE => RE_c,
WADDR => WADDR_c,
WCLK=> WCLK_c,
WCLKE => WCLKE_c,
WDATA => WDATA_c,
WE => WE_c
);

Table 6 is a complete list of SB_RAM1024x4 based primitives.

Table 6. SB_RAM1024x4 Based Primitives


Primitive Description
SB_RAM1024x4 //Positive edged clock RCLK WCLK
SB_RAM1024x4
(RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM1024x4NR // Negative edged Read Clock – i.e. RCLKN
SB_RAM1024x4NR
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM1024x4NW // Negative edged Write Clock – i.e. WCLKN
SB_RAM1024x4NW
(RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM1024x4NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN
SB_RAM1024x4NRNW
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);

SB_RAM2048x2
Figure 7. SB_RAM2048x2

SB_RAM2048x2

WDATA[1:0] RDATA[1:0]

WADDR[10:0] RADDR[10:0]

WE RE

WCLKE RCLKE

WCLK RCLK

Verilog Instantiation
SB_RAM2048x2 ram2048x2_inst ( 
.RDATA(RDATA_c[1:0]), 
.RADDR(RADDR_c[10:0]), 
.RCLK(RCLK_c), 
.RCLKE(RCLKE_c), 
.RE(RE_c), 
.WADDR(WADDR_c[1:0]), 
.WCLK(WCLK_c), 
.WCLKE(WCLKE_c), 
.WDATA(WDATA_c[10:0]), 

13
Memory Usage Guide
for iCE40 Devices

.WE(WE_c) 
);

defparam ram2048x2_inst.INIT_0 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_1 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_2 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_3 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_4 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_5 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_6 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_7 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_8 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_9 =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_A =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_B =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_C =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_D =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_E =
256'h0000000000000000000000000000000000000000000000000000000000000000;
defparam ram2048x2_inst .INIT_F =
256'h0000000000000000000000000000000000000000000000000000000000000000;

VHDL Instantiation
Ram2048x2_inst : SB_RAM2048x2
generic map (
INIT_0 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_4 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_5 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_6 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_7 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_8 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_9 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_C => X"0000000000000000000000000000000000000000000000000000000000000000",

14
Memory Usage Guide
for iCE40 Devices

INIT_D => X"0000000000000000000000000000000000000000000000000000000000000000",


INIT_E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_F => X"0000000000000000000000000000000000000000000000000000000000000000"
)

port map (
RDATA => RDATA_c,
RADDR => RADDR_c,
RCLK => RCLK_c,
RCLKE => RCLKE_c,
RE => RE_c,
WADDR => WADDR_c,
WCLK=> WCLK_c,
WCLKE => WCLKE_c,
WDATA => WDATA_c,
WE => WE_c
);

Table 7 is a complete list of the SB_RAM2048x2 based primitives.

Table 7. SB_RAM2048x2 Based Primitives


Primitive Description
SB_RAM2048x2 //Positive edged clock RCLK WCLK
SB_RAM2048x2
(RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM2048x2NR // Negative edged Read Clock – i.e. RCLKN
SB_RAM2048x2NR
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM2048x2NW // Negative edged Write Clock – i.e. WCLKN
SB_RAM2048x2NW
(RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);
SB_RAM2048x2NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN
SB_RAM2048x2NRNW
(RDATA, RCLKN, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA);

SB_RAM40_4K
SB_RAM40_4K is the basic physical RAM primitive which can be instantiated and configured to different depths
and data ports. The SB_RAM40_4K block has a size of 4 Kbits with separate write and read ports, each with inde-
pendent control signals. By default, input and output data is 16 bits wide, although the data width is configurable
using the READ_MODE and WRITE_MODE parameters. The data contents of the SB_RAM40_4K block are
optionally pre-loaded during iCE device configuration.

Table 8. SB_RAM40_4K Naming Convention Rules


RAM Primitive Name Description
SB_RAM40_4K Positive-edged read clock, positive-edged write clock
SB_RAM40_4KNR Negative-edged read clock, positive-edged write clock
SB_RAM40_4KNW Positive-edged read clock, negative-edged write clock
SB_RAM40_4KNRNW Negative-edged clock, negative-edged write clock

15
Memory Usage Guide
for iCE40 Devices

Figure 8. SB_RAM40_4K

SB_RAM40_4K

WDATA[15:0] RDATA[15:0]

MASK[15:0]

WADDR[7:0] RADDR[7:0]

WE RE

WCLKE RCLKE

WCLK RCLK

Table 9 lists the signals for both ports.

Table 9. SB_RAM40_4K Signal Descriptions


Signal Name Direction Description
WDATA[15:0] Input Write Data input.
Bit-line Write Enable input, active low. Applicable only when WRITE_MODE parameter is set
MASK[15:0] Input
to ‘0’.
WADDR[7:0] Input Write Address input. Selects up to 256 possible locations.
WE Input Write Enable input, active high.
WCLK Input Write Clock input, rising-edge active.
WCLKE Input Write Clock Enable input.
RDATA[15:0] Output Read Data output.
RADDR[7:0] Input Read Address input. Selects one of 256 possible locations.
RE Input Read Enable input, active high.
RCLK Input Read Clock input, rising-edge active.
RCLKE Input Read Clock Enable input.

Table 10 describes the parameter values to infer the desired RAM configuration.

Table 10. SB_RAM40_4K Primitive Parameter Descriptions


Parameter Parameter
Name Description Value Configuration
RAM Initialization Data. Passed using 16
INIT_0, … …,INIT_F parameter strings, each comprising 256 INIT_0 to INIT_F Initialize the RAM with predefined value
bits. (16 x 256=4096 total bits)
0 256 x 16
Sets the RAM block write port 1 512 x 18
WRITE_MODE
configuration 2 1024 x 4
3 2048 x 2
0 256 x 16
1 512 x 8
READ_MODE
2 1024 x 4
3 2048 x 2

16
Memory Usage Guide
for iCE40 Devices

Verilog Instantiation
// Physical RAM Instance without Pre Initialization
SB_RAM40_4K ram40_4kinst_physical (
.RDATA(RDATA),
.RADDR(RADDR),
.WADDR(WADDR),
.MASK(MASK),
.WDATA(WDATA)
.RCLKE(RCLKE),
.RCLK(RCLK),
.RE(RE),
.WCLKE(WCLKE),
.WCLK(WCLK),
.WE(WE)
);

defparam ram40_4kinst_physical.READ_MODE=0;
defparam ram40_4kinst_physical.WRITE_MODE=0;

VHDL Instantiation
-- Physical RAM Instance without Pre Initialization
ram40_4kinst_physical : SB_RAM40_4K
generic map (
READ_MODE => 0,
WRITE_MODE= >0
)

port map (
RDATA=>RDATA,
RADDR=>RADDR,
WADDR=>WADDR,
MASK=>MASK,
WDATA=>WDATA,
RCLKE=>RCLKE,
RCLK=>RCLK,
RE=>RE,
WCLKE=>WCLKE,
WCLK=>WCLK,
WE=>WE
);

17
Memory Usage Guide
for iCE40 Devices

EBR Utilization Summary in iCEcube2 Design Software


The placer.log file in the iCEcube2 design software shows the device utilization summary. The Final Design Statis-
tics and Device Utilization Summary sections show the number of EBRs (or RAMs) used against the total number.
Figure 9 shows the EBR usage when one SB_RAM256x16 was instantiated in the design.

Figure 9. iCEcube2 Design Software Report File

Technical Support Assistance


Submit a technical support case via www.latticesemi.com/techsupport.

18
Memory Usage Guide
for iCE40 Devices

Revision History
Date Version Change Summary
June 2016 1.5 Updated Introduction section. Added iCE40 UltraPlus to introductory
paragraph.
Updated Signals section. Added footnote to RE signal in Table 1, EBR
Signal Descriptions.
Updated Timing Diagram section. Revised Figure 3, EBR Module Tim-
ing Diagram.
Added Memory Initialization section.
Updated SB_RAM512x8 section. Minor correction in Verilog Instantia-
tion and VHDL Instantiation.
Updated SB_RAM1024x4 section. Minor correction in VHDL Instantia-
tion.
Updated iCE40 sysMEM Embedded Block RAM Memory Primitives
section.
— Revised SB_RAM512x8 Verilog Instantiation and VHDL Instantia-
tion.
— Revised SB_RAM1024x4 Verilog Instantiation and VHDL Instantia-
tion.
— Revised SB_RAM2048x2 Verilog Instantiation.
Updated Technical Support Assistance section.
January 2015 1.4 Added support for iCE40 UltraLite.
June 2014 01.3 Added support for iCE40 Ultra.
December 2013 01.2 Added information to EBR Signal Descriptions table.
October 2013 01.1 Removed iCE40 Family EBRs table.
Updated Technical Support Assistance information.
September 2012 01.0 Initial release.

19
Memory Usage Guide
for iCE40 Devices

Appendix A. Standard HDL Code References


This appendix contains standard HDL (Verilog and VHDL) codes for popular memory elements, which can be used
to infer a sysMEM EBR automatically. Standard HDL coding techniques do not require you to know the details of
the Block RAMs of the device and are inferred automatically.

Single-Port RAM
Verilog
module ram (din, addr, write_en, clk, dout);// 512x8
parameter addr_width = 9;
parameter data_width = 8;
input [addr_width-1:0] addr;
input [data_width-1:0] din;
input write_en, clk;
output [data_width-1:0] dout;
reg [data_width-1:0] dout; // Register for output.
reg [data_width-1:0] mem [(1<<addr_width)-1:0];

always @(posedge clk)


begin
if (write_en)
mem[(addr)] <= din;
dout = mem[addr]; // Output register controlled by clock.
end
endmodule

VHDL
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity ram is
generic (
addr_width : natural := 9;--512x8
data_width : natural := 8);
port (
addr : in std_logic_vector (addr_width - 1 downto 0);
write_en : in std_logic;
clk : in std_logic;
din : in std_logic_vector (data_width - 1 downto 0);
dout : out std_logic_vector (data_width - 1 downto 0));
end ram;

architecture rtl of ram is


type mem_type is array ((2** addr_width) - 1 downto 0) of
std_logic_vector(data_width - 1 downto 0);
signal mem : mem_type;
begin
process (clk)
begin
if (clk'event and clk = '1') then
if (write_en = '1') then
mem(conv_integer(addr)) <= din;
end if;

20
Memory Usage Guide
for iCE40 Devices

dout <= mem(conv_integer(addr));


end if;

-- Output register controlled by clock.


end process;
end rtl;

Dual Port Ram


Verilog
module ram (din, write_en, waddr, wclk, raddr, rclk, dout);//512x8
parameter addr_width = 9;
parameter data_width = 8;
input [addr_width-1:0] waddr, raddr;
input [data_width-1:0] din;
input write_en, wclk, rclk;
output reg [data_width-1:0] dout;
reg [data_width-1:0] mem [(1<<addr_width)-1:0]
;

always @(posedge wclk) // Write memory.


begin
if (write_en)
mem[waddr] <= din; // Using write address bus.
end
always @(posedge rclk) // Read memory.
begin
dout <= mem[raddr]; // Using read address bus.
end
endmodule

VHDL
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity ram is
generic (
addr_width : natural := 9;--512x8
data_width : natural := 8);
port (
write_en : in std_logic;
waddr : in std_logic_vector (addr_width - 1 downto 0);
wclk : in std_logic;
raddr : in std_logic_vector (addr_width - 1 downto 0);
rclk : in std_logic;
din : in std_logic_vector (data_width - 1 downto 0);
dout : out std_logic_vector (data_width - 1 downto 0));
end ram;

architecture rtl of ram is


type mem_type is array ((2** addr_width) - 1 downto 0) of
std_logic_vector(data_width - 1 downto 0);
signal mem : mem_type;

21
Memory Usage Guide
for iCE40 Devices

begin
process (wclk)
-- Write memory.
begin
if (wclk'event and wclk = '1') then
if (write_en = '1') then
mem(conv_integer(waddr)) <= din;
-- Using write address bus.
end if;
end if;
end process;
process (rclk) -- Read memory.
begin
if (rclk'event and rclk = '1') then
dout <= mem(conv_integer(raddr));
-- Using read address bus.
end if;
end process;
end rtl;

22

You might also like