[sci.electronics] PAL programming + other tools

robertb@cs.washington.edu (Robert Bedichek) (05/09/91)

(I sent this as email, it bounced, so I am posting it.  Perhaps others
will find the information here useful.)

In article <1991May8.053632.26564@uniwa.uwa.oz> you write:
>We are a couple of people thinking of designing a simple processor.
>After some consideration, we thought we'd have a look at what PAL's
>could do for us in terms of simplifying design.  Unfortunately we
>don't have any experience with PALs, and in paticular we don't 
>have any software to program them with.
>
>Any advice on programming, or where to get hold of an assembler
>would be greatly appreciated.
>

Designing with PLDs is much easier than designing without them.  We
(myself and others here in the CS&E department at the University of
Washington) use MacABEL, the McIntosh version of Data I/O's ABEL.  I've
tacked an example ABEL program at the end of this to give you a feel
for what a PLD specification might look like.

We also use Capilano's DesignWorks, a schematic entry and simulation
package.  It can synthesize simulation models and schematic symbols
from MacABEL output.  Being able to simulate a design, especially one
that will be in PCB first (i.e., not wire-wrap), is a very good thing.

I am doing a lot of debug now, before I do layout, instead of after the
boards come back from the board house.  And it is *easier* to debug the
simulated circuit than a real one because it is much easier to change
and measure than a real circuit.  The simulator might not catch
everything, but if it catches, say, 95% of the bugs that you would
otherwise find after layout, it is well worth it.

DW is $1000, ABEL is $2300, and a Data 2900 PAL/EPROM, burner is about
$5000.  You can get PAL burners for less.  We use Racal/Redac PCB
layout tools that run on the IBM PC, it is about $1500 I think.  Its
user interface is from the 1950's, but it is very reliable.  We've done
one complex board with it and it didn't screw up anything.   If you
want more information, let me know.  Good tools are worth some
sacrifice.

	Robert Bedichek		robertb@cs.washington.edu

module dramctl;

flag '-q02' " List original and reduced equations
flag '-r2'  " Use presto

" This PAL is part of the DRAM controller.  It decides when a request
" will be satisfied and drives the acknowledgement lines.  If a refresh
" request is pending, we do not start a data access.

u603  device      'p22v10';

" inputs
 ctlclk     pin   1;    " System clock
 a2         pin   2;    " Bit 2 of the Address Bus
 srd        pin   3;    " 1 = read, 0 = write
!ras        pin   4;    " Row-address-strobe is active
 ssiz0      pin   5;    " S-Bus size bit 0
 ssiz1      pin   6;    " S-Bus size bit 1
 ssiz2      pin   7;    " S-Bus size bit 2
 refreq     pin   8;    " 1 = refresh request is pending
 refresh    pin   9;    " 1 = refresh in progress
 sba        pin   13;   " 1 = S-Bus device is bus master (o.w. it is a CMMU)

" outputs
 sack0      pin   14;   " S-Bus acknowledge bit 0
 sack1      pin   15;   " S-Bus acknowledge bit 1
 sack2      pin   16;   " S-Bus acknowledge bit 2
 ack        pin   17;   " 1 = we are sending an acknowledgement on the S-Bus
 cyccnt2    pin   18;   " Bit 2 of the cycle counter
 a2out      pin   19;   " a2 that we generate for casgen
 cyccnt0    pin   20;   " Bit 0 of cycle counter
 cyccnt1    pin   21;   " Bit 1 of cycle counter
 seta3      pin   22;   " This is or'd with address bit 3 to select 2nd dword
 lastcyc    pin   23;   " 1 = this is the last cycle of the access
 
 cycle_count = [cyccnt2, cyccnt1, cyccnt0];
  
 " S-Bus transfer sizes
 SWORD = [0,0,0];
 SBYTE = [0,0,1];
 SHALF = [0,1,0];
 SEXT  = [0,1,1];
 SQUAD = [1,0,0];
 SOCT  = [1,0,1];
 SB16  = [1,1,0];
 SDOUB = [1,1,1];

 size = [ssiz2, ssiz1, ssiz0];
 
" S-Bus acknowledgements
 AIDLE  = [1,1,1];      " Idle/wait
 AERROR = [1,1,0];      " Error Acknowledgement
 ABYTE  = [1,0,1];      " Byte (Data) Acknowledgement
 ARERUN = [1,0,0];      " Rerun Acknowledgement
 AWORD  = [0,1,1];      " Word (Data) Acknowledgement
 ADWORD = [0,1,0];      " Double-word (Data) Acknowledgement
 AHWORD = [0,0,1];      " Half-word (Data) Acknowledgement 
 
 acknowledgement = [sack2, sack1, sack0];

equations

" 'a2out' goes to the rasgen and casgen PALs.  It selects the bank.
" When it is 0, it selects bank 0, when 1, it selects bank 1.  The
" timing for reads is one cycle longer than for writes when a CMMU is
" bus master.

when (!sba & srd)  then a2out = a2 # (cycle_count == 2) # (cycle_count == 4);
when (!sba & !srd) then a2out = a2 # (cycle_count == 1) # (cycle_count == 3);

" The timing for reads and writes is the same when an S-Bus slot device is
" master.  The first word takes three cycles, each word after the first takes
" two cycles.

when ( sba       ) then a2out = a2 # (cycle_count == 2) # (cycle_count == 6);

" Or a 1 into address bit a3 so that we select
" the second two words out of a four-word chunk (a cache line).  There
" may be a race condition here, where this signal causes address bit a2
" to go from 0 to 1 via the or gate and the address mux too quickly and
" the falling /CAS causes the DRAMs to latch a column address that has
" changed before it should have.

when (!sba &  srd) then seta3 = (cycle_count >= 3);
when (!sba & !srd) then seta3 = (cycle_count >= 2);
when (!sba       ) then seta3 = (cycle_count >= 4);

" Here we decide whether to start a DRAM access.  We do if there
" is no refresh request pending (it has higher priority), and if there
" is no refresh in progress, and if the /RAS generator PAL has already
" decided to start a cycle (it has the most advance information).

when (ras & !refreq & !refresh & ras & (cycle_count == 0)) 
                                    then cycle_count := cycle_count + 1;

" Here we decide whether to keep the DRAM access counter going.  W

" case 1: A CMMU is the bus master and the operation is read.  We take
"         six cycles.  (the first cycle is numbered 0).
when (ras & !sba &  srd & (0 < cycle_count) & (cycle_count <= 4))
                                    then cycle_count := cycle_count + 1;
when (ras & !sba &  srd & (cycle_count == 4)) then lastcyc := 1;

" case 2: A CMMU is the bus master and the operation is write.  We take
"         five cycles.  (the first cycle is numbered 0).
when (ras & !sba & !srd & (0 < cycle_count) & (cycle_count <= 3))
                                    then cycle_count := cycle_count + 1;
when (ras & !sba & !srd & (cycle_count == 3)) then lastcyc := 1;

" case 3: An S-Bus slot is the bus master and the operation is write.  We take
"         nine cycles for four words.  (the first cycle is numbered 0).
when (ras & sba & !srd & (0 < cycle_count) & (cycle_count <= 7)
          & (size == SQUAD))        then cycle_count := cycle_count + 1;
when (ras & sba & !srd & (cycle_count == 7)
          & (size == SQUAD))        then lastcyc := 1;

" case 4: An S-Bus slot is the bus master and the operation is write.  We take
"         five cycles for two words.  (the first cycle is numbered 0).
when (ras & sba & !srd & (0 < cycle_count) & (cycle_count <= 3)
          & (size == SDOUB))        then cycle_count := cycle_count + 1;
when (ras & sba & !srd & (cycle_count == 3)
          & (size == SDOUB))        then lastcyc := 1;

" case 5: An S-Bus slot is the bus master and the operation is write.  We take
"         three cycles for one word.  (the first cycle is numbered 0).
when (ras & sba & !srd & (0 < cycle_count) & (cycle_count <= 1)
          & ((size == SBYTE) # (size == SHALF) # (size == SWORD))) 
                                   then cycle_count := cycle_count + 1;
when (ras & sba & !srd & (cycle_count == 1)
          & ((size == SBYTE) # (size == SHALF) # (size == SWORD))) 
                                   then lastcyc := 1;


when (!sba & srd)  then ack = ras & (cycle_count > 1);
when (!sba & !srd) then ack = ras & (cycle_count > 0);
when ( sba       ) then ack = ras &
    ((cycle_count == 2) # (cycle_count == 4) # 
     (cycle_count == 6) # lastcyc);

enable sack0 = ras & ack;
enable sack1 = ras & ack;
enable sack2 = ras & ack;

when (size == SBYTE) then acknowledgement = ABYTE;           
when (size == SHALF) then acknowledgement = AHWORD;        
when (size == SWORD) then acknowledgement = AWORD;                            
when (size == SEXT)  then acknowledgement = AERROR;

" We can only handle quad word S-Bus transfers that start on
" a double-word boundary.  However, we only have a2 and not
" a3.  So we check a2 to make sure that the address is at least
" double-word aligned.  But if the address is not quad-word aligned,
" we won't know about it and the master will read or write the
" second double word in the 4-word chunk twice.

when ((size == SQUAD) & (a2 == 0)) then acknowledgement = AWORD;                                                        
when ((size == SQUAD) & (a2 == 1)) then acknowledgement = AERROR;

" We do not support 8-word or 16-word S-Bus burst transfers.
                            
when (size == SOCT)  then acknowledgement = AERROR;                            
when (size == SB16)  then acknowledgement = AERROR; 

" We can only handle double word S-Bus transfers that start on
" a double-word boundary.
                           
when ((size == SDOUB) & (a2 == 0)) then acknowledgement = AWORD;
when ((size == SDOUB) & (a2 == 1)) then acknowledgement = AERROR;

end dramctl;