Hello, in my previous article we talked about Ahmes programming model, VHDL coding and simulation using Altera’s Quartus II IDE. Now it’s time to take a step further and take a look at a real implementation of Ahmes.
Although it would be possible synthesizing Ahmes as shown in my previous article and program (actually configure) an FPGA with the original project, I decided to modify the project a little bit in order to make a better use of FPGA’s resources. Hence, instead of using the original VHDL described memory, I decided to use the internal RAM memory (embedded memory) available through Altera’s MegaFunctions. I also created an output port mapped to the address 255 of the memory map.
The MegaFunctions are libraries of logic circuits (known as Intellectual Property – IP) previously tested and made available by Altera for using with its components. The advantage of using MegaFunctions for Ahmes memory is that Quartus II will automatically assign internal embedded memory (in the form of embedded M9K memory on the Cyclone IV) instead of logic elements and registers as we saw on our previous article. Moreover, using an Altera’s IP based memory ensures high reliability and more flexibility as those memories are completed configurable, allowing contents initialization through HEX or MIF files and even real-time reading and writing of the memory content!
In order to verify and test Ahmes operation we used a small kit based on a Cyclone IV FPGA model EP4CE6. This board presents a single USB port (for supplying power and communication through an on-board FTDI FT232RL serial-USB converter), two user keys, eight LEDs, one configuration key, a 50MHz oscillator module, an EPCS4 configuration memory and the FPGA itself, a Cyclone IV model EP4CE6E22C8, packed with 6,272 logic elements, 30 M9K memory blocks (each one with 9,216 bits of storage, resulting in 276,480 bits of on-chip RAM memory), 15 18×18-bit multipliers and 2 PLLs.
Modifying Ahmes Memory
Exchanging the previous RAM memory, a VHDL defined one, for a new IP-based one, implies on inserting a new component into the project.
Before starting, notice that the target component for the project must be changed to Cyclone IV EP4CE6E22C8, which is the model mounted on the kit we used here.
By selecting the insert option on the schematic window a large listing of components is shown, including storage components as RAMs and ROMs in several flavours (single-port, dual-port, FIFO, etc) and also shift-registers. We are going to choose a synchronous memory based on the LPM_RAM_DQ IP.
Quartus II will then load the IP configuration wizard which guides the user through the memory parameterization and configuration process.
On the next screen the wizard presents the basic memory configuration parameters: data-bus width, memory capacity (in words) and clocking options. Ahmes uses a 256-word 8-bit memory and a single clock source. Notice in the bottom of the screen the wizard shows only one M9K embedded memory module (out of 30 available on the target FPGA) is being used.
The next screen shows more options for the memory ports and control signals. We chose to disable the output registers “q” as shown in figure 5.
The next screen allows configuring the memory output behavior during a write operation. We chose not to change the default option (read data is the newly written data).
The next screen (figure 7) allows configuring the memory contents during initialization. As for Ahmes, we are going to load the memory with a file (loop2.mif) which is part of the project. This file has the binary coding of a small program to blink the LEDs connected to the output port.
Another important and useful feature which should be enabled is the “Allow In-System Memory Content Editor to capture and update content independent of the system clock” option. It instructs Quartus II to make use of a dual-port RAM IP which enables both the Ahmes CPU and JTAG interface to access the memory! This is an interesting option for development and can be disabled later on (as it makes use of aditional FPGA resources).
Once completed the wizard will generate files for the component and all you have to do is to insert the new component into Ahmes schematic.
The memory initialization contents is defined in the loop2.mif file, which can be edited by using the Quartus II memory editor (figure 8). In fact, the mif file is a plain text file and can be edited on any text editor.
Along with the changes to the main memory, our new Ahmes also needs an output port in order to communicate with the real world! In order to do that we created a small component to work as an 8-bit output port (improperly named PIO, but without an input feature). This component makes use of a fairly simple VHDL code shown below:
LIBRARY ieee ; USE ieee.std_logic_1164.all ; USE ieee.std_logic_unsigned.all ; ENTITY pio IS PORT ( address_bus : IN INTEGER RANGE 0 TO 255; data_in : IN INTEGER RANGE 0 TO 255; out_port : OUT INTEGER RANGE 0 TO 255; mem_write : IN std_logic ); END pio; ARCHITECTURE porta_io OF pio IS BEGIN process (mem_write) BEGIN IF (RISING_EDGE(MEM_WRITE)) THEN IF (ADDRESS_BUS=255) THEN out_port <= DATA_IN; END IF; END IF; end process; END porta_io;
The code basically describes an 8-register which is written when the CPU writes onto address 255 of the memory. Notice that both the register and the memory address are written in the same operation, however, a read operation of address 255 always returns the memory contents.
The last step before starting final synthesis is defining which FPGA pins will connect to the clock, reset and output port signals. This assignment process is started by the “Assignment Editor” option on Quartus II Assignments menu. Figure 9 shows the pin assignment for our Cyclone IV kit.
After all the Ahmes schematic should look like the one pictured on figure 10. Notice we also included an inverting gate on the RAM clock input. It makes the memory reading and writing operations to be triggered on the falling edge of the system clock (remember that Ahmes puts addresses and data on the buses on the clock’s rising edges). We included that inverting gate in order to ensure addresses and data are stable when the memory read/write is triggered.
Synthesis and Configuration
After the project synthesis is completed, a summary with all FPGA resources used by the project is shown:
Note that the complete project, including Ahmes CPU, an output port and 256 bytes of RAM occupy only 459 out of 6,272 logic elements and only 2,048 out of 276,480 bits of available embedded memory! That means there is plenty space for a more complex CPU, more memory and more peripherals too! Also notice that the FPGA used in this project is the smaller device of the Cyclone IV product line, which includes devices with up to 115,000 logic elements and up to 4Megabits of embedded memory! Other FPGA families from Altera and other manufacturers are even more powerful!
Once the project was successfully synthesized, it is time to configure the FPGA. As a result of the project synthesis, a .sof file is generated. This file includes all FPGA configuration data and also the memory initialization data. In order to download the file to the FPGA we can use Quartus II programming tool:
After the configuration file is downloaded to the FPGA, it will be automatically configured and Ahmes will start operating immediately! Ahmes is “brought to life”! Welcome to the real world Ahmes!
One important thing to notice is that this process only configure the FPGA by using the JTAG interface (through the USB Blaster), but our FPGA (as most of them) is a RAM based device, meaning that it is a volatile device and will loose its configuration when powered down. That is why there is a configuration memory mounted on the board (the EPCS4 in our board): it is a serial FLASH memory which stores one (or more) configuration files and it is read by the FPGA during boot up process. That means the configuration stored inside this memory is loaded by the FPGA every time it is powered on.
In order to store our own configuration inside that memory, we must use a different approach than the one used to configure the FPGA. Instead of using the sof file, we are going to need a JTAG indirect configuration (jic) file. In practice that means configuring the FPGA as a transparent bridge which will transfer data from the JTAG interface to the configuration memory.
Generating the jic file is a very simple process. All you need to do is to open the programming file converter (menu File>Convert programming files…) as shown in figure 13.
You are going to select the JTAG indirect configuration file (jic) option, the configuration memory model (EPCS4) and also select the appropriate device on the flash loader (EP4CE6) and the project sof file (ahmes.sof). Click the Generate button and Quartus II will generate a fresh new jic file.
With the jic file ready, open the Quartus II programmer tool, remove the old programming file and add the newly jic file we’ve just created. Tick the “Program/Configure” option and press the Start button to program the configuration memory. Notice the programming process is clearly longer than the FPGA configuration download.
Once the programming process is completed you can press the “Config” button on the board to load the FPGA with the configuration from the memory. It will also be automatically loaded every time the board is powered on.
Another last important feature that I would like you to know is the In-System Memory Content Editor, which allows real-time inspection of the memory contents and even changing contents on-the-fly. This feature is available because we enabled it on the memory IP configuration wizard as shown before.
In order to see this tool in action, select the option “In-System Memory Content Editor” within Quartus II “Tools” menu. A new window similar to the one in figure 15 will be shown. Once the tool establishes communication with the target FPGA, all you have to do is to select the desired instance (0 in our case) and click the read button (or press F5 key) to make the tool read all memory contents and updates the screen! It is also possible to change the memory contents (F7) and start a real-time memory view (F6).
Remark: the attentive reader will notice the screen depicted in figure 15 is showing the connected device as an EP3C10/5 which is actually a Cyclone III. That fact also draw author’s attention and after some investigation (and considering the possibility of a remarked chip), found out that according to the Cyclone IV Handbook, the ID 0x020F1 presented by the tool is compatible with an EP4CE6 device. The conclusion is that possibly the tool itself has an internal bug.
This article showed that our Ahmes implementation not only works in theory, but also in practice.
We could see some additional features of Altera’s FPGAs, VHDL programming and Quartus II tool (version 9.1sp2).
I hope the reader can have as fun as the author on the adventures of these fabulous synthetic processors!
All project files are available on my GitHub account.
 – Ahmes a simple 8-bit CPU in VHDL
 – Altera
 – Altera MegaFunctions
 – Embedded M9K memories
 – Cyclone IV Handbook
 – Altera EPCS configuration memories datasheet