Saturday, April 1, 2023

Poring over the compile messages and cleaning up my FPGA logic

VERY THOROUGH REVIEW OF HUNDREDS OF MESSAGES FROM QUARTUS

During the process of synthesis, fitting, routing and generation of the final binary to load the Field Programmable Gate Array (FPGA) half of the Cyclone V chip, the toolchain emits many messages both benign and indicative of potential errors in the submitted code.

Some of the messages are warnings that result from choices made while running Platform Designer (formerly QSYS), such as deselecting the option to have a flipflop delay on a particular bridge between the Hard Processor System (HPS) and the FPGA sides. Since the flipflop is not connected, there will be errors reported about dangling lines to the flipflop, after which the toolchain does the right thing and removes it from the design.

There are true issues in my code that were reported also. Each possible error caused me to think about what the warning message stated and look over my code. I found some signals that I generated for module A and another signal for module B, but the intent is to feed the signal between the two modules so there should be only one signal used. 

BOLSTERING MY ADDRESSING OF RAM FOR DISK CARTRIDGE CONTENTS

Truncation errors highlighted weak VHDL in the logic that generated the RAM address to be used for each word read or written to the disk. This was a bit complex, as it involved groupings like sectors, heads and cylinders, with each of the sectors taking up 321 contiguous words in memory. Finally, the pathway I used to access the sdram on the HPS side from the FPGA reads or writes blocks of four words at a time (eight bytes). 

The address sent to access sdram is 29 bits, as each integral value is a different eight byte block of the possible four gigabytes of RAM. Since I will be addressing individual words as the disk modeling logic reads or writes to disk, we have to convert between a word address (16 bits for the IBM 1130), a byte address, and a block address for SDRAM. 

Selecting which of the four words in a block is the target for the sdram access is done by setting the eight bit byteenable signal - each bit activates or blocks one byte of the eight in a block. Thus after I generate a 32 bit byte address from the cylinder, head, sector etc of the current disk activity, we drop bits from the end successively. 

First a bit is dropped to create 31 bit word addresses. Then two more bits are dropped to create the 29 bit block address. Those dropped bits select which two of the eight bits of byteenable are flipped on. This allows us to write only one of the four words in a block, leaving the other three as they were. 

Out of the four gigabytes of addressable RAM, only 1GB is installed on the DE10-Nano board. Further, most of that is used by the Linux image that runs on the HPS side. We reserve the last megabyte of RAM for our purposes holding the disk image. Thus, the 29 bit block address starts at a base value that is the beginning of the last megabyte of memory. 

To that we add the relative block address for our current disk access. The disk is organized in sectors of 321 words, four sectors per rotation. With two surfaces and heads, there are eight sectors available as the disk spins. By moving the arm in and out to one of 203 radii, the 203 cylinders provide 1,624 total sectors on a disk cartridge. 

My math to calculate the relative word address on the disk cartridge is:
            (Cylinder * 8) + Head * 4 + Sector) * 321 + Word 

This requires 99.4% of the 1MB area we set aside to hold the disk contents. The word address is converted to a byte 32 bit address, adding on the base address of the last megabyte of RAM gives us an absolute byte address. Since we are addressing blocks of eight bytes, only the leftmost 29 bits of the address are used to send to the sdram access method. As described above, the byteenable works with the last 3 bits of the 32 bit byte address. 

FINDING SUPERFLUOUS SIGNALS AND ELIMINATING THEM

I had been used to the Xilinx toolchain which, at least with VHDL code, would cease synthesis if a signal was not declared. It also threw up errors highlighting signals that are defined but not used anywhere.

The Quartus toolchain acts similarly except in one important way. If a signal in a Verilog module is used but not declared with a wire or reg statement, the toolchain makes an implicit definition and proceeds to compile everything. This happened because, with signal names being case sensitive, I might have had DiskRunning used in many places but written it as diskrunning somewhere else. Thus two signals were created when I intended a single common signal. I found a few of these and fixed them.

Messages telling me that signals had no driver, or that they had no destination, were keys to superfluous signals that I could trim out of the top level file which was in Verilog instead of the VHDL I used for everything else. 

No comments:

Post a Comment