Skip to content

4. Fish: A Calculator with code memory

4.1 Introduction

Fish is “programmable invertebrate”: In fish, rather than supplying control signals and clock edges every time by a human hand, we record all the control signals that are required for the desired computation in a memory chip and replace the pushbutton with a real clock. After doing that, the memory chip supplies the required control signals automatically and sequentially to the processor at every clock edge. These recorded control signals are called “machine code”.

4.2 “Machine Code” for Fish

Recall that each instruction of invertebrate must generate four control signals, ie,

  1. ALUOp (4 bits) ,
  2. Ra (3bits),
  3. Rb (3 bits)
  4. Rc (3 bits)

If these four control signals are concatenated together into an 13 bit entity, the result is called “a machine instruction” for fish. In each machine instruction, we have¬†fields for ALUOp, Ra, Rb and Rc. The order of concatenation is arbitrary. We will use the ordering indicated in the figure below. Other orderings are also possible. But once we choose an ordering, we must stick with it, as the hardware is to be designed with that particular ordering in mind, and hardware will not understand any other ordering.

Each assembly language instruction has a corresponding machine language instruction and vice versa. Hence it is possible to translate between them.

In the following table, we give some assembly language instructions and their corresponding machine language translations as examples:

and 3 1 2 001 010 0010 010 0x512
or 0 3 0 000 011 0011 000 0x198
inc 5 101 ddd 0111 101 0x143D
dec 2 010 ddd 1000 010 0x842
not 0 3 011 ddd 010 1000 0xC28
mov 5 7 111 ddd 0110 101 0x1C35
sub 7 2 1 010 001 0001 111 0x88F
xor 1 1 1 001 001 0100 001 0x4A1

In Fish, we had needed a human operator to enter REG1CHOOSE, REG2CHOOSE, ALUOP and REGSELECT at every clock cycle. In frog, we store these commands into a memory chip whose data bus width is 13 bits, starting from address 0x000. We arbitrarily choose 10-bit for the address width. Hence, our program can be at most 1024 instructions long.

As an example, consider the following 4 instructions long program written in assembly:

and 3 1 2
or  0 3 0
inc 4
dec 3

The machine code corresponding to this program is

Before the start of the execution, this machine code must be written into the memory between the addresses 0x000-0x003.  In other words, after being written, the contents of the memory must be like
address     data
========    =====
0x000       0x512
0x001       0x030
0x002       0x103C
0x003       0xC43
0x004       0xddd  // d is don't care 
//from the address 0x004 down, memory will be empty.

At every clock cycle

  1. At the start of the operation, PC contains zero and the machine code is loaded into memory. Address bus of memory is 0x000 and the Dout of memory contains the first machine instruction.

Exercise: Assume that we use a different concatenation ordering. How would the diagram change?

4.3 Programming the Fish

Contrary to Fish, Frog is programmable.

The program must be already loaded into the memory at the start of the operation. Each location in memory

How the program is loaded into memory is left unspecified.

4.4 Example programs


4.5 Assembler for Fish

This assembler converts Fish assembly code into Fish machine code. Fill in the missing parts. Also, ordering of the fields ALUOP, Ra, Rb and Rc is wrong. Correct it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//Converts a hexadecimal string to integer.
int hex2int( char* hex)  
    int result=0;

    while ((*hex)!='\0')
        if (('0'<=(*hex))&&((*hex)<='9'))
            result = result*16 + (*hex) -'0';
        else if (('a'<=(*hex))&&((*hex)<='f'))
            result = result*16 + (*hex) -'a'+10;
        else if (('A'<=(*hex))&&((*hex)<='F'))
            result = result*16 + (*hex) -'A'+10; 

    FILE *fp;
    char line[100];
    char *token = NULL;
    char *op1, *op2, *op3, *label;
    char ch;
    int  chch;

    int program[1000];
    int counter=0;  //holds the address of the machine code instruction

    fp = fopen("name_of_program","r");

    while(fgets(line,sizeof line,fp)!= NULL)
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or labe

            if (strcmp(token,"add")==0) //-------- ADD ---------
                    op1 = strtok(NULL,"\n\t\r ");    
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<3)|((op3[0]-48)<<6);  
            else if (strcmp(token,"sub")==0)
                    //to be added
            else if (strcmp(token,"and")==0)
                    //to be added
            else if (strcmp(token,"or")==0)
                    //to be added
            else if (strcmp(token,"xor")==0)
                    //to be added
            else if (strcmp(token,"not")==0)
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
            else if (strcmp(token,"mov")==0)
                    //to be added
            else if (strcmp(token,"inc")==0)
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
            else if (strcmp(token,"dec")==0)
                                      //to be added
                     printf("no valid opcode\n");
     } //while

     fp = fopen("RAM","w");
     fprintf(fp,"v2.0 raw\n");  //needed for logisim, remove this line for verilog..
     for (i=0;i<counter+dataarea;i++)  //complete this for memory size in verilog
} //main