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;