This website uses cookies. By using this site, you consent to the use of cookies. For more information, please take a look at our Privacy Policy.
Home > FPGA Technical Tutorials > FPGAs: World Class Designs > Other Design Flows > EMBEDDED PROCESSOR-BASED DESIGN FLOWS

TABLE OF CONTENTS

Xilinx FPGA FPGA Forum

EMBEDDED PROCESSOR-BASED DESIGN FLOWS

FONT SIZE : AAA

We are concerned only with electronic systems that include one or more  FPGAs on the printed circuit board (PCB). The vast majority of such systems  also make use of a general-purpose microprocessor, or μ P, to perform a variety of control and data-processing applications. This is often referred to as the  central processing unit (CPU) or microprocessor unit (MPU).   

Until recently, the CPU and its peripherals typically appeared in the form  of discrete chips on the circuit board. There are an almost infinite number of  possible scenarios here, but the two main ones involve the way in which the  CPU is connected to its memory ( Figure 6-17 ).   

In both of these scenarios, the CPU is connected to an FPGA and some  other stuff via a general-purpose processor bus. (By “ stuff ” we predominantly  mean peripheral devices such as counter timers, interrupt controllers, communications devices, etc.)   

In some cases, the main memory (MEM) will also be connected to the CPU  by means of the main processor bus, as shown in Figure 6-17a (actually, this  connection will be via a special peripheral called a memory controller, which  is not shown here because we’re trying to keep things simple). Alternatively,  the memory may be connected directly to the CPU by means of a dedicated  memory bus, as shown in Figure 6-17b .

Two scenarios at the circuit board level.png

The point is that presenting the CPU and its various peripheral devices in  the form of dedicated chips on the circuit board costs money and occupies real  estate. It also impacts the reliability of the board because every solder joint  (connection point) is a potential failure mechanism.   

One alternative is to embed the CPU along with some of its peripherals in  the FPGA itself ( Figure 6-18 ).   

It is common for a relatively small amount of memory used by the CPU to  be included locally in the FPGA. At the time of this writing, however, it is rare  for all of the CPU’s memory to be included in the FPGA.   Creating an FPGA design of this type brings a whole slew of new problems  to the table:

● First, the system architects have to decide which functions will be implemented in software (as instructions to be executed by the CPU) and which  functions will be implemented in hardware (using the main FPGA fabric).

● Next, the design environment must support the concept of coverification, in  which the hardware and embedded software portions of the system can be  verified together to ensure that everything works as it should.   Both of these topics are considered in more detail later in this chapter.

Hard versus Soft Cores   

Hard Cores   

As defined previously, a hard microprocessor core is one that is implemented  as a dedicated, predefined (hardwired) block (these cores are only available in  certain device families). Each of the main FPGA vendors has opted for a particular processor type to implement its hard cores. For example, Altera offers  embedded ARM processors, QuickLogic has opted for MIPS-based solutions,  and Xilinx sports PowerPC cores.   

Of course, each vendor will be delighted to explain at great length why its  implementation is far superior to any of the others (the problem of deciding  which one actually is better is only compounded by the fact that different processors may be better suited to different tasks).   

As noted in Chapter 2, there are two main approaches for integrating such  cores into the FPGA. The first is to locate it in a strip to the side of the main  FPGA fabric ( Figure 6-19 ).   In this scenario, all of the components are typically formed on the same  silicon chip, although they could also be formed on two chips and packaged as  a multichip module (MCM).

Bird’s-eye view of chip with embedded core outside of the main fabricpng

One advantage of this implementation is that the main FPGA fabric is identical for devices with and without the embedded microprocessor core, which  can make things easier for the design tools used by the engineers. The other  advantage is that the FPGA vendor can bundle a whole load of additional functions in the strip to complement the microprocessor core, such as memory and  special peripherals.   

The second alternative is to embed one or more microprocessor cores  directly into the main FPGA fabric . One, two, and even four core implementations are currently available at the time of this writing ( Figure 6-20 ).   

In this case, the design tools have to be able to take account of the presence of these blocks in the fabric; any memory used by the core is formed  from embedded RAM blocks, and any peripheral functions are formed from  groups of general-purpose programmable logic blocks. Proponents of this  scheme can argue that there are inherent speed advantages to be gained from  having the microprocessor core in intimate proximity to the main FPGA  fabric.

Soft Microprocessor Cores   

As opposed to embedding a microprocessor physically into the fabric of the  chip, it is possible to configure a group of programmable logic blocks to act as  a microprocessor. These are typically called “ soft cores, ” but they may be more  precisely categorized as either soft or firm, depending on the way in which the  microprocessor’s functionality is mapped onto the logic blocks. For example,  if the core is provided in the form of an RTL netlist that will be synthesized  with the other logic, then this truly is a soft implementation. Alternatively, if  the core is presented in the form of a placed and routed block of LUTs/CLBs,  then this would typically be considered a firm implementation.

Bird’s-eye view of chips with embedded cores inside the main fabricpng

In both of these cases, all of the peripheral devices like counter timers,  interrupt controllers, memory controllers, communications functions, and so  forth are also implemented as soft or firm cores (the FPGA vendors are typically able to supply a large library of such cores).  

—Technology Trade-offs—  

● Soft cores are slower and simpler than their hard-core counterparts (of  course they are still incredibly fast in human terms). However, in addition  to being practically free, they also have the advantages that you only have  to implement a core if you need it and that you can instantiate as many  cores as you require until you run out of resources in the form of programmable logic blocks.   

Once again, each of the main FPGA vendors has opted for a particular processor type to implement its soft cores. For example, Altera offers the Nios, while  Xilinx sports the MicroBlaze. The Nios has both 16-bit and 32-bit architectural variants, which operate on 16-bit or 32-bit chunks of data, respectively  (both variants share the same 16-bit-wide instruction set). By comparison,  the MicroBlaze is a true 32-bit machine (that is, it has 32-bit-wide instruction  words and performs its magic on 32-bit chunks of data). Once again, each vendor will be more than happy to tell you why its soft core rules and how its  competitors ’ offerings fail to make the grade (sorry, you’re on your own here).   

One cool thing about the integrated development environment (IDE)  fielded by Xilinx is that it treats the PowerPC hard core and the MicroBlaze  soft core identically. This includes both processors being based on the same  CoreConnect processor bus and sharing common soft peripheral IP cores. All  of this makes it relatively easy to migrate from one processor to the other.   

Also of interest is the fact that Xilinx offers a small 8-bit soft core called  the PicoBlaze, which can be implemented using only 150 logic cells (give or  take a handful). By comparison, the MicroBlaze requires around 1,000 logic  cells (which is still extremely reasonable for a 32-bit processor implementation, especially when one is playing with FPGAs that can contain 70,000 or  more such cells).

Insider Info  

Some cynics say that those aspects of a design that are well understood are implemented in hardware, while any portions of the design that are somewhat undefined at the beginning of the design process are often relegated to a software  realization (on the basis that the software can be tweaked right up until the last  minute).

Partitioning a Design into Its Hardware and  Software Components   

As noted in Chapter 2, almost any portion of an electronic design can be  realized in hardware (using logic gates and registers, etc.) or software (as   instructions to be executed on a microprocessor). One of the main partitioning  criteria is how fast you wish the various functions to perform their tasks:  

● Picosecond and nanosecond logic : This has to run insanely fast, which  mandates that it be implemented in hardware (in the FPGA fabric).  

● Microsecond logic : This is reasonably fast and can be implemented either  in hardware or software (this type of logic is where you spend the bulk of  your time deciding which way to go).  

● Millisecond logic : This is the logic used to implement interfaces such as  reading switch positions and flashing light-emitting diodes, or LEDs.  It’s a pain slowing the hardware down to implement this sort of function  (using huge counters to generate delays, for example). Thus, it’s often better to implement these tasks as microprocessor code (because processors  give you lousy speed—compared to dedicated hardware—but fantastic  complexity).

The trick is to solve every problem in the most cost-effective way. Certain  functions belong in hardware, others cry out for a software realization, and  some functions can go either way depending on how you feel you can best  use the resources (both chip-level resources and hardware/software engineers)  available to you.   

It is possible to envisage an “ ideal ” electronic system level (ESL) environment in which the system architects initially capture the design via a graphical interface as a collection of functional blocks that are connected together.  Each of these blocks could then be provided with a system-/algorithmic level  SystemC representation, for example, and the entire design could be verified  prior to any decisions being made as to which portions of the design were to  be implemented in hardware and software.   

When it comes to the partitioning process itself, we might dream of having  the ability to tag each graphical block with the mouse and select a hardware or  software option for its implementation. All we would then have to do would be  to click the “ Go ” button, and the environment would take care of synthesizing  the hardware, compiling the software, and pulling everything together.   

And then we return to the real world with a resounding thud. Actually,  a number of next-generation design environments show promise, and new  tools and techniques are arriving on an almost daily basis. At the time of  this writing, however, it is still very common for system architects to partition a design into its hardware and software portions by hand, and to then  pass these top-level functions over to the appropriate engineers and hope for  the best.

With regard to the software portion of the design, this might be something as simple as a state machine used to control a human-level interface  (reading the state of switches and controlling display devices). Although the  state machine itself may be quite tricky, this level of software is certainly not  rocket science. At the other end of the spectrum, one might have incredibly  complex software requirements, including:  

● System initialization routines and a hardware abstraction layer  

● A hardware diagnostic test suite  

● A real-time operating system (RTOS)  

● RTOS device drivers  

● Any embedded application code

This code will typically be captured in C/C ++ and then compiled down to the  machine instructions that will be run on the processor core (in extreme cases  where one is attempting to squeeze the last drop of performance out of the  design, certain routines may be handcrafted in assembly code).   At the same time, the hardware design engineers will typically be capturing their portions of the design at the RTL level of abstraction using VHDL or  Verilog (or SystemVerilog).   Today’s designs are so complex that their hardware and software portions  have to be verified together.

Insider Info  

One of the biggest problems to overcome when it comes to the coverification of  the hardware and software portions of a design is the two totally different worldviews of their creators. The hardware folks typically visualize their portion of the  design as blocks of RTL representing such things as registers, logical functions,  and the wires connecting them together. When hardware engineers are debugging their portion of the design, they think in terms of an editor showing their RTL  source code, a logic simulator, and a graphical waveform display showing signals  changing values at specific times. In a typical hardware design environment, clicking on a particular event in the waveform display will automatically locate the corresponding line of RTL code that caused this event to occur. 

By comparison, the software guys and gals think in terms of C/C++ source  code, of registers in the CPU (and in the peripherals), and of the contents of various memory locations. When software engineers are debugging a program, they  often wish to single-step through the code one line at a time and watch the values  in the various registers changing. Or they might wish to set one or more breakpoints (this refers to placing markers at specific points in the code), run the program until they hit one of those breakpoints, and then pause to see what’s going  on. Alternatively, they might wish to specify certain conditions such as a register  containing a particular value, then run the program until this condition is met, and  once again pause to see what’s happening.

When a software developer is writing application code such as a game, he or  she has the luxury of being reasonably confident that the hardware (say, a home  computer) is reasonably robust and bug-free. However, it’s a different ball game  when one is talking about a software engineer creating embedded applications  intended to run on hardware that’s being designed at the same time. When a problem occurs, it can be mega tricky determining if it was a fault in the software or if  the hardware was to blame.

Using an FPGA as Its Own Development Environment   

Perhaps the simplest place to start is the scenario where the FPGA is used as  its own development environment. The idea here is that you have an SRAMbased FPGA with an embedded processor (hard or soft) mounted on a development board that’s connected to your computer. In addition to the FPGA, this  development board will also have a memory device that will be used to store  the software programs that are to be run by the embedded CPU ( Figure 6-21 ).   

Once the system architects have determined which portions of the design  are to be implemented in hardware and software, the hardware engineers  start to capture their RTL blocks and functions and synthesize them down to  a LUT/CLB-level netlist. Meanwhile, the software engineers start to capture  their C/C ++ programs and routines and compile them down to machine code.  Eventually, the LUT/CLB-level netlist will be loaded into the FPGA via a configuration file, the linked machine code image will be loaded into the memory  device, and then you let the system run wild and free ( Figure 6-22 ).   

Also, any of the machine code that is to be embedded in the FPGA’s onchip RAM blocks would actually be loaded via the configuration file.  Improving Visibility in the Design   The main problem with the scenario discussed in the previous section is lack  of “ visibility ” as to what is happening in the hardware portion of the design.

Using an FPGA as its own development environmentpng

A (very) simple design flowpng

One way to mitigate this is to use a virtual logic analyzer to observe what’s  happening in the hardware.   

Things can be a little trickier when it comes to determining what’s h appening  with the software. One point to remember is that—as discussed in Chapter 3— an embedded CPU core will have its own dedicated JTAG boundary scan chain  ( Figure 6-23 ).   

Embedded processor JTAG boundary scan chainpng

This is true of both hard cores and the more sophisticated soft cores. In  this case, the coverification environment can use the scan chain to monitor the  activity on the buses and control signals connecting the CPU to the rest of the  system. The CPU’s internal registers can also be accessed via the JTAG port,  thereby allowing an external debugger to take control of the device and singlestep through instructions, set breakpoints, and so forth.  A Few Coverififi cation Alternatives   If you really want to get visibility into what’s happening in the hardware  portions of design, one approach is to use a logic simulator. In this case, the majority of the system will be modeled and simulated in VHDL or Verilog/ SystemVerilog at the RTL level of abstraction. When it comes to the CPU core,  however, there are various ways in which to represent this ( Figure 6-24 ).   

Alternative representations of the CPUpng

Irrespective of the type of model used to represent the CPU, the embedded software (machine code) portion of the design will be loaded into some  form of memory—either embedded memory in the FPGA or external memory devices—and the CPU model will then execute those machine code  instructions.   

Note that Figure 6-24 shows a high-level representation of the contents  of the FPGA only. If the machine code is to be stored in external memory  devices, then these devices would also have to be part of the simulation.

In fact, as a general rule of thumb, if the software talks to any stuff, then that  stuff needs to be part of the coverification environment.

RTL (VHDL or Verilog)   

Perhaps the simplest option here is when one has an RTL model of the CPU, in  which case all of the activity takes place in the logic simulator. One disadvantage of this approach is that a CPU performs tremendous numbers of internal  operations in order to perform the simplest task, which equates to incredibly  slow simulation runs (you’ll be lucky to be able to simulate 10 to 20 system  clocks per second in real time).   

The other disadvantage is that you have no visibility into what the software  is doing at the source code level. All you’ll be able to do is to observe logic  values changing on wires and inside registers.   

And there’s always the fact that whoever supplies the real CPU doesn’t  want you to know how it works internally because that supplier may be using  cunning proprietary tricks and wish to preserve their IP. In this case, you may  well find it very difficult to lay your hands on an RTL model of the CPU at all.   

C/C ++ , SystemC, etc.   

As opposed to using an RTL model, it is very common to have access to some  sort of C/C ++ model of the CPU. (The proponents of SystemC have a vision  of a world in which the CPU and the main peripheral devices all have SystemC  models provided as standard for use in this type of design environment.)   

The compiled version of this CPU model would be linked into the simulation via the programming language interface (PLI) in the case of a Verilog  simulator or the foreign language interface (FLI)—or equivalent—in the case  of a VHDL simulator.   

The advantages of such a model are that it will run much faster than its  RTL counterpart; that it can be delivered in compiled form, thereby preserving  any secret IP; and that, at least in FPGA circles, such a model is usually provided for free (the FPGA vendors are trying to sell chips, not models).   

One disadvantage of this approach is that the C/C ++ model may not provide a 100-percent cycle-accurate representation of the CPU, which has the  potential to cause problems if you aren’t careful. But, once again, the main disadvantage of such a model is that its only purpose is to provide an engine to  execute the machine code program, which means that you have no visibility  into what the software is doing at the source code level. All you’ll be able to do  is observe logic values changing on wires and inside registers.   

Physical Chip in Hardware Modeler   

Yet another possibility is to use a physical device to represent a hard CPU  core. For example, if you are using a PowerPC core in a Xilinx FPGA, you can e asily lay your hands on a real PowerPC chip. This chip can be installed in  a box called a hardware modeler, which can then be linked into the logic simulation system. The advantage of this approach is that you know the physical model (chip)  is going to functionally match your hard core as closely as possible. Some   disadvantages are that hardware modelers aren’t cheap and they can be a pain  to use.   

The majority of hardware-modeler-based solutions don’t support sourcelevel debugging, which, once again, means that you have no visibility into  what the software is doing at the source code level. All you’ll be able to do is  to observe logic values changing on wires and inside registers.

Instruction Set Simulator   

As previously noted, in certain cases, the role of the software portion of a  design may be somewhat limited. For example, the software may be acting as a  state machine used to control some interface. Alternatively, the software’s role  may be to initialize certain aspects of the hardware and then sit back and watch  the hardware do all of the work. If this is the case, then a C/C ++ model or a  physical model is probably sufficient—at least as far as the hardware design  engineer is concerned.   

At the other extreme, the hardware portions of the design may exist mainly  to act as an interface with the outside world. For example, the hardware may  read in a packet of data and store it in the FPGA’s memory, and then the CPU  may perform huge amounts of complex processing on this data. In cases like  these, it is necessary for the software engineer to have sophisticated sourcelevel debugging capabilities. This requires the use of an instruction set simulator (ISS), which provides a virtual representation of the CPU.   

Although an ISS will almost certainly be created in C/C ++ , it will be  architected very differently from the C/C ++ models of the CPU discussed  earlier in this section. This is because the ISS is created at a very high level of  abstraction; it thinks in terms of transactions like “ get me a word of data from  location x in the memory, ” and it doesn’t concern itself with details like how  signals will behave in the real world.

How It Works  

The easiest way to explain how this works is by means of an illustration ( Figure 6-25 ). 

First, the software engineers capture their program as C/C++ source code. This is  then compiled using the -d (debug) option, which generates a symbol table and other  debug-specific information along with the executable machine code image.  

When we come to perform the coverification, there are a number of pieces to  the puzzle. At one end we have the source-level debugger, whose interface is used  by the software engineer to talk to the environment. At the other end we have the logic s imulator, which is simulating representations of the memory, stuff like peripheral  devices, general-purpose logic, and so forth (for the sake of simplicity, this illustration  assumes that all of the program memory resides in the FPGA itself). 

In the case of the CPU, however, the logic simulator essentially sees a hole where  this function should be. To be more precise, the simulator actually sees a set of inputs  and outputs corresponding to the CPU. These inputs and outputs are connected to an  entity called a bus interface model (BIM), which acts as a translator between the simulator and the ISS. 

Both the source code and the executable image (along with the symbol table  and other debug-centric information) are loaded into the source-level debugger. At  the same time, the executable image is loaded into the MEM block. When the user  requests the source-level debugger to perform an action like stepping through a line  of source code, it issues commands to the ISS.  In turn, the ISS will execute high-level  transactions such as an instruction fetch, or a memory read/write, or an I/O command. These transactions are passed to the BIM, which causes the appropriate pins to  “ wiggle ” in the simulation world. 

Similarly, when something connected to the processor bus in the FPGA attempts  to talk to the CPU, it will cause the pins driving the BIM to “ wriggle. ” The BIM will  translate these low-level actions into high-level transactions that it passes to the ISS,  which will in turn inform the source-level debugger what’s happening. The source-level  debugger will then display the state of the program variables, the CPU registers, and  other information of this ilk.

Insider Info  

There are a variety of incredibly sophisticated (often frighteningly expensive) environments of this type on the market. Each has its own cunning tricks and capabilities, and some are more appropriate for ASIC designs than FPGAs or vice versa. As  usual, however, this is a moving target, so you need to check around to see who is  doing what before putting any of your precious money on the table.






  • XC3S400A-4FG400I

    Manufacturer:Xilinx

  • FPGA Spartan-3A Family 400K Gates 8064 Cells 667MHz 90nm Technology 1.2V 400-Pin FBGA
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS:

  • XC3S400A-4FT256I

    Manufacturer:Xilinx

  • FPGA Spartan-3A Family 400K Gates 8064 Cells 667MHz 90nm Technology 1.2V 256-Pin FTBGA
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS: No RoHS

  • XC2C256-6PQG208C

    Manufacturer:Xilinx

  • CPLD CoolRunner -II Family 6K Gates 256 Macro Cells 256MHz 0.18um Technology 1.8V 208-Pin PQFP
  • Product Categories: CPLDs

    Lifecycle:Active Active

    RoHS:

  • XC2C256-7CP132C

    Manufacturer:Xilinx

  • CPLD CoolRunner -II Family 6K Gates 256 Macro Cells 152MHz 0.18um Technology 1.8V 132-Pin CSBGA
  • Product Categories: Embedded - CPLDs (Complex Programmable Logic Devices)

    Lifecycle:Active Active

    RoHS: No RoHS

  • XC2C256-7FTG256C

    Manufacturer:Xilinx

  • CPLD CoolRunner -II Family 6K Gates 256 Macro Cells 152MHz 0.18um Technology 1.8V 256-Pin FTBGA
  • Product Categories: Embedded - CPLDs (Complex Programmable Logic Devices)

    Lifecycle:Active Active

    RoHS:

Need Help?

Support

If you have any questions about the product and related issues, Please contact us.