Making a 4-Bit Computer in GKC (Chapter 1: CPU, Part 4: Negatives? and Half-Adder)

Previous Parts

Making a 4-Bit Computer in GKC (Chapter 1: CPU, Part 3: Registers and Beginning the ALU)
Making a 16-bit Computer in Gimkit! (Chapter 1: CPU, Part 2: Logic Gates)
Making a 16-bit Computer in Gimkit! (Chapter 1: CPU; Part 1: Instruction Set and CPU)2. 3. 4. 5. 2. 3. 4.

Making a 4-Bit Computer in GKC

Chapter 1: CPU, Part 4: Negatives? and Half-Adder


Negative Numbers?

In the last guide in this series, I briefly touched on signed and unsigned numbers. Basically, signed numbers support negative numbers, but how? Computers can’t read a “-” before a number like -1011011, so how do they do it? It’s simple: the Most Significant Bit. The MSB (Most Significant Bit) is the first digit in a binary number. For example, in 011011, it would be 0. In signed numbers, if the MSB is 0, the number is positive, while if the MSB is 1, the number is negative. But, signed numbers don’t use the usual method of converting binary to decimal. For an unsigned number, 0001 would be

0 × 2^3 + 0 × 2^2 + 0 × 2^1 + 1 × 2^0 = 1
1010 is
1 × 2^3 + 0 × 2^2 + 1 × 2^1 + 0 × 2^0 = 10
But, for signed numbers, if the MSB is 0, convert normally, but if the MSB is 1 you must use the Two’s Complement. You invert all the bits, add 1, convert normally, then add the negative sign. For example,
1011:

  1. Invert bits: 0100
  2. Add 1: 0101
  3. Convert: 5
  4. Add negative: -5
    To convert negative decimal numbers to signed binary, you don’t move backwards. You first convert the absolute value to binary, invert the bits, then add 1.
    For example,
    5:
  5. Convert: 0101
  6. Invert: 1010
  7. Add 1: 1011
    In 4-bits, unsigned binary numbers range from 0 (0000) to +15 (1111). 4-bit signed binary ranges from -8 (1000) to +7 (0111). Notice they have the same range, but the minimum and maximum are different.

How does the ALU know whether the operands are signed or unsigned?

With the new introduction of signed numbers, adding 2 numbers can yield 2 completely different results. For example, 1000 and 1011 yields 19 if unsigned, but -13 if signed, but both in binary is 10011. The ALU doesn’t inherently know if they’re signed, it just does the math blindly. The fact that 1000+1011 is always 10011, no matter if they’re signed or not, help us a lot. The ALU sees the output has exceeded the 4-bit limit, and outputs 0011, and 2 flags: a Carry Flag and an Overflow Flag. One of these flags are to be used in unsigned arithmetic, while the other is to be used in signed. These 3 outputs (0011, CF, and OF) go to the CU, and the CU knows what the output should be. If the CU expects a signed value, it takes the OF, but if its expecting an unsigned value, it takes the CF.

I’m very sorry If my explanation stinks, I’m really bad at teaching :((. I will try to clarify questions.


Half-Adder

Okay, now we’re starting to build the ALU. A half-adder takes 2 inputs, A and B, and outputs Cout (carry out) and Q, where Q is the result and Cout is the carry. Here is the truth table for a half-adder:

A B Q Cout
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1

Using the same method as the 2-4 decoder, we can figure out the boolean expression(s) (logic gates) used to go from A & B to Q or Cout.

Q = A⊕B (⊕ meaning XOR)
Cout = A·B (· meaning AND if you don’t remember)

Block Code:

(btw A+B-2AB = (A-B)^2, and the second one uses less blocks)


Note: in the next part we will finish the rest of the arithmetic operations in the ALU

also I kinda overestimated how long each guide would take

6 Likes

Maybe touch a little on the flags more? I get the gist, but I don’t think a little more detail would hurt any sleep-deprived teenagersone

You’re doing good so far. Keep up the good work! o7 o7 o7

3 Likes

Oki more on flags: there are 4 flags

Carry/Borrow (CF): length of output exceeds the limit (4)
Overflow (OF, but not the questionable website where u buy stuff): if the output sign doesn’t match the input sign. For example of your adding 2 negative numbers, you should output a negative number, but in signed numbers, sometimes smth goes wrong. For example, 1001 (-7) plus 1000 (-8). Obviously, the answer is -15. But, in binary the answer is 10001, which when truncated to the 4-bit length limit, is 0001 (+1). The signs are incorrect! So the ALU outputs a overflow flag. Another example with positive result to negative is 0100 (4) and 0101 (5). When you add them, you should have a positive number, but the result is 1001, which is -7! Again, signs don’t match, so an Overflow flag is sent. A overflow flag cannot be sent if one input is negative and one is positive, as the result signs can be mixed, depending on the numbers of the inputs itself.

Zero flag (ZF) : if the output is zero (obv)

SIgn Flag (SF): the MSB is 1 (so its negative if signed)

3 Likes

Great job.
Notes:

  1. Isn’t (A-B)^2 = A^2 - 2AB + B^2 not A+B-2AB?
  2. Possibly expand on Two’s Complement(not needed, but helpful).
  3. Maybe explain how the CU expects the output of the ALU to be signed.
  4. Explain why the OF is taken in when the CU expects a signed value, and why it takes in the CF when it expects an unsigned value.
4 Likes

oh wait I’m slow :sob:

haven’t done much math in the past months so I’m rusty with that

  1. I didn’t learn much more about Two’s complement
  2. oh man I should stop rushing my guides :sob: I forgot to mention that we will be doubling the size of our instruction set (refer to part 1), to be

ADD
SUB
MUL
DIV
SADD
SSUB
SMUL
SDIV

the “s” prefix means that the operation is signed, and if it doesn’t have a “s” prefix, its unsigned.
4. overflow flags (OF) are sent when the output MSB doesn’t match logically with the input MSB. For example, adding 2 positive numbers should yield positive number, but sometimes, the MSB can be 1 instad of 0. For example, adding 0101(5) and 0110 (6) is 1011, but that is -5 is two’s complement. Then, a OF flag is sent out and is up to the CU to interpret. carry flags, on the other hand, happen when the MSB doesn’t fit into the 4-bit limit. In signed arithmetic, the MSB is only used to show the sign of the number (0=+ 1=- if ya don’t remeber)

also u seem pretty experienced in this field

I legit js started learning like a couple months ago

3 Likes

Why would an OF be sent out when adding 0101 and 0110 if that wouldn’t be an overflow, it would be a carry(CF)?
Maybe you wrote that in reverse…when you say, “carry flags, on the other hand, happen when the MSB doesn’t fit into the 4-bit limit,” do you mean overflow flags?
Thanks for explaining that and maybe you should add those new instructions to part 1(if you can edit it).

1 Like

yes, ik, the names are confusing, but I’m like 99% sure I’m correct. Also, to add on, carry flags can also be sent out when a borrow on the MSB happens in subtraction

1 Like

So…to clarify: OF is when a bit is carried/borrowed over, and CF is when there are more than 4 bits?

2 Likes

@DXCTYPE you want me to create a sh enviroment for your CPU once it’s 8 bit


if it’s not alredy 99% memory ofc


if you can mimic the Z80 or 6502 that would be very helpful

4 Likes

no, OF is when in signed arithmetic, the output MSB doesn’t match logically with in 2 inputs,

example:

lets add 0101 and 0110 (5 and 6 respectivly)

0101
0110
1011

1011 is -5 in Two’s complement! Obviously the signs are wrong because in our universe, positives + posites = positives, not negatives. So then, a OF is sent out

But for carry flags on the other hand, its when there is carried or borrow on the MSB.

Example:

1000
1001
10001

This result will be truncated to 0001 and a CF would be sent out.

There is a secario when a CF and OF would be both sent out:

1011
1000
10011

Here, the result would be truncated to 0011, so a CF is sent out. But also, 0011 is positive in twos complement, while both the inputs are negativein twos complement, so a OF is sent out.

Now, you might think, the ALU should know if the arithmetic is signed or not, so it should know which one to send out? But, that incorrect. the ALU doesn’t inheretly know whether the arithmetic is signed or not, it just does math blindly, because any arithmetic in binary outputs the same binary number, signed or not (the beauty of twos complement). So, both flags are sent out and the CU checks whether that math are signed or unsigned, and then ignores the OF if unsigned and uses the CF, and ignores the CF if signed and uses the OF.

OF only applys to signed arithmetic while CF only applys to unsigned arithmetic if it isn’t clear.

3 Likes