Memory Usage Guide for iCE40 Devices January 2015 Technical Note TN1250 Introduction This technical note discusses memory usage for the iCE40™ device family (iCE40 LP/HX, iCE40LM, iCE40 Ultra™, iCE40 UltraLite™). 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 elements). Figure 1. Typical Layout of an iCE40 Device sysMEM Embedded Block RAM (EBR) PIOs Arranged into sysIO Banks Programmable Logic Block (PLB) sysCLOCK PLL © 2015 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.4 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 interconnect resources. Figure 2. sysMEM Embedded Block RAM READ Port WRITE Port WDATA[15:0] RDATA[15:0] MASK[15:0] WADDR[7:0] WE RADDR[7:0] iCE40 sysMEM Embedded Block RAM (256x16) WCLKE RE 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. MASK[15:0] Input Masks write operations for individual data bit-lines. 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 RADDR[7:0] Input Read Address input. Selects one of 256 possible RAM locations. Read Data output. 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. Timing Diagram Figure 3 shows the timing diagram for the EBR memory module. Figure 3. EBR Module Timing Diagram1 WCLK t HWE_EBR WRITE WE WCLKE t SUWE_EBR t SUWCLKE_EBR t SUADDR_EBR WADDR t HADDR_EBR ADD_0 t SUADDR_EBR t HADDR_EBR t SUDATA_EBR WDATA t HWCLKE_EBR ADD_1 t HDATA_EBR DATA_0 t SUDATA_EBR DATA_1 t HDATA_EBR RCLK t SURE_EBR READ RE RCLKE t SUADDR_EBR RADDR t SURCLKE_EBR t HADDR_EBR INVALID DATA t HRCLKE_EBR ADD_1 ADD_0 t SUADDR_EBR RDATA t HRE_EBR t HADDR_EBR DATA_0 t CO_EBR 1. Internal timing values are considered in the iCEcube2 software’s place and route. 3 DATA_1 Memory Usage Guide for iCE40 Devices 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 operations 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 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 automatically 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 during 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. 4 Memory Usage Guide for iCE40 Devices 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 contents 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 Configuration and Size WADDR Port Size (Bits) WDATA Port Size (Bits) RADDR Port Size (Bits) RDATA Port Size (Bits) MASK Port Size (Bits) SB_RAM256x16 SB_RAM256x16NR SB_RAM256x16NW SB_RAM256x16NRNW 256 x 16 (4K) 8 [7:0] 16 [15:0] 8 [7:0] 16 [15:0] 16 [15:0] SB_RAM512x8 SB_RAM512x8NR SB_RAM512x8NW SB_RAM512x8NRNW 512 x 8 (4K) 9 [8:0] 8 [7:0] 9 [8:0] 8 [7:0] No Mask Port SB_RAM1024x4 SB_RAM1024x4NR SB_RAM1024x4NW SB_RAM1024x4NRNW 1024 x 4 (4K) 10 [9:0] 4 [3:0] 10 [9:0] 4 [3:0] No Mask Port SB_RAM2048x2 SB_RAM2048x2NR SB_RAM2048x2NW SB_RAM2048x2NRNW 2048 x 2 (4K) 11 [10:0] 2 [1:0] 11 [10:0] 2 [1:0] No Mask Port Block RAM Configuration 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). 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 5 Memory Usage Guide for iCE40 Devices SB_RAM256x16 Figure 4. SB_RAM256x16 Primitive SB_RAM256x16 RDATA[15:0] WDATA[15:0] MASK[15:0] RADDR[7:0] WADDR[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; 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; 6 Memory Usage Guide for iCE40 Devices 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 ); Table 4 is a complete list of SB_RAM256x16 based primitives. 7 Memory Usage Guide for iCE40 Devices Table 4. SB_RAM256x16 Based Primitives Primitive Description SB_RAM256x16 SB_RAM256x16 //Positive edged clock RCLK WCLK (RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM256x16NR SB_RAM256x16NR // Negative edged Read Clock – i.e. RCLKN (RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM256x16NW SB_RAM256x16NW // Negative edged Write Clock – i.e. WCLKN (RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM256x16NRNW SB_RAM256x16NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN (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; defparam ram512x8_inst.INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; 8 Memory Usage Guide for iCE40 Devices 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, WCLKE => WCLKE_c, WDATA => WDATA_c, 9 Memory Usage Guide for iCE40 Devices 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 SB_RAM512x8 //Positive edged clock RCLK WCLK (RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM512x8NR SB_RAM512x8NR // Negative edged Read Clock – i.e. RCLKN (RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM512x8NW SB_RAM512x8NW // Negative edged Write Clock – i.e. WCLKN (RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM512x8NRNW SB_RAM512x8NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN (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 RCLK WCLK 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[3:0]), .WCLK(WCLK_c), .WCLKE(WCLKE_c), .WDATA(WDATA_c[9:0]), .WE(WE_c) ); defparam ram1024x4_inst.INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; defparam ram1024x4_inst.INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000; 10 Memory Usage Guide for iCE40 Devices 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, RADDR => RADDR_c, RCLK => RCLK_c, 11 Memory Usage Guide for iCE40 Devices 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 SB_RAM1024x4 //Positive edged clock RCLK WCLK (RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM1024x4NR SB_RAM1024x4NR // Negative edged Read Clock – i.e. RCLKN (RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM1024x4NW SB_RAM1024x4NW // Negative edged Write Clock – i.e. WCLKN (RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM1024x4NRNW SB_RAM1024x4NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN (RDATA, RCLKN, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM2048x2 Figure 7. SB_RAM2048x2 SB_RAM2048x2 RDATA[1:0] WDATA[1:0] WADDR[10:0] WE RADDR[10:0] RE WCLKE RCLKE WCLK RCLK Verilog Instantiation SB_RAM2048x2 ram2048x2_inst ( .RDATA(RDATA_c[2:0]), .RADDR(RADDR_c[10:0]), .RCLK(RCLK_c), .RCLKE(RCLKE_c), .RE(RE_c), .WADDR(WADDR_c[2:0]), .WCLK(WCLK_c), .WCLKE(WCLKE_c), .WDATA(WDATA_c[10:0]), .WE(WE_c) ); 12 Memory Usage Guide for iCE40 Devices 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", INIT_D => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_E => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_F => X"0000000000000000000000000000000000000000000000000000000000000000" ) 13 Memory Usage Guide for iCE40 Devices 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 SB_RAM2048x2 //Positive edged clock RCLK WCLK (RDATA, RCLK, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM2048x2NR SB_RAM2048x2NR // Negative edged Read Clock – i.e. RCLKN (RDATA, RCLKN, RCLKE, RE, RADDR, WCLK, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM2048x2NW SB_RAM2048x2NW // Negative edged Write Clock – i.e. WCLKN (RDATA, RCLK, RCLKE, RE, RADDR, WCLKN, WCLKE, WE, WADDR, MASK, WDATA); SB_RAM2048x2NRNW SB_RAM2048x2NRNW // Negative edged Read and Write – i.e. RCLKN WRCKLN (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 independent 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 14 Memory Usage Guide for iCE40 Devices Figure 8. SB_RAM40_4K SB_RAM40_4K WDATA[15:0] RDATA[15:0] MASK[15:0] RADDR[7:0] WADDR[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. MASK[15:0] Input Bit-line Write Enable input, active low. Applicable only when WRITE_MODE parameter is set 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 Name INIT_0, … …,INIT_F WRITE_MODE Parameter Value Description RAM Initialization Data. Passed using 16 parameter strings, each comprising 256 bits. (16 x 256=4096 total bits) Sets the RAM block write port configuration READ_MODE 15 Configuration INIT_0 to INIT_F Initialize the RAM with predefined value 0 256 x 16 1 512 x 18 2 1024 x 4 3 2048 x 2 0 256 x 16 1 512 x 8 2 1024 x 4 3 2048 x 2 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 ); EBR Utilization Summary in iCEcube2 Design Software The placer.log file in the iCEcube2 design software shows the device utilization summary. The Final Design Statistics 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. 16 Memory Usage Guide for iCE40 Devices Figure 9. iCEcube2 Design Software Report File Technical Support Assistance e-mail: [email protected] Internet: www.latticesemi.com Revision History Date Version Change Summary 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. September 2012 01.0 Updated Technical Support Assistance information. Initial release. 17 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; 18 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; 19 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; 20