Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
98 views10 pages

Example 42 - External RAM ROM

This document describes how to interface with external memory on a Digilent Spartan 3-S3 Prototype board. It contains 256K x 16 asynchronous static random-access memory (SRAM). The memory uses an 18-bit address bus and 16-bit bidirectional data bus. It is controlled using write enable, output enable, chip enable, and byte enable signals. Timing diagrams show read and write cycles require a maximum of 12ns. The board contains two such memories that can be used together as larger memories like 256Kx32, 512Kx16, or 1024Kx8. A component is created to interface with the external memories.

Uploaded by

Bárbara Bab
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
98 views10 pages

Example 42 - External RAM ROM

This document describes how to interface with external memory on a Digilent Spartan 3-S3 Prototype board. It contains 256K x 16 asynchronous static random-access memory (SRAM). The memory uses an 18-bit address bus and 16-bit bidirectional data bus. It is controlled using write enable, output enable, chip enable, and byte enable signals. Timing diagrams show read and write cycles require a maximum of 12ns. The board contains two such memories that can be used together as larger memories like 256Kx32, 512Kx16, or 1024Kx8. A component is created to interface with the external memories.

Uploaded by

Bárbara Bab
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Memory: External Memory 1

Example 42

Memory: External Memory


In this example we will learn how to create a component to interface with external
memory. As an example, we will interface to the external memory on the Digilent
Spartan 3-S3 Prototype board. The memory is fast, asynchronous static random-access
memory (SRAM).

Prerequisite knowledge:
Example 41 – Memory: Random-Access Memory

42.1 External Random-Access Memory

In Example 41, we implemented random-access memory using distributed


memory or block memory within the FPGA. Distributed memory uses reconfigurable
resources to implement memory; therefore, the amount of RAM that can be used is
limited to the size of the FPGA. Further, the amount of block memory on the FPGA is
also limited. Neither distributed nor block memory are suitable for applications that
require bulk memory for data storage. For these applications, an external memory is
generally used. Digilient’s S3 Board contains a Spartan 3 FPGA and external fast,
asynchronous memory. Since there are many different ways in which memories can
operate, it is important to consider the specification for the particular external memory
before developing interface hardware. Fig. 42.1 shows a block diagram for memory of
the type that is on the Digilent board.

A[17:0]

OE
I/O[15:0]
buff3 256K x 16
RAM
CE UB

WE LB

Figure 42.1 A Block Diagram for the 256K x 16 External SRAM


2 Example 42

To address 256K address spaces, the address bus, A, is an 18-bit input. A write
enable line, WE, is used to control whether data is being written to the memory or read
from the memory. The write enable line is active low as indicated by the bar over top of
the signal in the schematic. If data is to be written to the RAM, WE is asserted low.
Otherwise, if data is to be read from the RAM, WE is asserted high. The data bus, I/O, is
a shared, bidirectional bus. The output enable, OE, is enabled when OE is asserted low
and therefore I/O is an output data bus. When OE is asserted high, I/O is an input data
bus. Using a bidirectional bus for the input/output data requires fewer external pins than
if they were to separate busses. CE is a chip enable input. When CE is low, the RAM
chip is enabled and operates according to the WE, A, and I/O signals, otherwise it is
disabled. Finally, the active low UB and LB signals identify whether the memory
operation is to take place on the upper byte and/or lower byte of the 16-bit memory
location addressed by A. Since this RAM is asynchronous there is no clock signal,
instead reading and writing are controlled by the WE and OE signals. Figure 42.2 shows
a truth table for these signals and memory functions.

Figure 42.2 Truth Table for External SRAM Operation

When CE is high, the chip is disabled and all I/O pins are high impedance. When
CE is low, the chip is enabled and there are three basic modes of operation: output
disabled, read, and write. If OE is high, then the output is disabled. Likewise, if both LB
and UB signals are high, output is effectively disabled since neither the lower nor upper
bytes are active. In these cases I/O are also high impedance.
There are three ways to read data from the memory, selecting the lower byte, the
upper byte, or both. To read, the write enable, WE must be high since we do not want to
write and OE must be low since we want to enable the memory’s output. Finally, we
must select which byte or both that we wish to read by setting the active low LB and UB
signals accordingly. If LB is low and UB is high, for example, then I/O[0:7] will output
the data contained in the lower byte at address A while I/O[8:15] will be high impedance.
The opposite is true if LB is high and UB is low. If both LB and UB are low, then the
entire I/O bus will output 16 bits of data. These three mode selections can be helpful for
using the memory as a 256Kx16 or 512Kx8 RAM. For the 256Kx16, both LB and UB
would be active at all times. To operate the memory as a 512Kx8, LB:UB:A acts like a
Memory: External Memory 3

composite address where 01:A address the lower 256Kx8 while 10:A address the upper
256Kx8 memory locations.
There are also three ways to write data to the memory, selecting the lower byte,
the upper byte, or both. To write, the write enable, WE must be low and OE must be high
since we wish to write data to the memory. When OE is high, the I/O bus becomes an
input to the memory. Depending one which of the bytes (or both) are selected, the
corresponding I/O bus(es) will take input data to the memory. These three mode
selections are also used to write to the memory as a 256Kx16 or 512Kx8 RAM in the
same way described for reading data.
Fig. 42.1 contains a tri-state buffer to the I/O bus controlled by the active low OE
line. A tri-state buffer behaves according to the control line. If the control line is high,
the buffer is active and the buffer’s output is the same as the input. If the control line is
low, the buffer is not active and the output is high impedance. The opposite is true if the
buffer is active low. In this case, when OE is low, the buffer control line is low and
therefore the output is high impendence blocking the input data lines while the memory
outputs data for reading. When OE is high, the buffer control line is high and the input
data lines are connected to the memory for writing. It is important to implement such a
scheme using a tri-state buffer to avoid multiple devices driving the same, bi-directional
line at the same time.
So far, we have only considered how the memory works and have only identified
that a tri-state buffer is needed to arbitrate the bi-directional data bus since there is only a
single bus for data input and output. Finally, it is important to consider the timing
diagrams for reading from and writing to the memory. Considering this information, we
can learn how many clock cycles are required (if any) to read data from the memory, how
many clock cycles are required to write data to memory, and the maximum clock
frequency at which a read and write operation can correctly and completely execute. Fig.
42.3 shows a timing diagram for the read cycle. Fig. 42.4 shows a timing diagram for the
write cycle.

Figure 42.3 Timing Diagram for a Read Cycle


4 Example 42

Figure 42.4 Timing Diagram for a Write Cycle

According to the timing tables, the entire read cycle, trc, requires a maximum of
12 ns and the write cycle, twc, also requires a maximum of 12 ns. This means that the
maximum clock frequency for the memory is 83.3 MHz. As previously discussed, since
this memory is asynchronous, there is no input clock. It is up to the hardware controlling
the memory control signals, address bus, and data bus to ensure that the signals meet the
minimum timing according to the diagrams. Since the Digilent S3 Board contains a 50
MHz clock, there are no timing problems with this memory; reading and writing can both
be accomplished within the period of a single 50 MHz (or lower) clock cycle.

42.2 Creating a Component to Interface with the External SRAM


The Digilent S3 Board contains two of these fast, asynchronous 256Kx16
memories as shown in Fig. 42.5.

Figure 42.5 Wiring Diagram for the 2 SRAMs and the Spartan FPGA
Memory: External Memory 5

This type of wiring scheme offers several ways in which these two SRAMs can be
used. The WE and OE signals for both memories are tied together, therefore, a hardware
controller is either reading from or writing to the memories. The address lines, A, for
each are also tied together so that one common address bus is addressing both memories.
The CE, LB, and UB lines for each memory can be manipulated separately as CE1, CE2,
LB1, LB2, UB1, and UB2. Finally, the data input/output lines can also be accessed
separately as IO1 and IO2. Given this scheme, the two 256Kx16 memories can be used
as a single 256Kx32, 512Kx16, or 1024Kx8 memory.
To use the memories as a 256Kx32, a controller can be designed where LB1, LB2,
UB1, and UB2 are always active. The 256K memory locations can be addressed using
the 18-bit address line, A, and the 32-bit data can be accessed on the composite bus,
IO2:IO1.
The memories can be used as one larger 512Kx16 memory by enabling one
SRAM as the low 256K address and the other as the high 256K addresses. The LB1,
LB2, UB1, and UB2 signals would all be active at all times. For this, the composite
address CE1:CE2:A could be used. The low 256K addresses would be 0:1:A and the high
256K addresses would be 1:0:A where A is an 18 bit address. During the former, SRAM1
would be enabled and SRAM2 disabled while during the latter the opposite would occur.
A third method would be to use the memories as a single 1024Kx8 memory. In
this case, the first 256K bytes would be stored in the lower bytes of SRAM1, the second
256K bytes in the upper bytes of SRAM1, the third 256K bytes in the lower bytes of
SRAM2, and the final 256K bytes in the upper bytes of SRAM2. To accomplish this, a
composite address of CE1:LB1:UB1:CE2:LB2:UB2:A could be used. The addresses
would be as follows:
First 256K 0:0:1:1:1:1:A
Second 256K 0:1:0:1:1:1:A
Third 256K 1:1:1:0:0:1:A
Fourth 256K 1:1:1:0:1:0:A
where A is an 18-bit address. In this case, the 8 bits of data output by the controller
component would have to be repeated to all 32-bits of I/O bus, the high and low bytes for
SRAM1 and the high and low bytes for SRAM2.
For this example, we will develop a simple state machine that writes 8-bit data to
the first 16 memory locations and then reads these same values from memory for display
on the LEDs. This is the same objective as the state machine in the previous example,
Example 41, the data written to each memory location will be its address. We will only
need to use one of the two memories and can limit our example to using only the lower
bytes for storage. Fig 42.6 shows a diagram of this controller.
The tri-state buffer will switch between data input and output. Listing 42.1 shows
the VHDL code for the tri-state buffer. The tri-state buffer uses the generic statement to
declare a variable bus width. The output follows the input when the enable is high,
otherwise, the output data are high impedance.
Listing 42.2 gives the VHDL code for the state machine that writes incremental
data to the first 16 memory locations and then reads them back to the LEDs. LB is low
and UB is high since only the lower byte of each memory location is used. The controller
asserts WE low and OE high when writing and WE high and OE low, otherwise.
6 Example 42

FPGA
A[17:0] A[17:0]

OE OE
IO10
DataOut I/O[15:0]
buff3 256K x 16
ExtRAMsm RAM
CE CE UB

WE WE LB
CLR RAMData
To LEDS
CLK UB
LB

Figure 42.6 Schematic of an External RAM Controller

Listing 42.1 buff3.vhd a generic tri-state buffer

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity buff3 is
generic (width:positive);
port(
input : in STD_LOGIC_vector(width-1 downto 0);
en : in STD_LOGIC;
output : out STD_LOGIC_vector(width-1 downto 0)
);
end buff3;

architecture buff3 of buff3 is


begin
output <= input when en = '1' else (others => 'Z');
end buff3;

Listing 42.3 gives the VHDL code for the top level entity. This entity port maps
the controller and the tri-state buffer into the design. IO10 is declared as an inout signal
type. This indicates that the signal is both an input and an output. This is carefully
arbitrated by the tri-state buffer so that either the controller or the external RAM is
driving the signal at any given time and never both.
Memory: External Memory 7

Listing 42.2 ExtRAMsm.vhd the state machine for the controller

-- Simple state machine for writing to and reading from External RAM
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ExtRAMsm is
port ( clk : in std_logic;
clr : in std_logic;
WE : out std_logic;
LB1 : out STD_LOGIC;
UB1 : out STD_LOGIC;
CE1 : out STD_LOGIC;
OE : out STD_LOGIC;
DataOut : out std_logic_vector(7 downto 0);
addr : out std_logic_vector(17 downto 0)
);
end ExtRAMsm;

architecture ExtRAMsm of ExtRAMsm is

type state_type is (start, write, clear, read);


signal present_state, next_state: state_type;
signal addrcnt : std_logic_vector(3 downto 0);

begin

sreg: process(clk, clr)

begin
if clr = '1' then
present_state <= start;
elsif clk'event and clk = '1' then
present_state <= next_state;
case present_state is
when start =>
addrcnt := X"0"; --clear address variable
when write =>
addrcnt := addrcnt + 1; --inc addr var
when clear =>
addrcnt := X"0"; --clear address variable
when read =>
addrcnt := addrcnt + 1; --inc addr var
when others =>
null;
end case;
end if;
end process;
8 Example 42

C1: process(present_state, addrcnt)

begin
case present_state is
when start =>
next_state <= write;
when write =>
if addrcnt < 15 then
next_state <= write;
else
next_state <= clear;
end if;
when clear =>
next_state <= read;
when read =>
if addrcnt < 15 then
next_state <= read;
else
next_state <= start;
end if;
when others =>
null;
end case;

end process;

C2: process(present_state, addrcnt)

begin
LB1 <= '0'; --Activate lower byte only
UB1 <= '1'; --Deactivate upper byte
CE1 <= '0'; --Chip select active
OE <= '0'; --Output enable active (default read)
WE <= '1'; --Write enable inactive (default read)
case present_state is
when start => null;
when write =>
WE <= '0'; --Activate Write Enable
OE <= '1'; --Deactivate Output Enable
when clear => null;
when read => null;
when others => null;
end case;

end process;

addr <= "00000000000000" & addrcnt;


DataOut <= "0000" & addrcnt; --connect data to addr to write
--the addr as the data for each location

end ExtRAMsm;
Memory: External Memory 9

Listing 42.3 ExtRAMtest.vhd the top-level component


-- Top level for External RAM and the simple test state machine
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ExtRAMtest is
port ( clk : in std_logic;
clr : in std_logic;
A : out STD_LOGIC_vector(17 downto 0);
LB1 : out STD_LOGIC;
UB1 : out STD_LOGIC;
CE1 : out STD_LOGIC;
OE : out STD_LOGIC;
WE : out STD_LOGIC;
IO10 : inout STD_LOGIC_vector(15 downto 0);
RAMdata : out STD_LOGIC_vector(7 downto 0)
);
end ExtRAMtest;

architecture ExtRAMtest of ExtRAMtest is

component ExtRAMsm is
port ( clk : in std_logic;
clr : in std_logic;
WE : out std_logic;
LB1 : out STD_LOGIC;
UB1 : out STD_LOGIC;
CE1 : out STD_LOGIC;
OE : out STD_LOGIC;
DataOut : out std_logic_vector(7 downto 0);
addr : out std_logic_vector(17 downto 0)
);
end component;

component buff3 is
generic (width:positive);
port(
input : in STD_LOGIC_vector(width-1 downto 0);
en : in STD_LOGIC;
output : out STD_LOGIC_vector(width-1 downto 0)
);
end component;

signal DataOut : std_logic_vector(7 downto 0);


signal DataOut16 : std_logic_vector(15 downto 0);
signal OE_Sig : std_logic;

begin

TSBuffer: buff3 generic map (width => 16) port map(


input => DataOut16, en => OE_Sig, output => IO10);

DataOut16 <= "ZZZZZZZZ" & DataOut; --Since only lower byte is active
10 Example 42

--upper byte gets Zs

SM: ExtRAMsm port map(


clk => clk, clr => clr, WE => WE, LB1 => LB1, UB1 => UB1,
CE1 => CE1, OE => OE_Sig, DataOut => DataOut, addr => A);

OE <= OE_Sig;
RAMdata <= IO10(7 downto 0);

end ExtRAMtest;

Fig. 42.7 shows a simulation of this controller while it writes to the external
memory. Towards the end of the simulation, the controller begins reading the data from
the external memory. Since the external memory is not internal to the FPGA (as in the
case of the distributed and block memories), it is not being simulated. Therefore, when
the controller begins to read data back from the memory, high impedance is shown, the
output at the tri-state buffer.

Figure 42.7 Simulation of the External Memory Controller

You might also like