Bob Ammerman [RAMMERMAN at PRODIGY.NET] of RAm Systems (high performance, high function, low-level software) says
Actually, you can get by with fewer bits without much, if any, loss of functionality, performance, to wit: Assuming you are using '161 style counters to access 64KB of memory, here is a 12 I/O's solution:
- Use 8 I/Os as a bidirectional address/data bus. Connect these I/O's to the 8 data pins in the RAM, and to the D inputs of the two least significant '161 chips.
- Connect the Q outputs of the two least significant '161's not only to RAM address pins, but also to the D inputs of the two most significant '161 chips.
- Connect the Q outputs of the two most signicant '161's to the remaining RAM address pins.
- Connect the /LOAD input of all the '161s to a PIC I/O (call the I/O LOAD161)
- Connect the /OE pin of the RAM to a PIC I/O (call the I/O RAMOE)
- Connect the /WR pin of the RAM to a PIC I/O (call the I/O RAMWR)
- Hardwire the /CS pin of the RAM to ground.
- Connect the clock inputs of all the '161s to a PIC I/O (call the I/O CLK161)
- Properly connect the carries from one '161 to the next.
Note that this can easily be expanded, without using _any_ more I/O's by adding additional 161's and daisy chaining the Q outputs of each pair to the data inputs of the next pair.
To set a random address:
bsf RAMOE ; Tell the RAM not to drive the bus clrf RAMTRISPORT,F ; Drive the bus bcf LOAD161 ; Set counters up for sync load movlw high(desired address) movwf RAMDATAPORT bsf CLK161 ; Write high addr into low counters bcf CLK161 movlw low(desired address) movwf RAMDATAPORT bsf CLK161 ; Move high addr to high counters... bcf CLK161 ; ...and write low addr to low counters To read several sequential bytes: bsf LOAD161 ; Set counters up to count setf RAMTRISPORT,F ; Don't drive the bus bcf RAMOE ; Tell the RAM to drive the bus movf RAMDATAPORT,W ; Get the byte ...do something with it... bsf CLK161 ; Advance to the next byte bcf CLK161 movf RAMDATAPORT,W ; Get the byte ...do something with it... bsf CLK161 bcf CLK161 movf RAMDATAPORT,W ; Get the byte etc.Writing works very similarly, but you have to disable the /WR input the the RAM while changing the data and address:
Assume we have just set a random address as outlined above:
bsf LOAD161 ; Set counters up to count movlw data_to_write movwf RAMDATAPORT bcf RAMWR bsf RAMWR bsf CLK161 bcf CLK161 movlw data_to_write movwf RAMDATAPORT bcf RAMWR bsf RAMWR bsf CLK161 bcf CLK161 etc.You can reduce the number of I/O's to 11, at the cost of slower writes (which are usually much less frequent than reads), as follows:
- Eliminate the separate /RAMOE and /RAMWR outputs from the PIC, and replace them with a single /RAMGO output.
- Use a logic gate so that /RAMOE is active (ie: low) only when /RAMGO is low and /LOAD161 is high.
- Use another logic gate so that /RAMWR is active only when /RAMGO is low and /LOAD161 is low.
Now, when writing sequentially, do the following (assuming the address has been set up as described above):
movlw data_to_write movwf RAMDATAPORT bcf RAMGO ; Since LOAD161 is low this will write to the RAM bsf RAMGO bsf LOAD161 ; Get ready to count bsf CLK161 ; Bump address bcf CLK161 bcf LOAD161 movlw data_to_write movwf RAMDATAPORT bcf RAMGO ; Since LOAD161 is low this will write to the RAM bsf RAMGO bsf LOAD161 ; Get ready to count bsf CLK161 ; Bump address bcf CLK161 bcf LOAD161 etc.