Project 6: Moving Memory
Due 6 April 2015
The purpose of this project is to learn how to make use of a ROM and a RAM memory so that you can use them as part of a larger CPU design.
This is the first part of three coordinated projects. You should demonstrate that you can read and write the memory properly by the end of the first week.
The overall task is to create a circuit that has both a ROM and a RAM. Both the ROM and the RAM should be initialized from an MIF file. The circuit should first read through the RAM, displaying the contents on either the 7-segment displays or 8 LEDs. Then it should copy the contents of the ROM into the RAM and repeat the process. The initial contents of the RAM will be displayed only the first time it is read.
- Make a new project for lab 6 in a new folder. If you are going to use a 7-segment display to show the contents of memory, then copy over your 7-segment display driver in to the new folder. I'll refer to the project and top-level circuit as ramtest.
- Create an MIF file for your ROM that has 16 words of 8 bits each. Load the memory with a set of patterns.
- Using the Tools:MegaWizard Plug0in Manager, create a ROM that has 16 words of 8 bits each. Therefore, it should have 4 address bits and 8 data bits. I'll refer to this circuit as MemROM. Tell it to initialize the ROM using the MIF file you created in the prior step. This step will create a VHDL file that you will include in your project.
- Create an MIF file for your RAM that has 16 words of 8 bits each. Load the memory with a set of patterns that are different from the ROM.
- Using the Tools:MegaWizard Plug0in Manager, create a RAM that has 16 words of 8 bits each. Therefore, it should have 4 address bits and 8 data bits. I'll refer to this circuit as MemRAM, Tell it to initialize the RAM using the MIF file you created in the prior step. This step will create a VHDL file that you will include in your project.
Create a top-level VHDL file with an entity that has the same name as
the project (e.g. ramtest). Your ramtest entity will need a clock
signal, a reset signal, and an output port for sending signals to
either the 7-segment displays or 8 LEDs.
Create component statements for both the ROM and RAM in the architecture header. Be sure to include the two files created by the Wizard in your project and call them from your top level design. The component statement for the ROM should look like:
component MemROM PORT ( address : IN STD_LOGIC_VECTOR (3 DOWNTO 0); clock : IN STD_LOGIC; q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ); end component;
The port map statement will look something like the following.
romcircuit: MemROM port map ( address => std_logic_vector(ROMADDR), clock >= clk, q => romwire );
Create the internal signals you will need to build the state machine
and access the ROM and RAM. I would recommend using a model where the
address for the ROM is stored in one register (e.g. ROMADDR) and the
address for the RAM is stored in a second register (RAMADDR). These
will both be internal 4-bit unsigned signals.
Likewise, you will want an internal asynchronous signal (one not assigned inside a process) that will represent the wires connected to the output (q) of the ROM and RAM. You can call these something like romwire and ramwire and they should be 8-bit std_logic_vector or unsigned types.
Then you will need clocked registers to hold the contents being uploaded or downloaded from memory. These should be 8-bit std_logic_vector or unsigned internal signals that get assigned only inside a process statement. You could call these ROMDATA and RAMDATA.
Finally, you will need a state variable (4-bit std_logic_vector), a writeEnable (1-bit std_logic) and a startupcounter variable (2 bits unsigned).
Plan out your state machine. You will need to have at least three
clock ticks at startup before trying to use any of the memory circuits
to allow it to initialize. A good plan is to have state "0000" be
your startup state, increment your startupcounter each time the
circuit is in that state, and have the circuit leave the state when
the startup counter reaches 3.
Your state machine will have two parts to it. The first part should read through the RAM and send the contents to the output port by assigning the RAMDATA internal signal to the output port signal outside of the process.
The second part should read the contents of the ROM and assign them to the RAM. This will be a multistep process. You may be able to compress the process into fewer clock cycles, but the following steps are a good way to start. Both ROMADDR and RAMADDR should start at "0000". From step 5, if ROMADDR is 0 (the circuit has wrapped around) then return to part one where the circuit reads through the contents of the RAM.
step 1: let the ROMADDR be stable for 1 clock cycle step 2: assign the value on the romwire to ROMDATA step 3: assign the value of ROMDATA to RAMDATA and increment ROMADDR step 4: set write enable to '1' step 5: set write enable to '0' and increment RAMADDR
- Add a slowclock to your circuit and demonstrate the circuit on the board. Be sure to document your testing for your writeup.
- See how few states you can use to execute this task.
- Enable some kind of user input to the task.
- Write a Python program that can generate an MIF file from some other, more easily readable, format.
- Add a hold/freeze button to the state machine.
- Be creative.
Create a wiki page with your writeup. For each task, write a short description of the task, in your own words.
- Include a description of your top-level design.
- Include the initial contents of both your RAM and ROM.
- Describe the hardware testing you undertook to prove the circuit works. A short video is strongly recommended.
- Include a description, and pictures, of any extensions.
Give your wiki page the label cs232s15project6.
Put your VHDL files in your Private subdirectory on the handin server in folder for this project. If you have any issues with the server, use vpn.colby.edu or send a tgz or zip file to the prof.