Appendix |
Appendix A
State-Signal Assignment
State F0
Signal |
|
ALUMUXS |
00 |
MAMUXS |
10 |
IR_LOAD |
ü |
State F1
Signal |
Direct TAD |
InDirect TAD |
JMP(I) DCA(I) ISZ(D) |
ISZ(I) TAD(I) TAD(D) |
TAD(I) AUTO |
JMS(D) |
JMS(I) |
JMP(D) |
DCA(D) |
ALUMUXS |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
q |
00 |
ALUINC |
ü |
ü |
ü |
ü |
ü |
ü |
û |
q |
ü |
PC_MUXS |
ü |
ü |
ü |
ü |
ü |
û |
q |
û |
ü |
CA_LOAD |
ü |
ü |
ü |
ü |
ü |
û |
ü |
û |
û |
MAMUXS |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
PC_LOAD |
ü |
ü |
ü |
ü |
ü |
ü |
q |
ü |
ü |
MB_LOAD |
û |
û |
û |
û |
û |
û |
ü |
û |
û |
ALU_PASS |
û |
û |
û |
û |
û |
û |
ü |
q |
û |
MBMUXS |
q |
q |
q |
q |
q |
q |
q |
q |
00 |
AC_CLEAR |
û |
û |
û |
û |
û |
û |
û |
û |
ü |
State F2
Signal |
TAD (D) |
TAD (I) |
ISZ (D) |
DCA (I) |
JMP (I) |
ISZ (I) |
JMS (D) |
JMS (I) |
DCA (D) |
JMP (D) |
TAD (I) Auto |
ALUMUXS |
11 |
11 |
11 |
11 |
11 |
11 |
00 |
11 |
Finished |
Finished |
11 |
ALU(OP) |
ADD |
q |
q inc |
q |
q pass |
q |
q inc |
q inc |
q inc |
||
AC_LOAD |
ü |
û |
û |
û |
û |
û |
û |
û |
û |
||
CA_LOAD |
û |
ü |
û |
û |
û |
ü |
û |
û |
ü |
||
MAMUXS |
q |
10 |
00 |
10 |
q |
10 |
10 |
10 |
10 |
||
ALU_INC |
û |
û |
ü |
û |
û |
û |
ü |
ü |
ü |
||
AC_CLEAR |
û |
û |
û |
ü |
û |
û |
û |
û |
û |
||
MB_MUXS |
q |
q |
q |
00 |
q |
q |
10 |
10 |
q |
||
ALU_PASS |
û |
û |
û |
û |
ü |
û |
û |
û |
û |
||
MA_LOAD |
û |
û |
û |
û |
û |
ü |
û |
û |
ü |
||
PC_LOAD |
û |
û |
û |
û |
ü |
û |
ü |
ü |
û |
||
PC_MUXS |
q |
q |
q |
q |
1 |
q |
0 |
0 |
q |
||
MB_LOAD |
û |
û |
û |
û |
û |
û |
û |
û |
ü |
State E0
Signal |
TAD (D) |
TAD (I) |
ISZ (D) |
DCA (I) |
JMP (I) |
ISZ (I) |
JMS (D) |
JMS (I) |
DCA (D) |
JMP (D) |
TAD (I) Auto |
ALUMUXS |
Finished |
11 |
Finished |
Finished |
11 |
Finished |
Finished |
Finished |
Finished |
11 |
|
ALU(OP) |
ADD |
q inc |
q inc |
ADD |
|||||||
AC_LOAD |
ü |
û |
û |
ü |
|||||||
ALU_INC |
û |
ü zero |
ü |
û |
|||||||
PC_MUXS |
q |
1 |
q |
q |
|||||||
MA_MUXS |
q |
q |
01 |
01 |
|||||||
MB_MUXS |
q |
q |
01 |
10 |
|||||||
Skip Next |
û |
û |
ü zero |
û |
These state tables have been simplified for the purpose of this report
Appendix B - Signal Assignment
The table below defines the control pins required for each block in the design.
Block |
Signal |
No Bits |
Mnemonic |
PC |
Load |
1 |
PC_LOAD |
IR |
Load |
1 |
IR_LOAD |
MA |
Load |
1 |
MA_LOAD |
MB |
Load |
1 |
MB_LOAD |
CA |
Load |
1 |
CA_LOAD |
AC |
Load |
1 |
AC_LOAD |
Clear |
1 |
AC_CLEAR |
|
Complement |
1 |
AC_COMP |
|
LINK |
Load |
1 |
L_LOAD |
Clear |
1 |
L_CLEAR |
|
Complement |
1 |
L_COMP |
|
MAMUX |
Selector |
2 |
MAMUXS[0:1] |
MBMUX |
Selector |
2 |
MBMUXS[0:1] |
ALUMUX |
Selector |
2 |
MBMUXS[0:1] |
PCMUX |
Selector |
1 |
PCMUXS |
SHIFTER |
Enable |
1 |
SHIFT_E |
Direction |
1 |
SHIFT_D |
|
Length |
1 |
SHIFT_L |
|
ALU |
Increment |
2 |
ALU_INC[0:1] |
Pass Though |
21 |
ALU_PASS[0:1] |
|
PC Increment |
1 |
PC_INC |
|
Instruction |
3 |
IR_CTRL |
The PC increment requires a special increment in the ALU, since all other increments are twos complements increments. The PC increment should never have an effect on the Link bit.
Appendix B2
Appendix C – Memory Conversions Program
// Assembler output to Xilinx Mem Converter
// Jon Andrews
// 12/12/1999
// ========================================================
// This program converts the output of the PDP-8 PAL
// assembler to a format which can be used on the Xilinx
// Engineering Board
// ========================================================
// PDP-8 PAL Assembler required to generate initial memory file
// This can be downloaded from:
//
ftp://ftp.cs.uiowa.edu/pub/jones/pdp8/pal.c.Z// Compile using gcc –o asmtomem asmtomem.c
// Run using "> asmtomem <program name>" This will then read
// the program file with the extention .lst
// ========================================================
#include <stdio.h>
#include <stdlib.h>
struct memory_location {
char memaddr[10];
char memloc[10];
int imemloc;
int imeminst;
};
struct memory_location ci;
FILE *input_file;
FILE *output_file;
void print_hex(int data) {
if(data > 16) fprintf(output_file, "000");
if(data > 256 && data > 16 ) fprintf(output_file, "00");
if(data > 4096 && data > 256 ) fprintf(output_file, "0");
fprintf(output_file,"%x\n",ci.imeminst);
}
int decode(int location) {
if(location+1 == ci.imemloc) {
// good subsequent instruction
// fprintf(output_file,"%x\n",ci.imeminst);
print_hex(ci.imeminst);
location++;
}
else {
// requires padding
for(location; location<ci.imemloc; location++) {
fprintf(output_file,"0000\n");
}
// fprintf(output_file,"%x\n",ci.imeminst);
print_hex(ci.imeminst);
}
return location;
}
void main(int argc, char *argv[]) {
int location=0;
int memaddri=0;
int memloci=0;
int address_change=0;
int tempadd;
char ctemp;
char current_line[200];
// check that file was given
if(argc==1) {
printf("\n Usage: asmtomem file.lst\n\n");
exit(0);
}
// opens the input file
printf("PDP8 Assembler to Mem Converter\nProcessing File: %s\n",argv[1]);
if((input_file=fopen(argv[1],"r"))==NULL) {
printf("Unable to open input file\n");
exit(1);
}
if((output_file=fopen("test.mem","w"))==NULL) {
printf("Unable to open output file\n");
exit(1);
}
//temp = fgetc(input_file);
do {
fgets(current_line,200,input_file);
if(current_line[5] != ' ') { //check that not an empty line
for(memaddri=0;memaddri<=3;memaddri++){
ci.memaddr[memaddri]=current_line[memaddri+6];
}
for(memloci=0;memloci<=3;memloci++){
ci.memloc[memloci] = current_line[memloci+11];
}
// octal conversion for location
ctemp = ci.memloc[0];
tempadd = atoi(&ctemp);
address_change = tempadd*512;
ctemp = ci.memloc[1];
tempadd = atoi(&ctemp);
address_change += tempadd*64;
ctemp = ci.memloc[2];
tempadd = atoi(&ctemp);
address_change += tempadd*8;
ctemp = ci.memloc[3];
tempadd = atoi(&ctemp);
address_change += tempadd;
printf("INST:%d\n",address_change);
ci.imeminst = address_change;
// octal conversion for location
ctemp = ci.memaddr[0];
tempadd = atoi(&ctemp);
address_change = tempadd*512;
ctemp = ci.memaddr[1];
tempadd = atoi(&ctemp);
address_change += tempadd*64;
ctemp = ci.memaddr[2];
tempadd = atoi(&ctemp);
address_change += tempadd*8;
ctemp = ci.memaddr[3];
tempadd = atoi(&ctemp);
address_change += tempadd;
printf("LOC:%d\n",address_change);
ci.imemloc = address_change;
printf("%s\n",ci.memaddr);
printf("%s\n",ci.memloc);
location = decode(location);
}
} while (current_line[0] != 'e');
printf("Finished Processing\n");
}
Appendix D – Test Programs
Here you will find the full listings for test programs used on the PDP-8
/ ============================================================
/ Test Program - Load Constants using micro-coded instructions
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ This program uses a number of combinations of microcoded
/ instructions to store the values, 0,1,2,2047,2048,4095,4094
/ in consecutive memory locations.
/ Store operations are performed inside a small subroutine to
/ show its effectiveness.
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_constants.lst) through 'asmtomem tests_constants'
/ This converts the memory format to one which will
/ work on the Xilinx Board
/ ============================================================
*0001
ADRS, 0020
*0030
INCADR, .-.
CLA
ISZ ADRS
JMP I INCADR
*0200
CLA
DCA I ADRS / Mem[20] = 0
JMS INCADR
CLA IAC
DCA I ADRS / Mem[21] = 1
JMS INCADR
CLA CLL CML RTL
DCA I ADRS / Mem[22] = 2
JMS INCADR
CLA CMA CLL RAR
DCA I ADRS / Mem[23] = 2047
JMS INCADR
CLA CLL CML RAR / Mem[24] = 2048
DCA I ADRS
JMS INCADR
CLA CMA / Mem[25] = -1 4095
DCA I ADRS
JMS INCADR
CLA CMA CLL RAL / Mem[26] = -2 4094
DCA I ADRS
JMS INCADR
HLT / Halt the processor
/ ============================================================
/ ============================================================
/ Test Program – Tests Memory Pages
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ This program tests loading of values from the current page
/ and the zero page.
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_pages.lst) through 'asmtomem tests_pages'
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
/ Zero Page Variable Setup
CONST1, 0001
CONST2, 0002
ADDR1, 0002
BASE, 0020
*0200
JMP AFVAL / Jump over variables
/ Current Page Variable Setup
CONST3, 0001
CONST4, 0002
ADDR2, 0202
BASE1, 0000
AFVAL, CLA / Clear Accumulator
/ Page Zero Variables
TAD CONST1 / Load value CONST1
TAD I ADDR1 / Load value [ADDR1] = CONST2
DCA I BASE / Store in [BASE] = 0020
/ Current Page Variables
TAD CONST3 / Load value CONST3
TAD I ADDR2 / Load value [ADDR2] = CONST4
DCA BASE1 / Store in BASE
HLT / Stop the Processor
/ Result is that
/ MEM(0020) == MEM(0204) == 0003
/ ============================================================
/ ============================================================
/ Test Program – All Jump Instructions
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ Test JMP Instruction, Forward and Backwards Direct and
/ In-Direct
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_jumps.lst) through 'asmtomem tests_jumps'
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
CST, 5252 / 101 010 101 010
CST1, 0202 / Used for in-direct jump from TAR4
MEMLOC, 0020
*0200
JMP ENDSETUP
TAR3, JMP TAR4
JMP TAR5
ENDSETUP, / If all jumps complete ACC should not be zero
CLA
TAD CST
JMP TAR1 / If jump sucessful to TAR1 ACC not cleared
CLA
TAR1, JMP TAR2 / Tests sucessive jumps
CLA
TAR2, JMP TAR3 / Tests backwards jumps
CLA
TAR4, JMP I CST1 / Tests Indirect jumps through variable on page 0
CLA
TAR5, DCA I MEMLOC / At this point ACC should not be zero
HLT / Halt CPU
/ Result is that
/ MEM(0020) == CONST == 5252
/ ============================================================
/ ============================================================
/ Test Program - Basic Skip instruction testing
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ Test ISZ Instruction, to check both true and false skip
/ cases.
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_skips.lst) through 'asmtomem tests_skips'
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
CST, 2525
NEG, 7777 / Value of -1, used to make skip instr skip
NEG1, 7777 / Value of -1, " " " " " "
NEG2, 7777 / Value of -1, " " " " " "
MEMLOC, 0020
*0200 / If all Skips correct
/ value of ACC should remain constant
CLA
TAD CST / Set ACC to be 2525
ISZ NEG / Increment and Skip next instr if result 0
CLA
ISZ NEG / Shoudn't skip next inst
CMA / Complement ACC
ISZ NEG1 / Should skip since NEG1 is -1
ISZ NEG2 / Tests sucessive skips if failure
CMA / Complement ACC - Back to original value
DCA I MEMLOC / At this point the ACC should be 2525
HLT / Halt the CPU
/ Result is that
/ MEM(0020) == CONST == 2525
/ ============================================================
/ ============================================================
/ Test Program - Block Memory Cop
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ Copy a block of memory to a subsequent block
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_memcopy.lst) through 'asmtomem tests_memcopy'
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
MEMLOC, 0020
MEMRES, 0031 / base of subsequent memory block
COUNT, 7770 / used for loop control
*0020
K1, 0001 / block of memory
K2, 0002
K3, 0003
K4, 0004
K5, 0005
K6, 0006
K7, 0007
K8, 0010
*0200
/ Copy memory block starting at 0020 to block starting at 0036
START, CLA
TAD I MEMLOC
DCA I MEMRES
ISZ MEMLOC / increment source memory location
ISZ MEMRES / increment destination memory location
ISZ COUNT / loop until all memory locations copied
JMP START
HLT / Halt the CPU
/ Result is that
/ MEM(0020)->MEM(0027) == MEM(0031)->MEM(0040)
/ ============================================================
/ ============================================================
/ Test Program - Test Nested Subroutine Calls
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ This program will call subroutines nested within one another
/ and then return from each of them, incrementing the AC in
/ each routine
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_jumpsubs.lst) through 'asmtomem tests_jumpsubs'
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
MEMLOC, 0003
*0020
SUB3, .-.
IAC
JMP I SUB3 / Return
SUB2, .-.
IAC
JMS SUB3 / Call to subroutine 3
JMP I SUB2 / Return
SUB1, .-.
IAC
JMS SUB2 / Call to subroutine 2
JMP I SUB1 / Return
*0200
JMS SUB1 / Call to subroutine 1
DCA I MEMLOC
HLT / Halt the CPU
/ Result is that
/ MEM(0003) == 0003
/ ============================================================
/ ============================================================
/ Test Program – Test Microcoded Instructions
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ The optimised load constant test file used microcoded
/ instructions to a degree that shows their correctness
/
/ All microcoded instructions are tested as part of other
/ test files.
/
/ ============================================================
/ ============================================================
/ ============================================================
/ Test Program - Immidiate Mode Programming
/ Written by Jon Andrews on 05/02/2000
/ ============================================================
/ This program will check the processor can handle assembler
/ output when immidiates are used.
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (tests_immidiate.lst) through 'asmtomem tests_immidiate’
/ This converts the memory format to one which will work
/ on the Xilinx Board
/ ============================================================
*0001
MEMLOC, 0003
*0200
TAD (7) / Load immediate value 7
DCA I MEMLOC / Store ACC to memory
ISZ MEMLOC / Increment target memory location
JMS I [SUB1] / Call Off-page sub routine
DCA I MEMLOC / Store ACC to memory
ISZ MEMLOC / Increment target memory location
TAD I (CONST) / Load off Page constant
DCA I MEMLOC / Store ACC to memory
HLT / Halt the CPU
*0401
SUB1, .-.
IAC
JMP I SUB1
*407
CONST, 1111 / Off Page Constant
/ Result is that
/ MEM(0003) == 0007
/ MEM(0004) == 0001
/ MEM(0005) == 1111
/ ============================================================
Appendix E – Bubble Sort
/ ============================================================
/ Bubble Sort Program for PDP8
/ Written by Jon Andrews on 15/03/2000
/ ============================================================
/ This program sorts the array of numbers below
/ so that they are in descending order
/
/ This program should be assembler with the pdp8 PAL assembler
/ For use on the PDP8-FPGA you will need to run the assembler
/ listing (bubble.lst) through 'asmtomem bubble' This converts
/ the memory format to one which will work on the Xilinx Board
/ ============================================================
*0001
K1, 0001 / data block to sort /0001
K2, 0010 /0008
K3, 0005 /0005
K4, 0013 /000B
K5, 0100 /0040
K6, 0204 /0084
K7, 0504 /0144
K8, 0030 /0018
*0030
NUM, 0010 / number of elements to sort
ADDR1, 0001 / var1 memory location
ADDR2, 0002 / var2 memory location
LOOPO, 7771 / outer loop count - count towards zero
LOOPI, 7771 / inter loop count - count towards zero
TEMP, 0000 / temp location to do swap in
ORG1, 0001 / starting values for addr1
ORG2, 0002 / starting values for addr2
ORG3, 7771 / starting values for loopi
*0200
CLA CLL / start by clearing acc
TAD LOOPO / load outer loop counter
OUTER, SNA / if outer loop counter zero then need to hlt
JMP FINISH / jmp to halt when outer loop couter zero
CLA / clear ready to load ACC with counter
TAD LOOPI / load inner loop counter
JMP INNER / jump into inner loop
OUTERE, TAD LOOPO / load outer loop counter
IAC / increment inner loop counter
DCA LOOPO / store back incremented outer loop counter
TAD ORG1 / load in ORG1
DCA ADDR1 / store 1 into addr1
TAD ORG2 / load in ORG2
DCA ADDR2 / store 2 into addr2
TAD ORG3
DCA LOOPI / store 7771 back it LOOPI - effective reset
TAD LOOPO / load outer loop counter back into ACC
JMP OUTER / jump back into outer loop
INNER, SNA / if LOOPI is zero inner loop finished
JMP OUTERE / jump to end out outer loop
/ do subtraction by complement, inc and add
CLA CLL / clear ACC ready for next value
TAD I ADDR1 / load first variable
CMA IAC / complement ACC and increment
TAD I ADDR2 / load second variable
SMA / skip if result negative
JMP RPOS / if result is positive, write back in rpos
INNERE, ISZ ADDR1 / increment address of var1
ISZ ADDR2 / increment address of var2
CLA CLL
TAD LOOPI / load inner loop counter
IAC / increment inner loop counter
DCA LOOPI / store back incremented inner loop counter
CLL
TAD LOOPI / load loop counter back into ACC
JMP INNER / jump back to beginning of inner loop
RPOS, CLA CLL
TAD I ADDR1 / load in var1
DCA TEMP / store var1 into temporary location
TAD I ADDR2 / load in var2
DCA I ADDR1 / store var2 into location of var1
TAD TEMP / load temp back in
DCA I ADDR2 / store back into location of var2
JMP INNERE
FINISH, HLT / Halt the CPU