Tuesday 31 December 2013

Register Design v0.1

The Juno has the following registers
  • A - General purpose register
  • B - General purpose register
  • IX(L) - Index Register low byte
  • IX(H) - Index Register high byte
  • SP(L) - Stack Pointer low byte
  • SP(H) - Stack Pointer high byte
  • PC(L) - Program Counter low byte. 
  • PC'(L) - Copy of the Program Counter low byte. Connected to the Address bus.
  • PC(H) - Program Counter high byte.
  • PC'(H) - Copy of the Program Counter high byte. Connected to the Address bus.
  • MAR(L) - Memory Address Register low byte. Not visible to the programmer.
  • MAR(H) - Memory Address Register high byte. Not visible to the programmer.  
  • Status Register 
  • T - Temp Register. Not visible to the programmer. Connected to the ALU Right Bus.
The register inputs are connected to the ALU Z Bus and the outputs to the ALU Left Bus unless stated otherwise above. Memory to register operations require data to pass through the ALU therefore a logical OR operation with zero is performed if the data is to be loaded into the register unmodified (internally the ALU has the ability to select zero as an input).



Register Descriptions

A and B - General Purpose registers
The A and B registers are 8 bit general purposes registers implemented using octal positive edge triggered flip flops with 3 state outputs.

IX(L) and IX(H) - Index register
The Index Register is implemented using a pair of octal Positive edge triggered flip flops with 3 state outputs. The Resultant Address of an instruction using the index register is calculated and stored in the MAR Register for output onto the Address Bus.

SP(L) and SP(H) - Stack Pointer register
The Stack Pointer is implemented using a pair of octal positive edge triggered flip flops with 3 state outputs. The Resultant Address of an instruction using the stack pointer is calculated and placed into the MAR Register. The shift register has separate load enable control lines, see below, which allows the microcode to implement automatic increment and decrement when a PUSH or POP instruction is being performed.

PC(L) and PC(H) - Program counter
The Program Counter holds the address of the next instruction or operand to be fetched from memory and is incremented by one on completion of the fetch operation.

The Program Counter is implemented using two 8 bit counters whose outputs are connected to the 16 bit Address Bus. In order to support ALU calculations involving the PC and reading and writing the PC to memory the PC output also needs to be connected to the Left ALU Bus. The approach chosen for doing this, which requires the fewest ICs, is to implement a second PC named PC' whose output is connected to the Left ALU Bus. The inputs to the PC and PC' registers are tied together so that they always hold the same value. 

MAR(L) and MAR(H) - Memory Address Register
The Memory Address Register implemented using a pair of octal Positive edge triggered flip flops with 3 state outputs whose outputs are connected to the 16 bit Address Bus. The MAR is not visible to the programmer.

Status Register
The status register is a special 8 bit register implemented using 8 D flip-flops so that bits can be set individually.

The Status Register is connected to the Z Bus and the Left ALU Bus so that its value can be written and read to and from memory.

Four of the bits that represent the ALU flags are also connected directly to the ALU so that they can be individually set by the result of ALU operations.

The 8 ALU bits are also connected directly to the Micro-code decoder so that it can test their values e.g. to test the Negative Flag when executing a Branch on Zero instruction.

T - Temp Register
The Temp Register is implemented using an octal Positive edge triggered flip flop with 3 state outputs whose output is connected to the Right ALU Bus.

The T register is the only register whose outputs is connected to the Right ALU Bus and is used for performing register to register operations with the ALU. The Temp Register is not visible to the programmer.

Buses

The Juno CPU has three CPU buses that are completely internal to the CPU and connect the registers to the ALU. 
  • Left Bus - controlled by the 'L Bus Device Select' decoder
  • Right Bus - controlled by the 'R Bus Device Select' decoder
  • Z bus - only the ALU output can drive the Z bus therefore no device select decoder is required.
The Juno has two internal buses that connect the CPU to internal devices such as memory. 
  • Address Bus - controlled by the 'Address Bus Device Select' decoder
  • Data Bus - controlled by the 'Data Bus Device Select' decoder

The internal buses operate at CPU clock speed and are connected to external buses for communicating with slower external devices such as serial IO ports. 

Loading a register from the Z bus

A rising edge on a Register's CP (clock) input causes it to latch the value present on its inputs. As all the  registers are connected to a single bus there needs to be a way of ensuring only the desired register(s) receive the clock pulse.

This is done by using a decoder to gate the clock signal so that only the selected register receives a clock pulse and is loaded. When the /E line of the decoder is low it outputs '1' on the currently selected line and all other lines are '0'.

The Juno CPU is designed to change state on the rising edge of the clock pulse therefore the CPU clock to the decoder is inverted so that /E goes low on the rising CPU clock edge.

The Z bus load decoder is a 4-to-16 decoder and is used to select which register is loaded from the Z bus apart from the MAR(H+L) registers which have separate load control lines. This is to enable to certain operations to be implemented with fewer lines of micro-code and hence fewer clock cycles.

For example, the instruction PUSH A requires the Stack Pointer to be decremented by 1 and then loaded into MAR. By having separate load controls on MAR this can be done in two clock cycles
SP(L) - 1 -> SP(L), MAR(L)  << SP(L)-1 is loaded into SP(L) and MAR(L) simultaneously
SP(H) - carry -> SP(H), MAR(H)

Outputting a register onto a bus 

A register can place its contents onto the bus it is connected to but only one register can drive the bus at any single point in time and the outputs of the other registers must be in their high impedance state (hi-Z).

A simple way to ensure this is the case and avoid mistakes e.g. in the microcode is to use a decoder to select which device is driving the bus. As the output enable of the registers is active low (/OE) an output inverting decoder is required which drives the selected line low and all other lines high. When the decoder is not enabled all outputs are forced high.

Outputting onto the Address Bus

The CPU can drive the 16-bit Address Bus using the PC'(H+L) and MAR(H+L) registers. The CPU interface to the address bus is uni-directional meaning the CPU cannot read the value from the address bus.

The PC' and MAR register output enables are controlled by the Address Bus 3-to-8 Decoder as follows
  • 0 - no bus device is selected to drive the address bus
  • 1 - PC'(L+H)
  • 2 - MAR(L+H) 
  • 3-7 - reserved for other non-CPU devices connected to the address bus

Outputting onto the Left Bus

The majority of the CPU's registers are connected to the CPU internal Left Bus and are controlled by the Left Bus 4 to 16 Decoder as follows
  • 0 - no bus device selected (not strictly required but feels safer to not be driving the bus unless a device has specifically been selected)
  • 1 - A register
  • 2 - B register
  • 3 - IX(L)
  • 4 - IX(H)
  • 5 - PC(L)
  • 6 - PC(H)
  • 7 - SP(L)
  • 8 - SP(H)
  • 9 - Status Register
  • 10 - Data Bus 
  • 11-15 - reserved

Outputting onto the Right Bus

The temp register and data bus are connected to the CPU internal Right Bus and are controlled by the Right Bus 2 to 4 Decoder as follows
  • 0 - no bus device selected
  • 1 - T register
  • 2 - Data Bus
  • 3 - reserved

CPU to Data Bus Interface

The external Data Bus is connected to both the internal Left and Right buses and is bi-directional therefore requires additional logic to ensure only one device is driving the bus at a time.

Transceivers are used to control the connection between the internal Left and Right buses and the Data Bus. A tranceiver has both direction and Output Enable controls. The Data Bus Decoder selects which tranceiver is active and the direction control is governed by the Left / Right Bus decoder thereby ensuring no bus conflict. 

Monday 25 November 2013

ALU Shift & Flag Design v0.1

The ALU Shift & Flag board allows the output of the ALU to be optionally shifted left or right and calculates the flag outputs.

The shift operations supported are
  • No shift
  • Rotate Right - set carry to bit 0, move all bits one place to the right and set bit 7 to carry input
  • Rotate Left - set carry to bit 7, move all bits one place to the left and set bit 0 to carry input
  • Arithmetic Shift Right - set carry to bit 0, move all bits one place to the right and set bit 7 to zero
  • Arithmetic Shift Left - set carry to bit 7, move all bits one place to the left and set bit 0 to zero 
  • Shift Right fill with 1 - set carry to bit 0, move all bits one place to the right and set bit 7 to one 
  • Shift Left fill with 1 - set carry to bit 7, move all bits one place to the left and set bit 0 to one 
For information on how to use the Rotate and Arithmetic shift operations to perform multi-byte division and multiplication see CPU multi-byte mathematical operations.

The Shift Right and Shift Left fill with 1 operations are not of mathematical use but are supported as a consequence of the design. 

The ALU flags supported are
  • Zero Flag (Z) - set to 1 if the output of the ALU is zero
  • Overflow Flag (V) - set to 1 if addition or subtraction has resulted in an overflow. The flag output is  always calculated but only makes sense when a 2's complement addition or subtraction is being performed. 
  • Negative Flag (N) - set to 1 if the 7th bit of the ALU result is 1. The Negative flag output is always calculated but only makes sense when 2's complement numbers are being used by the programmer. 
  • Carry Flag - set to 1 if a carry has occurred. The Carry flag is always calculated but only makes sense when an addition or subtraction operation is being performed. NB the value of carry is controlled by the CSEL inputs. To select the carry from the adder the CSEL inputs need to be set to 3.

The Eagle schematic can be downloaded here

ALU Flag and Shifter schematic

The Inputs are as follows
INPUT[0..3] - output from the first ALU board processing bits 0..3
  • I0 - bit 0 of the ALU result
  • I1 - bit 1
  • I2 - bit 2
  • I3 - bit 3
INPUT[4..7] -  ouput from the second ALU board processing bits 4..7. Includes various other inputs from the second ALU board.
  • I4 - bit 4
  • I5 - bit 5
  • I6 - bit 6
  • I7 - bit 7
  • ADDERCOUT - carry out from the adder
  • L7 - the Left Bus bit 7 input to the ALU. Used for calculating overflow.
  • R7 - the Right Bus bit 7 input to the ALU. Used for calculating overflow. 
  • CIN - the carry input to the ALU. Used in shift operations.
 CONTROL - control inputs
  • SHIFT SEL0 - combined with SHIFT SEL1 selects the shift operation performed
    • SEL1 | SEL0
    • 00 = no shift
    • 01 = shift right
    • 10 = shift left
    • 11 = not used (results in output of zero)
  • SHIFT SEL1 - combined with SHIFT SEL0
  • CSEL0- combined with CSEL1 selects the value to use for carry
    • CSEL1 | CSEL0
    • 00 = Carry in from the status register
    • 01 = 0 (force the value of carry to 0)
    • 10 = 1 (force the value of carry to 1)
    • 11 = Adder Carry Out
The outputs are as follows

FLAG_OUTPUT
  • Overflow flag
  • Cout - Carry Out (NB dependent upon the CSEL control)
  • Zero Flag 
  • Neg Flag  - Negative flag
SHIFT_OUTPUT - ALU output onto the Z bus

  • Z0..7 - bits 0 to 7
The PCB board layout can be downloaded here

ALU Flag and Shifter PCB layout


EDIT - the Flag Outputs are labelled incorrectly on the silk screen and should be like this



The parts list

Exported from ShifterAndFlagLogicv0.1.brd at 10/11/2013 21:48:37

EAGLE Version 6.5.0 Copyright (c) 1988-2013 CadSoft

Assembly variant:

Part         Value          Package      Library  Position (inch)       Orientation

C1           10uF           E5-5         rcl      (0.9 0.35)            R90
C2           0.1uF          C050-030X075 rcl      (1.35 2.25)           R270
C4           0.1uF          C050-030X075 rcl      (2 0.35)              R270
C5           0.1uF          C050-030X075 rcl      (3 1.4)               R270
C6           0.1uF          C050-030X075 rcl      (1.35 1.3)            R270
C7           0.1uF          C050-030X075 rcl      (0.35 0.55)           R270
C8           0.1uF          C050-030X075 rcl      (2 1.3)               R270
C9           0.1uF          C050-030X075 rcl      (2 2.25)              R270
C10          0.1uF          C050-030X075 rcl      (1.1 1.6)             R90
CONTROL      4              1X04         pinhead  (1.45 0.2)            R180
FLAG_OUTPUT  4              1X04         pinhead  (2.85 0.2)            R0
IC1          74HC153N       DIL16        74xx-eu  (2.3 2.7)             R90
IC2          74HC153N       DIL16        74xx-eu  (0.7 1.95)            R270
IC3          74HC251N       DIL16        74xx-eu  (0.7 1)               R90
IC4          74HC153N       DIL16        74xx-eu  (1.65 2.7)            R90
IC5          74HC153N       DIL16        74xx-eu  (2.3 1.75)            R90
IC6          74HC153N       DIL16        74xx-eu  (1.65 1.75)           R90
IC7          74HC153N       DIL16        74xx-eu  (2.3 0.8)             R90
IC10         4078N          DIL14        40xx     (3.3 1.8)             R90
INPUT[0..3]  8              1X08         pinhead  (0.2 2.3)             R270
INPUT[4..7]  8              1X08         pinhead  (0.2 1.45)            R270
POWER                       1X02         pinhead  (0.6 0.25)            R180
SHIFT_OUTPUT 8    

Saturday 23 November 2013

Bus control notes

A bus connects together multiple devices so that they can talk to one another through shared communication lines. Only one device can write to the bus, drive it, at any point in time but multiple devices can simultaneously read from it. 

A tri-state device is one that has a third output state in addition to 0 and 1. This third state is a high impedance state called Hi-Z which has the effect of disconnecting the device from the circuit. This Hi-Z state can be used to disconnect device outputs from the bus and allow one device to drive the  bus. Tri-state devices commonly have an /Output Enable which when asserted forces the devices output into the Hi-Z state.

One method of ensuring only one device is driving the bus at a time is to connect the /OE controls of all the tri-state devices to a decoder and use the decoder to select which device is enabled. All other devices will be forced into their high impedance Z state. This is a fairly fool proof method and there are decoders that will 'break before make' when switching between devices.

As the /OE is active low an inverting decoder needs to be used so that the selected output is low and all the other outputs are high.

A single 3-to-8 decoder can be used to select between 8 devices connected to a bus. If control of more than 8 devices is required two or three decoders can be chained together e.g. to create a 4-to-16 decoder.

A similar method can be used to select between multiple devices that can read from the bus. Assuming the devices latch their value from the bus on the next rising edge of the clock signal a decoder combined with AND gates can be used to 'arm' the clock input of the selected device so that only one of the devices sees the rising clock on it's clock input and reads from the bus.

Unlike ensuring that only one device is driving the bus at a time using a decoder to select between devices to read from the bus is not an electrical necessity but simply a convenience as we only need to write to one device at a time and it reduces the number of control lines required.

A transceiver such ad the 74HC245 is a bus driving device with 3-state outputs in both directions. 






74 series Flip Flop notes

The following are different 74 series flip flops.
  • 74 - two independent D type flip flops with individual D, preset, clear and clock inputs. A low level at the preset or clear sets or resets the flip flop irrespective of the D or clock. When preset and clear are disabled by being high the flip flop is set to the value of the D input on the positive clock edge.
  • 175 - four D type flip flops with individual D inputs and both Q and /Q outputs. Common clock and -master reset inputs load and reset all flip flops simultaneously. 
  • 273 - octal edge triggered D type flip flops with Individual D inputs and Q outputs. Common clock and /master reset inputs load and reset all flip flops simultaneously. 
  • 373 - octal transparent latch D type flip flops with 3-state outputs. A common Latch Enable (LE) enables all flip flops and a common Output Enable (/OE) enables all the outputs.The 573 has a more convenient pin arrangement.
  • 374 - octal edge triggered D type flip flops with 3-state outputs. Common clock loads all flip flops simultaneously and a common Output Enable (/OE) enables all the outputs. The 374 does not have a seperate input enable, see 377.
  • 377 - octal edge triggered D type flip flops. Common clock loads all flip flops simultaneously when input enable (date enable) is low. The 377 does not have 3-state output.
  • 533 - Functionally the same as 373 but with inverting outputs.
  • 563 - Functionally the same as 373 but with inverting outputs and a more convenient pin arrangement. 
  • 564 - Functionally the same as the 574 but has inverting outputs.
  • 573 - Functionally the same as 373 but with a more convenient pin arrangement.
  • 574 - Functionally the same as the 374 but has a more convenient pin arrangement.


Monday 4 November 2013

ALU Design v0.2

The ALU Design v0.2 is a slight variation on the previous ALU 0.1 design

The modification adds the Carry IN from the ALU board's input buses to the board's output bus so that Cin can form part of the input into the shifter and flags board. Cin is used by the shifter when shifting.

The Eagle CAD schematic for ALU Design v0.2 can be downloaded here.


The Eagle CAD board for ALU Design v0.2 can be downloaded here.


Post manufacture of the board I realised it would be better for the OR and AND controls to be swapped around so that OR is selected by the control input 00 rather than AND. This is so that zero in the microcode can be used when the intention is to pass a value straight through the ALU. Given the pin out of the AND and OR ICs are the same it is a simple job to just swap the ICs around.

Control input
The control input consists of 8 signals
  • C0 (lsb) -  Combined with C1 used to select ALU operation to output; 00 = OR, 01=AND, 10=XOR, 11=ADDER
  • C1 - see above
  • CIN - Carry input from the Control Register
  • LBUSINPUTSELECT - select between the external left bus (L) or hardcoded zero (H) for the ALU's left input
  • RBUSINPUTSELECT - select between the external right bus (L) or hardcoded zero (H) for the ALU's right input
  • CINPUTSEL0 - combined with CINPUTSEL1to select the carry input into the adder; 00 = 0, 01=1, 10 = CIN, 11 = 0
  • CINPUTSEL1 - see above
  • INVB (msb) - If enabled (H) inverts the ALU's right input. Used for performing subtraction. 

    Data Input

    There are two bus data inputs consisting of 4 bits each, bits 0 to 3.  
    1. L_0 (lsb) - left bus bit 0
    2. L_1 - left bus bit 1
    3. L_2 - left bus bit 2
    4. L_3 - left bus bit 3
    5. R_0 - right bus bit 0
    6. R_1 - right bus bit 1
    7. R_2 - right bus bit 2
    8. R_3 (msb) - right bus bit 3

    Ouput

    The output consists of 8 bits 
    1. Z0 - output bus bit 0
    2. Z1 - output bus bit 1
    3. Z2 - output bus bit 2
    4. Z3 - output bus bit 3
    5. Cout - Carry out from the adder. NB the carry is always calculated but only makes sense when an Add or Subtract operation is being performed
    6. L_3 - left input bit 3 pass through. This is used by the down stream Shifter and Flag board to calculate the overflow flag.
    7. R_3 - right input bit 3 pass through. 
    8. Cin - pass through of Cin to the down stream Shifter and Flag board.

    The three pass through outputs are a convenience as they make the physical connection to the Shifter and Flag board simpler as all the inputs are gathered together and can be connected with a single 8 line ribbon cable from the second ALU board.

    Tuesday 29 October 2013

    Arduino library shiftIn function bug

    Found a bug in the Arduino library ShiftIn() function whilst testing an ALU board.

    In order to test the ALU board they are connected to an Arduino via an IO board which provides 16 input and output pins using 74HC165 shift register ICs.

     
    The test program generates the two 4-bit inputs for the ALU and eight control signals to select the mathematical operation to be performed. The test values are then serially written to the two 74HC595 SIPO shift registers on the IO board, the parallel outputs are wired to the ALU board.

    The ALU output is then serially read from the 74HC165 PISO shift register and the result displayed in the Arduino IDE.

    The test program cycles through a large numbers of tests to test the ALU thoroughly.
     
    Initially the ALU did not work and I spent two hours debugging it. It became apparent that the problem was with the IO board as manually probing the ALU board showed it was working fine. Initially, I suspected a floating input on one of the logic pins but after extensive probing could not find the problem.

    Eventually my suspicion turned to the Arduino library and the ShiftIn() function and I decided to look at the source code to check what it was doing.

    Whilst Googling for the source code I came across a bug report (issue 467) within the source code repository for the Arduino library shiftIn function. The bug report described a problem with the way the clock line is driven causing the 8th bit to be missed. Eureka!

    Quickly replacing the ShiftIn() function with my own code and retesting the problem went away.
     
     

    Monday 30 September 2013

    CPU multi-byte mathematical operations

    In order to be more than a toy the 8 bit Juno CPU needs to be capable of performing multi-byte mathematical operations. 

    It is capable of adding, subtracting and shifting of multi-byte numbers as described below. The  shifting operations are used to support multiplication and division. 

    In order to make the examples below simpler and shorter 4 bit numbers are used but the Juno CPU is 8 bit.


    Multi-byte addition

    In order to add two multi-byte numbers the bytes are added starting with the least significant bytes first. Adding the least significant bytes calculates the least significant byte of the result and the carry. The next two bytes are then added plus the carry and so on.

    Example

    28 + 28 = 56

    In binary this is
    0001 1100 + 0001 1100

    This is calculated 4 bits at a time as follows
    Set carry = 0
    1100 + 1100 + carry = 1000 (carry =1)
    0001 + 0001 + carry = 11 (carry = 0)

    Two CPU instructions are required to perform the above calculation in assembler code. The first instruction is to clear the carry flag e.g. CLC. The second instruction is to add two number with carry e.g. ADC.

    The inclusion of a third instruction to the Instruction set add without carry, ADD, which over-rides the carry flag with 0 allows the addition to be implemented more optimally in fewer lines of code as it removes the need to explicitly clear the carry flag first.

    Multi-byte subtraction

    In order to subtract two multi-byte numbers the fact that mathematically a- b is the same as a + (-b) is exploited as it is easy to calculate -b and doing so allows the logic of the adder to be reused rather than building an entirely seperate piece of logic dedicated to subtraction.

    -b is calculated by inverting b and adding 1 to produce the two's complement representation of -b. The invertion can be achieved through the application of not logic and the adding of 1 can be done by forcing the carry to 1 for the addition of the first two bytes. The addition of subsequent bytes adds the resultant carry of the previous calculation.

    Example
    28 - 27 = 1

    In binary this is
    0001 1100 - 0001 1011 

    This is calculated 4 bits at a time as follows
    Set carry = 1 (force carry to 1 to calculate the two's complement)
    1100 + (invert 1011) + carry =
    1100 + 0100 + carry =
     0001 (carry = 1)

    0001 + (invert 0001) + carry =
    0001 + 1110 + carry = 
    0000 (carry = 1)

    The final carry of 1 is ignored.

    Two CPU instructions are required to perform the above calculation in assembler code. The first instruction is to set the carry flag e.g. SEC. The second instruction is to subtract two numbers with carry e.g. SBC.

    The addition of a third instruction to subtract without carry, SUB, which over-rides the carry flag with 1 allows the subtraction to be implemented more optimally in fewer lines of code as it removes the need to explicitly set the carry flag first.

    Shifting multi-byte numbers left and right

    The ability to shift numbers is key to implementing multiplication and division efficiently in assembler as the Juno CPU does not have dedicated multiplication and division instructions.

    Mathematically shifting a number 1 place to the left is the equivalent of multiplying by 2. Likewise, mathematically shifting a number 1 place to the right is the equivalent of dividing by 2.

    In order to shift multi-byte numbers two types of shift operation are required, mathematical shift and rotation.

    Mathematical shift fills the gap created by the shift with a zero and moves the bit that drops off into the carry flag.

    Examples

    1101 mathematically shifted to the left becomes 1010 (carry = 1)
    0101 mathematically shifted to the left becomes 1010 (carry = 0)
    1101 mathematically shifted to the right becomes 0110 (carry = 1)

    The value of carry before the shift is irrelevant.

    Rotational shift is similar to mathematical shift but fills the gap with the input value of carry. Like mathematical shift the output value of the carry flag is set to the bit that drops off.

    Example

    carry = 1
    1101 rotated to the left becomes 1011 (carry = 1)

    In order to multiply a multi-byte number by two the least significant byte is first mathematically shifted to the left by one place. The subsequent bytes are then rotated to the left by one place starting with the second least significant byte. This approach preserves the bit that 'drops off' and moves it into the next byte.

    In order to divide a multi-byte number by two a similar approach is taken but starting with mathematically shifting the most significant byte to the right by 1 place. Subsequent bytes are then rotated to the right by one place starting with the second most significant byte.

    The rotate and shift operations can be implemented by two CPU instructions.

    ROR - ROtate Right through carry. Fill with carry.
    ROL  - ROtate Left through carry. Fill with carry.

    In order to optimise assemble code additional instructions could be provided that over-ride the value of carry removing the need to clear, or set, carry before performing a Mathematical Shift instruction.

    SL0 - Shift Left filling with 0
    SL1 - Shift Left filling with 1
    SR0 - Shift Right filling with 0
    SR1 - Shift Left filling with 1



    Saturday 28 September 2013

    Overflow flag implemented using an 8:1 multiplexer

    The overflow flag is used to indicate an error condition when adding, or subtracting, two's complement numbers. The error indicates that the result does not fit within the number of ALU bits and is therefore incorrect.
    The overflow flag is different to the carry flag which indicates that a mathematical carry or borrow has been generated out of the most significant bit.

    In a two's complement number the most significant bit indicates whether the number is negative or positive. Zero indicates positive and one indicates negative. When adding two's complement positive numbers (msb is 0) the result should be positive (msb 0) likewise when adding two negative numbers (msb is 1) the result should be negative (msb 1).

    In an 8 bit ALU adding 127 and 127 gives 254 which in binary is 1111 1110. But if two's complement notation is being used then the output is not interpreted as 254 but -2.This error occures because the result is two large to fit within 8 bits and has overflowed.

    It is important to understand that the overflow flag is set for every addition but it only makes sense when two's complement notation is being used. If two's complement representation is not being used it should be ignored.

    The calculation of the overflow flag for addition is given below. Within Juno subtraction is performed using addition therefore we only need to calculate overflow for addition.

    Inputs  Outputs
    A B Z   Overflow Flag
    0 0 0   0
    0 0 1   1 (adding two positives should be positive)
    0 1 0   0
    0 1 1   0
    1 0 0   0
    1 0 1   0
    1 1 0   1 (adding two negatives should be negative)
    1 1 1   0


    The calculation of the overflow flag can be done in logic as shown below






    But this would require a number of logic chips of different types. An alternative approach is to implement the logic using a single 8:1 multiplexer such as the 74HC251.The 8:1 multiplexer has three select inputs(S0,S1,S2) which correspond to A, B and Z above and are used to select one of the eight inputs to be the output. By appropriately hard wiring the eight inputs high or low it is possible to create the logic table above and implement the overflow logic using a single IC.

    The table below shows how the input values need to be set. 

    A  B  Z   
    S2 S1 S0  input  value
    0  0  0   I0     0
    0  0  1   I1     1
    0  1  0   I2     0
    0  1  1   I3     0
    0  0  0   I4     0
    1  0  0   I5     0
    1  0  1   I6     0
    1  1  0   I7     1
    1  1  1   I8     0  





    ALU Design v0.1

    The ALU Design v0.1 is a slight variation on the previous ALU (bits 0..3) design which means the same board design can be used for both the ALU bits 0..3 and the ALU bits 4..7 boards.

    The modification adds the A3 and B3 from the ALU board's input buses to the board's output bus so that these input values form part of the input into the shifter and flags board.

    Bits 7 of the A and B inputs into the ALU are required by the shifter and flags board to calculate the overflow flag. The design means both bits 3 and 7 of the ALU input will go the the shifter and flags board but the board design will simply ignore the bits from the ALU bits 0..3 board.

    The Eagle CAD schematic for ALU Design v0.1 can be downloaded here.





    The Eagle CAD board for ALU Design v0.1 can be downloaded here.




    The bill of materials
    Part     Value          Package      Library  Position (inch)       Orientation

    C1       0.1uF          C050-030X075 rcl      (0.55 0.6)            R0
    C2       0.1uF          C050-030X075 rcl      (0.95 0.6)            R180
    C4       0.1uF          C050-030X075 rcl      (2.35 0.6)            R0
    C5       0.1uF          C050-030X075 rcl      (0.9 2.95)            R90
    C6       0.1uF          C050-030X075 rcl      (1.5 2.95)            R90
    C7       0.1uF          C050-030X075 rcl      (2.1 2.95)            R90
    C8       0.1uF          C050-030X075 rcl      (3.55 1)              R270
    C9       0.1uF          C050-030X075 rcl      (3.55 2.15)           R270
    C10      10uF           E5-5         rcl      (0.9 0.3)             R90
    C11      0.1uF          C050-030X075 rcl      (2.7 2.9)             R90
    C12      10uF           E5-5         rcl      (3.2 2.7)             R270
    CONTROL                 1X08         pinhead  (1.85 0.3)            R180
    IC1      74HC08N        DIL14        74xx-eu  (1.2 2.5)             R270
    IC2      74HC32N        DIL14        74xx-eu  (1.8 2.5)             R270
    IC3      74HC86N        DIL14        74xx-eu  (2.4 2.5)             R270
    IC4      74HC157N       DIL16        74xx-eu  (1.2 1.15)            R90
    IC5      74HC153N       DIL16        74xx-eu  (3.2 1.9)             R270
    IC6      74HC153N       DIL16        74xx-eu  (3.2 0.75)            R270
    IC7      7483N          DIL16        74xx-eu  (1.8 1.15)            R90
    IC8      74HC157N       DIL16        74xx-eu  (0.55 2.5)            R270
    IC9      74HC153N       DIL16        74xx-eu  (2.4 1.15)            R90
    IC10     74HC86N        DIL14        74xx-eu  (0.6 1.2)             R90
    INPUT                   1X08         pinhead  (0.2 1.4)             R90
    JP4                     1X02         pinhead  (0.6 0.2)             R180
    JP5                     1X02         pinhead  (3.45 2.8)            R0
    OUTPUT                  1X08         pinhead  (3.75 1.45)           R270


     

    ALU Sketch #2 - PCB board layout

    Having experimented laying out the PCB for the ALU sketch #2 design it is clear it will not fit on a single board within the EagleCAD size constraints therefore I have split it into 3 PCBs as follows




    • Board 1 is the 4 bit ALU for bits 0 to 3
    • Board 2 is the 4 bit ALU for bits 4 to 7
    • Board 3 contains the shifter and flag logic
    For details of the ALU design see ALU Sketch #2

    Wednesday 25 September 2013

    Little Endian vs Big Endian

    Little Endian and Big Endian refers to the order in which multi-byte numbers are stored in memory. The  Juno CPU is Little Endian like Intel chips used in PCs and the 6502.

    What is Endianess? 
    It is easier to demonstrate Endianess using hexadecimal numbers, which is one of the reasons why system programmers like using hexadecimal so much as it makes things much simpler.

    Take the two byte hexadecimal value 0xFF08 (65288 in decimal) in Big Endian notation the 2 byte value 0xFF08 is stored in memory most significant byte first as follows

    Address 100 = FF
    Address 101 = 08

    In Little Endian notion the same two byte value is stored in memory least significant byte first

    Address 100 = 08
    Address 101 = FF

    If you read the contents of memory as part of a memory dump then Big Endian notation would be written left to right as FF08 whereas Little Endian notation would be written 08FF. 

    Note that byte order Endianess does not apply to the order in which the individual bits within a byte are stored only the bytes themselves.

    So why would anybody want to use Little Endian notation as it appears backwards and awkward to read? 

    There are many articles on the web discussing the advantages and disadvantages of Little vs big Endian and even many articles arguing there are no real advantages or disadvantages to either.

    For the Juno PC there is one clear advantage of using Little Endian which is why I have chosen to use it. Little Endian makes some multi-byte operations easier to implement in micro-code because the program counter will be pointing to the least significant byte following the fetch of the instruction and the least significant bytes need to be added first in order to calculate the carry in multi-byte operations

    For example, consider an instruction to jump relative by a two byte offset e.g. JMR #1000. In micro-code this instruction is implemented by adding the 2 byte value to the program counter in an intermediate register such as MAR and loading PC with the result. After fetching the JMR instruction the PC will point to the least significant byte of the offset. This can be fetched and added to MAR and the carry will be calculated ready for the addition of the second byte to MAR. If the value was stored in Big Endian order then the PC would need to be incremented to point to the LSB and then decremented to point to the MSB which would require more micro-code steps and hence clock cycles.




    Sunday 15 September 2013

    ALU Design (bits 0 - 3) #1 PCB


    The ALU (bits 0..3) board lay out in EagleCAD. The EagleCAD board file can be downloaded here and the schematic here.


    The following settings were used whilst laying out the board everything else was left as default
    • DRC set to Eurocircuits-EAGLE design rules setup for 2-layer PatternClass6 BaseCopper018 eCDefault. The DRC rules can be downloaded from Eurocircuits website. 
    • The version text used size = 0.05, ratio 8 %, line distance 50%, and font set to vector
    • The labelling of the input & outputs header pins used text  size = 0.04, ratio 8%, line distance 50%, and font set to vector
    • Silkscreen text placed on layer 21 tPlace.
    • DRC clearance changed to 0.2mm (8mil) for wire: wire, pad and via
    • DRC minimum width changed to 0.25mm (10mil) for signal and 0.30 (12mil) for power
    • Restring changed to 0.25mm (10mil) for pads: top and bottom. 
    • Restring changed to 0.25mm (10mil) for vias outer
     A net class was defined for power with a width of 0.3mm, drill 0mil and clearance 0.mm. The default net class was set to 0.25mm width, 0mil drill and 0.22mm clearance.

    Partlist

    The parts list exported from EagleCAD. 

    Part     Value          Package      Library  Position (inch)       Orientation

    C1       0.1uF          C050-030X075 rcl      (0.55 0.6)            R0
    C2       0.1uF          C050-030X075 rcl      (0.95 0.6)            R180
    C4       0.1uF          C050-030X075 rcl      (2.15 0.6)            R180
    C5       0.1uF          C050-030X075 rcl      (0.9 2.95)            R90
    C6       0.1uF          C050-030X075 rcl      (1.5 2.95)            R90
    C7       0.1uF          C050-030X075 rcl      (2.1 2.95)            R90
    C8       0.1uF          C050-030X075 rcl      (3.55 1)              R270
    C9       0.1uF          C050-030X075 rcl      (3.55 2.15)           R270
    C10      10uF           E5-5         rcl      (0.9 0.3)             R90
    C11      0.1uF          C050-030X075 rcl      (2.7 2.9)             R90
    C12      10uF           E5-5         rcl      (3.2 2.7)             R270
    CONTROL                 1X08         pinhead  (1.85 0.3)            R180
    IC1      74HC08N        DIL14        74xx-eu  (1.2 2.5)             R270
    IC2      74HC32N        DIL14        74xx-eu  (1.8 2.5)             R270
    IC3      74HC86N        DIL14        74xx-eu  (2.4 2.5)             R270
    IC4      74HC157N       DIL16        74xx-eu  (1.2 1.15)            R90
    IC5      74HC153N       DIL16        74xx-eu  (3.2 1.9)             R270
    IC6      74HC153N       DIL16        74xx-eu  (3.2 0.75)            R270
    IC7      7483N          DIL16        74xx-eu  (1.8 1.15)            R90
    IC8      74HC157N       DIL16        74xx-eu  (0.55 2.5)            R270
    IC9      74HC153N       DIL16        74xx-eu  (2.4 1.15)            R90
    IC10     74HC86N        DIL14        74xx-eu  (0.6 1.2)             R90
    INPUT                   1X08         pinhead  (0.2 1.4)             R90
    JP4                     1X02         pinhead  (0.6 0.2)             R180
    JP5                     1X02         pinhead  (3.45 2.8)            R0
    OUTPUT                  1X08         pinhead  (3.75 1.45)           R270

    The mount holes used library component: MOUNT-HOLE3.0 (MOUNT-HOLE).

    Friday 13 September 2013

    Shift Register IO Test Board PCB

    The IO test board PCB has arrived from Eurocircuits. In fact they have sent two even though I only ordered one. Thanks!

     

    and with parts soldered in place.




    Running a demo test program which cycles through the values 0 to 255 on the first 75HC595 which in turn is connected to LEDs. Being the first PCB I have ever designed I am pleased with how it has turned out.




     

    The demo source code can be found here.