18
\$\begingroup\$

I have seen that, in 32-bit microcontroller, each address of memory holds only 8 bits of data; it is the same for a 16 bit MC as well. For 32-bit data, it uses a combination of 4 addresses. Why can't an address made to hold 32-bit data directly (making it 32 bits or 16 each instead of 8)?

\$\endgroup\$
  • 2
    \$\begingroup\$ It depends on Data bus of Microcontroller. Which 32-bit microcontroller has byte memory? Do you have any example? \$\endgroup\$ – Swanand Oct 27 '16 at 7:40
  • 4
    \$\begingroup\$ Simply not true, which is the reason why programming languages like C and C++ incorporate the possibility for a byte to be greater than 8 bit. Its just that the majority works best with 8 bit bytes, but 9bit or 18bit is out there. \$\endgroup\$ – PlasmaHH Oct 27 '16 at 8:01
  • 6
    \$\begingroup\$ It's like candy bars. They keep making them smaller for the same price. \$\endgroup\$ – Olin Lathrop Oct 27 '16 at 11:37
  • 4
    \$\begingroup\$ Can this question be rephrased "Why are all addresses aligned to 8 bits" ? \$\endgroup\$ – Florian Castellane Oct 28 '16 at 11:21
  • 2
    \$\begingroup\$ @FlorianCastellane This. The addresses are not 8 bits in size (unless you can find a device with < 256 bits of memory, then they might be). \$\endgroup\$ – jayjay Oct 28 '16 at 12:24
11
\$\begingroup\$

This is effectively a design choice, there is no hard reason why it has to be so. Back in the old days, when high volume commodity processors operated on 8-bit values, the mapping was more consistently 1:1. For consistency as designs evolved to modern 32 and 64 bit processors, it made sense to keep the older mapping of byte-addressing even though the data buses increased (with a changing immplementation cost trade-off). Some 32 bit MCUs may still implement only 16 bit data busses to some memory, high-end processors will have 256 bit or above, and are able to load multiple core registers in a single memory transaction. Wide interfaces are good for burst or streaming operations.

The small addressable memory size is useful not only in the case of handling byte values in code, but to work with structures in memory like ethernet packets where specific bytes need to be read or modified. Frequently this sort of operation needs to be able to perform small operations but very efficiently.

There are also scenarios where it is necessary to operate with big-endian, little-endian or mixed endian data. Now there is often dedicated hardware support for this, but again, byte addressing of memory will make this type of operation more efficient in some scenarios.

It is fairly recent that the number of address bits in a register have been a limiting factor for the address space, so wasting 2 bits to address bytes rather than 32 bit words would not have been much of a concern 10-15 years ago (and now with 64 bit pointers, its common to implement 48 or 56 bit wide, byte addresses). Introductory Computer science teaching is still a little stuck in the just-post mainframe age, and doesn't always address the evolution aspects very clearly. Lots of terminology came into use (and definition) around the time that low-volume high cost architectures (in the most general sense) started to be complemented by more resource constrained and more commodity focused processor designs.

I've not answered specifically for MCUs, the architectural boundaries are not as clear as you might assume. Even a modern ground-up MCU design has a good chance of being integrated along with a many-core server processor, or exist as only one point in a scalable set of products; either way a consistent approach to accessing memory is beneficial to the end user who needs to write or port code.

I asked a question on the retrocomputing SE about register sizes to follow up on the historical aspects of this question.

\$\endgroup\$
  • 2
    \$\begingroup\$ I think processors with longer word sizes predated 8-bit processors. An 8-bit processor would be pretty useless without an efficient means of adding two multi-byte numbers, and early processors could not efficiently handle numbers larger than a single machine word. \$\endgroup\$ – supercat Oct 27 '16 at 21:40
  • 1
    \$\begingroup\$ I worked with 8-bit processors enough to know that they could easily add multi-byte numbers, but not with a single CPU instruction. First, add the two lowest bytes, and get the lowest result byte, and a separate carry bit. For as many other bytes are present, add the next input bytes and the carry bit from the previous step, giving the next output byte and the next carry bit. When there are no input bytes left, convert the last carry bit into one more output byte. \$\endgroup\$ – user6030 Oct 28 '16 at 3:43
  • \$\begingroup\$ @user6030: Isn't it common to have an ADC instruction? AVR does (an 8-bit RISC microcontroller so gcc has to use ADC for int and long), so does x86, so does ARM. I assume most 8-bit CPUs would, since there'd be even more demand for it than on a system with wider regs. Oh, is supercat saying that early processors lacked an efficient ADC? \$\endgroup\$ – Peter Cordes Oct 28 '16 at 5:10
  • \$\begingroup\$ I think its a valid point regarding the evolution of register size (although I lack data) \$\endgroup\$ – Sean Houlihane Oct 28 '16 at 7:24
25
\$\begingroup\$

There are a few DSPs (e.g., TI C54x) that cannot address values smaller than 16 bits, and some audio DSPs use 24 bits. However, 8-bit values are used in pretty much all general-purpose code, so all general-purpose CPUs support it.

And just because the smalled unit used for memory addresses is 8-bit bytes does not mean that this would be the largest unit that is actually used on the bus; most CPUs use their native word size (16/32 bits) or even a larger size to address memory, and when using byte accesses, automatically extract the byte from the larger word.

For example, the PCI bus always uses 32-bit transactions, but has byte enable signals for access that must be smaller.

\$\endgroup\$
  • \$\begingroup\$ Thank you. is there any MC that is a nibble wide instead of byte in memory ? \$\endgroup\$ – Arun Joe Oct 27 '16 at 7:48
  • 4
    \$\begingroup\$ Maybe the Intel 4004? \$\endgroup\$ – pjc50 Oct 27 '16 at 7:53
  • 6
    \$\begingroup\$ @ArunCheriyan An example of a CPU that worked with nibbles as the smallest adressable word is the Saturn: a CPU designed by HP and used in their high-end calculators back in the last century (the well-known HP48 in particular). It had a very unusual architecture (64 bit registers, 4 bit ALU, 20 bit adresses, ...). \$\endgroup\$ – dim Oct 27 '16 at 8:45
  • \$\begingroup\$ Another example: The smallest addressable unit for TI's TMS320C3x is 32-bits. \$\endgroup\$ – kkrambo Oct 27 '16 at 12:42
  • 1
    \$\begingroup\$ @davidcary Oh, well... Dates and time have never been my strong suit, anyway. Ask my wife about her birthday presents, and my boss about the deadlines... \$\endgroup\$ – dim Oct 28 '16 at 8:57
18
\$\begingroup\$

A 16-bit or 32-bit microcontroller often needs to manipulate data that is only 8-bits wide (a byte). For example, text strings are usually stored with a single character per byte. By having a memory addressing scheme which allows each individual byte to be addressed the microcontroller can efficiently process 8-bit wide data. What this means is that 32-bit data usually resides on addresses that are multiples of 4 bytes, eg 04, 08, 0C, etc. But if the memory is 32-bit wide then the microcontroller can read 32-bits in one read cycle. Micro's often have machine instructions that can operate on different length data, so you will find that a move data instruction (MOV) can have 3 forms, MOV.B, MOV.W and MOV.L to move 8, 16 and 32 bits of data in one instruction.

\$\endgroup\$
7
\$\begingroup\$

The basic answer is "because that's how long a byte is". With a large established body of code which makes that assumption, breaking it would cause all sorts of problems.

Back in the early days, there was no established body of code. Processors frequently would use all manner of strange architectures, as shown by other answers. By the time 16-bit processors came out though, there was enough code assuming availability of 8-bit data that failing to make that easy would have been a real barrier to adoption.

Having one 32-bit word per address doesn't give any disadvantage in memory speed. On a 32-bit system, the lower 2 address bits often don't go to the memory. The processor will usually read the whole 32-bit word and select (or mask off) the 8-bit byte it needs within that word. So long as your address space can store enough data (limited to 2^32 bytes with a 32-bit system) then no worries. In fact, on many 16-bit/32-bit processors it takes longer to do processing with byte values than with native-word-length values - reading a 32-bit word and discarding part of that word will clearly take an extra operation, compared to just reading the 32-bit word.

Conversely, if you have a system where you need to use memory efficiently, then you need to be able to access individual bytes. If you can't, you're going to run out of memory. With that in mind, being able to reference individual bytes is clearly necessary, so it makes sense to have your memory chunked in bytes.

\$\endgroup\$
  • 3
    \$\begingroup\$ Indeed. And then there's the additional question if a processor can handle the two distinct accesses needed to load or store an unaligned 32 bit value automatically in hardware, or if that must be explicitly handled in software. \$\endgroup\$ – Chris Stratton Oct 27 '16 at 18:05
5
\$\begingroup\$

This is what's called having byte addressable memory. It's normally a good thing, unless you're running out of address space (e.g. 4GB with 32-bit pointers, instead of 16GB with 32-bit pointers where every address is a separate 32-bit word).

\$\endgroup\$
  • \$\begingroup\$ Note that address space can go past such limits if you split the addresses into parts that will fit into one register each. I once had some 8-bit computers that reached 64 KB of memory by splitting the addresses into two parts kept in separate registers, and saw ads for computers also with 8-bit processors that could reach 1 MB of memory by splitting the addresses into three parts. \$\endgroup\$ – user6030 Oct 28 '16 at 3:50
  • \$\begingroup\$ AVR (8-bit RISC microcontroller) does that: three pairs of the 32 general-purpose 8-bit registers can be dereferenced as a 16-bit pointer. There's also some facility to combine that with another 8-bit segment to get 24-bit addresses. \$\endgroup\$ – Peter Cordes Dec 30 '16 at 9:52
4
\$\begingroup\$

The Analog Devices Shark 32 bit DSPs have 32 bits as the smallest unit of addressable memory, so sizeof (int) == sizeof (short) == sizeof (char) == 1 (Yes, they have 32 bit chars, perfectly valid per the C standard).

Also things like int_8, int_16 and such are not defined in , a nasty surprise when porting code from other platforms.

\$\endgroup\$
1
\$\begingroup\$

The size of the addressable memory unit is essentially a compromise between how much memory you can address vs. how much memory you will waste.

Addressable memory. Consider a 32-bit CPU: if you address bytes, you can address up to 4GB of memory. If you address individual bits, that amount will be reduced to 512MB, and if you address 32-bit words you'll have 16GB. (your question seem to suggest the latter).

Wasted memory. If you have a variable which can be represented with X bits, and you only can allocate units of N bits for it, you'll waste (N-1)/2 bits on average, assuming X > N. If you address individual bits, you will use the memory with 100% efficiency (at least from addressing point of view). With bytes, you will waste 3.5 bits per variable (56% efficiency), and with 32-bit words, you'll waste 15.5 bits (52% efficiency). But it gets worse: if most of your variables are small (think characters, booleans, status flags), you'll end up wasting most of the memory if your addressable units are too big.

For example, let's assume the average size of a variable is 8 bit.

  • on a bit-addressable computer, you will be able to allocate with 100% efficiency, which will give you 512*1024*1024*100% = 0.54 billion variables.
  • on a byte-addressable computer, you will allocate with 56% efficiency, which will give you 4096*1024*1024*56% = 2.4 billion variables. That's almost 5 times as much compared to a bit-addressable computer! Of course, you'll need to buy 8 times more memory.
  • on a 32-bit-addressable computer, since at least half of your variables will occupy less than 8 bits, they will be allocated with efficiency below 7% (using 4.5 bits out of 32). In any case, you won't get more that 4.3 billion variables (since you only have have that many distinct addresses), and less than that in reality. Avoiding complex calculations, I'd guess will get perhaps 20-30% more useful storage compared to byte-addressable computer, while paying 4 times the price for the RAM.
\$\endgroup\$
1
\$\begingroup\$

Probably already said various ways in the other answers. In general today, but not necessarily historically, a byte is 8 bits. Most of the time we deal with "byte addressable memory" meaning the SMALLEST thing we can access with a single address is a byte. But that does not mean that is the ONLY thing we can address. Depending on the platform a single address can be used to access a byte, a halfword/word (16 bits), a word/doubleword (32 bits) and so on 64 bits whatever. The instruction basically determines what the size of the desired access is (8,16,32,64, etc) usually in those units 8, 16, 32, 64. But that is not hard and fast, "it depends".

Also depending on the design of the processor and/or system there is no reason to assume that the size of the access is the size of the memory or the size of the smallest access. With larger and larger requirements it makes less and less sense over time to actually implement the memory system using the smallest size, the computer you are reading this on likely uses a 32 bit wide data bus or 64 bit wide data bus for all accesses, you want to read one byte, it does a 64 bit read and tosses the rest of the bits, why it doesnt cost anything extra keep the bus that wide all the way to near the processor core and the processor selects the right byte lane. costs more logic and or clocks to make the bus narrower or move the bytes around in the byte lanes, (is done sometimes). so internal rams in a microcontroller might be 32 bits wide for example if that makes sense for the system. might be 16. Yes for writes you do burn more cycles, you have to read-modify-write somewhere along the line. Want to write a single byte on your pc, somewhere a 64 bit read happens, and then somewhere one byte of that 64 bits is modified, depending on what you do after that that 64 bits may go back out to dram with only those 8 bits different from what was there before, caching and your code make this not a generic rule though. Writes are fire and forget though, the memory controller can collect the address and data from the processor and allow the processor to keep running while it eventually does the write saving clocks, maybe more clocks that are burned in a read-modify-write (if in cache already), not likely saving clocks if in a cache miss.

There are exceptions even today to pretty much all of this, there are perhaps instructions or access types in some systems that are bit addressable, there are some systems where the address is in units of something other than a byte. A byte was not always 8 bits and maybe there are systems still running that that is true (we used to use octal and a 9 bit byte 18 or 36 bit word make a lot of sense to human programmers and chip designers that think octal, an 8 bit makes a lot of sense to hexadecimal thinkers).

Now the computer you are reading this on, even though the data bus for that dram controller might be 32 or 64 bits wide, the actual dram module itself is likely made up of multiple 8 bit wide parts, which you can easily see. If it has 8 or 9 chips on one side it is probably a 64 bit or 72 bit (64 bits plus 8 bits of ECC) wide bus implemented with 8 bit wide parts. If you have 4 or 5 chips one one side of the module but have still tons of pins, then it is either a 32 bit wide (unlikely these days) or 4 of the chips are 16 bit wide and if there is a 5th it may be 16 bits wide and only 8 are used or it is an 8 bit wide part. There are 32 bit wide parts too, but 8 bit wide is most common. A very common practice that goes way back. Due to manufacturing costs and other factors it makes more sense that the first parts to be produced at a new density are 8 bits wide, then over time as legacy computers remain working, 16 and maybe wider parts for that speed/interface become available as density increases.

We would need to know what microcontroller. Since you mention 32 bit it is quite likely (without detailed info though we cannot tell) that the memory inside that part is 32 bits wide, and all accesses to it are 32 bits wide. the instructions would likely determine what the program wants which probably offers an 8 bit, 16 bit and 32 bit access type, the smaller ones on writes would require a read-modify-write somewhere, reads you just ignore byte lanes. Same goes for the flash, although flash writes are another topic. But the internal flash is most likely 32 bits wide and all reads are in units of 32 bits. An external flash though, that is another story, most likely they are one bit wide (spi or i2c), although spi parts can sometimes support 1, 2 or 4 bits, but one miso pin is most common. Internally they are organized in units of bytes, could be 8 bit wide or 16 or 32, or who knows, you shift out and address them in units of bytes though. with spi you can shift out anywhere between one byte and the whole memory in a single transaction, depends on the flash part design.

\$\endgroup\$
0
\$\begingroup\$

You can get 1 bit processors too!

The data width will follow the register (accumulator) width. this is normally the 'processor width' whereas the address buss may be different (usually wider), but could technically be narrower depending on the use.

8 of course is a power of two number. We have history to thank for the ubiquitous use of 8 bits - and COST/ability of technology. For a long time 8 bits ruled, part of the reason being the width of busses and the difficulty in making registers (and RAM) more than 8 bits wide (no point in 16 bit data if your registers are all 8 bit). 8 bits is rather nifty, and makes a lot of sense in Hex. 8 bits could hold your alphabet, numbers, drawing & control characters (ASCII), or 0 to 255 or +-127 Accessing more than 256 bytes of data (8bit address bus) is easy with paging, Select the page, then the byte e.g. 256 pages of 256 gets you to 64K (65536). Usually page zero would be a scratch pad as it would be faster to access as this would not require the page to be set. My first computer had 1k x 8bits of static ram! (dynamic RAM was cheaper, but needed more hardware to refresh it). With a few flags (c, nc, z, nz), add, subtract, rotate left and right, you can do some pretty complex math on an 8bit machine. You don't need a floating point arithmetic unit! Not super fast, but doable! Many early processors could be single stepped, and used with simple static RAM made debugging really easy; adding some octal buffers and early red LEDs, you could watch the address and data busses changing :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.