You are on page 1of 4

1.

0 Introduction of lpm_ram_dq() function


There are several ways to implement a memory module. Altera recommends using the
lpm_ram_dq to implement asynchronous memory or memory with synchronous inputs
and/or outputs. The lpm_ram_dq function uses EABs in FLEX 10K devices, or latch
arrays in other device families. If you are using a FLEX 10K device, Altera strongly recommends that you use synchronous rather than asynchronous RAM functions. However,
in the midterm examination, the asynchronous RAM function will be adopted because of
its simplicity and easy to incorporate into the design.
Embedded Array Block (EAB)
A physically grouped set of 8 embedded cells that implement memory (RAM or ROM) or
combinatorial logic in a FLEX 10K device. An EAB consists of an embedded cell array,
with data, address, and control signal inputs and data outputs that are optionally registered.
A single EAB can implement a memory block of 256 x 8, 512 x 4, 1,024 x 2, or 2,048 x 1
bits. Each embedded cell within the EAB implements up to 256 bits of memory. For memory blocks of these sizes, an EAB has 8, 4, 2, or 1 outputs, respectively. Multiple EABs
can be combined to create larger memory blocks. The EAB is fed by row interconnect
paths and a dedicated input bus.

1.1 VHDL Component Declaration:


COMPONENT lpm_ram_dq
GENERIC (LPM_WIDTH: POSITIVE;
LPM_TYPE: STRING := L_RAM_DQ;
LPM_WIDTHAD: POSITIVE;
LPM_NUMWORDS: STRING := UNUSED;
LPM_FILE: STRING := UNUSED;
LPM_INDATA: STRING := REGISTERED;
LPM_ADDRESS_CONTROL: STRING := REGISTERED;
LPM_OUTDATA: STRING := REGISTERED);
PORT (data: IN STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0);
address: IN STD_LOGIC_VECTOR(LPM_WIDTHAD-1 DOWNTO 0);
we: IN STD_LOGIC := '1';
inclock: IN STD_LOGIC := '1';
outclock: IN STD_LOGIC := '1';
q: OUT STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0));
END COMPONENT;

1.2 Input ports


data : Data input to the memory with LPM_WIDTH wide.
March 26, 1999

address: Address input to the memory with LPM_WIDTHAD wide.


we: Write Enable input. Enables write operations to the memory when high. It is required
if inclock is not present. If only we is used, the data on the address port should not change
while we is high. If the data on the address port changes while we is high, all memory
locations that are addressed are overwritten with data and the content of the memory is
nondeterminated.
inclock: Synchronizes memory loading. If the inclock port is used, the we port acts as an
enable for write operations synchronized to the rising edge of the inclock signal. If the
inclock port is not used, the we port acts as an enable for asynchronous write operations.
outclock: Synchronizes q outputs from memory.The address memory content-to-q
response is synchronous when the outclock port is connected, and asynchronous when it is
not connected. The asynchronous method will be adopted in the midterm examination.
Whenever the address is changed, the output will be available right away.

1.3 Output prots


q: Data output from the memory with LPM_WIDTH wide.

1.4 Parameters:
LPM_WIDTH: It is required and used to specify the Width of data and q ports.
LPM_WIDTHAD: It is required and used to specify the Width of the address port.
LPM_WIDTHAD should be (but is not required to be) equal to
log2(LPM_NUMWORDS). If LPM_WIDTHAD is too small, some memory locations
will not be addressable. If it is too large, the addresses that are too high will return undefined (X) logic levels.
LPM_NUMWORDS: It is used to specify total number of words stored in memory. If
omitted, the default is 2 ^ LPM_WIDTHAD. In general, this value should be (but is not
required to be) 2 ^ LPM_WIDTHAD-1 < LPM_NUMWORDS <= 2 ^ LPM_WIDTHAD.
If omitted, the default is 2 ^ LPM_WIDTHAD.
LPM_FILE: Name of the Memory Initialization File (.mif) or Hexadecimal (Intel-Format)
File (.hex) containing ROM initialization data ("<filename>"). If omitted, contents default
to all 0's.
LPM_INDATA: Possible Values are "REGISTERED" or "UNREGISTERED". Controls
whether the data port is registered. If omitted, the default is "REGISTERED".
LPM_ADDRESS_CONTROL: Possible Values are "REGISTERED" or "UNREGISTERED". Controls whether the address and we ports are registered. If omitted, the default
is "REGISTERED". If LPM_ADDRESS_CONTROL is "UNREGISTERED", the we port

March 26, 1999

is level-sensitive, so that when the we port is high, the address port must be stable to prevent other memory locations from being overwritten.
LPM_OUTDATA: Possible Values are "REGISTERED" or "UNREGISTERED". Controls whether the q and internal eq ports are registered. If omitted, the default is "REGISTERED".

1.5 Asynchronous Memory Operations (Example)


-- An example to use lpm_ram_dq function
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY lpm;
USE lpm.lpm_components.ALL;
USE ieee.std_logic_arith.all;
ENTITY fifo3 IS
PORT(
data: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address: IN STD_LOGIC_VECTOR (2 DOWNTO 0);
we, inclock: IN STD_LOGIC;
q: OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END fifo3;
ARCHITECTURE example OF fifo3 IS
BEGIN
inst_1: lpm_ram_dq
GENERIC MAP (lpm_widthad => 3,
lpm_address_control => "unregistered",
lpm_outdata => "unregistered",
lpm_width => 8)
PORT MAP (data => data, address => address, we => we,
inclock => inclock, q => q);
END example;

1.6 Simulation result (Wrong)


The following example shows a wrong instance at address 3 due to the change of address
when we is high. The content at address 3 is supposed to be 6 but it have been changed
into 10.

March 26, 1999

1.7 Simulation result (Corrected)


In order to solve the problem, we has to be changed to be logic low when addresses
change. This is the most tricky part when dealing with the asynchronous lpm_ram_dq
memory module.

March 26, 1999