I was reading about arduino and the AVR architecture and got stuck at the point that how does pipeline stall or bubbling is solved by Harvard architecture introduction in the AVR.I mean what Harvard does is just provide different storage location to data memory and program memory which makes it possible to load program without an operator.But how does it help solve the above problem?
The Harvard architecture, which incidentally was used long before AVRs were ever invented, does indeed have separate address spaces for the program memory and for the data memory. What this brings to the party is the ability to design the circuit in a way such that a separate bus and control circuit can be used to handle the information flow from the program memory and the information flow to the data memory. The use of the separate buses means that it is possible for the program fetching and execution to continue without disruption from an occasional data transfer to the data memory. For example in the simplest version of the architecture the program fetching unit can be busy fetching the next instruction in the program sequence in parallel with data transfer operation that may have been part of the previous program instruction.
At this simplest level the Harvard architecture has a limitation in that it is generally not possible to put program code into the data memory and have it be executed from there.
There are many variations and complexities that can be added on top of this simplest form of the architecture that I have described. One common addition is adding instruction caching to the program information bus that allows the instruction execution unit faster access to the next program step without having to go off to slower memory to fetch the program step each time it is required.
Some notes in addition to Michaels answer:
1) the Harvard architecture does not require that there are two separate spaces for data and code, just that they are (mostly) fetched over two different busses.
2) the problem that is solved by the Harvard architecture is bus contention: for a system where the code memory can just about provide the instructions quickly enough to keep the CPU running full speed, the additional burden of data fetches/stores will slow the CPU down. That problem is solved by a Hardvard architecture: a memory that is (a bit) too slow for the speed of the CPU.
Note that caching is another way to solve this problem. Often Harvarding and caching are used in interesting combinations.
Harvard uses two busses. There is no inherent reason to stick to two, in very special cases more than two are used, mainly in DSPs (Digital Signal processors).
Memory Banking (in the sense of distributing memory accesses to different sets of chips) can be seen as a sort of Harvarding inside the memory system itself, not based on the data/code distinction, but on certain bits of the address.
A pure Harvard architecture will generally allow a computer with a given level of complexity to run faster than would a Von Neuman architecture, provided that no resources need to be shared between the code and data memories. If pinout limitations or other factors compel the use of one bus to access both memory spaces, such advantages are apt to be largely nullified.
A "pure" Harvard architecture will be limited to running code which is put in memory by some mechanism other than the processor that will run the code. This limits the utility of such architectures for devices whose purpose isn't set by the factory (or someone with specialized programming equipment). Two approaches may be used to alleviate this issue:
Some systems have separate code and memory areas, but provide special hardware which can be asked to briefly take over the code bus, perform some operation, and return control to the CPU once such operation is complete. Some such systems require a fairly elaborate protocol to carry out such operations, some have special instructions to perform such a task, and a few even watch for certain "data memory" addresses and trigger the takeover/release when an attempt is made to access them. A key aspect of such systems is that there are explicitly-defined areas of memory for "code" and "data"; even if it's possible for the CPU to read and write "code" space, it is still recognized as being semantically different from data space.'
An alternative approach which is used in some higher-end systems, is to have a controller with two memory buses, one for code and one for data, both of which connect to a memory arbitration unit. That unit in turn connected to various memory subsystems using a separate memory bus for each. A code access to one memory subsystem may be processed simultaneously with a data access to another; only if code and data try to access the same subsystem simultaneously will either one have to wait.
On systems which use this approach, non-performance-critical parts of a program may simply ignore the boundaries between memory subsystems. If the code and data happen to reside in the same memory subsystem, things won't run as fast as if they were in separate subsystems, but for many parts of a typical program that won't matter. In a typical system, there will be a small part of code where performance really does matter, and it will only operate on a small portion of the data held by the system. If one had a system with 16K of RAM that was divided into two 8K partitions, one could use linker instructions to ensure that the performance-critical code was located near the start of the overall memory space, and the performance-critical data was near the end. If overall code size grows to e.g. 9K, code within the last 1K would run slower than code placed elsewhere, but that code wouldn't be performance critical. Likewise, if code were e.g. only 6K, but data grew to 9K, access to the lowest 1K of data would be slow, but if the performance-critical data were located elsewhere, that wouldn't pose a problem.
Note that while performance would be optimal if code were under 8K and data were under 8K, the aforementioned memory-system design would not impose any strict partition between code and data space. If a program only needs 1K of data, code could grow up to 15K. If it only needs 2K of code, data could grow to 14K. Much more versatile than having an 8K area just for code and an 8K area just for data.
One aspect that has not been discussed is that for small microcontrollers, typically with only a 16-bit address bus, a Harvard architecture effectively doubles (or triples) the address space. You can have 64K of code, 64K of RAM, and 64k of memory-mapped I/O (if the system is using memory-mapped I/O instead of port numbers, the latter already separating the I/O addressing from the code & RAM spaces).
Otherwise you have to cram the code, RAM, and optionally I/O address all within the same 64K address space.