Back to PARTHENON User's Manual


2.1 Description using SFL

Description of Interface Specifications
Description of Main Timer Unit
Descriptions of Functions and Implementation Methods
Supplement to SFL Description


List 2.1 shows an SFL description of the clock timer having the specifications mentioned above. Let us examine what this description means and how it was obtained.

<List2.1> Description of the Clock Timer (in entirety)

 1:	declare DECR8 {
 2:	    input      IN<8> ;
 3:	    output     OUT<8> ;
 4:	    instrin    ENABLE ;
 5:	    instr_arg  ENABLE( IN ) ;
 6:	}
 7:	
 8:	module TIMER {
 9:	    instrin    START, RESET ;
10:	    input      INIT<8>      ;
11:	    instrout   EXPIRE       ;
12:	    reg        REMAINED<8>  ;
13:	    DECR8      DECR         ;
14:	
15:	    stage_name MAIN { task RUN( REMAINED ) ; }
16:	    instruct   START generate MAIN.RUN( INIT ) ;
17:	
18:	    stage MAIN {
19:	        state_name  DOWN, ASSERT ;
20:	        first_state DOWN ;
21:	        state DOWN  any{
22:	            RESET | START : finish ;
23:	            else          : par{
24:	                REMAINED := DECR.ENABLE( REMAINED ).OUT ;
25:	                if( DECR.OUT == 0x00 ) goto ASSERT ;'
26:	            }
27:	        }
28:	        state ASSERT any{
29:	            RESET | START : par{ goto DOWN ; finish ; }
30:	            else          : EXPIRE() ;
31:	        }
32:	    }
33:	}

• Description of Interface Specifications

Now, let us look at List 2.2. This is an SFL description of just the interface specification of the clock timer. The declaration of the interface specification is like a function prototype declaration in the C language; it is unnecessary in the description of a timer design alone, but is necessary if the timer of this specification is to be used as a sub module in a later design.

<List2.2> Interface Specification of Clock Timer

 1:	declare TIMER {
 2:	    instrin    START, RESET  ;
 3:	    input      INIT<8>       ;
 4:	    instrout   EXPIRE        ;
 5:	    instr_arg  START( INIT ) ;
 6:	}

It should be clear intuitively that the third line declares that “INIT“ is an 8-bit input terminal. This input is a reserved word for declaring the “data input terminal,“ In addition, you will see the unfamiliar words, “instrin“ and “instrout,“ in the second and fourth lines. Instrin (abbreviation of “instruction-in“) is a reserved word to declare “control input terminal.“ Instrout (abbreviation of “instruction-out“) is a reserved word to declare “control output terminal.“

In short, List 2.2 shows that INIT is a data input terminal, that START and RESET are control input terminals, and that EXPIRE is a control output terminal.

In this way, SFL makes a clear distinction between control objects and data objects in order to improve description readability. Generally, data objects are used for “transmission or storage of data to be processed “ and control objects are used for “indication of data transmission timing (for synchronization).“ In this program, START, RESET, and EXPIRE are terminals to trigger operations and, therefore, are to be declared as control objects.

The statement declaration of “instr_arg“ (abbreviation of instruction-argument) in the fifth line indicates that “when the control input terminal START is asserted (made valid), the data necessary for the assertion must be given to INIT.“


• Description of Main Timer Unit

Definition of Component Elements
Behavioral Description (part 1)
Behavioral Description (part 2)
Behavioral Description (part 3)
SFL Description in relation to Timing


After the description of the interface specifications, we will describe the design of the main timer unit. The function used here is to count down the remaining time.

First, we must determine what is required: in this case a register to hold the remaining time and a decrementer for reducing the value. If a counter containing these is provided in a library, that library module should be used. However, since this section is intended to familiarize the reader with SFL description, we will explain the process from the beginning.


>

• Definition of Component Elements

What is important in the SFL description is to determine "what components should be used, and when and how they should be used." Since it is not clear how a decrementer can be implemented, let us initially assume that the decrementer is to be implemented as a separate module and will be designed later (so-called hierarchical design). As long as we are concerned with the timer behavior, it is not essential to know how the decrementer is implemented. In fact, someone else may design the decrementer.

However, if a separate module is to be used, the declaration of its interface specifications (List 2.3) is required. If such a decrementer exists as a library file, you will only need to write the following instead of List 2.3.

%i "file name"

<List2.3> Interface Specifications of an 8-bit Decrementer

 1:	declare DECR8 {
 2:	    input      IN<8>   ;
 3:	    output     OUT<8>  ;
 4:	    instrin    ENABLE  ;
 5:	    instr_arg  ENABLE( IN ) ;
 6:	}

Now, let us start the description of the main timer unit, giving names, "REMAINED" and "DECR," to an 8-bit register and a decrementer respectively (registers can be freely declared as built-in types in SFL). All objects described above are defined below (List 2.4).

<List 2.4> Declaration of Clock Timer

 1:	module TIMER {
 2:	    instrin   START, RESET ;
 3:	    input     INIT<8>      ;
 4:	    instrout  EXPIRE       ;
 5:	    reg       REMAINED<8>  ;
 6:	    DECR8     DECR         ;
 7:	}

The declaration of the Interface specifications in List 2.2 includes the description "instr_arg" for START while the definition of the timer module does not. This "instr_arg " is the description on how to assert START. Since START is not asserted within the timer module (i.e. it is asserted by an external module), such a description is not required in this case. In contrast, EXPIRE is asserted by the timer module itself, therefore "instr_arg" should normally be usually describedincluded. However, the description can be omitted if there are no data that accompany the assertion of EXPIRE.


< >

• Behavioral Description (part 1)

Now that the required objects have been defined, the specifications can now be described at the implementation level. It seems appropriate to distinguish some different states.

We can now proceed to the next stage.

It is possible to provide registers that represent each of these states and to manage the states using their values. However, this is not necessary because SFL provides a "stage," namely, a framework for clear description of state transition.

The term stage means,an object that has an internal state and executes sequential control such as can be expressed by a state transition. The stage is accompanied by a concept called a task. Task should be literally interpreted as a "task to be performed in the stage." The task in the stage has "either the value ON (task is provided) or OFF (no task is provided)." When the task is ON, " the state is active and state transition may occur." When the task is OFF, " the state is inactive and no state transition occurs." If the stage is used, "State 0" can be expressed by the task being OFF. Therefore, it is necessary to describe only two states; States 1 and 2.


< >

• Behavioral Description (Part 2)

Let's try writing the declaration of states and what is to be done in each state (List 2.5). Behavioral Description of Clock Timer (Part 1)
<List2.5> Behavioral Description of Clock Timer (Part 1)

 1:	stage_name      MAIN { task RUN( REMAINED ) ; }
 2:	stage MAIN {
 3:	    state_name   DOWN, ASSERT ;
 4:	    first_state  DOWN ;
 5:	
 6:	    state DOWN   :      /* state 1  */
 7:	        REMAINED := DECR.ENABLE( REMAINED ).OUT
 8:	    state ASSERT :      /* state 2  */
 9:	        EXPIRE() ;
10:	}

The first line declares that the stage MAIN accepts a task called RUN and that a parameter necessary for the task is set in register REMAINED. The two states are named DOWN and ASSERT (in the third line) and the initial state of stage MAIN is named DOWN (in the fourth line). In state DOWN (in the sixth line and after), the value of register REMAINED is given to the decrementer and the subtraction result (output at OUT of DECR) is used as the next value for REMAINED (in the seventh line). In the ASSERT state (in the eighth line and after), the EXPIRE output is asserted (in the ninth line).

Then, when a state transition (goto) is added, the list becomes List 2.6 (in the ninth and 13th lines). Since the sleep mode is designated as task OFF, assertion at the RESET terminal finishes the task (in the sixth and 13th lines). Where:

<List 2.6> Behavioral Description of Clock Timer (Part 2)

 1:	stage_name      MAIN { task RUN( REMAINED ) ; }
 2:	
 3:	stage MAIN {
 4:	    ............
 5:	    state DOWN   : any{
 6:	        RESET : finish() ;
 7:	        else  : par{
 8:	            REMAINED := DECR.ENABLE( REMAINED ).OUT ;
 9:	            if( DECR.OUT == 0 ) goto ASSERT ;
10:	        }
11:	    }
12:	    state ASSERT : any{
13:	        RESET : par{ goto DOWN ; finish() ; }
14:	        else  : EXPIRE() ;
15:	    }
16:	}


< >

• Behavioral Description of Clock Timer (Part 3)

The behavioral description of the clock timer is completed after adding the description that task RUN is generated, with the value given at the INIT terminal as a parameter, after the assertion of START, as shown in the second line of List 2.7. Note that the assertion of START also finishes the task (in the seventh and 14th lines); an old task is canceled and a new task is generated as indicated in the second line.

<List2.7> > Behavioral Description of Clock Timer (Part 3)

 1:	stage_name MAIN  { task RUN( REMAINED ) ; }
 2:	instruct   START generate MAIN.RUN( INIT ) ;
 3:	
 4:	stage MAIN {
 5:	    ............
 6:	    state DOWN   : any{
 7:	        START | RESET : finish ;
 8:	        else          : par{
 9:	            REMAINED := DECR.ENABLE( REMAINED ).OUT ;
10:	            if( DECR.OUT == 0x00 ) goto ASSERT ;
11:	        }
12:	    }
13:	    state ASSERT : any{
14:	        START | RESET : par{ goto DOWN ; finish ; }
15:	        else          : EXPIRE() ;
16:	    }
17:	}



< >

• Timing related to SFL Description

List 2.1, provided a complete description for the clock timer. This description can be used in a simulator and for logic synthesis. However, few people may be satisfied that the clock timer operates as specified. This is because no clock appears in the description even though we are talking about a clock timer. Also, no explanation is given on timing. However, believe or not, the description related to timing is already included in List 2.1. Timing is so simple in the world of SFL that no explicit description of timing is necessary.

Circuits described in SFL are designed to operate as synchronous circuits with a (logically) single-phase clock (see, the word "clock" crops up!). Individual statements written in SFL define behavior between clock pulses.

For example, consider a case where START is asserted while EXPIRE is being output. When START is asserted at state ASSERT, par{goto DOWN; finish;} is to be executed. The action of START is generate MAIN.RUN(INIT). Figure 2.2(a) shows the time chart of this part. (0x40 is assumed to be given to INIT.)

<Fig2.2>Timing of a synchronous circuit

Although this figure gives the impression that the order of changes in signals within a clock cycle are significant, they are not, as is evident from the fact that there is no description of such matters in SFL. Only the value immediately prior to the rising edge (or falling edge) of the next clock pulse is significant.

This is the very nature of a synchronous circuit. If START and RESET, for example, occur within the same clock cycle in whichever order, SFL (i.e., synchronous circuit) only perceives that both of them are asserted. Therefore, SFL statements are not concerned about time relationships between events within a clock cycle.

Except for the exclusive conditions of any and alt and block containment relationship (neither of which has to do with timing relation, but priorities of conditions), the same results will be obtained regardless of the order of SFL statements. All statements are assumed to occur in parallel. For example, the same result is obtained if:

 par{REMAINED:=DECR.ENABLE(REMAINED).OUT;if(DECR.out==0)goto ASSERT;}

is replaced by

 par{if(DECR.OUT==0)goto ASSERT;REMAINED:=DECR.ENABLE(REMAINED).OUT;}

In no case, DECR.OUT in the if-statement in the latter is undefined or assumes the value of the previous clock.

The occurrence of a clock pulse concurrently changes the values of all objects with memory, as shown in Figure 2.2 (b). This is all there is to timing in SFL.


It should now be clear that SFL in List 2.1 was correct. If you are still not sure, write down the time charts of all patterns by referring to Figure 2.3, and then verify them with the simulator (SECONDS). With this simple example, it won't take much time.

<Fig2.3> Time Chart of Clock Timer


<

• Description of Functions and Description of Implementation
• Description of Functions

We said that the decrementer will be designed later. However, for the convenience of simulation, let us at least list its functions.

List 2.8 is an 8-bit decrementer. SFL does not provide the operator "-" (subtraction) (because the notation for a negative value has not been determined), but it does provide "+"(addition), albeit without a sign. Since the subtraction of 1 in an 8-bit number is equivalent to the addition of 0xff for the limited world of non-negative numbers, the meaning of the description below should be clear.

<List2.8> Functional Description of an 8-bit Decrementer


 1:	circuit DECR8{
 2:	    input     IN<8>   ;
 3:	    output    OUT<8>  ;
 4:	    instrin   ENABLE  ;
 5:	    instruct  ENABLE OUT = IN + 0xff ;
 6:	}

Notice that the keyword used here is not module but circuit. Circuit indicates that it is not subject to logic synthesis. Circuit is to be used only in the following two cases.


• Description of Implementation (Logic synthesis)

Logic synthesis with the decrementer included requires substitution of "module" for "DECR8." Since addition and shift cannot be used with a "module," we must consider an alternative solution.

As is clear in the function description formula, we only have to consider the case where all bits of an input to the adder are "1." Output Si of the i-th bit of the adder is as follows (LSB is assumed to be Bit 0):

Si   = Ai @ Bi @ Ci-1                           : i >= 0

Ci = (Ai & Bi) | (Bi & Ci-1) | (Ci-1 & Ai) : i >= 0

C-1 = 0

(Where:"^" represents NOT, "&" AND, "|" OR, and "@" EXCLUSIVE-OR.)

Let Bi=1,then,

Si   = ^(Ai @ Ci-1) 

Ci = Ai | Ci-1 | (Ci-1 & Ai)

= Ai | Ci-1

= Ai | Ai-1 | .... | A0 | 0

All that is left to be done is to translate this into SFL.

List 2.9 shows the description of the above in SFL. ( "||" represents a concatenation of bit strings, "<m:n>"represents a partial string from the m-th bit to n-th bit with LSB being 0, and "/|" represents logic AND of all bits).

<List2.9>  Carry-look-ahead 8-bit Decrementer 

1: module DECR8 { 2: input IN<8> ; 3: output OUT<8> ; 4: sel_v C<8> ; /* temporal terminal */ 5: instrin ENABLE ; 6: 7: instruct ENABLE par{ 8: C = /|( IN<6:0> ) /* IN<6> | ... | IN<0> */ 9: || /|( IN<5:0> ) /* IN<5> | ... | IN<0> */ 10: || /|( IN<4:0> ) /* IN<4> | ... | IN<0> */ 11: || /|( IN<3:0> ) /* IN<3> | ... | IN<0> */ 12: || /|( IN<2:0> ) /* IN<2> | ... | IN<0> */ 13: || /|( IN<1:0> ) /* IN<1> | ... | IN<0> */ 14: || IN<0> || 0b0 ; 15: OUT = ^( IN @ C ) ; 16: } 17: }

List 2.9 describes the implementation of the decrementer function with 8-bit carry-look-ahead. There can be other implementations. For example, it is possible to propagate carry bit by bit, considering simplicity and economy of circuits. An intermediate method between them (2-bit/4-bit carry-look-ahead) is also possible. For reference, an example of propagating carry is shown in List 2.10.

<List2.10>  Carry-propagation 8-bit Decrementer 

1: declare DECR_CP{ 2: input IN, CI ; 3: output NS, CO ; 4: instrin EN ; 5: instr_arg EN( IN, CI ) ; 6: } 7: 8: module DECR_CP{ 9: input IN, CI ; 10: output NS, CO ; 11: instrin EN ; 12: instruct EN par{ NS = ^(IN @ CI) ; CO = IN | CI ; } 13: } 14: 15: module DECR8 { 16: input IN<8> ; 17: output OUT<8> ; 18: sel_v C<8> ; /* temporal terminal */ 19: instrin ENABLE ; 20: DECR_CP CP6, CP5, CP4, CP3, CP2, CP1 ; 21: 22: instruct ENABLE par{ 23: C = CP6.EN( IN<6>, C<6> ).CO || 24: CP5.EN( IN<5>, C<5> ).CO || 25: CP4.EN( IN<4>, C<4> ).CO || 26: CP3.EN( IN<3>, C<3> ).CO || 27: CP2.EN( IN<2>, C<2> ).CO || 28: CP1.EN( IN<1>, C<1> ).CO || 29: IN<0> || 0b0 ; 30: OUT = ^( IN<7> @ C<7> ) || 31: CP6.NS||CP5.NS||CP4.NS||CP3.NS||CP2.NS||CP1.NS|| 32: ^IN<0> ; 33: } 34: }



This concludes the description of the clock timer. We hope that you now have an idea of how to write (i.e. how to design) SFL . As in the case of programming languages, please deepen your understanding by describing more examples of designs and using the tools.


<ColumnA> Control Terminal and Data Terminal


Objects to be described in SFL are classified into:

They can also be classified into:

As shown in Table A.1, objects can be classified using keywords in SFL.

<TableA.1> Classification of objects

Since stage, segment and task are concepts specific to SFL, and models of register and memory (memory is also synchronized with the clock) in SFL are straightforward, the concept of objects with memory (registers) should not be confusing. However, objects without memory (terminal type) will require an understanding of the models specific to SFL because they are different from simple signal lines (and their terminals).

In SFL, it is not assured that a data terminal always has a value. The value of a data terminal is defined only when an assignment statement for the object is executed (driven). Two or more assignment statements cannot drive the same data object with different values.

On the other hand, the control terminal should always have its value defined because it is an important object for timing control. Therefore, it is assured that a control terminal has a value of "0" or "1" at all times. Unlike data terminals, assigning a value to a control terminal is not allowed. When an asserting statement of the control terminal, which is similar to a function call in C language, is executed, the control terminal is asserted (set to "1"). Only when no asserting statements are executed, is the control terminal negated (to be "0"). Therefore, forced negation of a control terminal is impossible.

It may be possible to illustrate these characteristics with the following:

However, since the synthesis tool of PARTHENON optimizes circuits within the range consistent with the above model, the above circuits are not necessarily synthesized.

This explains why the RESET terminal is defined not as a data terminal but as a control input terminal. In the later sections, the value of RESET will be used to discriminate between different conditions. If a RESET is defined as a data terminal, whose value is not necessarily defined, discrimination of true or false conditions may be impossible (a high impedance is equivalent to "high" in TTL, but the tools of PARTHENON do not assume specific technologies).

The situation is slightly different in the case of the ENABLE terminal of the decrementer. If the input value (IN) is not defined, the output (OUT) can take any value ("does not care"). Therefore, the ENABLE terminal is not an essential object. What it does is cosmetic in nature, only making the SFL description look nicer. In simulation, however, a warning message appears when the value of IN is not defined in the case where the ENABLE terminal is not provided.


<ColumnB> Stages and Tasks


A task,to be more accurate, means part of a piece of work. If you call the entire work a job, a task of a stage is a job step assigned to the stage.

In this example, a job starts with the assertion of the control terminal START with the initial value given in the parameter. The the initial value is counted down, and when it becomes zero, assertion of EXPIRE occurs and is continued until the next job is initiated (assertion of START) or a stop instruction (assertion of RESET) is entered. In this way, a job is terminated when START or RESET is asserted.

The above explanation may appear to be only repeating the description of the state transition, but it actually adds a dynamic perspective of a job to a static view of state transition. For example, from the job perspective, the first timer behavior and the second one are considered to be separate jobs. The process before setting the initial value to REMAINED is the job step assigned to control terminal START, and the step after that is a job step assigned to stage MAIN, named RUN.

Though a stage can describe only sequential control, i.e., state transition, more than one stage can be described in a module. If a job is divided into several job steps, and if job steps are assigned to stages, the stage with its job steps completed can execute a job step of the next job, and therefore, parallel processing through a pipeline can be achieved.

You may notice similarity between task declaration and control terminal declaration, and between task activation and control terminal assertion. In many cases, a control terminal is actually used as the intermediary to transfer jobs between modules.

This can be seen if you give the name TIMER to control terminal START, task name RUN for stage MAIN, and control terminal ENABLE for the decrementer module. Control terminal TIMER would seem to represent the job of this module, and control terminal TIMER for the decrementer module can be considered to be a part of the job step TIMER in MAIN.


<ColumnC> Synchronous Circuits and Logic Synthesis



It was said above that, "since SFL is used exclusively for synchronous circuits, only the value just before the rising edge (or falling edge) of a clock pulse is significant." In other words, SFL is unable to describe any design that does not meet this requirement. For example, SFL can neither modify clock signals nor apply signals other than clocks to the trigger input of a flip-flop. Similarly, neither a loop path without a register in it nor a combinational circuit with a delay longer than a clock cycle is allowed.

Those who are accustomed to designing asynchronous circuits may think that the START and RESET signals in this example should be processed asynchronously, but SFL does not allow such a circuit design (note that we are not talking about asynchronous communication protocols, such as handshaking). Though this may seem inconvenient, it is not. In a synchronous circuit which can be described in SFL, there is no hazard of START or RESET signal, nore is there any racing. The description in SFL has many advantages. Since there is no need to look at detailed timing, simulation can be faster, the number of parameters for logic synthesis can be drastically reduced, and the synthesized circuits are more likely to behave as expected.

Timing restrictions in a synchronous circuit can be summarized as concerns about whether there is data leakage from registers due to clock skew (whether the hold time is assured), and whether data transfer between registers will be completed within a clock cycle (whether the set-up time has any margin).

In PARTHENON, these concerns are verified statically by the technology-mapper (OPT_MAP), and the circuit which satisfies the requirements the best is synthesized. In other words, SFL is not for a design that assumes specific semiconductor manufacturers or their libraries. Rather, it allows the selection of manufacturers and their libraries for appropriate implementation of a design by automatic synthesis.