chrstrbrts
Senior member
Easy example:
16 bit address space = 64k
To keep it simple, no mirroring, banking, etc, lets say we have a 32k ROM and a 32k RAM you want to map into that 64k.
The ROM and RAM chips are going to have 15 address lines and 8 data lines.
The CPU is going to have 16 address lines and 8 data lines.
How do we connected it all?
Lets say this is a 65C02. And we'll use 32k static RAM so we don't have to worry about DRAM controllers and all that. Hardware definition dictates we need a zero page @ $00xx and a stack at $01xx, these must be writable. In addition, reset and other interrupt vectors are hard wired at $FFFx.
This means we would want the ROM on the top half and RAM on the bottom half of the 64k map.
$0000-7FFF = 32k RAM
$8000-FFFF = 32k ROM
The first 15 address lines A0-A14 of the CPU would be would be ganged together in parallel with the only 15 address lines of the RAM + ROM chips. Same for data bus lines D0-D7. We have an extra address line on the CPU that will be used to determine when we cross the 32k mark and use that pin to determine which chip to talk to.
Now use the 16th address line from the CPU, A15 and observe that any time the CPU accesses an address $8000 or higher this line will go active and below that it will be inactive.
I'd have to look up specs, but lets say the CPU A15 line is a active high (drive to +5v @ $8000+) and the ROM/RAM chip enable /CE is active low (0v turns it on 5v turns it off).
If A15 is on (address $8000-$FFFF) we want to toggle ROM's /CE and if A15 is off ($0000-7FFF) we want to toggle RAM's /CE.
But we want the inverse because the CPU is active high and the chips are active low. In addition, we want the ROM and RAM /CE to complement each other so if one is on the other is off and vice versa, all determined by A15 from the CPU.
So we do CPU A15 > inverter gate > to ROM /CE and A15 directly to RAM /CE.
When CPU hits $8000 or higher, A15 will turn on and drive RAM /CE high disabling it, but be inverted to low at ROM /CE and enable it. Below $8000 RAM /CE will be active low, while ROM /CE is active high.
From the programmer's perspective we see a memory map that looks like $0000-7FFF is RAM and $8000-FFFF is ROM.
Note that byte 0 in the ROM chip is byte 32768 ($8000) to the CPU and that byte 32767 in the ROM chip is byte 65535 ($FFFF) to the CPU.
In our ROM lets say our startup code starts at the first byte (0) in the ROM chip. To the CPU this is location $8000. CPU location $FFFC and $FFFD are defined by the CPU maker to contain the power on reset address, and this maps to third and forth to last bytes in the ROM. ROM would look like
ROM is burned in a programmer like this:
$0000 boot code
... xx xx
$7FFC 00 80
$7FFE xx xx
To the CPU it would look like:
$0000
...
$8000 boot code
...
$FFFC 00 80 <- on power on goto address $8000 (stored in little endian), eg the reset vector in ROM points to boot code located within itself at an address that doesn't exist when you are burning the ERPOM but is valid in the CPU memory map once the ROM is mapped in!
Devices are the same way. They have address and data lines and a chip enable or chip select pin. Interrupt controllers, DMA controllers, timers, serial UARTs, other microcontrollers (the original 8042 keyboard controller itself is it's own self contained microcontroller with it's own RAM and ROM and instructions). The same buses the CPU uses to access the registers on a DMA controller to start a transfer are the very same buses the DMA controller itself manipulates to do the transfer. Data and address lines are all wired together, that's why it's called a bus. A device that needs only 4 memory mapped registers would have mere 2 address lines A0-A1 but will still have 8-32 data lines depending on the word width of it's registers.
Is all of this done over PCI express infrastructure?
Isn't PCI express the new bus / point-to-point standard?