Using Memory in ispXPLD 5000MX Devices ™ March 2005 Technical Note TN1030 Introduction This document describes memory usage and flow in the Lattice ispXPLD™ family of devices. A brief overview of the ispXPLD’s memory resources are presented along with the parameterizable memory elements supported by Lattice’s ispLEVER™ design tool. The ispXPLD architecture is built around the Multifunction Block (MFB), which can be configured either as traditional logic or as memory. When it is configured as memory it can function as dual-port SRAM, pseudo-dual port SRAM, single-port SRAM, FIFO, or CAM memory. Multifunction Blocks The ispXPLD architecture allows the MFB to be configured as a variety of memory blocks as detailed in Table 1. Table 1. MFB Memory Configurations Memory Mode Configurations Dual-port 8,192 x 1 4,096 x 2 2,048 x 4 1,024 x 8 512 x 16 Single-port, Pseudo Dual Port, FIFO 16,384 x1 8,192 x 2 4,096 x 4 2048 x 8 1024 x 16 512 x 32 CAM 128 x 48 Once the MFB has been configured as memory, no other logic can be implemented in that block. The one exception is a FIFO block that requires 32 data outputs, as it will need an additional MFB for flag generation. To generate the control circuitry for the four FIFO flags, four macrocells and six inputs are required. This leaves 28 macrocells and 62 logic inputs for generic logic implementation in the additional MFB. Initializing Memory In each of the memory modes it is possible to specify the power-on state of each bit in the memory array. This allows the memory to be used as ROM if desired. Each bit in the memory array can have one of four values: 0, 1, X (always match) or U (never match). Note that X (always match) and U (never match) values only apply for CAM. For all other memory modes, use ones and zeroes. Increased Depth And Width Memory that requires a depth or width that is greater than that supported by a single MFB, can be supported by cascading multiple blocks. For dual port, single port, and pseudo-dual port memory blocks, additional width is easily provided by sharing address lines. Additional depth is supported, by multiplexing the RAM output. For FIFO and CAM modes additional width is supported through the cascading of MFBs. For FIFOs up to four MFBs can be cascaded for additional width ranging to 128 bits. The CAM can also cascade up to four MFBs to provide additional width, allowing the implementation of a CAM to a maximum of 128x192. Lattice’s ispLEVER design tool automatically combines blocks to support the memory size specified in the user’s design. www.latticesemi.com 1 tn1030_05.1 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Bus Size Matching All of the memory modes apart from the CAM mode support different widths on each of the ports. The RAM bits are mapped LSB word 0 to MSB word 0, LSB word 1 to MSB word 1 and so on. Although the word size and number of words for each port varies this mapping scheme applies to each port. With CAM memory the port size is 48 bits for a single MFB. Cascading up to three additional MFBs can expand the width of the CAM to 192 bits. Use of the mask register allows for comparisons of less than 48 bits but the port width will still be 48 bits. This is more fully explained in the CAM description later in this document. Different Data Bus Widths on Two Ports True Dual Port and Pseudo Dual Port modes support different data bus widths. The two ports in the memory can have different data bus widths. In True Dual Port Mode different widths for read/write port A and read/write port B is supported. In Pseudo Dual Port mode, different widths for the read and write ports can also be specified. While the two ports are operating with different data bus widths, the addressing scheme ensures that the RAM location addressed with each address follow a certain order. Each word written on a wider side can be read as successive multiple words on a narrower port. For example if port A writes 32-bit words, and port B reads 8-bit words, one word written on port A is read as four consecutive words from port B. Supported Memory Modes True Dual-Port SRAM Mode In Dual-Port SRAM mode, the Read/Write address lines share two independent read/write ports, and can access up to 8,192-bits of memory. Data widths of 1, 2, 4, 8, and 16 are supported by the MFB. Figure 1 shows the block diagram of the dual port SRAM. Write data, address, chip select and read/write signals are always synchronous (registered). The output data signals can be synchronous or asynchronous. Resets are asynchronous. All inputs on the same port share the same clock, clock enable, and reset selections. All outputs on the same port share the same clock, clock enable, and reset selections. Port A and Port B are completely independent from a data width and from a control standpoint. There may be instances when both data ports attempt to write to the memory. This should be avoided as there is no arbitration logic to control which port controls the writing of data into the memory. Table 2 shows the possible sources for the clock, clock enable and initialization signals for the various registers. 2 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 1. Dual-Port SRAM Block Diagram CLK0 CLK1 CLK2 CLK3 RESET PORT A Read/Write Address RD Data A (DOA[0:0-15]) (ADA[0:8-12]) Reset A (RSTA) Clock A (CLKA) Clk En A (CENA) Write/Read A (WRA) 68 Inputs From Routing Chip Sel A (CSA [0:1]) Write Data ‘ ‘ Dual Port SRAM Array (DIA[0:0,1,3,7,15]) PORT B Similar signals as PORT A: ADB[0:8-12], RSTB, CLKB, CENB, WRB, CSB[0,1], DIB[0:0,1,3,7,15] RD Data B (DOB[0:0-15]) Table 2. Register Clock, Clock Enable and Reset in Dual-Port SRAM Mode Register Address, Write Data, Read Data, Read/Write, and Chip Select Input Source Clock Selected from CLKA (CLKB) or one of the global clocks (CLK0 - CLK3). The selected signal can be inverted if desired. Clock Enable Selected from CENA (CENB) or two of the global clocks (CLK1 - CLK 2). The selected signal can be inverted if required. Reset Created by the logical OR of the global reset signal and RSTA (RSTB). RSTA (RSTB) can be inverted if desired. 3 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual-Port SRAM Mode In Pseudo Dual-Port SRAM mode the MFB is configured as an SRAM memory with independent read and write ports that access the same 16,384-bits of memory. Data widths of 1, 2, 4, 8, 16 and 32 are supported by the MFB. Figure 2 shows the block diagram of the Pseudo Dual-Port SRAM Write data, write address, chip select and write enable signals are always synchronous (registered.) The read data and read address signals can be synchronous or asynchronous. Reset is asynchronous. All write signals share the same clock, and clock enable. All read signals share the same clock and clock enable. Reset is shared by both the read and write signals. Table 3 shows the possible sources for the clock, clock enable and initialization signals for the various registers. Figure 2. Pseudo Dual-Port SRAM Block Diagram CLK0 CLK1 CLK2 CLK3 RESET Read Address Read Data (RAD[0:8-13]) (RD[0:0-15]) Write Address (WAD[0:8-13]) Write Data 16,384 bit Pseudo ‘ Dual Write Enable (WE) ‘ Port Write Clock (WCLK) SRAM Write Chip Sel (WCS[0,1]) Array (WD[0:0,1,3,7,15,31]) 68 Inputs From Routing Write Clk Enable (WCEN) Read Clk Enable (RCEN) Read Clock (RCLK) Reset (RST) Table 3. Register Clock, Clock Enable, and Reset in Pseudo Dual-Port SRAM Mode Register Input Write Address, Write Clock Data, Write Enable, and Write Chip Select Clock Enable Reset Read Data and Read Clock Address Source Chosen from WCLK or one of the global clocks (CLK0 -CLK3). The selected signal can be inverted if desired. Chosen from WCEN or two of the global clocks (CLK0 - CLK3). The selected signal can be inverted if desired. Created by the logical OR of the global reset signal and RST. RST may have inversion if desired. Chosen from RCLK or one of the global clocks (CLK0 - CLK3). The selected signal can be inverted if desired. Clock Enable Chosen from RCEN or two of the global clocks (CLK1 - CLK2). The selected signal can be inverted if desired. Reset Created by the logical OR of the global reset signal and RST. RST may have inversion if desired. 4 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Single-Port SRAM Mode In Single-Port SRAM mode, one port is shared by the Read/Write address lines, and can access up to 16,384-bits of memory. Data widths of 1, 2, 4, 8, 16 and 32 are supported by the MFB. Figure 3 shows the block diagram of the single-port SRAM. Write data, write address, chip select and write enable signals are always synchronous (registered). The read data and read address signals can be synchronous or asynchronous. Reset is asynchronous. All signals share a common clock, clock enable, and reset. Table 4 shows the possible sources for the clock, clock enable and reset signals. Figure 3. Single-Port SRAM Block Diagram CLK0 CLK1 CLK2 CLK3 RESET Read Data Read/Write Address (DO[0:0-31]) (AD[0:8-13]) Write Data (DI[0:0,1,3,7,15,31]) Write/Read (WR) 68 Inputs from Routing 16,384-Bit ‘ ‘SRAM Array Clock (CLK) Chip Select (CS[0,1]) Clk Enable (CEN) Reset (RST) Table 4. Register Clock, Clock Enable, and Reset in Single-Port SRAM Mode Register Input Address, Write Clock Data, Read Data, Clock Enable Read/Write, and Chip Select Reset Source CLK or one of the global clocks (CLK0 - CLK3). Each of these signals can be inverted if required. CEN or two of the global clocks (CLK1 - CLK 2). Each of these signals can be inverted if required. Created by the logical OR of the global reset signal and RST. RST is routed by the multifunction array from GRP, with inversion if desired. 5 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor FIFO Mode In FIFO mode the multifunction array is configured as a FIFO (First In First Out) buffer with built in control. The read and write clocks are independent of each other but can be tied together if the application requires it. Four flags show the status of the FIFO: Full, Almost Full, /Empty and /Almost Empty. /Empty and /Almost Empty are negative true signals. The thresholds for almost full and almost empty are programmable by the user. It is possible to reset the read pointer, allowing support of frame retransmit in communications applications. The Almost Full and /Almost Empty flags indicate the status of the stack pointer with respect to Full and /Empty. Almost Full is an offset subtracted from the highest memory address, and /Almost Empty is an offset added to the lowest memory address. These flags are defined in the instantiation template via the lpm_amempty_flag and lpm_amfull_flag parameters. Values for both can range from 1 to the maximum number of address locations. In this mode one port accesses 16,384-bits of memory. Data widths of 1, 2, 4, 8, 16 and 32 are supported by the MFB. Figure 4 shows the block diagram of the FIFO. These MFB blocks are cascaded to create FIFO sizes larger than 16K. Cascading sometimes requires extra logic elements like counters that occupy additional macrocells. For width cascading, no external logic is required if the depth can fit into the maximum depth of a single block. However, for depth cascading, external counters are needed. For example, in a 16K x 16 (depth x width) FIFO configuration, no extra counters are needed. This is width cascading. For 32K X 1 FIFO, counters will be needed since the depth (32K) is larger than the depth available in a single MFB (16K). When the configuration needs both width and depth cascading, the software optimizes it to the maximum depth with width cascading. Write data, write enable, flag outputs and read enable are synchronous. The Write Data, Almost Full flag and Full flag share the same clock and clock enables. Read outputs are synchronous. The Read Data, /Empty flag and /Almost Empty flag share the same clock and clock enables. Reset is shared by all signals. Table 5 shows the possible sources for the clock, clock enable and reset signals for the various registers. The Full and Almost Full flags are based on the write port. The Full and Almost Full flags change state only on write clock rising edges. The Empty and Almost Empty flags are based on the read port. The /Empty and /Almost Empty flags change state only on read clock rising edges. FIFO flag latency is reduced when both read/write clocks are left running. If the read/write clocks are free running, data is inserted/retrieved by synchronously controlling the Read/Write Enable strobes. Once the Full or Empty flag goes active, the internal FIFO pointer is frozen at the last active value, and no operation is performed on the memory. In other words, Writes to the FIFO after the full flag goes active or Reads after the Empty flag goes active are ignored. 6 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 4. FIFO Block Diagram CLK0 CLK1 CLK2 CLK3 RESET Write Enable (WE) Write Clock (WCLK) Reset FIFO Control Logic (RST) Read Clock (RCLK) Reset_RP (RSTRP) FIFO Flags* Full, Empty, Almost Full, Almost Empty Read Enable (RE) ‘‘ 68 Inputs From Routing Write Data 16,384-bit Read Data (DO[0:0-31]) SRAM Array (DI[0:0-31]) *Control logic can be duplicated in adjacent MFB in 32-bit mode Table 5. Register Clocks, Clock Enables, and Initialization in FIFO Mode Register Write Data, Write Enable Input Clock WCLK or one of the global clocks (CLK0 - CLK3). Each of these signals can be inverted if required. Clock Enable WEN or two of the global clocks (CLK1 - CLK 2). Each of these signals can be inverted if required. Reset Full and Almost Clock Full Flags Read Data, Empty and Almost Empty Flags Source N/A WCLK or one of the global clocks (CLK0 - CLK3). Each of these signals can be inverted if required. Clock Enable WEN or two of the global clocks (CLK1 - CLK 2). Each of these signals can be inverted if required. Reset Created by the logical OR of the global reset signal and RST. RST is routed by the multifunction array from GRP, with inversion if desired Clock RCLK or one of the global clocks (CLK0 - CLK3). Each of these signals can be inverted if required. Clock Enable REN or two of the global clocks (CLK1 - CLK 2). Each of these signals can be inverted if required. Reset Created by the logical OR of the global reset signal and RST. RST is routed by the multifunction array from GRP, with inversion if desired CAM Mode In CAM mode the multifunction array is configured as a ternary Content Addressable Memory (CAM.) CAM behaves like a reverse memory where the input to the memory is data and the output is an address at which the input data is located. It can be used to perform a variety of high-performance look-up functions. As such CAM has two modes of operation. In write or update mode the CAM behaves as a RAM, and the data is written to the supplied address. When reading or comparing, data is supplied to the CAM. If that data matches any of the entries in the CAM array the Match or Multi-Match (if there is more than one match) flag is set to true, and the lowest address with matching data is the output. The MFB can be configured as a CAM that contains 128 entries of 48 bits. Figure 5 shows the block diagram of the CAM 7 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor To further enhance the flexibility of the CAM a mask register is available for both update and compare operations. If the mask register is enabled during updates, bits corresponding to those set to a ‘1’ in the mask register are not updated. If it is enabled during compare operations, bits corresponding to those set to a ‘1’ in the mask register are not included in the compare. A Write Don’t Care signal allows don’t cares to be programmed into the CAM if desired. As with other write operations, the mask register controls this. Data is written into the Mask Register by enabling the WrMask (Write Mask) bit. When WrMask is enabled during write mode, the data written into the CAM array is also automatically stored in the Mask Register. Once the mask is configured, it can be used during Update and Compare modes by enabling the EnMask (Enable Mask) bit. The WrDC (Write Don’t Care) bit functions much like the EnMask and WrMask inputs. When in write mode and WrDC is set to a 1, the data written to the CAM array during the next write operation is stored in the Write Don’t Care register. The Write/Comp Data, Write Address, Write Enable, Write Chip Select, and Write Don’t Care signals are synchronous. The CAM Output signals, Match flag, and Multi-Match flag signals can be either synchronous or asynchronous. The Enable mask register input is not latched but must meet setup and hold times relative to the Write Clock. All inputs must use the same clock and clock enable signals. All outputs must use the same clock, and clock enable signals. Reset is common for both inputs and outputs. Table 6 shows the allowable sources for clock, clock enable, and reset for the various CAM registers. For additional information on the CAM memory in the ispXPLD family of devices please refer to application note AN8071, Content Addressable Memory Applications for ispXPLD Devices. Figure 5. CAM Mode CLK0 CLK1 CLK2 CLK3 RESET Write/Comp Data (WD[0:31]) CAM Output Write Address CO[0:6] (WAD[0:6]) En Mask Reg (EN_MASK) Write Enable (WE) Write Chip Sel (WCS[0:1])‘ 68 Inputs From Routing ‘ WR Mask Reg (WR_MASK) 128X48 CAM Match Out MATCH WR don’t care (WR_DC) Reset (RST) Multimatch Out CLK (CLK) Clock Enable (CE) MUL_MATCH Table 6. Register Clocks, Clock Enables, and Initialization in CAM Mode Register Input Clock Write data, Write address, Enable mask register, Write enable, write chip select, and Clock Enable write don’t care, CAM Output, Match, and Multimatch Reset Source CLK or one of the global clocks (CLK0 - CLK3). Each of these signals can be inverted if required. WE or two of the global clocks (CLK1 - CLK 2). Each of these signals can be inverted if required. Created by the logical OR of the global reset signal and RST. RST is routed by the multifunction array from GRP, with inversion if desired 8 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Including Memory in ispXPLD 5000MX Designs To use memory in ispXPLD 5000MX designs the desired memory function must be instantiated into the HDL source code describing the design. This is done in the form of LPM primitives, which are passed through the synthesis tool to Lattice backend design tools. These backend tools then work to implement the memory requested in the source code. The remainder of this document details the LPM primitives and example templates. Configurable Memory Primitives Configurable memory primitives are provided to allow easy configuration of the MFBs. These primitives are added to your design source. With the addition of parameters these memory primitives can be easily configured to match your design needs. This section describes the six types of configurable memory primitives that are supported. • • • • • • LPM_RAM_DP LPM_RAM_DP_PSEUDO LPM_RAM_DQ LPM_FIFO_DC LPM_CAM LPM_ROM – Dual-Port RAM – Pseudo Dual Port RAM – Single-port RAM – FIFO – CAM – ROM 9 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor True Dual-Port Random Access Memory (LPM_RAM_DP) DataInA QA AddressA ClockA ClockEnA WrA ResetA LP LPM_RAM_DP DataInB AddressB QB ClockB ClockEnB WrB ResetB Ports Port QA Type Out Description Data out, port A Comments Port width is user defined DataInA In Data in, port A Port width is user defined AddressA In Address, port A Address depth is user defined ClockA In Clock, port A ClockEnA In Clock Enable, port A WrA In Write Enable, Port A ResetA In Reset, port A Asynchronous Reset Data out, port B Port width is user defined Data in, port B Port width is user defined Address depth is user defined QB DataInB Out In AddressB In Address, port B ClockB In Clock, port B ClockEnB In Clock Enable, port B WrB In Write Enable, Port B ResetB In Reset, port B Asynchronous Reset 10 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Properties Parameter Description Comments Value lpm_widtha Defines data width for port A User-defined Number of data bits lpm_widthada Defines address width for port A User-defined Number of address lines lpm_numwordsa Defines memory depth for port A User-defined Number of address locations lpm_widthb Defines data width for port B User-defined Number of data bits lpm_widthadb Defines address width for port B User-defined Number of address lines lpm_numwordsb Defines memory depth for port B User-defined Number of address locations lpm_outdata Defines read data to be synchronous or asynchronous User-defined Registered or Unregistered lpm_indata Defines write data to be synchronous Synchronous Registered lpm_addressa_control Defines that port A address lines will be synchro- Synchronous nous Registered lpm_addressb_control Defines that port B address lines will be synchro- Synchronous nous Registered lpm_init_file Defines initialization file File for initializing Name of the initialization file data in the RAM True Dual Port RAM with Asynchronous Read tDPRWAS tDPRWAH Write/ Read A (WRA) tDPRWBS tDPRWBH Write/ Read B (WRB) tDPCEAS Clk En A (CENA) tDPCEAH Clock A (CLKA) Clk En B (CENB) tDPCLKSKEW tDPCEBS Clock B (CLKB) tDPMSAH tDPMSAS Chip Sel A (CSA[0:1]) tDPMSBS Chip Sel B (CSB[0:1]) Read/ Write Address A (ADA[0:8-12]) Read/ Write Address B (ADB[0:8-12]) tDPADDAS Add_1_A Add_1_A Add_0_A tDPADDAH Add_1_A Add_0_B tDPDATAAS tDPADDBS Write Data A (DIA[0:0,1,3,7,15]) tDPADDBH Data_1_A Add_1_B tDPDATAAH Data_2_A Write Data B (DIB[0:0,1,3,7,15]) Data_1_B tDPRCLKAO tDPDATABS RD Data A (DOA[0:0-15]) Invalid/ Previous Data Data_0_A Data_1_A tDPDATABH Data_2_A tDPRCLKBO RD Data B (DOB[0:0-15]) Invalid/ Previous Data Data_0_B Data_1_A Data_2_A Data_1_B Note: While one port is writing and the other port tries to read or write at the same memory location, there must be a minimum tDPCLKSKEW between the two clocks. 11 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor True Dual Port RAM with Synchronous Read tDPRWAS tDPRWAH Write/ Read A (WRA) Write/ Read B (WRB) tDPCEAH tDPCEAS Clk En A (CENA) Clock A (CLKA) Clk En B (CENB) tDPCLKSKEW tDPCEBS Clock B (CLKB) tDPMSAS tDPMSAH Chip Sel A (CSA[0:1]) tDPMSBS Chip Sel B (CSB[0:1]) Read/ Write Address A (ADA[0:8-12]) tDPADDAS tDPADDAH Read/ Write Address B (ADB[0:8-12]) Write Data A (DIA[0:0,1,3,7,15]) Add_0_B tDPADDBS Add_1_A tDPDATAAS tDPADDBH tDPDATAAH Data_1_A Write Data B (DIB[0:0,1,3,7,15]) RD Data A (DOA[0:0-15]) Add_1_A Add_1_A Add_0_A Data_2_A tDPRCLKAO Data_0_A Invalid/ Previous Data Data_1_A Data_2_A tDPRCLKBO RD Data B (DOB[0:0-15]) Invalid/ Previous Data Data_0_B Data_1_A Data_2_A Note: While one port is writing and the other port tries to read or write at the same memory location, there must be a minimum tDPCLKSKEW between the two clocks. For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 12 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual-Port Random Access Memory (LPM_RAM_PSEUDO) Data Q WrAddress WrClock WrClockEN LPM_RAM_DP PSEUDO RdAddress RdClock RdClockEN WE Reset Ports Port Q Type Out Description Comments Data out Port width is user defined Data In Data in Port width is user defined WrAddress In Write Address Address Depth is user defined WrClock In Write Clock WrClockEN In Write Clock Enable RdAddress In Read Address RdClock In Read Clock RdClockEN In Read Clock Enable WE In Write Enable Reset In Reset Address Depth is user defined Asynchronous Reset Properties Parameter Description Comments User-defined Value lpm_widthw Defines data width for write port Number of data bits to write lpm_widthadw Defines address width for write port User-defined Number of write address lines lpm_numwordsw Defines memory depth for write User-defined Number of address locations lpm_widthr Defines data width for read port User-defined Number of data bits to read lpm_widthadr Defines address width for read port User-defined Number of read address lines lpm_numwordsr Defines memory depth for read User-defined Number of read address locations lpm_outdata Defines read data to be synchronous or asynchronous User-defined Registered or unregistered lpm_addressr_control Defines that read address lines will be synchronous Synchronous Registered lpm_addressw_control Defines that write address lines will be synchronous Synchronous Registered lpm_init_file File for initializing data in the RAM Name of the initialization file Defines initialization file 13 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual Port RAM with Asynchronous Read tPDPMSH Write Chip Select (WCS[0,1]) tPDPMSS tPDPRWS tPDPRWH Write Enable (WE) Write Clock (WCLK) tPDPWCES tPDPWCEH Write Clk Enable (WCEN) tPDPCLKSKEW Read Clock (RCLK) tPDPRCES tPDPRCEH Read Clk Enable (RCEN) tPDPWADDS tPDPWADDH Write Address (WAD[0:0,1,3,7,15,31]) Read Address (RAD[0:8-13]) Add_1 Add_1 tPDPRADDH tPDPRADDS Add_2 Add_2 tSPADDDATA Add_0 tPDPDATAS Write Data (WD[0:0,1,3,7,15,31]) tPDPDATAH Data_1 Read Data (RD[0:0-15]) Data_3 tPDPRCLKO Invalid / Previous Data Data_0 Data_1 Data_2 Data_3 Notes: While Write port is writing and the Read port tries to read at the same memory location, there must be a minimum tPDPCLKSKEW between the two clocks. As shown above, if Add_1 is where the the read and write is occurring then there should be a minimum clock skew of tPDPCLKSKEW between the RCLK and WCLK. Further, when we read from an address and in the next Write clock cycle, we start writing to that address, then the Read Data gets updated tSPADDDATA after the address is stable. This is shown, when we are reading Add_2 and the Read Data is Data_2. In the next write clock cycle, Add_2 is witten with Data_3. The Read Data gets updated tSPADDDATA after the Add_2 is stable. Both Data_2 and Data_3 are from the same location Add_2. 14 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual Port RAM with Synchronous Read tPDPMSH Write Chip Select (WCS[0,1]) tPDPMSS tPDPRWS tPDPRWH Write Enable (WE) Write Clock (WCLK) tPDPWCES tPDPWCEH Write Clk Enable (WCEN) tPDPCLKSKEW Read Clock (RCLK) tPDPRCES tPDPRCEH Read Clk Enable (RCEN) tPDPWADDS tPDPWADDH Write Address (WAD[0:0,1,3,7,15,31]) Add_1 tPDPRADDS Add_2 tPDPRADDH Read Address (RAD[0:8-13]) Add_1 Add_2 tPDPDATAH Add_0 tPDPDATAS Write Data (WD[0:0,1,3,7,15,31]) Read Data (RD[0:0-15]) Data_1 tPDPRCLKO Invalid / Previous Data Data_0 Data_3 Data_1 Data_2 Data_3 Notes: While the Write port is writing and the Read port tries to read at the same memory location, there must be a minimum tPDPCLKSKEW between the two clocks. As shown above, if Add_1 is where the the read and write is occurring then there should be a minimum clock skew of tPDPCLKSKEW between the RCLK and WCLK. Further, when we read from an address and in the next Write clock cycle, we start writing to that address, then the Read Data gets updated tSPADDDATA after the address is stable. This is shown when we are reading Add_2 and the Read Data is Data_2. In the next write clock cycle, Add_2 is witten with Data_3. The Read Data gets updated tSPADDDATA after the Add_2 is stable. Both Data_2 and Data_3 are from the same location, Add_2. For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 15 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Single-Port RAM (LPM_RAM_DQ) Data Q Address LPM_RAM_DQ Clock ClockEN WE Reset Ports Port Q Type Out Description Comments Data Out Port width is user defined Data In Data In Port width is user defined Address In Read/Write Address Port width is user defined Clock In Clock ClockEn In Clock Enable WE In Write Enable Reset In Reset Asynchronous Reset Properties Parameter Description Comments Value lpm_width Defines Data width User-defined Number of data bits lpm_widthad Defines address width User-defined Number of address lines lpm_numwords Defines memory depth User-defined Number of address locations lpm_outdata Defines read data to be synchronous or asynchronous User-defined Registered or unregistered lpm_address_control Defines the value of the read address User-defined lines. In unregistered mode, the output toggles at each address change. In registered mode, Q is toggled by the clock. Registered or unregistered lpm_init_file Name of the initialization file Defines initialization file File for initializing data in the RAM 16 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Single Port RAM with Asynchronous Read tSPRWS tSPRWH Write/ Read (WR) tSPCES Clk Enable (CEN) Clock (CLK) tSPADDS tSPADDH Add_0 Read / Write Address (AD[0:8-13]) Add_1 tSPADDDATA Data_1 Write Data (DI[0:0,1,3,7,15,31]) Read Data (DO[0:0-31]) tSPDATAS Invalid/ Previous Data tSPDATAH Data_1 Data_0 Single Port RAM with Synchronous Read tSPRWS tSPRWH Write/ Read (WR) tSPCES Clk Enable (CEN) Clock (CLK) Add_1 Add_0 Read / Write Address (AD[0:8-13]) tSPADDS tSPADDH Data_1 Write Data (DI[0:0,1,3,7,15,31]) tSPCLKO t SPDATAS Read Data (DO[0:0-31]) Invalid/ Previous Data tSPDATAH Data_0 For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 17 Data_1 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor First-In-First-Out Memory (LPM_FIFO) Data Q WrClock Full WrEn RdClock Empty LPM_FIFO RdEN AmFull RPReset AmEmpty Reset Ports Port Type Description Comments Q Out Data Out Port width is user defined Full Out Flag Set when FIFO is Full, user defined Empty Out Flag Clear (logic “0”) when FIFO is empty AmFull Out Flag Set at user defined value AmEmpty Out Flag Clear (logic “0”) at user defined value Data In Port width is user defined Data In WrClock In Write Clock WrEn In Write Enable RdClock In Read Clock RdEn In Read Enable RPReset In Read Control Pointer Reset In Reset Asynchronous Reset Properties Parameter Description Comments Value lpm_width Defines data width User-defined Number of data bits lpm_widthu Defines address width User-defined Number of address lines required to access lpm_numwords FIFO entries lpm_numwords Defines memory depth User-defined Number of data entries the FIFO can store lpm_amfull_flag Almost full flag User-defined offset Offset subtracted from lpm_numwords lpm_amempty_flag Almost empty flag User-defined offset Offset added to address 0 18 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor FIFO tFIFOWES tFIFOWEH Write Enable (WE) Write Clock (WCLK) tFIFORES tFIFOREH Read Enable (RE) Read Clock (RCLK) tFIFOWCLKH Write Data (DI[0:0-31]) Data_0 Data_1 Data_2 Invalid Data Read Data (DO[0:0-31]) Data_0 Data_1 Data_2 tFIFOFULL tFIFORCLKO Full tFIFOAFULL tFIFOCLKSKEW Almost Full Empty tFIFOAEMPTY tFIFOEMPTY Almost Empty For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 19 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Content Addressable Memory (LPM_CAM) Data Address WAD Clock ClockEn WE EnMask WrMask WrDc Reset Match MulMatch LPM_CAM Ports Port Type Description Comments Address Out Write Address Port width is user defined Match Out Flag Set when match MulMatch Out Flag Set when Multiple matches Data In Data In Port width is user defined Port width is user defined Wad In Write Address Clock In Clock ClockEn In Clock Enable We In Write Enable EnMask In Enable Mask Register Enables use of global mask register WrMask In Write Mask Register Enables writing to the Mask Register WrDC In Write Don’t Care Don’t Cares can be written to the CAM Reset In Reset Asynchronous Reset Properties Parameter Description Comments Value lpm_width Defines data width User-defined Number of data bits lpm_widthad Defines address width User-defined Number of address lines lpm_numwords Defines memory depth User-defined Number of address locations lpm_init_file Defines initialization file File for initializing data in the CAM Name of the initialization file 20 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor CAM with Asynchronous Read tCAMRWS tCAMRWH Write Enable (WE) tCAMENMSKS tCAMENMSKH En Mask Reg (EN_MASK) tCAMWMSKS tCAMWMSKH WR Mask Reg (WR_MASK) tCAMDCS tCAMDCH WR don't care (WR_DC) tCAMCES Clock Enable (CE) CLK (CLK) Write / Comp Data (WD[0:31]) Data_0 tCAMDATAS Data_1 Data_2 Data_3 Data_3 Data_4 Address_4 tCAMDATAH Address_5 Write Address (WAD[0:6]) tCAMADDH tCAMADDS tCAMMATCH Match Out (MATCH) tCAMMMATCH Multi-Match Out (MUL_MATCH) tCAMCO Invalid Address CAM Output (CO[0:6]) Address_0 Address_4 Address_2 CAM with Synchronous Read tCAMRWS tCAMRWH Write Enable (WE) tCAMENMSKS tCAMENMSKH En Mask Reg (EN_MASK) tCAMWMSKS tCAMWMSKH WR Mask Reg (WR_MASK) tCAMDCS tCAMDCH WR don’t care (WR_DC) tCAMCES Clock Enable (CE) CLK (CLK) Write / Comp Data (WD[0:31]) Data_0 tCAMDATAS Data_1 Data_2 Data_3 Data_3 Address_4 tCAMDATAH Write Address (WAD[0:6]) tCAMMATCH tCAMADDS Data_4 Address_5 tCAMADDH Match Out (MATCH) tCAMMMATCH Multi-Match Out (MUL_MATCH) tCAMCO CAM Output (CO[0:6]) Invalid Address Address_0 For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 21 Address_2 Address_4 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Read-Only Memory (LPM_ROM) Q Address OutClock OutClockEn Reset LPM_ROM Ports Port Q Type Out Description Comments Data Out Port width is user defined Port width is user defined Address In Read Address OutClock In Clock OutClockEn In Clock Enable Reset In Reset Asynchronous Reset Properties Parameter Description Comments Value lpm_width Defines data width User-defined Number of data bits lpm_widthad Defines address width User-defined Number of address lines lpm_numwords Defines memory depth User-defined Number of address locations lpm_outdata Defines read data to be synchronous or asynchronous User-defined Registered or unregistered lpm_address_control Defines the value of the read address User-defined lines. In unregistered mode, the output toggles at each address change. In registered mode, Q is toggled by the clock. Registered or unregistered lpm_init_file Name of the initialization file Defines initialization file File for initializing data in the ROM ROM with Asynchronous Read Clk Enable (CEN) Clock (CLK) Read Address (AD[0:8-13]) Read Data (DO[0:0-31]) Add_1 Add_0 Invalid/ Previous Data Data_0 22 Data_1 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor ROM with Synchronous Read Clk Enable (CEN) Clock (CLK) Read Address (AD[0:8-13]) Read Data (DO[0:0-31]) Add_0 Add_1 Data_0 Invalid/ Previous Data For timing numbers, please refer to the ispXPLD 5000MX Data Sheet. 23 Data_1 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Appendix A. Memory Primitive Source Examples (Verilog) Note: The Verilog templates shown here can also be found in the software examples directory: \<isptools_instalation_directory>\ispcpld\examples\ispXPLD\verilog True Dual-Port Random Access Memory (LPM_RAM_DP) module tramdp8kx2x2( QA, QB, DataInA, AddressA, DataInB, AddressB, ClockA, ClockEnA, ClockB, ClockEnB, WrA, WrB, ResetA, ResetB); output [1:0] QA; output [1:0] QB; input [1:0] DataInA; input [12:0] AddressA; input [1:0] DataInB; input [12:0] AddressB; input ClockA,ClockEnA,ClockB,ClockEnB,WrA,WrB,ResetA,ResetB; L_RAMDP U0(.QA(QA),.QB(QB),.DataInA(DataInA),.AddressA(AddressA),.DataInB(DataInB),.A ddressB(AddressB),.ClockA(ClockA),.ClockEnA(ClockEnA),.ClockB(ClockB),.ClockE nB(ClockEnB),.WrA(WrA),.WrB(WrB),.ResetA(ResetA),.ResetB(ResetB)); defparam defparam defparam defparam defparam defparam defparam defparam defparam defparam U0.lpm_widtha=2; U0.lpm_widthada=13; U0.lpm_numwordsa=8192; U0.lpm_widthb=2; U0.lpm_widthadb=13; U0.lpm_numwordsb=8192; U0.lpm_outdata = “REGISTERED”; U0.lpm_addressa_control = “REGISTERED”; U0.lpm_addressb_control = “REGISTERED”; U0.lpm_init_file = “RAM_init”; endmodule module L_RAMDP( QA, QB, DataInA, AddressA, 24 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor DataInB, AddressB, ClockA, ClockEnA, ClockB, ClockEnB, WrA, WrB, ResetA, ResetB); parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter lpm_type = “LPM_RAM_DP”; lpm_widtha = 1; lpm_widthada = 1; lpm_numwordsa = 1; lpm_widthb = 1; lpm_widthadb = 1; lpm_numwordsb = 1; lpm_indata = “REGISTERED”; lpm_outdata = “UNREGISTERED”; lpm_addressa_control = “REGISTERED”; lpm_addressb_control = “REGISTERED”; lpm_hint = “UNUSED”; lpm_init_file = “dummy”; output [lpm_widtha-1:0] QA; output [lpm_widthb-1:0] QB; input [lpm_widtha-1:0] DataInA; input [lpm_widthada-1:0] AddressA; input [lpm_widthb-1:0] DataInB; input [lpm_widthadb-1:0] AddressB; input ClockA,ClockEnA,ClockB,ClockEnB,WrA,WrB,ResetA,ResetB; endmodule //lpm_ramdp 25 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual-Port Random Access Memory (LPM_RAM_PSEUDO) module tramdps16kwx2rx2( Q, Data, WrAddress, RdAddress, WrClock, WrClockEn, RdClock, RdClockEn, WE, Reset); output [1:0] Q; input [1:0] Data; input [13:0] WrAddress; input [13:0] RdAddress; input WrClock,WrClockEn,RdClock,RdClockEn,WE,Reset; L_RAMDPS U0(.Q(Q),.Data(Data),.WrAddress(WrAddress),.RdAddress(RdAddress),.WrClock(WrC lock),.WrClockEn(WrClockEn),.RdClock(RdClock),.RdClockEn(RdClockEn),.WE(WE),. Reset(Reset)); defparam defparam defparam defparam defparam defparam defparam defparam defparam U0.lpm_widthw=2; U0.lpm_widthadw=14; U0.lpm_numwordsw=16384; U0.lpm_widthr=2; U0.lpm_widthadr=14; U0.lpm_numwordsr=16384; U0.lpm_outdata = “REGISTERED”; U0.lpm_addressr_control = “REGISTERED”; U0.lpm_init_file=”RAM_init”; endmodule module L_RAMDPS( Q, Data, WrAddress, RdAddress, WrClock, WrClockEn, RdClock, RdClockEn, WE, Reset); parameter parameter parameter parameter parameter lpm_type = “LPM_RAM_DP_PSEUDO”; lpm_widthw = 1; lpm_widthr = 1; lpm_numwordsw = 1; lpm_widthadw = 1; 26 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor parameter parameter parameter parameter parameter parameter parameter parameter lpm_widthadr = 1; lpm_numwordsr = 1; lpm_indata = “REGISTERED”; lpm_outdata = “UNREGISTERED”; lpm_addressw_control = “REGISTERED”; lpm_addressr_control = “REGISTERED”; lpm_hint = “UNUSED”; lpm_init_file = “dummy”; output [lpm_widthr-1:0] Q; input [lpm_widthw-1:0] Data; input [lpm_widthadw-1:0] WrAddress; input [lpm_widthadr-1:0] RdAddress; input WrClock,WrClockEn,RdClock,RdClockEn,WE,Reset; endmodule // lpm_ram_dp_pseudo 27 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Random Access Memory (LPM_RAM_DQ) module tramdq16kx2( Q, Data, Address, Clock, ClockEn, WE, Reset); output [1:0] Q; input [1:0] Data; input [13:0] Address; input Clock,ClockEn,WE,Reset; L_RAMDQ U0(.Q(Q),.Data(Data),.Address(Address),.Clock(Clock),.ClockEn(ClockEn),.WE(WE ),.Reset(Reset)); defparam defparam defparam defparam defparam defparam U0.lpm_width=2; U0.lpm_widthad=14; U0.lpm_numwords=16384; U0.lpm_outdata=”REGISTERED”; U0.lpm_address_control=”REGISTERED”; U0.lpm_init_file=”RAM_init”; endmodule module L_RAMDQ( Q, Data, Address, Clock, ClockEn, WE, Reset); parameter parameter parameter parameter parameter parameter parameter parameter parameter lpm_type = “LPM_RAM_DQ”; lpm_width = 1; lpm_numwords = 1; lpm_widthad = 1; lpm_indata = “REGISTERED”; lpm_outdata = “UNREGISTERED”; lpm_address_control = “REGISTERED”; lpm_hint = “UNUSED”; lpm_init_file = “dummy”; output [lpm_width-1:0] Q; input [lpm_width-1:0] Data; input [lpm_widthad-1:0] Address; input Clock,ClockEn,WE,Reset; endmodule // lpm_ram_dq 28 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor First-In-First-Out Memory (LPM_FIFO_DC) module test_fifo16kx2 (Q,Full,Empty,AlmostFull,AlmostEmpty,Data,WrClock,WrEn,RdClock,RdEn,Reset,RPReset); output [1:0] Q; output Full,Empty,AlmostFull,AlmostEmpty; input [1:0] Data; input WrClock,WrEn,RdClock,RdEn,Reset,RPReset; L_FIFO U0(.Q(Q), .Full(Full), .Empty(Empty), .AlmostFull(AlmostFull), .AlmostEmpty(AlmostEmpty), .Data(Data), .WrClock(WrClock), .WrEn(WrEn), .RdClock(RdClock), .RdEn(RdEn), .Reset(Reset), .RPReset(RPReset) ); defparam defparam defparam defparam defparam U0.lpm_width=2; U0.lpm_widthu=14; U0.lpm_numwords=16384; U0.lpm_amfull_flag=11; U0.lpm_amempty_flag=11; endmodule module L_FIFO(Q,Full,Empty,AlmostFull,AlmostEmpty,Data,WrClock,WrEn,RdClock,RdEn,Reset,RPReset) ; parameter parameter parameter parameter parameter parameter parameter output output output output output input input input input input lpm_type = “LPM_FIFO_DC”; lpm_width = 1; lpm_widthu = 1; lpm_numwords = 2; lpm_amfull_flag=1; lpm_amempty_flag=1; lpm_hint = “UNUSED”; [lpm_width-1:0] Q; Full; Empty; AlmostFull; AlmostEmpty; [lpm_width-1:0] Data; WrClock; WrEn; RdClock; RdEn; 29 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor input input Reset; RPReset; endmodule // lpm_fifo 30 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Content Addressable Memory (LPM_CAM) module tcam128x48 (Address,Match,MulMatch,Wad,Data,Clock,ClockEn,We,EnMask,WrMask,WrDc,Reset); output [6:0] Address; output Match,MulMatch; input [47:0] Data; input [6:0] Wad; input Clock,ClockEn,We,EnMask,WrMask,WrDc,Reset; L_CAM U0(.Address(Address),.Match(Match),.MulMatch(MulMatch),.WrAddress(Wad),.Data( Data),.Clock(Clock),.ClockEn(ClockEn),.WE(We),.EnMask(EnMask),.WrMask(WrMask) ,.WrDC(WrDc),.Reset(Reset)); defparam defparam defparam defparam U0.lpm_width=48; U0.lpm_widthad=7; U0.lpm_numwords=128; U0.lpm_init_file= “CAM_init”; endmodule module L_CAM(Address,Match,MulMatch,WrAddress,Data,Clock,ClockEn,WE,EnMask,WrMask,WrDC,Reset); parameter parameter parameter parameter parameter parameter lpm_type = “LPM_CAM”; lpm_width = 1; lpm_widthad = 1; lpm_numwords = 1; lpm_hint = “UNUSED”; lpm_init_file = “dummy”; output [lpm_widthad-1:0] Address; output Match; output MulMatch; input [lpm_widthad-1:0] WrAddress; input [lpm_width-1:0] Data; input Clock; input ClockEn; input WE; input EnMask; input WrMask; input WrDC; input Reset; endmodule // lpm_cam 31 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Read-Only Memory (LPM_ROM) module test_rom16kx2( Q, Address, OutClock, OutClockEn, Reset); output [1:0] Q; input [13:0] Address; input OutClock,OutClockEn,Reset; L_ROM U0(.Q(Q),.Address(Address),.OutClock(OutClock),.OutClockEn(OutClockEn),.Reset(Reset)); defparam defparam defparam defparam defparam defparam U0.lpm_width=2; U0.lpm_widthad=14; U0.lpm_numwords=16384; U0.lpm_outdata=”REGISTERED”; U0.lpm_address_control=”UNREGISTERED”; U0.lpm_init_file =”ROM_init”; endmodule module L_ROM( Q, Address, OutClock, OutClockEn, Reset); parameter lpm_type = “LPM_ROM”; parameter lpm_width = 1; parameter lpm_numwords = 1; parameter lpm_widthad = 1; parameter lpm_outdata = “REGISTERED”; parameter lpm_address_control = “UNREGISTERED”; parameter lpm_hint = “UNUSED”; parameter lpm_init_file = “dummy”; output [lpm_width-1:0] Q; input [lpm_widthad-1:0] Address; input OutClock,OutClockEn,Reset; endmodule // lpm_rom 32 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Appendix B. Memory Primitive Source Examples (VHDL) Note: The VHDL templates shown here can also be found in the software examples directory: \<isptools_instalation_directory>\ispcpld\examples\ispXPLD\VHDL True Dual-Port Random Access Memory (LPM_RAM_DP) library IEEE; use IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity tramdp8kx2x2 is port ( DataInA AddressA DataInB AddressB ClockA ClockEnA ClockB ClockEnB WrA WrB ResetA ResetB QA QB end tramdp8kx2x2 ; : : : : : : : : : : : : : : in std_logic_vector( 1 downto 0); in std_logic_vector( 12 downto 0); in std_logic_vector( 1 downto 0); in std_logic_vector( 12 downto 0); in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; out std_logic_vector(1 downto 0); out std_logic_vector(1 downto 0)); architecture behave of tramdp8kx2x2 is component L_RAMDP generic( LPM_TYPE : string := “LPM_RAM_DP”; LPM_WIDTHA : positive := 1; LPM_WIDTHADA : positive := 1; LPM_NUMWORDSA : positive := 2; LPM_WIDTHB : positive := 1; LPM_WIDTHADB : positive := 1; LPM_NUMWORDSB : positive := 2; LPM_INDATA : string :=”REGISTERED”; LPM_OUTDATA : string :=”UNREGISTERED”; LPM_ADDRESSA_CONTROL : string :=”REGISTERED”; LPM_ADDRESSB_CONTROL : string :=”REGISTERED”; LPM_INIT_FILE : string := “dummy”; LPM_HINT : string :=”UNUSED”); port( DataInA : in std_logic_vector(LPM_WIDTHA-1 downto 0); AddressA:in std_logic_vector(LPM_WIDTHADA-1 downto 0); DataInB : in std_logic_vector(LPM_WIDTHB-1 downto 0); 33 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor AddressB:in std_logic_vector(LPM_WIDTHADB-1 downto 0); ClockA : in std_logic := ‘0’; ClockEnA : in std_logic := ‘0’; ClockB : in std_logic := ‘0’; ClockEnB : in std_logic := ‘0’; WrA : in std_logic; WrB : in std_logic; ResetA : in std_logic; ResetB : in std_logic; QA : out std_logic_vector(LPM_WIDTHA-1 downto 0); QB : out std_logic_vector(LPM_WIDTHB-1 downto 0)); end component ; begin U0: L_RAMDP generic map ( LPM_WIDTHA => 2, LPM_WIDTHADA => 13, LPM_NUMWORDSA => 8192, LPM_WIDTHB => 2, LPM_WIDTHADB => 13, LPM_NUMWORDSB => 8192, LPM_INDATA => “REGISTERED”, LPM_OUTDATA => “UNREGISTERED”, LPM_ADDRESSA_CONTROL => “REGISTERED”, LPM_ADDRESSB_CONTROL => “REGISTERED”, LPM_INIT_FILE => “RAM_init”) port map ( DataInA => DataInA, AddressA => AddressA, DataInB => DataInB, AddressB => AddressB, ClockA => ClockA, ClockEnA => ClockEnA, ClockB => ClockB, ClockEnB => ClockEnB, WrA => WrA, WrB => WrB, ResetA => ResetA, ResetB => ResetB, QA => QA, QB => QB); end behave; 34 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Pseudo Dual-Port Random Access Memory (LPM_RAM_PSEUDO) library IEEE; use IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity tramdps16kwx2rx2 is port ( Data WrAddress RdAddress WrClock WrClockEn RdClock RdClockEn WE Reset Q end tramdps16kwx2rx2 ; : : : : : : : : : : in std_logic_vector(1 downto 0); in std_logic_vector(13 downto 0); in std_logic_vector(13 downto 0); in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; out std_logic_vector(1 downto 0)); architecture struct of tramdps16kwx2rx2 is component L_RAMDPS generic( lpm_type : string := “LPM_RAM_DP_PSEUDO”; lpm_widthw : integer := 1; lpm_widthr : integer := 1; lpm_numwordsw : integer := 1; lpm_widthadw : integer := 1; lpm_widthadr : integer := 1; lpm_numwordsr : integer := 1; lpm_indata : string := “REGISTERED”; lpm_outdata : string := “UNREGISTERED”; lpm_addressw_control : string := “REGISTERED”; lpm_addressr_control : string := “REGISTERED”; lpm_init_file : string := “dummy”; lpm_hint : string := “UNUSED”); port( Data : in std_logic_vector(lpm_widthw-1 downto 0); WrAddress:in std_logic_vector(lpm_widthadw-1 downto 0); RdAddress:in std_logic_vector(lpm_widthadr-1 downto 0); WrClock : in std_logic := 0; WrClockEn : in std_logic := 0; RdClock : in std_logic := 0; RdClockEn : in std_logic := 0; WE : in std_logic; Reset : in std_logic; Q : out std_logic_vector(lpm_widthr-1 downto 0)); end component ; 35 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor begin lpm_gen: L_RAMDPS generic map ( lpm_widthw => 2, lpm_widthadw => 14, lpm_numwordsw => 16384, lpm_widthr => 2, lpm_widthadr => 14, lpm_numwordsr => 16384, lpm_indata => “REGISTERED”, lpm_addressr_control => “REGISTERED”, lpm_init_file => “RAM_init”, lpm_indata => “UNREGISTERED”, ) port map ( Data WrAddress RdAddress WrClock WrClockEn RdClock RdClockEn WE Reset Q => => => => => => => => => => end struct; 36 Data, WrAddress, RdAddress, WrClock, WrClockEn, RdClock, RdClockEn, WE, Reset, Q); Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Random Access Memory (LPM_RAM_DQ) library IEEE; use IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity tramdq16kx2 is port ( Data Address Clock ClockEn WE Reset Q end tramdq16kx2 ; : : : : : : : in std_logic_vector( 1 downto 0); in std_logic_vector( 13 downto 0); in std_logic; in std_logic; in std_logic; in std_logic; out std_logic_vector(1 downto 0)); architecture behave of tramdq16kx2 is component L_RAMDQ generic ( LPM_TYPE : string := “LPM_RAM_DQ”; LPM_WIDTH : positive := 1; LPM_WIDTHAD : positive := 1; LPM_NUMWORDS : positive := 2; LPM_INDATA : string :=”REGISTERED”; LPM_OUTDATA : string :=”UNREGISTERED”; LPM_ADDRESS_CONTROL : string :=”REGISTERED”; LPM_INIT_FILE : string := “dummy”; LPM_HINT : string :=”UNUSED”); port ( Data : in std_logic_vector(LPM_WIDTH-1 downto 0); Address : in std_logic_vector(LPM_WIDTHAD-1 downto 0); Clock : in std_logic := ‘0’; ClockEn : in std_logic := ‘0’; WE : in std_logic; Reset : in std_logic; Q : out std_logic_vector(LPM_WIDTH-1 downto 0)); end component ; begin U0: L_RAMDQ generic map ( LPM_WIDTH => 2, LPM_WIDTHAD => 14, LPM_NUMWORDS => 16384, LPM_ADDRESS_CONTROL => “UNREGISTERED”, LPM_INIT_FILE => “RAM_init”, LPM_OUTDATA => “UNREGISTERED”) port map ( Data => Data, 37 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Address Clock ClockEn WE Reset Q => => => => => => end behave; 38 Address, Clock, ClockEn, WE, Reset, Q); Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor First-In-First-Out Memory (LPM_FIFO_DC) LIBRARY IEEE; USE IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity tfifo4kx4 is port ( Data WrClock WrEn RdClock RdEn Reset RPReset Q Full Empty AlmostFull AlmostEmpty end tfifo16kx1 ; : : : : : : : : : : : : in std_logic_vector(3 downto 0); in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; out std_logic_vector(3 downto 0); Out std_logic; Out std_logic; Out std_logic; Out std_logic); architecture struct of tfifo4kx4 is component L_FIFO generic ( lpm_type : string := “LPM_FIFO_DC”; lpm_width : integer := 1; lpm_widthu : integer := 1; lpm_numwords : integer := 2; lpm_amfull_flag: integer :=1; lpm_amempty_flag: integer :=1; lpm_hint : string := “UNUSED”); port ( Data : in std_logic_vector (lpm_width-1 downto 0); WrClock : in std_logic; WrEn : in std_logic; RdClock : in std_logic; RdEn : in std_logic; Reset : in std_logic; RPReset : in std_logic; Q : out std_logic_vector (lpm_width-1 downto 0); Full : out std_logic; Empty : out std_logic; AlmostFull : out std_logic; AlmostEmpty : out std_logic); end component ; begin U0: L_FIFO 39 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor generic map (LPM_WIDTH => 4, LPM_WIDTHU => 12, LPM_AMFULL_FLAG => 1, LPM_AMEMPTY_FLAG => 1, LPM_NUMWORDS => 4096) port map ( Data WrClock WrEn RdClock RdEn Reset RPReset Q Full Empty AlmostFull AlmostEmpty => => => => => => => => => => => => end struct; 40 Data, WrClock, WrEn, RdClock, RdEn, Reset, RPReset, Q, FULL, EMPTY, AlmostFull, AlmostEmpty ); Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Content Addressable Memory (LPM_CAM) library IEEE; use IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity tcam128x48 is port ( Data WrAddress ClockEn Clock We EnMask WrMask WrDc Reset Address Match MulMatch end tcam128x48 ; : : : : : : : : : : : : in std_logic_vector(47 downto 0); in std_logic_vector(6 downto 0); in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic; out std_logic_vector(6 downto 0); Out std_logic; Out std_logic); architecture struct of tcam128x48 is component L_CAM generic ( lpm_type : string := “LPM_CAM”; lpm_width : integer := 1; lpm_numwords : integer := 1; lpm_widthad : integer := 1; lpm_init_file : string := “dummy”; lpm_init_flag : integer := 0; lpm_hint : string := “UNUSED”); port( Data : in std_logic_vector(lpm_width-1 downto 0); WrAddress : in std_logic_vector(6 downto 0); ClockEn : in std_logic; Clock : in std_logic; WE : in std_logic; EnMask : in std_logic; WrMask : in std_logic; WrDC : in std_logic; Reset : in std_logic; Address : out std_logic_vector(6 downto 0); Match : Out std_logic; MulMatch : Out std_logic); end component ; begin U0: L_CAM generic map (LPM_WIDTH => 48, 41 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor LPM_WIDTHAD LPM_NUMWORDS LPM_INIT_FILE LPM_INIT_FLAG port map ( Data WrAddress ClockEn Clock WE EnMask WrMask WrDC Reset Address Match MulMatch => => => => => => => => => => => => => => => => end struct; 42 7, 128, “CAM_init”, 1) Data, WrAddress, ClockEn, Clock, We, EnMask, Wrmask, WrDc, Reset, Address, Match, MulMatch); Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Read-Only Memory (LPM_ROM) library IEEE; use IEEE.std_logic_1164.all; LIBRARY lc5kmx; USE lc5kmx.components.all; entity trom16kx2 is port ( Address OutClock OutClockEn Reset Q end trom16kx2 ; : : : : : in std_logic_vector( 13 downto 0); in std_logic; in std_logic; in std_logic; out std_logic_vector(1 downto 0)); architecture struct of trom16kx2 is component L_ROM generic ( lpm_type lpm_width lpm_numwords lpm_widthad lpm_outdata lpm_address_control lpm_init_file lpm_hint : : : : : : string := “LPM_ROM”; integer := 1; integer := 2; integer := 1; string := “UNREGISTERED”; string := “REGISTERED”; : string := “dummy”; : string := “UNUSED”); port ( Address : in OutClock OutClockEn Reset Q : out end component ; std_logic_vector (lpm_widthad-1 downto 0); : in std_logic; : in std_logic; : in std_logic; std_logic_vector (lpm_width-1 downto 0)); attribute syn_black_box: boolean; attribute syn_black_box of L_ROM: component is true; begin U0: L_ROM generic map ( LPM_WIDTH => 2, LPM_WIDTHAD => 14, LPM_NUMWORDS => 16384, LPM_OUTDATA => “REGISTERED”, LPM_ADDRESS_CONTROL => “REGISTERED”, LPM_INIT_FILE => “ROM_init”) port map ( Address => Address, OutClock => OutClock, 43 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor OutClockEn Reset Q => OutClockEn, => Reset, => Q); end struct; 44 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Appendix C. Initialization File Usage Guide Introduction The initialization file is a text file primarily used for preloading user-specified data into the memory array. This file is mainly used for configuring ROM, but is optional for dual-port, pseudo dual port and single port SRAM, FIFO and CAM modes. Figure 6 is an example of an initialization file. Figure 6. Sample Initialization File (20x32) 11111111111111110000000000010001 11111111111111100000000000010000 11111111111111011111111111111111 11111111111110111111111111111111 11111111111110101111111111111111 11111111111110011111111111111111 11111111111110001111111111111111 11111111111101111111111111110001 11111111111101101111111111110001 11111111111101001111111111110001 11111111111100110000000000100100 11111111111100100000000000100100 11111111111100010000000000100100 11111111111100000000000000100100 11111111111011110000000000100100 11111111111011010000000000000110 00000000000100010000000000000110 00000000000100000000000000000110 00000000000011110000000000000110 00000000000011100000000000000110 Address locations are numbered sequentially from 0 to lpm_numwords -1. The first or topmost entry corresponds to the initialization data at address 0, and the last entry to address LPM_NUMWORDS-1. Bits are read right to left, starting from the LSB to MSB. In the initialization file shown above for example, the top right-most bit correlates to bit 0 of Address 0, while the bottom left-most bit correlates to bit 31 of Address 19. Initialization data can only be entered in binary format. Data depth and width are defined by the size of the user instantiated memory. The number of rows corresponds to the number of address locations in the array (depth), and the number of columns matches the data width. Inputs are specified in binary format, and each bit can either be a 1, 0, X (don’t care) or a U (undefined). Note that ‘X’ and ‘U’ inputs only apply for CAM. Excess bits and/or undefined characters in the initialization file are flagged as errors during compilation. An initialization file can have any name, but it should match the filename specified in the HDL source file. The file cannot have a trailing three-character extension or file type. Initialization filenames with trailing extensions are not valid, and therefore flagged as errors during compilation. To preload memory using an initialization file, simply define the ‘lpm_init_file’ parameter in your top-level HDL source file and specify the initialization file name. Figure 7 shows an example of a VHDL ROM module using an initialization file. In this case, the ‘lpm_init_file: string: = “ROM_init”;’ declaration was added into the component instantiation. The same concept applies for Verilog designs. The example shown in Figure 8 has been modified to include the ‘defparam U0.lpm_init_file=”init1”;’ declaration. 45 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 7. VHDL ROM instantiation with lpm_init_file defined entity trom512x121 is port ( Address OutClock OutClockEn Reset Q end trom512x121 ; : : : : : in std_logic_vector( 8 downto 0); in std_logic; in std_logic; in std_logic; out std_logic_vector(120 downto 0)); architecture struct of trom512x121 is component L_ROM generic ( lpm_type lpm_width lpm_numwords lpm_widthad lpm_outdata lpm_address_control lpm_init_file lpm_hint port ( Address OutClock OutClockEn Reset Q end component ; : : : : : : : : : : : : : string integer integer integer string string string string in in in in out := := := := := := := := “LPM_ROM”; 1; 1; 1; “UNREGISTERED”; “REGISTERED”; “ROM_init”; “UNUSED”); std_logic_vector (lpm_widthad-1 downto 0); std_logic; std_logic; std_logic; std_logic_vector (lpm_width-1 downto 0)); begin U0: L_ROM generic map ( LPM_WIDTH => 121, LPM_WIDTHAD => 9, LPM_NUMWORDS => 512, LPM_OUTDATA => “REGISTERED”, LPM_ADDRESS_CONTROL => “REGISTERED”, LPM_INIT_FILE => “ROM_init”) port map ( Address => Address, OutClock => OutClock, OutClockEn => OutClockEn, Reset => Reset, Q => Q); end struct; 46 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 8. Verilog ROM instantiation with lpm_init_file defined module test_rom512x121( Q, Address, OutClock, OutClockEn, Reset); output [120:0] Q; input [8:0] Address; input OutClock,OutClockEn,Reset; L_ROM U0(.Q(Q),.Address(Address),.OutClock(OutClock),.OutClockEn(OutClockEn),.Reset(Reset)); defparam defparam defparam defparam defparam U0.lpm_width=121; U0.lpm_widthad=9; U0.lpm_numwords=512; U0.lpm_outdata=”UNREGISTERED”; U0.lpm_init_file=”init1”; endmodule module L_ROM( Q, Address, OutClock, OutClockEn, Reset); parameter parameter parameter parameter parameter parameter parameter parameter lpm_type = “LPM_ROM”; lpm_width = 1; lpm_numwords = 1; lpm_widthad = 1; lpm_outdata = “UNREGISTERED”; lpm_address_control = “REGISTERED”; lpm_hint = “UNUSED”; lpm_init_file=”dummy”; output [lpm_width-1:0] Q; input [lpm_widthad-1:0] Address; input OutClock,OutClockEn,Reset; endmodule // lpm_rom For additional examples, refer to Appendices A and B. 47 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Common Mistakes and Error Messages Most initialization file issues are related to the memory file size or the filename format. The most common errors in generating initialization files are: 1. Specifying an incorrect depth (number of rows) or width (number of columns) 2. Using invalid filenames (i.e. CAM_init.dat) 3. Using invalid characters (i.e. Use of any other character aside from a ‘1’, ‘0’ or ‘X’) Below are some sample error messages that can help diagnose an initialization file problem. For reference, the following example uses a 96X128 CAM. Figure 9 shows the error generated when the initialization file data width exceeds the predefined CAM width. Because the CAM configuration width is set at 96, and the initialization file data has 98 bits, an error is generated by the compiler. Figure 9. Error: Data width is greater than the defined memory width Figure 10 shows an error generated by the compiler when the initialization file data exceeds the total word count in the CAM array. By definition, the CAM can only hold 128 words. Since the initialization file has 129 words (rows), the compiler automatically errors out. 48 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 10. Error: Data depth is greater than the defined number of words Figure 11 illustrates the error generated when invalid characters are detected in the initialization file. In this case, invalid ASCII characters are inserted into the file (not shown) to show the error message. Figure 11. Error: Invalid characters are used in the initialization file The compiler also flags incorrectly named initialization files. Figure 12 shows an example where the initialization file is associated with a three-character file extension. In this case the lpm_init_file = “CAM_init.dat” definition is included in the source file. Upon compilation, the compiler is unable to resolve the ‘.DAT’ file extension and errors out. 49 Using Memory in ispXPLD 5000MX Devices Lattice Semiconductor Figure 12. Error: Initialization file is associated with a three-character extension or file Technical Support Assistance Hotline: 1-800-LATTICE (North America) +1-408-826-6002 (Outside North America) e-mail: [email protected] Internet: www.latticesemi.com 50