Skip to content

Reference for Second Project

Bird Instruction Format

Format for new instructions of Bird. (as discussed in the lecture)

Machine Code Format PUSH
Push r

Machine Code Format POP
POP r

Machine Code Format CALL
CALL x

Machine Code Format RET
RET

Main Module

//Main module


module main_module (
			output wire [3:0] rowwrite,
			input [3:0] colread,
			input clk,
			output wire [3:0] grounds,
			output wire [6:0] display,
			input pushbutton //may be used as clock
			);

reg [15:0] data_all;
wire [3:0] keyout;
reg [25:0] clk1;
reg [1:0] ready_buffer;
reg ack;
reg statusordata;

//memory map is defined here
localparam	BEGINMEM=12'h000,
		ENDMEM=12'h1ff,
		KEYPAD=12'h900,
		SEVENSEG=12'hb00;
//  memory chip
reg [15:0] memory [0:127]; 
 
// cpu's input-output pins
wire [15:0] data_out;
reg [15:0] data_in;
wire [11:0] address;
wire memwt;


sevensegment ss1 (//to be added);

keypad  kp1(//to be added);

bird br1 (//to be added);


//multiplexer for cpu input
always @*
	if ( (BEGINMEM<=address) && (address<=ENDMEM) )
		begin
			data_in=memory[address];
			ack=0;
			statusordata=0;
		end
	else if (address==KEYPAD+1)
		begin	
			statusordata=1;
			data_in=keyout;
			ack=0;
		end
	else if (address==KEYPAD)
		begin
			//to be added 
		end
	else
		begin
			data_in=16'hf345; //any number
			ack=0;
			statusordata=0;
		end

//multiplexer for cpu output 

always @(posedge clk) //data output port of the cpu
	if (memwt)
		if ( (BEGINMEM<=address) && (address<=ENDMEM) )
			memory[address]<=data_out;
		else if ( SEVENSEG==address) 
			data_all<=data_out;


initial 
	begin
		data_all=0;
		ack=0;
		statusordata=0;
		$readmemh("ram.dat", memory);
	end

endmodule

 

CPU Module

//bird CPU
module bird (
		input clk,
		input [15:0] data_in,
		output reg [15:0] data_out,
		output reg [11:0] address,
		output memwt
		);

reg [11:0] pc, ir; //program counter, instruction register

reg [4:0] state; //FSM
reg [15:0] regbank [7:0];//registers 
reg zeroflag; //zero flag register
reg [15:0] result; //output for result
 
 
localparam	FETCH=4'b0000,
		LDI=4'b0001, 
		LD=4'b0010,
		ST=4'b0011,
		JZ=4'b0100,
		JMP=4'b0101,
		ALU=4'b0111,
		PUSH=4'b1000,
		POP1=4'b1001,
		POP2=4'b1100,
		CALL=4'b1010,
		RET1=4'b1011,
		RET2=4'b1101;
 

wire zeroresult; 

always @(posedge clk)
	case(state) 
		FETCH: 
			begin
				if ( data_in[15:12]==JZ) // if instruction is jz  
					if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
						state <= JMP;
					else
						state <= FETCH; //stay here to catch next instruction
				else
					state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
				ir<=data_in[11:0]; //read instruction details into instruction register
				pc<=pc+1; //increment program counter
			end

		LDI:
			begin
				regbank[ ir[2:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
				pc<=pc+1; //for next instruction (32 bit instruction)  
				state <= FETCH;
			end

		LD:
			begin
				regbank[ir[2:0]] <= data_in;
				state <= FETCH;  
				end 
 
		ST:
			begin
				state <= FETCH;  
			end
 
		JMP:
			begin
				pc <= pc+ir;
				state <= FETCH;  
			end
 
		ALU:
			begin
				regbank[ir[2:0]]<=result;
				zeroflag<=zeroresult;
				state <= FETCH;
			end

		PUSH:
			begin
				 regbank[7]<=regbank[7]-1;
				 state <= FETCH;
			end

		POP1:
			begin
				//to be added
			end

		POP2: 
			begin
				//to be added
			end

		CALL: 
			begin
			        //to be added 
			end

		RET1:
			begin
				//to be added
			end

		RET2:
			begin
				//to be added 
			end

	endcase

always @*
	case (state)
		LD:	address=regbank[ir[5:3]][11:0];
		ST:	address=regbank[ir[5:3]][11:0];
		PUSH:	address=regbank[7];
		POP2:	//to be added
		CALL:	//to be added
		RET2:	//to be added
		default: address=pc;
	endcase
 
 
assign memwt=(state==ST)|| // to be added
 
always @*
	case (state)
		CALL: data_out = //to be added 
		default: data_out = regbank[ir[8:6]];
	endcase

always @* //ALU Operation
	case (ir[11:9])
		3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
		3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
		3'h2: result = regbank[ir[8:6]]&regbank[ir[5:3]]; //010
		3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
		3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
		3'h7: case (ir[8:6])
			3'h0: result = !regbank[ir[5:3]];
			3'h1: result = regbank[ir[5:3]];
			3'h2: result = regbank[ir[5:3]]+1;
			3'h3: result = regbank[ir[5:3]]-1;
			default: result=16'h0000;
		     endcase
		default: result=16'h0000;
	endcase
 
assign zeroresult = ~|result;

initial begin;
	state=FETCH;
	zeroflag=0;
	pc=0;
end

endmodule

Keypad Module

module keypad (
						output reg [3:0] rowwrite,
						input [3:0] colread,
						input clk,
						input ack,
						input statusordata,
						output reg [15:0] keyout
						);
wire keypressed;		
reg [25:0] clk1;
reg ready;
reg [3:0] keyread, data;
reg [3:0] rowpressed;
reg [3:0] pressedcol [0:3];
reg [11:0] rowpressed_buffer0, rowpressed_buffer1, rowpressed_buffer2, rowpressed_buffer3;
reg [3:0] rowpressed_debounced;

always @(posedge clk)
	clk1<=clk1+1;

always @(posedge clk1[15])
	rowwrite<={rowwrite[2:0], rowwrite[3]};

always @(posedge clk1[15])
	if (rowwrite== 4'b1110)
		begin
			rowpressed[0]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 1, colread=1101-->2, 1011-->3, 0111->A
			pressedcol[0]<=colread;
		end
	else if (rowwrite==4'b1101)
		begin
			rowpressed[1]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 4, colread=1101-->5, 1011-->6, 0111->B
			pressedcol[1]<=colread;
		end
	else if (rowwrite==4'b1011)
		begin
			rowpressed[2]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 7, colread=1101-->8, 1011-->9, 0111->C
			pressedcol[2]<=colread;
		end
	else if (rowwrite==4'b0111)
		begin
			rowpressed[3]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> *(E), colread=1101-->0, 1011-->#(F), 0111->D
			pressedcol[3]<=colread;
		end
		
wire transition0_10;
wire transition0_01;

assign transition0_10=~|rowpressed_buffer0;
assign transition0_01=&rowpressed_buffer0;

wire transition1_10;
wire transition1_01;

assign transition1_10=~|rowpressed_buffer1;
assign transition1_01=&rowpressed_buffer1;

wire transition2_10;
wire transition2_01;

assign transition2_10=~|rowpressed_buffer2;
assign transition2_01=&rowpressed_buffer2;

wire transition3_10;
wire transition3_01;

assign transition3_10=~|rowpressed_buffer3; //kpd=1-->0
assign transition3_01=&rowpressed_buffer3;  //kpd=0-->1


always @(posedge clk1[15])
	begin
		rowpressed_buffer0<= {rowpressed_buffer0[10:0],rowpressed[0]};
		if (rowpressed_debounced[0]==0 && transition0_01)
			rowpressed_debounced[0]<=1;
		if (rowpressed_debounced[0]==1 && transition0_10)
			rowpressed_debounced[0]<=0;
	
	rowpressed_buffer1<= {rowpressed_buffer1[10:0],rowpressed[1]};
		if (rowpressed_debounced[1]==0 && transition1_01)
			rowpressed_debounced[1]<=1;
		if (rowpressed_debounced[1]==1 && transition1_10)
			rowpressed_debounced[1]<=0;
			
	rowpressed_buffer2<= {rowpressed_buffer2[10:0],rowpressed[2]};
		if (rowpressed_debounced[2]==0 && transition2_01)
			rowpressed_debounced[2]<=1;
		if (rowpressed_debounced[2]==1 && transition2_10)
			rowpressed_debounced[2]<=0;
	
	rowpressed_buffer3<= {rowpressed_buffer3[10:0],rowpressed[3]};
		if (rowpressed_debounced[3]==0 && transition3_01)
			rowpressed_debounced[3]<=1;
		if (rowpressed_debounced[3]==1 && transition3_10)
			rowpressed_debounced[3]<=0;
	end 

always @*
	begin
		if (rowpressed_debounced[0]==1)
			begin
				if (pressedcol[0]==4'b1110)
					keyread=4'h1;
				else if (pressedcol[0]==4'b1101)
					keyread=4'h2;
				else if (pressedcol[0]==4'b1011)
					keyread=4'h3;
				else if (pressedcol[0]==4'b0111)
					keyread=4'hA;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[1]==1)
			begin
				if (pressedcol[1]==4'b1110)
					keyread=4'h4;
				else if (pressedcol[1]==4'b1101)
					keyread=4'h5;
				else if (pressedcol[1]==4'b1011)
					keyread=4'h6;
				else if (pressedcol[1]==4'b0111)
					keyread=4'hB;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[2]==1)
			begin
				if (pressedcol[2]==4'b1110)
					keyread=4'h7;
				else if (pressedcol[2]==4'b1101)
					keyread=4'h8;
				else if (pressedcol[2]==4'b1011)
					keyread=4'h9;
				else if (pressedcol[2]==4'b0111)
					keyread=4'hC;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[3]==1)
			begin
				if (pressedcol[3]==4'b1110)
					keyread=4'hE;
				else if (pressedcol[3]==4'b1101)
					keyread=4'h0;
				else if (pressedcol[3]==4'b1011)
					keyread=4'hF;
				else if (pressedcol[3]==4'b0111)
					keyread=4'hD;
				else keyread=4'b0000;
			end
		else keyread=4'b0000;
	end //always


assign keypressed= rowpressed_debounced[0]||rowpressed_debounced[1]||rowpressed_debounced[2]||rowpressed_debounced[3];

reg [1:0] keypressed_buffer; //yeni karakter için parmağı çekip tekrar basmamız için gerekli

always @(posedge clk)
	keypressed_buffer<={keypressed_buffer[0],keypressed};

always @(posedge clk)
	if ((keypressed_buffer==2'b01)&&(ready==0))
		begin
			data<=keyread;
			ready<=1;
		end
	else if ((ack==1)&&(ready==1))
		ready<=0;
	
always @(*)
	if (statusordata==1)
		keyout={15'b0,ready};
	else
		keyout={12'b0,data};
	
initial 
	begin
		rowwrite=4'b1110;		
		ready=0;
	end
endmodule

 

Seven Segment Display Module

module sevensegment(datain, grounds, display, clk);

	input wire [15:0] datain;
	output reg [3:0] grounds;
	output reg [6:0] display;
	input clk;
	
	reg [3:0] data [3:0];
	reg [1:0] count;
	reg [25:0] clk1;
	
	always @(posedge clk1[15])
		begin
			grounds <= {grounds[2:0],grounds[3]};
			count <= count + 1;
		end
	
	always @(posedge clk)
		clk1 <= clk1 + 1;
	
	always @(*)
		case(data[count])	
			0:display=7'b1111110; //starts with a, ends with g
			1:display=7'b0110000;
			2:display=7'b1101101;
			3:display=7'b1111001;
			4:display=7'b0110011;
			5:display=7'b1011011;
			6:display=7'b1011111;
			7:display=7'b1110000;
			8:display=7'b1111111;
			9:display=7'b1111011;
			'ha:display=7'b1110111;
			'hb:display=7'b0011111;
			'hc:display=7'b1001110;
			'hd:display=7'b0111101;
			'he:display=7'b1001111;
			'hf:display=7'b1000111;
			default display=7'b1111111;
		endcase
	
	always @*
		begin
			data[0] = datain[15:12];
			data[1] = datain[11:8];
			data[2] = datain[7:4];
			data[3] = datain[3:0];
		end
	
	initial begin		
		count = 2'b0;
		grounds = 4'b1110;
		clk1 = 0;
	end
endmodule



 

Bird Assembler

// to compile, gcc assembler.c -o assembler
// No error check is provided.
// Variable names cannot start with numeric characters, ie, with 0-9.
// hexadecimals are twos complement.
// first address of the code section is zero, and the data section follows the code section in memory.
// four tables are formed: jump table, ldi table, label table and variable table.

#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;
        hex++;
    }
    return(result);
}


main()
{
    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


    struct label_or_variable
    {
        int location;
        char *name;
    };

// A label is a symbol which mark a location within the code section. In the example
// program above, the strings "lpp", "loop" and "lp1" are labels.
// In reptile, labels are used by jump, jz and ldi instructions.
    struct label_or_variable labeltable[50]; //there can be 50 labels at most in our programs
    int nooflabels = 0;                       //number of labels encountered during assembly.

 // A variable is a symbol which mark a location within the data section. In the example
// program above, the strings "", "" and "" are variables.
// In reptile, variables are used by ldi instructions.
    struct label_or_variable variabletable[50]; // The list of variables in .data section and their locations.
    int noofvariables = 0;    //number of jumps encountered during assembly.

// Jump instructions cannot be assembled readily because we may not know the value of
// the label when we encountered a jump instruction. This happens if the label used by
// that jump instruction appear below that jump instruction. This is the situation
// with the label "loop" in the example program above. Hence, the location of jump
// instructions must be stored.
    struct label_or_variable jumptable[100]; //There can be at most 100 jumps
    int noofjumps=0;                        //number of jump instructions encountered during assembly.


//Variables and labels are used by ldi instructions.
//The memory for the variables are traditionally allocated at the end of the code section.
//Hence their addresses are not known when we assemble a ldi instruction. Also, the value of
//a label may not be known when we encounter a ldi instruction which uses that label.
//Hence, the location of the ldi instructions must be kept, and these instructions must be
//modified when we discover the address of the label or variable that it uses.
    struct label_or_variable lditable[100];
    int noofldis=0;



    fp = fopen("code.txt","r");

    if (fp != NULL)
    {
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .code section
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )
                break;
        }
        while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or label

//========================================   FIRST PASS  ======================================================
            while (token)
            {
                if (strcmp(token,"ldi")==0)        //---------------LDI INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                                //get the 1st operand of ldi, which is the register that ldi loads
                    op2 = strtok(NULL,"\n\t\r ");                                //get the 2nd operand of ldi, which is the data that is to be loaded
                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction
                    counter++;                                                   //move to the second 16-bit of the ldi instruction
                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal
                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit
                    else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal
                        program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit
                    else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.
                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.
                        lditable[noofldis].location = counter;                 //record the location of this 2nd 16-bit
                        op1=(char*)malloc(sizeof(op2));                         //and the name of the label/variable that it must contain
                        strcpy(op1,op2);                                        //in the lditable array.
                        lditable[noofldis].name = op1;
                        noofldis++;
                    }
                    counter++;                                                     //skip to the next memory location
                }

                else if (strcmp(token,"ld")==0)      //------------LD INSTRUCTION---------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    ch = (op1[0]-48)| ((op2[0]-48) << 3);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x2000+((ch)&0x00ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                }
                else if (strcmp(token,"st")==0) //-------------ST INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    chch = (op1[0]-48)<<3| ((op2[0]-48) << 6);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x3000+((chch)&0x01ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                    
                }
                else if (strcmp(token,"jz")==0) //------------- CONDITIONAL JUMP ------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x4000;            //write the incomplete instruction (just opcode) to memory
                    counter++;
                    
                }
                else if (strcmp(token,"jmp")==0)  //-------------- JUMP -----------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x5000;            //write the incomplete instruction (just opcode) to memory
                    counter++;                    //skip to the next empty location in memory.
                }
                else 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)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7000+((chch)&0x01ff);
                    counter++;
                }
                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);
                    program[counter]=0x7E00+((ch)&0x00ff);
                    counter++;
                }
                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);
                    program[counter]=0x7E80+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"dec")==0)
                {
                     //to be added
                }
                else if (strcmp(token,"push")==0)
                {
                      //to be added
                }
                else if (strcmp(token,"pop")==0)
                {
                      //to be added
                }
                else if (strcmp(token,"call")==0)  //-------------- CALL -----------------------------
                {
                    //to be added
                }
                else if (strcmp(token,"ret")==0)
                {
                    //to be added
                }
                else //------WHAT IS ENCOUNTERED IS NOT AN INSTRUCTION BUT A LABEL. UPDATE THE LABEL TABLE--------
                {
                    labeltable[nooflabels].location = counter;  //read the label and update labeltable.
                    op1=(char*)malloc(sizeof(token));
                    strcpy(op1,token);
                    labeltable[nooflabels].name=op1;
                    nooflabels++;
                }
                token = strtok(NULL,",\n\t\r ");  // if what is read before is an instruction, this will be NULL
                                                  //if what is read before is an label, this will be an opcode.
            }
        }


//================================= SECOND PASS ==============================

//supply the address fields of the jump and jz instructions by matching jumptable and labeltable
        int i,j;
        for (i=0; i<noofjumps;i++)   //for all jump/jz instructions encountered
        {
            j=0;
            while ((j<nooflabels)&&( strcmp(jumptable[i].name , labeltable[j].name ) != 0 ))  //if the label for this jump/jz does not match with the
                j++;                                            // jth label in the labeltable, check the next label..
            program[jumptable[i].location] +=(labeltable[j].location-jumptable[i].location-1)&0x0fff;       //copy the jump address into memory.
        }


//search for the start of the .data segment
        rewind(fp);
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .data, if no .data, also ok.
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".data")==0 )
                break;

        }

// process the .data segment and generate the variabletable[] array.
        int dataarea=0;
         while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )  //go till the .code segment
                break;
            else if (token[strlen(token)-1]==':')
            {
                token[strlen(token)-1]='\0';  //will not cause memory leak, as we do not do malloc
                variabletable[noofvariables].location=counter+dataarea;
                op1=(char*)malloc(sizeof(token));
                strcpy(op1,token);
                variabletable[noofvariables].name=op1;
                token = strtok(NULL,",\n\t\r ");
                if (token==NULL)
                    program[counter+dataarea]=0;
                else if (strcmp(token, ".space")==0)
                {
                    token=strtok(NULL,"\n\t\r ");
                    dataarea+=atoi(token);
                }
                else if((token[0]=='0')&&(token[1]=='x'))
                    program[counter+dataarea]=hex2int(token+2)&0xffff;
                else if ((  (token[0])=='-') || ('0'<=(token[0])&&(token[0]<='9'))  )
                    program[counter+dataarea]=atoi(token)&0xffff;
                noofvariables++;
                dataarea++;
            }
        }


// supply the address fields for the ldi instructions from the variable table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<noofvariables)&&( strcmp( lditable[i].name , variabletable[j].name)!=0 ))
                j++;
            if (j<noofvariables)
                program[lditable[i].location] = variabletable[j].location;
        }


// supply the address fields for the ldi instructions from the label table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<nooflabels)&&( strcmp( lditable[i].name , labeltable[j].name)!=0 ))
                j++;
            if (j<nooflabels){
                program[lditable[i].location] = (labeltable[j].location)&0x0fff;
                printf("%d %d %d\n", i, j, (labeltable[j].location));
            }
        }


//display the resulting tables
        printf("LABEL TABLE\n");
        for (i=0;i<nooflabels;i++)
            printf("%d %s\n", labeltable[i].location, labeltable[i].name);
        printf("\n");
        printf("JUMP TABLE\n");
        for (i=0;i<noofjumps;i++)
            printf("%d %s\n", jumptable[i].location, jumptable[i].name);
        printf("\n");
        printf("VARIABLE TABLE\n");
        for (i=0;i<noofvariables;i++)
            printf("%d %s\n", variabletable[i].location, variabletable[i].name);
        printf("\n");
        printf("LDI INSTRUCTIONS\n");
        for (i=0;i<noofldis;i++)
            printf("%d %s\n", lditable[i].location, lditable[i].name);
        printf("\n");
        fclose(fp);
        fp = fopen("RAM","w");
        fprintf(fp,"v2.0 raw\n");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp,"%04x\n",program[i]);
        fclose(fp);
        fp = fopen("ram.dat","w");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp, "%04x\n", program[i]);
    }
}