Lab 6: Moving Memory
The purpose of this lab is to give you experience working with both read-only and random-access memory. Reading and writing from memory is a multi-step process and requires setting signals in the proper order and giving the memory sufficient time to respond to the signals.
- Create a new project in a new folder for lab 6 (e.g. romtest).
Create an MIF file for your ROM that has 16 words of 4 bits each. Load
the memory with a set of patterns. You can do this within Quartus or
using any text editor. The format is simple: define the size and radix
of the addresses and data, then define the memory contents. The
example below defines a 16-element memory with 4-bits in each memory
location. Note how the last 8 elements are defined in a single
statement using a range of addresses.
-- program memory file DEPTH = 16; WIDTH = 4; ADDRESS_RADIX = HEX; DATA_RADIX = BIN; CONTENT BEGIN 0 : 1010; 1 : 0101; 2 : 0010; 3 : 0001; 4 : 0000; 5 : 1000; 6 : 0100; 7 : 0010; [8..F] : 1111; -- fill A0 to A1 with all 1s END
Using the Tools:MegaWizard Plug-in Manager, select 'Create a new
custom megfunction variation', then select the 1-port ROM from under
'Memory Compiler' and give it a name like memrom.
Using the setup dialog, create a ROM that has 16 words of 4 bits each. In the Mem Init step, select the MIF file you already created. The output of the wizard will be a VHDL file from which we can copy the component and port map statements. When you are done, open the file and look at it. Note how the generic statements define the size and functionality of the memory circuit in the port map statement.
- Create a top-level VHDL file for your project (e.g. romtest). The entity should have a clock, reset, and a 4-bit std_logic_vector output port. Copy the port statement from the ROM VHDL file created above and put it in a component statement in your architecture header section.
- Add internal signals for the ROM address (4-bit unsigned), ROM data (4-bit std_logic_vector), a ROM wire the same size as the ROM data (4-bit std_logic_vector), and a state variable that can represent 8 states (3-bit unsigned).
- Create a port map statement for the ROM circuit and link the ROM wire to the ROM output (q), link the ROM address variable to the address input, and link the clock signal to the clock input.
Make a process statement that is sensitive to the clock and reset
signals. In the reset case, set the ROM address variable to "0000",
set the state to "000", and set the ROM data register to all zeros.
In the rising edge case, make a state machine with 8 states. The first five states, from "000" through "100" should increment the state variable. Note that you can make a single when represent multiple states by using an expression like the following.
when "000" | "001" | "010" =>
States "101" and "110" should also increment the state variable. State "111" should write the value in the ROM wire variable to the ROM data variable, increment the address, and set the state variable back to "101".
- Outside the process, make a concurrent signal assignment that assigns the ROM data to the output port signal.
Simulating this circuit is slightly more complex because we are using
the built-in Altera functions. The following commands should enable
you to simulate the circuit using ghdl and gtkwave. Note that you
should execute the first instruction only the first time you run
the simulation. Use membench.vhd to test
ghdl -a --ieee=synopsys -fexplicit --work=altera_mf /opt/altera/12.1/quartus/eda/sim_lib/altera*.vhd
ghdl -a --ieee=synopsys -fexplicit --work=altera_mf membench.vhd memtest.vhd memrom.vhd
ghdl -e --ieee=synopsys -fexplicit --work=altera_mf membench
ghdl -r membench --vcd=membench.vcd
There may be lots of warnings when compiling the altera libraries, and you may also get many warnings in the -e stage, the first time you run it.
It is not necessary to close gtkwave each time you run the simulation. Instead, leave it running, execute the -a / -e / -r ghdl commands and then select File->Relead Waveform from within gtkwave.
- Add a counter and a process to your architecture that slows down the clock so you can see the memory process occur on the board. If you want, modify your port statement so that you can also view the address. Set up the pins so 4 LEDs are connected to the circuit output. When you run the circuit on the board, you should see the contents of memory cycle by.
When you have completed the lab assignment, go ahead and get started on the current project.