Section 4.12. Understanting Registers

4.12. Understanting Registers

The most common and convenient method of communicating between Impulse C processes is to use streams. Depending on the application requirements and the target hardware capabilities, shared memories and/or signals may also be used. What these methods of communication have in common is that they are synchronized and support buffering of the data. This makes it possible to create highly parallel systems without the need to handle low-level process synchronization, assuming the application being described lends itself to data-centric methods of process synchronization.

Many applications, however, require more direct, unsynchronized input and output of data. Some applications may interface directly to hardware devices and their corresponding control signals, while other applications may require that an unsynchronized direct connection be set up between two independent hardware processes.

For this purpose Impulse C includes the co_register data object, which corresponds to a wired connection (input or output) in hardware. Like streams and signals, registers are declared and created in the configuration process of your application (using co_register_create) and are passed as register pointers to the processes of your application in the configuration function, as in the following example:

 void config_counter(void *arg) {   co_register counter_dir;   co_register counter_val;   co_process main_process;   co_process counter_process;   counter_dir = co_register_create("counter_dir", UINT_TYPE(1));   counter_val = co_register_create("counter_val", INT_TYPE(32));   main_process = co_process_create("main_process",                      (co_function)counter_main,                      2, counter_dir, counter_val);   counter_process = co_process_create("counter_process",                        (co_function)counter_hw,                        2, counter_dir,                        counter_val); } 

In this example, two processes are declared and connected via two registers, counter_dir and counter_val. Register counter_dir represents an unbuffered control input to the counter process, while counter_val represents the output of the counter process, which is also unbuffered. Within a process, the Impulse C functions co_register_get, co_register_read, co_register_put, and co_register_write are used to access the value appearing on a register or to write a value to that register.

The following process uses co_register_get and co_register_put to describe a simple 32-bit up/down counter:

 void counter_hw(co_register direction, co_register count) {   int32 nValue = 0;   while ( 1 ) {      /* Main processing loop... */    if (co_register_get(direction) == 1)        nValue++;        else          nValue--;        co_register_put(count, nValue);  } } 

In this process, the variable nValue represents a local storage element (a set of clocked hardware registers), while the direction and count register parameters represent inputs and outputs that may be tied directly to device I/O pins or to other hardware elements in the system as a whole.

Controlling Registers from Software Processes

In most (perhaps all) cases you will use registers to communicate only between hardware elements of your application (hardware processes and other, external hardware interfaces). It is also possible to interface between hardware and software processes using registersfor example, to communicate status information back to the software process or to set hardware configuration registers from a software process.

You might want to create software test benches in order to test your application (including the register connections) in desktop simulation such as within Visual Studio. You can do this, but you need to keep in mind that the order in which processes (and the statements within processes) will run in a desktop operating system environment or debugger can not be guaranteed. The result is that values placed on a register in one process cannot be guaranteed to be available to the destination process unless some other synchronization method (a signal, for example) is used to pause (or yield) the originating process.


The hardware implementation of registers also requires that there be only one process that writes to a given register. There is no concept of a bidirectional register, and the hardware compiler reports an error if more than one process writes to the same register, as indicated by calls to either co_register_put or co_register_write. This condition may or may not be detected during software (desktop) simulation.

    Practical FPGA Programming in C
    Practical FPGA Programming in C
    ISBN: 0131543180
    EAN: 2147483647
    Year: 2005
    Pages: 208 © 2008-2017.
    If you may any questions please contact us: