Skip to content

Reptile-8: IO Design

 

//addition
.code
ldi 3 0xb00
loop ldi 2 0x901
ld 0 2 
ldi 1 0x1
and 1 0 1 
jz loop
ldi 2 0x900
ld 0 2
ldi 7 0x000f
xor 7 0 7
jz pressed
add 4 6 6
add 6 6 6
add 6 6 6
add 6 6 6
add 6 4 6
add 6 0 6
st 3 6
jmp loop
pressed st 3 0 
add 5 5 6
st 3 5
xor 6 6 6 
jmp loop

 

 

Main Module

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


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 (.datain(data_all), .grounds(grounds), .display(display), .clk(clk));

keypad_ex  kp1(.rowwrite(rowwrite),.colread(colread),.clk(clk),.keyout(keyout),.statusordata(statusordata),.ack(ack));

reptile rr1 (.data_in(data_in), .data_out(data_out), .clk(clk), .memwt(memwt), .address(address));


 //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
					data_in=keyout;
					statusordata=0;
					ack=1;
				end
        else
            begin
					data_in=16'hf345;    
					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

Keypad Module

 

//Keypad Module
module keypad_ex (
						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

CPU Module
//Reptile CPU

module reptile (
		input clk,
		input [15:0] data_in,
		output [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;
 
	 
    wire zeroresult; //zeroflag value 
 
    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
 
        endcase
 
 
 
    always @*   
        case (state)
            LD:      address=regbank[ir[5:3]][11:0];
            ST:      address=regbank[ir[5:3]][11:0];
            default: address=pc;
         endcase
 
 
 assign memwt=(state==ST);
 
 assign data_out = regbank[ir[8:6]];
    always @*
        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

Reptile 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
                    //to be added
                }
                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++;
                    //to be added
                }
                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)
                {
                    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]=0x7200+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"and")==0)
                {
                    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]=0x7400+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"or")==0)
                {
                    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]=0x7600+((chch)&0x01ff);
                    counter++;//to be added
                }
                else if (strcmp(token,"xor")==0)
                {
                    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]=0x7800+((chch)&0x01ff);
                    counter++;
                    //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)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E40+((ch)&0x00ff);
                    counter++;
                    //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)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7EC0+((ch)&0x00ff);
                    counter++;                   //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]);
    }
}