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:

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:

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.