Coding for Reuse Course - Module 2 Lesson 1
Register File and Multiplexers

In this lesson we will study and develop the register file and the source and destination logic for our microprocessor.

The Register File  

A register file is a group of bi-stable devices that occupy some logical space, such as address, with some signal or group of signals to choose a specific physical entity during data storage or modification. In simpler terms, it is a read/write memory. The only difference occurs during read cycles; where the data from every entity is simultaneously available. This concept of concurrent reads is extremely important, especially in processors that may require multiple data sources to accomplish certain instructions.

Our register file consists of a group of eight and sixteen-bit registers. Most of the eight bit registers may be paired to form a sixteen-bit register. This architecture will require those registers or register halves to occupy different physical spaces on both the input (source) and output (destination) data busses.

Register File

These devices also need distinct input and output signals; moreover, each input signal or signal group requires a separate enable.

Most registers connect directly to the destination bus in the appropriate bit positions. However, the DE register requires an alternate, destination bus to allow the contents of HL and DE registers to be exchanged simultaneously.

When naming the registers or the associated signals, you must keep in mind the constraints of Rule 1.13.

The current flag state is part of our register file. In order to fully comply with the requirements or suggestions of Rule 1.4, Rule 6.6, and Rule 6.12; we should modify our parameter file to define flag bit positions as follows:

Parameter File with Flag Bit Positions Added

Now, observing all the criteria from the previous discussion, we are ready to code our register file:

Project Skeleton with Register File Coded

Note that when we coded our register file we brought all our register enables to the top level and then connected them to sequencer_r in accordance with Rule 3.6. There are a couple of other items that you might question in this code. The flags were split out individually because, if you examine any available literature on programming the 8085 series microprocessor series ( for example), you will immediately see that different instructions effect different flags. The flag bit positions are defined in our parameter file; therefore, our code requires an '`include' compiler directive to associate these definitions with our module. The attachment of registers to different sections of the destination bus reflects our 16-bit internal architecture; and the temporary register must be split in order to incorporate both 8 and 16-bit instructions.

Mux Considerations  

Before we begin coding our source and destination multiplexers, let's back up for a minute and examine some objectives. When we examine our instruction set, we can see both 8 and 16-bit mathematical operations. These operations imply immediate value, absolute value, and both one's and two's complement operands.

The source and destination multiplexers are a key component in achieving an architecture that results in the highest instruction execution speeds. You must combine your knowledge of Boolean math with your understanding of programmable logic.

  1. First let's examine a few Boolean math principles:

    1. A one's complement of a value can be achieved via an 'EXCLUSIVE OR' function with a number that has a 'one' in each corresponding bit position.

    2. A two's complement (negative) of a value is its one's complement incremented by one.

    3. The two's complement (negative) of a value followed by a one's complement of the result will decrement the original value by one.

  2. We must also look at our register arrangement and its effect on 8-bit operations. The fact that some registers occupy the upper eight bits of a sixteen-bit architecture presents a potential problem. In effect, those upper eight bits represent the value multiplied by 256. Thus we must borrow some of the 'NORMALIZATION' principles from floating point arithmetic and discard the exponents during the eight-bit operation and re-introduce them later. The source mux is unaffected, since all registers are already presented normalized. However, the destination mux must account for 'NORMALIZATION' and effectively multiply 8-bit results by 256 when those destination registers logically occupy bits 15:8 of the destination bus.

    This 'crossover' affects only 8-bit results that are stored in 8-bit registers attached to bits 15:8 of the destination bus.

  3. 8-bit operands may also be used in 16-bit two's complement arithmetic. This means that 8-bit operands must use 'sign extension' to match the width of the larger operand. To accomplish this, we set the upper 8 bits of the smaller operand to same value as bit 7 of the operand. In FPGA logic, those upper eight bits are first set to zero and then use an 'EXCLUSIVE OR' function with bit 7 of the original value. Sign extension is normally implemented after any required one's or two's complements.

  4. You must take into account other potential data sources and where those data sources may logically reside. For the lower 8-bits of the source bus, the address/DATA bus is an obvious one. But we also know that the 'DAA' instruction alters data, and therefore will require some kind of source data. The 'RIM' instruction will read from the 'SID' and interrupt inputs. The interrupt vector (address) must also be accounted for.

    Some register halves, such as the upper bytes of the SP and PC, may never occupy the lower eight bits of the source bus; based upon the instruction set. The address latch and instruction registers are not used as source data in any instruction.

From these observations, we can derive that:

  1. Both the source and destinations muxes must be capable of performing a one's complement of at least one operand.

  2. The source mux must accomplish sign extension for 8-bit operands during or after the one's complement.

  3. The destination mux needs to multiply 8-bit results that will occupy bits 15:8 of paired destination registers by 256 during or after the one's complement.

The Source Mux  

The source mux for our project is split into two separate paths:

  1. The lower source bus select is used in every instruction execution except 'NOP' and 'HALT', and for all internal bus cycles. It must select between one of the following data sources:

    1. The address/data bus.

    2. The accumulator register.

    3. The flags register.

    4. The 'B' register.

    5. The 'C' register.

    6. The 'D' register.

    7. The 'E' register.

    8. The 'H' register.

    9. The 'L' register.

    10. The lower half of the temp register.

    11. The lower half of the SP register.

    12. The lower half of the PC register.

    13. The DAA adjustment value.

    14. The interrupt mask.

    15. The interrupt vector.

    It must also be able to perform a one's complement of those bits; which leads to the following architecture:

    Lower Source Mux Architecture

    The dashed lines in this diagram represent a single logic level for the function. In short, we can select one of sixteen possible sources and potentially complement the selected source in just three logic levels.

  2. The upper source mux, contrary to expectations, is also used during most operations. Its primary responsibility is to select the most significant 8-bits of the source when 16-bit operations are performed. This means that it must also perform the sign extension of all eight-bit operands that are used within sixteen-bit functions.

    Possible data sources for the upper source mux are as follows:

    1. The accumulator register.

    2. The 'B' register.

    3. The 'D' register.

    4. The 'H' register.

    5. The lower half of the temp register.

    6. The upper half of the temp register.

    7. The upper half of the SP register.

    8. The upper half of the PC register.

    9. 8'b00000000 for sign extension.

    10. 8'b11111111 for sign extension.

    There are a couple of items that need further explanation here. The reason that the lower half of the temp register appears as a possible source for the upper byte has to do with I/O instructions. During an I/O instruction, the device address is contained in the immediate byte following the instruction opcode. During the subsequent I/O device cycle, this address is replicated on both AD[7:0] and A[15:8]. Rather than introduce the necessary extra logic to handle this situation, it is much more efficient to use the lower half of the temp register, the serves as the destination for immediate bytes, as a data source.

    There are therefore ten possible data sources for the upper source mux; implying two logic levels for source selection and complement, as we saw in the lower source mux. The way in which we add this additional logic level can influence routing costs. To minimize the impact of these costs, we take advantage of the fact that sign extension only occurs when no other upper source byte is selected. This automatically generates a zero. Secondarily, we tap bit 7 of the lower source muxes before combination and possible complement occurs. We must then enable this combination for sign extension. Any required operand complement is implemented after this selection is complete.

    The upper source mux then appears as follows:

    Upper Source Mux Architecture

We can now code our source select multiplexer as such:

Skeleton with Preliminary Source Multiplexer Added

You may notice certain terms are duplicated as an array. This is because compilers and simulators may vary in the application of operands that have differing bit widths. Since we have one bit signals that can modify every bit of 8 bit values, we duplicate them in all corresponding bit positions to ensure compatibility.

The Destination Mux  

Compared to the source select, the destination mux is relatively simple. It must accomplish three primary missions:

  1. It must select between data the originates from the source bus directly and data that has also been modified by the arithmetic/logic block.

  2. It can potentially perform a one's complement of the selected data.

  3. It must 'crossover' 8-bit results to the upper 8-bits of the destination bus.

  4. It must provide an auxiliary destination bus for the DE register pair to implement the XCHG instruction in a single clock cycle.

The following diagram depicts one realization of this destination mux:

Destination Mux Architecture

In this architecture, the standard mux is not ruled out for the first level selection. However, taking full advantage of the 4-input cells that are prevalent in most FPGA architectures, we can also add the destination complement selection.

Rather than adding the extra logic to handle the upper and lower destination bus inputs based upon the register's logical bit position on the destination bus; we can simply duplicate the least significant 8-bits into the most significant bit positions during eight-bit operations and let register input enables take care of the rest. Which leads us to the following:

Skeleton with Preliminary Destination Mux Added

  1. Why did we modify our parameter file?

  2. How did we incorporate this parameter file into our code?

  3. Why do we attach different data bit fields of the selected source to dissimilar bit positions of the destination bus?

  4. How did we do this?

  5. Why did we use two different multiplexer IPs.?

  6. Why did we use a virtual UDP rather than one of our standard multiplexers during first level selection?