Fetch Unit ########## .. include:: /header.inc .. vim:filetype=rst spell: The first major module in a Von Neumann machine is the ``Fetch Unit``. This part of the machine is responsible for selecting the next instruction to be processed by the machine. Here is a diagram showing this part of our machine in detail: .. circuits:: :width: 500 :align: center %-------------------------------------------------------------------- \newcommand{\pin}[3]{ % {coord}{color}{label} \begin{scope}[shift={(#1)}] \draw [fill=#2!30] (0.000000,0.000000) -- (0.250000,0.000000) -- (0.250000,0.250000) -- (0.000000,0.250000) -- cycle; \node at (0.125,0.125) {\tiny{#3}}; \end{scope} } \newcommand{\ctrl}[3]{% {coord}{color}{label} \begin{scope}[shift={(#1)}] \draw [fill=#2!30] (0.000000,0.000000) -- (0.175,-0.175) -- (0.350000,0.000000) -- (0.350000,0.350000) -- (0.000000,0.350000) -- cycle; \node at (0.175,0.175) {\tiny{#3}}; \end{scope} } \newcommand{\tick}[1]{% tick marker \begin{scope}[shift={(#1)}] \draw[fill=red!30] (0,0) -- (0.125,0.125) -- (0.25,0) -- cycle; \end{scope} } % fetch signals % Program counter wires \draw[ultra thick] (2.25,2.5) -- node[below] {w1} ++(2.5,0.0); % pc->im \draw[ultra thick] (3.5,2.5) -- (3.5,4.5) -- (7.75,4.5); \draw[ultra thick] (6.25,2.5) -- node[below] {op2} ++(1.5,0.0); % pc->im \draw[ultra thick] (6.25,1.5) -- node[below] {op1} ++(1.5,0.0); % pc->im % Decode Unit \begin{scope}[shift={(1,0)}] \pin{-0.25,2.375}{blue}{1}; \pin{1.00,2.375}{yellow}{2}; \draw [fill=blue!30] (0,0) -- (1.000000,0.000000) -- (1.000000,5.000000) -- (0.000000,5.000000) -- cycle; \node at (0.500000,2.500000) {pc}; \tick{0.375,0}; \end{scope} % Registers \begin{scope}[shift={(5,0)}] \pin{-0.25,2.375}{blue}{1} \pin{1,1.375}{yellow}{2} \pin{1.00,2.375}{yellow}{3} \draw [fill=green!30] (0,0) -- (1.000000,0.000000) -- (1.000000,4.000000) -- (0.000000,4.000000) -- cycle; \node at (0.500000,2.500000) {im}; \end{scope} .. note:: In this diagram, pins are simply numbered. Input pins are shown in blue, and output pins are shown in yellow. This diagram is missing signals coming from the control unit, we will discuss those in this lecture. Registers ********* A ``register`` is a single-value memory component. Registers need a read/write control signal, a data-in and a data-out path. When we call the ``tick`` method for this part, the read/write control signal determines what happens: * read: out <- val * write: val <- in A real memory array can be constructed using many simple register components. In that case, we need additional contorl lines, which we will discuss later. Program Counter Register ************************ The most important register in the machine controls the flow of instructions we want processed. For this, we create a special register that holds the address of the next instruction to be processed by the machine. We call this register the ``program counter``, or ``PC`` register. We initialize the ``PC`` address on the input side of the register with some known value, zero in our case. Normally, we will update this address so we "sequence" our instructions. When a real machine is first powered up, this address has to point to a valid program so the machine does not just "run away" processing random instructions. We will also need to provide a special "reset" signal for this register, in case we want to restart a program from that initial state. Some machines have a button that will reset the program counter, in case the program goes haywire! (Of course, you would never write such a program would you?) We will add that detail later. Fetching an Instruction *********************** The "fetch" step unit starts off by triggering the ``PC`` register, which sends the address of the instruction we want to process to the ``instruction memory`` (``IM``). The ``instruction memory`` is a simple memory unit that will hold all instructions to be processed by the machine. This memory unit does not support write operations (except for some feature that lets us load a program into the memory). So, when we deliver an address to the `IM`` unit, it will simply look up the selected instruction, and deliver it to the next point in the circuit. Barrier Registers ***************** That point is something we will call a ``Barrier Regisrer``. This one marks the end of the ``fetch`` phase, and the beginning of the ``decode`` phase. The barrier acts to stall one or more signals until all needed signals are ready to be passed along to the next stage in the machine. Signals will arrive at the input side of this barrier, and will sit there until we trigger them to begin flowing along to some other point in the system. The Next PC Address ******************* The ``Fetch Unit`` in this design also is responsible for updating the value held in the ``PC`` register. Normally, in our simple simulator, Instructions occupy one memory cell in the ``IM`` unit. This kind of machine is called a ``Harvard Machine`` because we separate instructions from data in this design. By separating these two major parts of memory in this way, we can make our ``instruction memory`` big enough to hold a full instruction, not just a single byte. In the ATtiny85, instructions are normally 16-bits wide, and data is eight-bits wide. That means that in normal sequencing of instructions, we need to add one to the ``PC`` register after we deliver an address to the ``IM`` unit. To do this, we simply pass the current address through an "incrementer``, which adds one to the current ``PC`` value, and then we pass that new value around to the input side of the ``PC`` register. Multiplexors ************ Sometimes, we need a way to select one signal from several possible signals we could deliver along to some point. The selector, which we call a ``Multiplexor``, needs to be controlled somehow, but all it does is to decide which of several signals to pass along. All other signals are ignored. In our current design, we need to be able to pass the normal next address along to the input side of the ``PC``, but there will be times when we want to send some other address to the ``PC`` instead. This is how we control "branching" in our machine. As we have seen, branching is needed to implement loops and decision structures. The ``Multiplexor`` along the next address path can switch between the signal coming out of the incrementer and another signal coming from elsewhere in the machine. This second signal is the ``banch address`` indicating that we are modifying the flow of instructions to set up a ``branch``. We have not seen where this branch address is set up, so we simply show it coming into the barrier register from stages we will get to eventually! Exactly how we control the timing of this part of the machine, and the decision to branch or not, is something we need to discuss next.