<?xml version="1.0"  encoding="ISO-8859-2"?> 
<!DOCTYPE zprava SYSTEM "techrep.dtd" >
<zprava cislo="3/2004" jazyk="en">  
<nazev>Verification Results in Liberouter Project
<footnote>This work is supported by the FP5 project No. IST-2001-32603, the CESNET project 02/2003, and the GACR grant No. 201/03/0509.</footnote><!-- Nevím zda je tento grant OK, zeptám se na semináři nebo doplníme později. -->
</nazev> 
<autor>Jan~Holeček, Tomáš~Kratochvíla, Vojtěch Řehák, David~Šafránek, and Pavel~Šimeček</autor> 
<datum>September 16, 2004</datum> 

<h1>Abstract</h1>
<p>
This technical report presents current results of the formal verification of <i>VHDL</i> design of <i>Liberouter</i>
and <i>Scampi</i>
hardware accelerator card for packet routing, originating from the
<i>Liberouter</i> project.
We use the symbolic model checker <b>Cadence SMV</b>~<cite href="SMV"></cite> to prove
desired properties of separate units of the design. We have verified many
properties of the number of units. Moreover, we have also gained
precious experiences concerning the fight with the state explosion
problem.
</p>

<h1>Introduction</h1>

<p>The aim of the <i>Liberouter</i> project~<cite href="LibWWW"></cite>
is to design and develop the hardware accelerated router.
The most important part of this project is development
of the <i>Combo6</i> and <i>Scampi</i> hardware accelerator card~<cite
href="Nov04"></cite>
allowing to route the most of traffic of 
<i>Gigabit Ethernet</i> in the hardware.
</p>
<p>
More introduction into the problematics of the verification
in this project can be found in~<cite href="VerifVHDLCombo6"/>.
</p>
<p>
After finishing the technical report~<cite href="VerifVHDLCombo6"/> we have
found significant failures in our verification. Unfortunately, our previous
definition of LATRS register entity was not correct and also further
registers (e. g. DFFRS and DFFERS) were translated in the wrong way (by
<b>vl2smv</b> utility).
</p>
<p>
For this reason we have created new models of these registers.
We have also created new models of the registers in
the cases with more than one clock signal, where it is necessary
to have more detailed descriptions (see~<cite href="FormalVHDL"/>).
</p>
<p>
After corrections of our translation process
we have focused our effort to the real model checking of
separate units of the design. We have gained precious experience.
Now we are able to formulate
very interesting formulas and preconditions in <i>LTL</i>, furthermore
we can manually model (on the very high level of abstraction) the behavior
of certain parts of the design. And this way we are able to simulate the
behavior of the units which create inputs (environment) of the verified
component (see the verification of Statistic Unit).
</p>
<p>
In this report we would like to present results and experiences
with the model checking of <i>VHDL</i> source in the <i>Liberouter</i>
project in the
form of description of verification of single units. Techniques used
in verification slightly vary according to the particular verified unit. 
</p>

<h1>Current state of translation process from VHDL to Cadence SMV</h1>

<p>
In the technical report <cite href="VerifVHDLCombo6"/> we have introduced
our approach to the translation of <i>VHDL</i> to <i>Verilog</i> and then
to the <b>Cadence SMV</b>. After releasing the report we have found significant
errors in the definition of LATRS entity and we have also found out that further
entities representing registers were wrong. The main reason of these
mistakes is based on the fact that <b>vl2smv</b> is not able to correctly
translate <tt>always</tt> blocks in a <i>Verilog</i> source code.
</p>

<p>
The first step which have to be done to verify source codes is downloading them
from <a href="http://www.liberouter.org/cgi-bin2/cvsweb.cgi" >CVS</a>.
You can download them directly via web interface of our CVS
or you can use anonymous account and CVS client to download the entire CVS.
</p>

<p>
The process of translation is almost the same as in
<cite href="VerifVHDLCombo6"/>. The difference is in definitions
and counts of replaced entities. The process
of translation and substitutions for entities was strongly automatized.
We have created
scripts called <b>vhd2v</b> (written in <i>Bash</i> scripting language)
and <b>v2smv.pl</b> (written in <i>Perl</i>), which can be found in our 
<a href="http://www.liberouter.org/cgi-bin2/cvsweb.cgi/liberouter/ver/scripts/">CVS</a>.
<b>vhd2v</b> calls the synthesizer on the design given in the command line
with some optional parameters:
  <blockquote>
   vhd2v [-vhd] DESIGN TO_OPTIMIZE [MOD ..] SRC
  </blockquote>
where <tt>DESIGN</tt> is the name of the synthesized design,
<tt>TO_OPTIMIZE</tt> is the name of the part of the design to optimize
(value <tt>-</tt> stands for the optimization of the entire design),
<tt>MOD</tt> is the <i>VHDL</i> module used for synthesis and
<tt>SRC</tt> is the <i>VHDL</i> module with top-level design.
</p>
<p>
<b>v2smv.pl</b> calls <b>vl2smv</b> and do few other transformations
(e.g. substitutions for the modules). This is the syntax of its usage:
  <blockquote>
  v2smv.pl [-async/-sync] SRC
  </blockquote>
where <tt>SRC</tt> is the <i>Verilog</i> source (preferably the one produced
by <b>vhd2v</b>) and parameters have the following meaning:
<ul>
  <li><tt>-async</tt> means that for default substitutions we want to use
      definitions of modules determined for designs with multiple clocks
      placed in <br/><tt>$LIBEROUTER_PATH/ver/smv_codes/ASYNC</tt>
  </li>
  <li><tt>-sync</tt> means that for default substitutions we want to use
      definitions of modules determined for designs with single clock
      placed in <br/><tt>$LIBEROUTER_PATH/ver/smv_codes/SYNC</tt>
  </li>
</ul>
<tt>LIBEROUTER_PATH</tt> is the environmental variable (it should
represent the root of local copy of CVS).
</p>

<h2>Required Software</h2>
<p>
This is the list of software required for
translation, verification, presentation of our results:
<ul>
    <li><b>LeonardoSpectrum/Precision</b> for <i>VHDL</i> synthesis.<br/>
            (<a href="http://www.mentor.com/">http://www.mentor.com/</a>)</li>
    <li><b>Cadence SMV</b> for model checking.<br/>
            (<a href="http://www-cad.eecs.berkeley.edu/~kenmcmil/smv/">http://www-cad.eecs.berkeley.edu/&vlnka;kenmcmil/smv/</a>)</li>
    <li><b>saxon</b> for XSLT transformations of Verification reports.<br/>
            (<a href="http://saxon.sourceforge.net/">http://saxon.sourceforge.net/</a>)</li>
</ul>
</p>
<p>
   Of course, these applications require some additional libraries and
applications installed. For example <b>Cadence SMV</b> needs Tk Interface
eXtension <b>TIX</b> and <b>saxon</b>, written in <i>Java</i>, requires Java Runtime Environment
(available from web page of Sun).
</p>

<h2>Scampi project translation</h2>
<p>
This section is about the synthesis of <i>Scampi</i> project
and its translation to <b>Verilog</b> and <b>Cadence SMV</b>.

Working directory for <i>Scampi</i> project is

<blockquote>$LIBEROUTER_PATH/vhdl_design/combo6/projects/scampi_ph1</blockquote>

In this working directory the content of the file <prikaz>Modules.tcl</prikaz>
determines which modules will be included in the translation.
Translation of <prikaz>top_level.vhd</prikaz> to <prikaz>top_level.v</prikaz>
and then to <prikaz>top_level.smv</prikaz>
is performed using <prikaz>gmake top_level.smv</prikaz>
or just <prikaz>make top_level.smv</prikaz>.
</p>

<p>
This translation is provided by <b>v2smv.pl</b> script and uses the following files:
</p>
<p>
$LIBEROUTER_PATH/vhdl_design/combo6/projects/scampi_ph1/Makefile<br/>
$LIBEROUTER_PATH/vhdl_design/base/Makefile.fpga.inc (included)
</p>
And Leonardo spectrum depends on the following files:
<p>
$LIBEROUTER_PATH/vhdl_design/combo6/projects/scampi_ph1/&ldots;<br/>&ldots;Leonardo.ver.tcl<br/>
$LIBEROUTER_PATH/vhdl_design/combo6/projects/scampi_ph1/Modules.tcl<br/>
$LIBEROUTER_PATH/vhdl_design/base/Leonardo.inc.tcl (included)
</p>
<p>
The translation to <b>Cadence SMV</b> can produce empty modules.
They can be for example:
</p>
<p>
DCM, RAM16X1D, RAM32X1D, RAM64X1D, RAMB16_S18_S18, RAMB16_S18_S36, RAMB16_S9_S18</p>
<p>
Keeping these modules empty we abstract 
from their behavior and so all
possible outputs of these modules are taken in consideration.
The reason is that saving every state of memory module (e. g. RAM16X1D, RAM32X1D) to the computer memory is unfeasible.
</p>


<h1>Obtaining Assertions</h1>
<p>
One of the biggest problems is the way of obtaining properties which should be verified.
There are three main sources of assertions:
<ul>
    <li>Assignment from <i>VHDL</i> designer: verbal description 
            or assertions in comments in <i>VHDL</i> codes
            (for more details see~<cite href="VC"></cite>).
    </li>
    <li>Documentation of components contains a large amount of specifications.</li>
    <li>Analysis of <i>VHDL</i> source codes and Applications notes from various sources (e. g. Xilinx).</li>
</ul>
</p>

<h1>Cadence SMV on Different Platforms</h1>
<p>
<b>Cadence SMV</b> model checker is freely available on the following platforms: <prikaz>HP/UX</prikaz>, <prikaz>MIPS/IRIX</prikaz>, <prikaz>i386/Linux</prikaz>, <prikaz>Sparc/Solaris</prikaz> and <prikaz>Windows</prikaz>.
The latest version of <b>Cadence SMV</b> is only available
on the <prikaz>i386/Linux</prikaz>, <prikaz>Windows</prikaz> and <prikaz>Sparc/Solaris</prikaz> platforms.
Ports to the <prikaz>HP/UX</prikaz> and <prikaz>MIPS/IRIX</prikaz> platforms are no longer being maintained.
</p>
<p>
We want to choose the best platform for fast verification process.
For this purpose the test verification was created and the time and space
consumed by <b>Cadence SMV</b> with the test verification as input was
analysed. The time and space consumption on different platforms is shown
in logarithmic scale in <a href="#space_complexity">Figure</a>. 
We found difference between <b>Cadence SMV</b> versions
on different platforms in memory consuming with the same input.
On <prikaz>Windows XP</prikaz> the test verification never finished. It is unusual because on other platforms the space consumption was at most 151 MB and on <prikaz>Windows XP</prikaz> the 600 MB of free physical memory is not enough.

<obr src="space_complexity" id="space_complexity">On <prikaz>Windows XP</prikaz> the test verification not finished (memory exceeded).</obr>
</p>

<p>
Running time of <b>Cadence SMV</b> with the testing input
on several different machines is in <a href="#time_complexity">Figure</a>.
These times are the average from two running times.
On every row there is a different computer although it may seem that
<i>Pentium 4 2,6 GHz, Linux</i> and <i>Pentium 4 3 GHz, Linux</i>
are only identical copy.
<obr src="time_complexity" id="time_complexity">On <prikaz>Windows XP</prikaz> the test verification not finished (memory exceeded).</obr>
</p>
<p>
For efficient usage of <b>Cadence SMV</b> we recommended computer
with the latest Pentium or Athlon with some Linux distribution installed.
The psychical memory size should be 2 GB for huge state spaces.
</p>

<h1>Components Under Verification</h1>

<p>
We will present selected components from <i>Liberouter</i> and <i>Scampi</i>
designs which we currently verify according to several properties each time
the new version of design appears in CVS.
The basic outline of components is depicted in <a href="#cover">Figure</a>.
The highlighted components are currently under verification.
Numbers under components are counts of unique verified properties.
The similar properties are counted as one (see examples of verification to
understand what "similar" means).
</p>
<obr src="cover" id="cover">Parts of design under verification with number of properties verified:</obr>
<p>
<!-- Nejdříve by tu měla být diskuse o tom JAK VELKÉ části děláme
(proč tam neprskout celý design, nebo proč třeba naopak ano - cone
of influence) -->

</p>
<p>
Using the number of examples we would like to present the techniques used
to achieve sufficiently efficient model checking in <b>Cadence SMV</b>.
</p>

<h2>Edit Engine</h2>

<p>
Basic documentation of <prikaz>Edit Engine</prikaz> (<prikaz>EE</prikaz>)
is in the <i>Liberouter</i> CVS. <cite href="EditEngine"/>
<prikaz>EE</prikaz> is a block for output packet processing.
The record from <prikaz>Priority Queues</prikaz> is the first input information.
It contains pointer to DRAM memory, where the packet data is stored,
pointer to the parameters data structure, 
and the information on how to process the packet (so called <i>edit parameters</i>).
</p>
<p>
When <prikaz>EE</prikaz> gets record from <prikaz>Priority Queues</prikaz>
it loads all parameters important for further processing.
Then <prikaz>EE</prikaz> just loads packet data from
DRAM memory and proceeds its processing.
The example of <prikaz>EE</prikaz> work is changing L2 header,
decrementation of Hop Limit entry (Time To Live in IPv4),
processing Routing Header, control of ICMPv6,
or Encapsulation/Decapsulation of packet in a tunnel.
</p>

<p><ol>
  <li><blockquote>G (! ( plx_wr and plx_rd ) );</blockquote></li>
  <li><blockquote>G ( ( !DRAM_COM_U.RESET and DRAM_COM_U.START ) -&gt; ( X DRAM_WR_REQ ) );</blockquote></li>
  <li><blockquote>G ( ( !DRAM_COM_U.RESET and DRAM_COM_U.START ) -&gt; ( X DRAM_ACK ) );</blockquote></li>
  <li><blockquote>G ( ( !DRAM_COM_U.RESET and DRAM_COM_U.START ) -&gt; ( X DRAM_RD_REQ ) );</blockquote></li>
  <li><blockquote>G ( ( !DRAM_COM_U.RESET and DRAM_COM_U.START ) -&gt; ( X DRAM_DEC_REQ ) );</blockquote></li>
  <li><blockquote>G ( ( !DRAM_COM_U.RESET and DRAM_COM_U.START ) -&gt; ( X CTRL_U.DRAM_FINISH) );</blockquote></li>
  <li><blockquote>G ( !DRAM_COM_U.RESET and !( (DRAM_COM_U.INP_PTR + 1) = DRAM_COM_U.OUT_PTR) );</blockquote></li>
</ol></p>

<p>
The first assertion is simple mutual exclusion of signal 
<tt>plx_wr</tt> and <tt>plx_rd</tt>.
This assertion is true and verification takes only 0.62 seconds.
</p>

<p>
All other assertions are the matter of <prikaz>DRAM_COM_U</prikaz>
(DRAM Scheduler Communication Unit). 
It is assumed that at the beginning of the run the
reset signal <prikaz>DRAM_COM_U.RESET</prikaz>
resets the DRAM Scheduler Communication Unit and then 
the signal <prikaz>DRAM_COM_U.RESET</prikaz> is supposed to be disabled
(to logical value 0).
</p>

<p>
The second assertion for <prikaz>WR REQ FSM</prikaz>
(Write Request Finite State Machine) only ensures that after the
<prikaz>START</prikaz> signal, which starts communication of DRAM Scheduler,
the signal <prikaz>DRAM_WR_REQ</prikaz> for writing request
will be enabled in one step.
</p>
<p>
Similarly for the other assertions.
We considered these assertions as one unique property.

Some of them are even isomorphic and <prikaz>Cadence SMV</prikaz>
primarily skips the model checking process when it finds a model checking problem
which is isomorphic to some that has been already solved in the past.
(To prevent this behaviour, use <prikaz>-force</prikaz> argument,
or remove <prikaz>.smv_history</prikaz>.)
</p>

<p>
The fourth assertion is false.
The reason is not the bug in design but a very imperfect specification.
More preconditions would have to be added to make this assertion valid.
</p>

<p>
The last assertion is very important.
DRAM scheduler coordination of data transfer into <prikaz>PD</prikaz> block
using <prikaz>CNT CE FSM</prikaz> (Counter Clock Enable Finite State Machine).
If the condition "(InputPointer + 1) = OutputPointer" is not satisfied,
then the data that was still not processed will be rewritten.
This situation should not happen.
</p>

<p>
No matter which abstraction we have used, the state space was always larger than 4 GB memory.
The limit of 4 GB memory is given by our
precompiled binary version of <b>Cadence SMV</b>.
</p>

<h2>Sampling Unit</h2>
<p>
VHDL structure of <i>Scampi</i> <cite href="VHDLScampi"/> project contains
16 <prikaz>Sampling Units</prikaz> (<prikaz>SAU</prikaz>). 

Each can be configured to do:
<ul>
<li><b>probability sampling</b> -- the packet is passed through the unit with the probability <i>1/n</i>.</li>
<li><b>deterministic sampling</b> -- each <i>n</i>-th packet is passed through.</li>
<li><b>byte deterministic sampling</b> -- the packet containing each <i>n</i>-th byte is passed through.</li>
</ul>
The packet could be processed simultaneously in more than one <prikaz>SAU</prikaz>.
If the packet is not passed through any of these units, it is discarded.
The required processing of the packet is coded in the control word.
First half of 32-bit control word is <prikaz>SAMASK</prikaz> -- sampling unit assignment.
Each <prikaz>SAU</prikaz> has one bit in this bit array and
'1' means that packed will be processed by corresponding <prikaz>SAU</prikaz>.
The <prikaz>SAMASK</prikaz> field is masked by the result of <prikaz>SAU</prikaz> processing.
The '1' is remained only if the packet is passed through the corresponding <prikaz>SAU</prikaz>.
</p>
<p>Special configuration of <prikaz>SAU</prikaz> is the case of deterministic sampling with <i>n=1</i>.
this case represents the situation, when all specified packets are required to pass to the application.</p>

<h3>Assignment from hardware developers</h3>

<p>Assertions obtained from hardware developer:
<ol>
<li><blockquote>Mutual exclusion of control_flag and data_flag.</blockquote></li>
<li><blockquote>Mutual exclusion of mode_wr and init_wr_vec.</blockquote></li>
<li><blockquote>Mutual exclusion of signals CONTROL_A, CONTROL_B, CONTROL_C, and CONTROL_D.</blockquote></li>
</ol></p>

<p>
In the first assertion both signals have been synthesized into
<tt>NOT_control_flag</tt> and <tt>NOT_data_flag</tt>
in component <prikaz>SAU_INS_notri</prikaz>.
These signals are undefined when one of the resets <tt>SAU_INS_notri.RESET</tt>
or <tt>LRESET</tt> is enabled. Hence the complete formula looks like:
<pre>
G ( ! ( 
        (!SAU_INS_notri.RESET) and
        (!LRESET) and
        SAU_INS_notri.NOT_control_flag and
        SAU_INS_notri.NOT_data_flag
      )   );
</pre>
</p>
<p>
The second assertion is a mutual exclusion of signal <tt>mode_wr</tt>
and
vector of 16 signals <tt>init_wr_vec</tt> in component <tt>SAU_INS_notri</tt> again.

Signal <tt>mode_wr</tt> is synthesized into signal <tt>nx72</tt> and
vector <tt>init_wr_vec</tt> is synthesized into 16 signals <tt>nx57, nx58, .., nx71, nx73</tt>.
No bit of vector <tt>init_wr_vec</tt> should be enabled,
when <tt>mode_wr</tt> is enabled,
hence the formula of mutual exclusion should be
<prikaz>G ( ! ( SAU_INS_notri.nx72 and SAU_INS_notri.nx57 and SAU_INS_notri.nx58 and ... and SAU_INS_notri.nx73);</prikaz>
</p>

<p>
The third assertion was not verified. It is due to the size of the state space
generated by the resulting formula: 
<pre>
G ( ! ( SAU_INS_notri.sau_cores_0_U_SAU_CORE.CONTROL_A and
        SAU_INS_notri.sau_cores_0_U_SAU_CORE.CONTROL_B and
        SAU_INS_notri.sau_cores_0_U_SAU_CORE.CONTROL_C and
        SAU_INS_notri.sau_cores_0_U_SAU_CORE.CONTROL_D ) );</pre>

In each tested abstraction the state space was larger than 4 GB memory.
Same as it was for the last assertion in <prikaz>Edit Engine</prikaz> component.
</p>




<!-- Pavlova část: HFE, UH_FIFO, STU-->
<!--Struktura:
  * ziskane formule (odkud), jejich popis
  * popis jak se verifikovalo, pridavaly se predpoklady (rozdeleno
    podle formuli)
  * popis zmen v modelu
  * pokud se neco namodelovalo v SMV, tak dobre popsat, aby se to v mysli
    cloveka dalo zobecnit a treba jindy pouzit
-->
<h2>Header Field Extractor</h2>
<p>
Header Field Extractor (<prikaz>HFE</prikaz>)
processes the instructions stored in block RAM.
Its purpose is to perform packet analysis and store packets into DRAM.
HFE is implemented as a full scope processor that is controlled by binary
instructions. These instructions form a program that may be described by an
assembler. If the parsing program has to be modified or extended in the future,
only the parsing program will have to be updated without changing the hardware
design.
</p>
<h3>Basic assignment</h3>
<p>
We have chosen the subcomponent <prikaz>HFE_CORE</prikaz>, because in due
time the top-level design was in the continuous development. Below are
assertions from developer and from our mind using developer's description
of the design:
<ol>
<li><blockquote>G F (loop_cntr_0_ or loop_cntr_1_ or loop_cntr_2_ or loop_cntr_3_ or loop_cntr_4_ or loop_cntr_5_ or loop_cntr_6_ or loop_cntr_7_);</blockquote></li>
<li><blockquote>G ( (indd_inc -&gt; (not indd_dec)) and (indd_dec -&gt; (not indd_inc)))</blockquote></li>
<li><blockquote>G ( (set_int -&gt; (not clear_int)) and (clear_int -&gt; (not set_int)))</blockquote></li>
<li><blockquote>
((not CLK) U G ( not ( ( shortcut_en and sel_gpr ) or ( shortcut_en and sel_din ) or ( shortcut_en and sel_din_i) or ( sel_gpr and sel_din ) or ( sel_gpr and sel_din_i) or ( sel_din and sel_din_i ) ) ));
</blockquote></li>
<li><blockquote>G ( (ds_ren -&gt; F (not ds_ren)) and ((not ds_ren) -&gt; F ds_ren) )</blockquote></li>
</ol>
</p>
<p>
The first assertion is devised by the verifier. It can be rewritten into
the assertions described in <cite href="VC"/> as:
<blockquote>loop_cntr is always alive</blockquote>
This assertion is true, when we specify some additional preconditions about
the instruction input, as it will be shown in the next subsection.
</p>
<p>
The second and the third
were assigned by the developer in this form
(which is described in <cite href="VC"/>):
<ul>
  <li><prikaz>exclusion indd_inc, indd_dec</prikaz></li>
  <li><prikaz>exclusion set_int, clear_int</prikaz></li>
</ul>
Here we can see that for a developer it is very easy to understand what the
exclusion of signals is.
</p>
<p>
Unfortunately it was not the case of the fifth assertion that was given
by this assignment: <prikaz>alive ds_ren</prikaz>
</p>
<p>
<tt>ds_ren</tt> is the signal, which value determines whether
it is possible to read data. Of course it is very natural to think about
it in such a way that we would like to be always able to see the signal
<tt>ds_ren</tt> enabled (equal to 1) in the future. But is it
true to specify it in a way the designer did? No, because this requirement
strongly depends on instructions which are processed by the processor (coming
from processor input).
But we do not have instructions for the processor encoded in the design.
Therefore if it will always come <prikaz>NOP</prikaz>, then
<tt>ds_ren</tt> signal will be 0 forever. And this is only
one of many possible counterexamples falsifying activeness of
<tt>ds_ren</tt>.
</p>
<p>
The fourth assertion was given by developer in this form:
  <blockquote>exclusion shortcut_en, sel_gpr, sel_din, sel_din_i</blockquote>
It is valid, but it is also very special. This is the
fragment of code of HFE_CORE (<tt>hfe_core.vhd</tt>, version <tt>1.10</tt>):
<pre>
-- Data in bus address decoder     
din_addr_decoder : process(clk,src_addr_i, dst_addr_i,
                           res_wen_reg, acc_wen_reg)
begin
   if clk'event and clk = '1' then
      sel_gpr &lt;= '0';
      sel_din &lt;= '0';
      sel_din_i &lt;= '0';
      shortcut_en &lt;= '0';
      if ( (src_addr_i = dst_addr_i) and
           (res_wen_reg = '1' ) ) or
         -- "shortcut" enable process
      . . .
</pre>
Here you can see that signals <tt>sel_gpr</tt>, <tt>sel_din</tt>,
<tt>sel_din_i</tt> and <tt>shortcut_en</tt> are set by the edge
of clock. But they are not set by signal <tt>reset</tt>. Nevertheless it is not
the fault, because it suffices to initialize the signal at the first
tick of clock. Suppose that formula <prikaz>Frm</prikaz> expresses
mutual exclusion of those four signals. Then the validity of
<prikaz>Frm</prikaz> can be falsified by the run where all four signals are
initialized to 1 (it is possible, because
they are not reset at the beginning of the run). Therefore
we have to create new formula, that exactly corresponds to the
requirement of exclusivity after the first tick of clocks:
<blockquote>(not CLK) U Frm</blockquote>
This formula assumes that signal <prikaz>CLK</prikaz> representing clock
is initialized to 0. This is given as a precondition:
<blockquote>not CLK</blockquote>
</p>
<p>
In this place it is also proper to list some basic preconditions we made
about the system:
<ol>
<li><prikaz>RESET and X G not RESET</prikaz>&ldots; It means that signal
    <prikaz>RESET</prikaz> is 1 only at the first state and then it is 0.
</li>
<li><prikaz>G (( F CLK ) and ( F not CLK ))</prikaz>&ldots; It means
that clock is always changed in future.</li>
<li><prikaz>assert (not CLK)</prikaz>&ldots; It means that clock is
initiated to zero (we do not have to use this precondition always)</li>
</ol>
</p>

As we have continued in trying to prove the assertions, we were continuously
persuaded by model checker, that these assertions are false, if we use such
a small count of preconditions. Therefore we had to enlarge the set of
preconditions according to the counterexample we had got from the
model checker for the given <i>LTL</i> formula.

<h3>More preconditions</h3>
<p>
In the case of <i>LTL</i> formulas number 2, 3 and 4 only first two
preconditions from the given above suffice to show validity of assertions.  In
the case of the first <i>LTL</i> formula we get validity only if we add many
additional (but valid) preconditions.
</p>
<p>
First we have to assign the precondition saying that instruction
<tt>REPI</tt> comes infinitely times. In general it has not to be true,
but we want to verify, that there is no obstacle to correctly increase and
decrease <tt>loop_cntr</tt> in future. The obstacle should not be the
absence of <tt>REPI</tt> instructions, because we know that
<tt>REPI</tt> instructions are the only instructions working with
<tt>loop_cntr</tt> and therefore these instructions are the only possible
source of liveness of <tt>loop_cntr</tt>.
<blockquote>
G F ( (INSTR_IN1[17..10] = 30 and not reg_pc_sel) or <br/>
      (INSTR_IN2[17..10] = 30 and reg_pc_sel) )
</blockquote>
The instruction <tt>REPI</tt> has one argument. If this argument was
always zero, then the <tt>REPI</tt> instruction would not cause
the increase of <tt>loop_cntr</tt> and the assertion would not be true.
Therefore we have to add one more precondition:
<blockquote>
G ( (INSTR_IN1[17..10] = 30 -&gt; INSTR_IN1[7..0]>=2) and<br/>
    (INSTR_IN2[17..10] = 30 -&gt; INSTR_IN2[7..0]>=2) )
</blockquote>
</p>
<p>
Unfortunately it does not suffice for validity of the first assertion.
The reason is the asynchronism of the instruction input (signal buses
<tt>INSTR_IN1</tt> and <tt>INSTR_IN2</tt>). This piece of code is the
only piece, that modifies <tt>loop_cntr</tt>:
<pre>
if reset = '1' then
   loop_cntr        &lt;= (others =&gt; '0');
   ...
elsif clk'event and clk = '1' then
   ...
   if lc_wen='1' then
      loop_cntr &lt;= ALU_RES(7 downto 0) - 1;
   end if;
   if from_loop_ld = '1' then      -- write to loop_cntr
      loop_cntr &lt;= instruction(7 downto 0)-1;
   elsif loop_in_progress = '1' and lc_gtz='1'
         and stop='0' then
      loop_cntr &lt;= loop_cntr - 1;
   end if;
end if;
</pre>
Signal <tt>from_loop_ld</tt> is dependent only on the instruction input
(when <tt>REPI</tt> instruction occurs).
Instruction input is not explicitly synchronized with clock and hence
<tt>REPI</tt> can cause enabling of <tt>from_loop_ld</tt> for so short
time that it is not noticed by the above code synchronized with clock.
</p>
<p>
This would cause invalidity of the first <i>LTL</i> formula. Therefore we have to
add the set of preconditions, which set the synchronism of instruction
input with clock:
<blockquote>
G (X CLK -&gt; CLK)-&gt;(INSTR_IN1[0]&lt;-&gt;X INSTR_IN<i>i</i>[<i>bit</i>])
</blockquote>
where <i>i</i> is the number of the instruction bus (it can be 1 or 2) and
<i>bit</i> is the number of the single bit (it can be from 0 to 17). Therefore
the set of preconditions setting synchronism of instruction bus with clock
contains 36 preconditions.
</p>
<p>
All assertions except for the liveness of <tt>ds_ren</tt> has been found true.
To be able to finish the model checking of single formulas we had to make
the abstraction. We have deleted the content of <prikaz>HFE_ALU</prikaz>.
This abstraction has broken the relation between the present content
of the most of registers and the far history, because <prikaz>HFE_ALU</prikaz>
lies on the circular way of the data through the registers of
<prikaz>HFE</prikaz>.
</p>


<h2>Unified Header FIFO</h2>
<p>
Unified Header FIFO (<prikaz>UHFIFO</prikaz>) is the data queue between
<prikaz>HFE</prikaz> and <prikaz>LUP</prikaz> (Look up Processor).
<prikaz>UHFIFO</prikaz> was verified continuously during the development. The
verifications from year 2003 are not fully reliable because there were some
mistakes in the verification procedures and verifications were not repeated.
The more reliable and interesting verification was the verification of
<prikaz>UHFIFO</prikaz> exported on 22/02/2004 and 18/04/2004.

<h3>Export from 22/02/2004</h3>
This export corresponds to the version 1.1 of <tt>uh_fifo.vhd</tt>
in the new CVS repository.
It is the old version of <prikaz>UHFIFO</prikaz> that had to be redesigned
because of problems connected with two clocks in one design. But from
the simple point of view, when we work on the level of abstraction
where these problems do not occur, this model works well.
</p>
<h4>Basic assignment</h4>
<p>
We have verified this set of assertions:
<ol>
  <li><prikaz>alive ready</prikaz></li>
  <li><prikaz>globally if (ready(conv_integer(unsigned(lup_block)))) then ((hfe_block &lt;&gt; lup_block) or (not write_i))</prikaz></li>
  <li><prikaz>(hfe_block does not change after HFE_RDY=1 until hfe_is_producing=1)  <br/>or (hfe_block does not change forever after HFE_RDY=1)</prikaz></li>
  <li><prikaz>(uh_valid=0 after HFE_RDY=1 until HFE_VALID=1) or
      <br/>(uh_valid=0 forever after HFE_RDY=1)</prikaz></li>
  <li><prikaz>HFE_RDY=1 infinitely-times</prikaz></li>
  <li><prikaz>hfe_is_producing=1 infinitely-times</prikaz></li>
</ol>
</p>
<p>
First two assertions are given by the developer. The others are devised by
the verifier. Rewriting to <i>LTL</i> was not so easy as it could seem. The first
assertion is rewritten to the set of 32 <i>LTL</i> formulas:
<ul>
  <li>16 formulas of the form <prikaz>not (F G ready_<i>i</i>_)</prikaz> &ldots;  it means that <i>i</i>-th bit of <tt>ready</tt> does not stay
  constant 1 in the future.</li>
  <li>16 formulas of the form <prikaz>not (F G not ready_<i>i</i>_)</prikaz>
  &ldots; it means that <i>i</i>-th bit of <tt>ready</tt> does not stay
  constant 0 in the future.</li>
</ul>
The transcription to the 32 formulas instead of the single one is necessary
mainly for the memory complexity reasons.
</p>
<p>
For the purpose of formal verification the second assertion is simplified
so that <tt>lup_block</tt> is substituted by 0 (therefore we verify the
assertion only for one of sixteen possible values of <tt>lup_block</tt>).
It is probably not wrong because cases of the verification for different
values of <tt>lup_block</tt> look very similar. The simplified assertion is
this one:
 <blockquote>
  <prikaz>globally if ready(0) and LUP_ADDR[8..5]=0 then (hfe_block or not write_i)</prikaz>
 </blockquote>
It can be easily rewritten to <i>LTL</i> (some variables are substituted by their
real counterparts in the <i>SMV</i> code):
  <blockquote>
   <prikaz>G ((ready_0_ and LUP_ADDR[8..5]=0) -&gt; (hfe_block_0_ or hfe_block_1_ or hfe_block_2_ or hfe_block_3_ or not (HFE_WEN and hfe_allocated)))</prikaz>
  </blockquote>
</p>
<p>
Third assertion is rewritten to <i>LTL</i> using 8 formulas:
 <ul>
  <li>4 formulas of the form
  <blockquote><prikaz>G ((HFE_RDY and hfe_block_<i>i</i>_)-&gt;
       <br/>((hfe_block_<i>i</i>_ U hfe_is_producing)</prikaz>
       or <prikaz>(G hfe_block_<i>i</i>_)))</prikaz>
  </blockquote>
  where <i>i</i> is the number of bit (from 0 to 3)</li>
  <li>4 formulas of the form
  <blockquote><prikaz>G ((HFE_RDY and not hfe_block_<i>i</i>_)-&gt;
        <br/>(((not hfe_block_<i>i</i>_) U hfe_is_producing)</prikaz>
  or <prikaz>(G not hfe_block_<i>i</i>_)))</prikaz>
  </blockquote>
  where <i>i</i> is the number of bit (from 0 to 3)</li>
 </ul>
</p>

The rest of assertions is rewritten to <i>LTL</i> in this way:
<ul>
  <li><prikaz>G (HFE_RDY -&gt; ((G not uh_valid) or ((not X uh_valid) U hfe_is_producing )))</prikaz></li>
  <li><prikaz>G F HFE_RDY</prikaz></li>
  <li><prikaz>G F hfe_is_producing</prikaz></li>
</ul>

<p>
The assertions 3 and 4 need only the precondition restricting the signal
<tt>RESET</tt> to be valid:
<!--In this place it is proper to list some basic preconditions we made
about the system:-->
<blockquote>
<prikaz>RESET and X G (not RESET)</prikaz>&ldots;This means that signal
  <tt>RESET</tt> is 1 only at the first state and then it is 0.
</blockquote>
</p>

<b>More preconditions</b>
<p>
The rest of assertions needs many more preconditions. These preconditions
model the behavior of inputs (sometimes with regard to outputs). There
is the list of preconditions used in verification of the rest of assertions.
<ul>
  <li><prikaz>G ( (F HFE_CLK) and (F not HFE_CLK) )</prikaz>&ldots;<tt>HFE_CLK=1</tt> infinitely-times and also <tt>HFE_CLK=0</tt> infinitely-times</li>
  <li><prikaz>G ( (F LUP_CLK) and (F not LUP_CLK) )</prikaz>&ldots;<tt>LUP_CLK=1</tt> infinitely-times and also <tt>LUP_CLK=0</tt> infinitely-times</li>
  <li><prikaz>G F (HFE_REQ)</prikaz>&ldots;<tt>HFE_REQ=1</tt> infinitely-times</li>
  <li><prikaz>G F (LUP_SR_CLEAN)</prikaz>&ldots;<tt>LUP_SR_CLEAN=1</tt> infinitely-times</li>
  <li><prikaz>G (HFE_RDY -&gt; F not HFE_REQ)</prikaz>&ldots;After enabling of <tt>HFE_READY</tt>, <tt>HFE_REQ</tt> will be disabled</li>
  <li><prikaz>G (LUP_SR_VALID -&gt; F LUP_SR_CLEAN )</prikaz>&ldots;There comes <tt>LUP_SR_CLEAN=1</tt> after <tt>LUP_SR_VALID=1</tt></li>
  <li>This formula is so big that it is better to write it structured:
  <pre>
G (
   ( (LUP_ADDR[5] xor (X LUP_ADDR[5])) or
     (LUP_ADDR[6] xor (X LUP_ADDR[6])) or
     (LUP_ADDR[7] xor (X LUP_ADDR[7])) or
     (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ) -&gt;
   (
    (X not LUP_SR_CLEAN) and
    X (
       ( not ( (LUP_ADDR[5] xor (X LUP_ADDR[5])) or
               (LUP_ADDR[6] xor (X LUP_ADDR[6])) or
               (LUP_ADDR[7] xor (X LUP_ADDR[7])) or
               (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ))
       U LUP_SR_CLEAN
      )
   )
  );
</pre>
  After change of LUP_ADDR there is no further change of LUP_ADDR until
  LUP_SR_CLEAN=1. The only magic about this formula are the positions
  of <prikaz>X</prikaz> operators.
  </li>
  <li><prikaz>G F ( (LUP_ADDR[5] xor (X LUP_ADDR[5])) or <br/>
                    (LUP_ADDR[6] xor (X LUP_ADDR[6])) or <br/>
            (LUP_ADDR[7] xor (X LUP_ADDR[7])) or <br/>
            (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ) <br/></prikaz>
      &ldots; <tt>LUP_ADDR[8..5]</tt> is not constant</li>
  <li><prikaz>LUP_ADDR[8..5]=0</prikaz>
      &ldots; <tt>LUP_ADDR[8..5]</tt> is initialized to zero</li>
  <li><prikaz>hfe_block_0_=0 and hfe_block_1_=0 and hfe_block_2_=0 and hfe_block_3_=0</prikaz>
      &ldots; <tt>hfe_block</tt> is initialized to zero</li>
  <li><prikaz>G ((LUP_ADDR[8..5]=<i>x</i>) -&gt; X( (LUP_ADDR[8..5]=<i>x</i>) or (LUP_ADDR[8..5]=<i>y</i>)  ) )</prikaz>, where <i>x</i> is a value from 0 to 15 and <i>y</i><tt>=</tt><i>x</i><tt>+1 mod 16</tt> &ldots; <tt>LUP_ADDR[8..5]</tt> can only be the constant or it can increase (except for the overflow, of course)</li>
  <li><prikaz>G (((X HFE_CLK) -&gt; HFE_CLK) -&gt; ((HFE_REQ&lt;-&gt;X HFE_REQ)))</prikaz>&ldots;<tt>HFE_REQ</tt> is synchronized with clock of <prikaz>HFE</prikaz></li>
  <li><prikaz>G (((X LUP_CLK) -&gt; LUP_CLK) -&gt; ((LUP_SR_CLEAN&lt;-&gt;X LUP_SR_CLEAN)))</prikaz> &ldots;<tt>LUP_SR_CLEAN</tt> is synchronized with clock of <prikaz>LUP</prikaz></li>
</ul>
</p>

<h3>Export from 18/04/2004</h3>
<p>
This is absolutely new implementation of <prikaz>UHFIFO</prikaz> implemented
using component <prikaz>DP_REGFLAGS</prikaz> = <prikaz>Dual Ported Register of
Flags</prikaz>. We want to verify the same properties as in the case of
the previous implementation. Fortunately inner signals used in formulas
remained unchanged. Therefore it is possible to simply run the verification
with the same formulas and preconditions as in the previous implementation.
</p>
<p>But if you simply repeat the verification in the same way as above it
will not finish because of high memory complexity. There is not any
other way than that of making changes inside of <i>VHDL</i> code. We have decided
to shrink the length of FIFO to only 4 items. Of course, this modification
may cause that the formula which is valid for the modified code would not
be valid for the original one, but it is the matter of good reasoning of
the verifier to choose formulas, which are valid equivalently in both designs.
Formal proof of this equality would be hard and a lot of time consuming.
</p>
<p>
There are <i>LTL</i> formulas for the shrunk <prikaz>UHFIFO</prikaz>:
<ol>
  <li><ul>
    <li>4 formulas of the form <prikaz>not (F G ready_<i>i</i>_)</prikaz>
    &ldots;  it means that <i>i</i>-th bit of <tt>ready</tt> does not stay
    constant 1 in the future.</li>
    <li>4 formulas of the form <prikaz>not (F G not
    ready_<i>i</i>_)</prikaz> &ldots; it means that <i>i</i>-th bit of
    <tt>ready</tt> does not stay constant 0 in the future.</li>
      </ul>
  </li>
  <li><prikaz>G ((ready_0_ and (LUP_ADDR[8..7]=0)) -&gt; (hfe_block_0_ or hfe_block_1_ or not (HFE_WEN  and  hfe_allocated)))</prikaz></li>
  <li>
      <ul>
       <li>2 formulas of the form <prikaz>G ((HFE_RDY and
       hfe_block_<i>i</i>_)-&gt;((hfe_block_<i>i</i>_ U hfe_is_producing) or (G
       hfe_block_<i>i</i>_)))</prikaz> where <i>i</i> is the number of bit
       (from 0 to 1)</li>
       <li>2 formulas of the form <prikaz>G ((HFE_RDY and not
       hfe_block_<i>i</i>_)-&gt;(((not hfe_block_<i>i</i>_) U hfe_is_producing)
       or (G not hfe_block_<i>i</i>_)))</prikaz> where <i>i</i> is the
       number of bit (from 0 to 1)</li>
      </ul>
  </li>
  <li><prikaz>G (HFE_RDY -&gt; ((G not uh_valid) | ((not X uh_valid) U hfe_is_producing )))</prikaz></li>
  <li><prikaz>G F HFE_RDY</prikaz></li>
  <li><prikaz>G F hfe_is_producing</prikaz></li>
</ol>
</p>

<p>
There are preconditions for the shrunk <prikaz>UHFIFO</prikaz>:
<ul>
  <li><prikaz>RESET and X G (not RESET)</prikaz></li>
  <li><prikaz>G ( (F HFE_CLK) and (F not HFE_CLK) )</prikaz></li>
  <li><prikaz>G ( (F LUP_CLK) and (F not LUP_CLK) )</prikaz></li>
  <li><prikaz>G F (HFE_REQ)</prikaz></li>
  <li><prikaz>G F (LUP_SR_CLEAN)</prikaz></li>
  <li><prikaz>G (HFE_RDY -&gt; F not HFE_REQ)</prikaz></li>
  <li><prikaz>G (LUP_SR_VALID -&gt; F LUP_SR_CLEAN )</prikaz></li>
  <li>
  <pre>
G (
   ( (LUP_ADDR[7] xor (X LUP_ADDR[7])) or
     (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ) -&gt;
   (
    (X not LUP_SR_CLEAN) and
    X (
       ( not ( (LUP_ADDR[7] xor (X LUP_ADDR[7])) or
               (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ))
       U LUP_SR_CLEAN
      )
   )
  );
</pre>
  </li>
  <li><prikaz>G F ( (LUP_ADDR[7] xor (X LUP_ADDR[7])) or <br/>
            (LUP_ADDR[8] xor (X LUP_ADDR[8]))  ) </prikaz>
      </li>
  <li><prikaz>LUP_ADDR[8..7]=0</prikaz></li>
  <li><prikaz>hfe_block_0_=0 and hfe_block_1_=0 and hfe_block_2_=0 and hfe_block_3_=0</prikaz></li>
  <li><prikaz>G ((LUP_ADDR[8..7]=<i>x</i>) -&gt; X( (LUP_ADDR[8..7]=<i>x</i>) or (LUP_ADDR[8..7]=<i>y</i>)  ) )</prikaz>, where <i>x</i> is a value from 0 to 3 and <i>y</i><tt>=</tt><i>x</i><tt>+1 mod 4</tt></li> 
  <li><prikaz>G (((X HFE_CLK) -&gt; HFE_CLK) -&gt; ((HFE_REQ&lt;-&gt;X HFE_REQ)))</prikaz>&ldots;<tt>HFE_REQ</tt> is synchrinized with clock of <prikaz>HFE</prikaz></li>
  <li><prikaz>G (((X LUP_CLK) -&gt; LUP_CLK) -&gt; ((LUP_SR_CLEAN&lt;-&gt;X LUP_SR_CLEAN)))</prikaz> &ldots;<tt>LUP_SR_CLEAN</tt> is synchronized with clock of <prikaz>LUP</prikaz></li>
</ul>
</p>

<p>The <i>VHDL</i> code of the shrunk <prikaz>UHFIFO</prikaz> is placed in the
<b>Appendix A</b>
The model checking for the shrunk <prikaz>UHFIFO</prikaz> runs relatively
fast.
</p>
<p>
  By the process of verification there have not been found any
  mistakes in the design of <prikaz>UHFIFO</prikaz>, but surprisingly
  the mistakes have been found in <prikaz>LUP</prikaz>, which was
  under development at that time. <prikaz>LUP</prikaz> did not control the part of signals leading to <prikaz>UHFIFO</prikaz>.
  This mistake was found during the search for the possible
  preconditions for <prikaz>UHFIFO</prikaz>. It was not found by
  the model checker, but by verificators during studying of the source code
  of <prikaz>LUP</prikaz>.
</p>

<h2>Statistic Unit</h2>
<p>
Currently there have been verified only properties of the part <prikaz> 
STU_LENGTH</prikaz> of the <prikaz>Statistic Unit</prikaz>, because the part 
for the processing of time stamps has not been implemented yet.
The verification 
of <prikaz>STU_LENGTH</prikaz> has been very specific, because we have focused 
our attention to the mechanism of addressing in this unit.
<prikaz>LBCONN_MEM</prikaz> is accessing the same memory at the same time as the
finite state machine inside <prikaz>STU_LENGTH</prikaz>. Therefore, it is
necessary that the highest bit of the address used by
<prikaz>LBCONN_MEM</prikaz>
and the finite state machine of <prikaz>STU_LENGTH</prikaz> has to be different.
The highest bit of the address is called a bank. <prikaz>LBCONN_MEM</prikaz> sets
the bank used by the finite state machine of <prikaz>STU_LENGTH</prikaz> in
the following way:
  <ol>
    <li><prikaz>LBCONN_MEM</prikaz> sends the special address value via the
        address bus.</li>
    <li>Concurrently with the special address value <prikaz>LBCONN_MEM</prikaz>
        sends a new flag register value and the new bank value is the part
        of the flag register.</li>
  </ol>
It is wanted to verify that the bank stored in <prikaz>STU_LENGTH</prikaz>
is always the inverse of the bank used by <prikaz>LBCONN_MEM</prikaz> for an
access to the memory.
</p>
<h3>The different approaches to the verification</h3>
<p>
The first approach to the verification of this property was very simple.
We took the component <prikaz>STU_LENGTH</prikaz> together with
the component <prikaz>LBCONN_MEM</prikaz> and translated the code
to <i>SMV</i>. But the verification of even the simple properties did not
finish in the time limit. The reason was the complex structure of
<prikaz>LBCONN_MEM</prikaz>.
</p>
<p>
This situation is now solved by the abstraction. The component
<prikaz>LBCONN_MEM</prikaz> has been be deleted. This simple abstraction
would cause invalidity of the property. First we were trying to put
additional preconditions on the signals leading from <prikaz>LBCONN_MEM</prikaz>,
but the set of preconditions was too large, complex and finally even incorrect.
We were not capable to set the sufficiently detailed behavior of
<prikaz>LBCONN_MEM</prikaz> only using the preconditions written in <i>LTL</i>.
Therefore we have created the abstract model of <prikaz>LBCONN_MEM</prikaz> (it
has not been proved that it is correct abstract model, but we believe it) - the
source code of this abstract model can be found in <b>Appendix B</b>.
</p>
<p>
Furthermore it has been given by developer that the clock of <prikaz>LBCONN_MEM
</prikaz> can be at most twice as fast as the clock of <prikaz>STU_LENGTH
</prikaz>. This precondition has played the important role in the verification.
Again it seems too hard to write the formula expressing such a property of
clock.
Therefore the system of clocks has been modeled in <i>SMV</i>:
<pre>
init(LBCLK) := 0;
init(lbclk_count) := 0;
init(CLK) := 0;

if ((LBCLK=0) &amp;&amp; (lbclk_count=2))
  --no lbclk edge when the count of lbclk is high
  aux_lbclk := 0;
else
  aux_lbclk := {0,1};

next(LBCLK) := aux_lbclk;

if (CLK=0 &amp; lbclk_count=0)
  --no clk edge when the count of lbclk is low
  aux_clk := 0;  
else
  aux_clk := {0,1};

next(CLK) := aux_clk;

--computation of lbclk_count:
if (CLK=0 &amp; aux_clk=1)
 {
  if (LBCLK=0 &amp; aux_lbclk=1)
    next(lbclk_count) := lbclk_count;
  else
    next(lbclk_count) := 0;
 }
else
 {
  if (LBCLK=0 &amp; aux_lbclk)
    next(lbclk_count) := lbclk_count + 1;
  else
    next(lbclk_count) := lbclk_count;
 }
</pre>
</p>
<p>
The developer also states that <tt>READY</tt> is enabled at most each 5
ticks of clock. It has been modeled in <i>SMV</i> this way:
<pre>
init(READY) := 0;
init(delay_ready) := 0;

delay_ready_decrease := {0,1};
if (CLK=0 &amp; aux_clk=1)
 {
  if (delay_ready~=0)
   {
    if (delay_ready_decrease)
      { next(delay_ready) := delay_ready - 1; }
    else { next(delay_ready) := delay_ready; }
    next(READY) := 0;        --while waiting producing 0
   }
  else
   {
    --after at most 5 ticks it decides to produce 1:
    next(delay_ready) := 5;
    next(READY) := 1;
   }
 }
else { next(READY) := READY; }
</pre>
</p>
<p>
The <i>LTL</i> property, which has been verified in the system with the above modifications, is the following:
<blockquote>
<prikaz>G (not en_reg_5 and (reg_phase_1_ or reg_phase_2_ or reg_phase_3_ or reg_phase_4_)  -&gt;<br/>(not reg_addr_out_8_ &lt;-&gt; br_addr_lb_9_))</prikaz>
</blockquote>
</p>
<p>
To prove it we only need these two basic preconditions:
<ul>
  <li><prikaz>RESET and (X G not RESET)</prikaz>&ldots; This means that signal
      <prikaz>RESET</prikaz> is 1 only at the first state and then it is 0.
      </li>
  <li><prikaz>(G F CLK) and (G F not CLK)</prikaz>&ldots; This means
      that clock is always changed in future.</li>
</ul>
</p>
<p>
Take notice that the source code of abstract model of
<prikaz>LBCONN_MEM</prikaz> in <b>Appendix B</b> contains the variable
<tt>delay</tt>, which sets the speed of abstract model of
<prikaz>LBCONN_MEM</prikaz>.  The <tt>delay</tt> is set to 8 ticks of
<tt>LB_CLK</tt>. If it was less than 8 ticks, the design would be incorrect,
because <prikaz>LBCONN_MEM</prikaz> would be able to read from the address with
new bank earlier than <prikaz>STU_LENGTH</prikaz> would be able to finish the
writing operation to the address with the old bank.  Therefore the conflict
would be possible. In fact this way it has been shown that
<prikaz>LBCONN_MEM</prikaz> may change its outputs at most each 8 ticks of
<tt>LB_CLK</tt>. There arises the new task for a verification of
<prikaz>LBCONN_MEM</prikaz>.
</p>
<p>
There has been also verified the property of the phase register, which says, that
any of bits of the phase register does not remain a zero forever. Expressed in
<i>LTL</i> as:
<blockquote>
<prikaz>not F G reg_phase_<i>i</i>_ = 0</prikaz> &ldots; where <i>i</i> is
the index of the bit in the phase register.
</blockquote>
There is only needed one more precondition (together with two above):
<blockquote>
 <prikaz>G F READY</prikaz> &ldots; <tt>READY</tt> is infinitely-times 1
</blockquote>
</p>

<h1>Conclusion</h1>
<p>
In this paper it has been shown that in the complex formal verification we have to
use techniques which are not absolutely formal. For example in
the verification of <prikaz>UHFIFO</prikaz> a shrunk model was used 
without any proof of equality of <i>LTL</i> formulas in the shrunk and in
the original model. This is because of the lack of time for the verification.
If the verification was finished one year after the design it would be
useless.
</p>
<p>
It has been also shown that the fight with the state explosion problem may be not always
successful. When it is successful, it is often in spite of the price of large
changes in the model. It was found out that the space complexity
is not directly dependent on the length of source code or the count of
registers. By the virtue of <prikaz>cone of influence</prikaz> it more
depends on the complexity of an <i>LTL</i> formula and the variables which appear
in the formula (including the variables which affect the value of these
variables).
</p>
<p>
On one hand we have gained the pessimistic results, because we had to do
many changes in the design and write large amounts of preconditions
ourselves. It took a lot of time and human resources. On the other hand
we have shown that even using such simple freeware verification tool
as <b>Cadence SMV</b> it is possible to verify the large amount of
complex properties of hardware components.
</p>

<!-- tomasovu cast doporucuju jeste projet ispelem -->

<h1>Appendix A - the source code of shrunk UHFIFO</h1>

<pre>
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library unisim;
use unisim.all;

entity UH_FIFO is
   port(
      -- HFE interface 
      HFE_DOUT   : in std_logic_vector(15 downto 0);
      HFE_ADDR   : in std_logic_vector(5 downto 0);
      HFE_RDY    : out std_logic;   -- Control signals
      HFE_REQ    : in std_logic;
      HFE_WEN    : in std_logic;
      HFE_CLK    : in std_logic;
     
      -- LUP interface
        -- whether cell contains unfied header:
      LUP_SR_VALID    : out std_logic;
         -- clean addressed cell:
      LUP_SR_CLEAN    : in  std_logic;
      LUP_DATA        : out std_logic_vector(31 downto 0);
      LUP_ADDR        : in  std_logic_vector(8 downto 0); 
      LUP_CLK         : in std_logic;
      
      RESET      : in std_logic
   );
end UH_FIFO;

architecture behavioral of UH_FIFO is

signal hfe_block        : std_logic_vector(1 downto 0);
signal hfe_block_aux    : std_logic_vector(1 downto 0);
signal ready            : std_logic_vector(3 downto 0);
signal reg_ready        : std_logic_vector(3 downto 0);
signal hfe_allocated    : std_logic;
signal addra_i          : std_logic_vector(9 downto 0);
signal write_i          : std_logic;
signal uh_valid         : std_logic;
signal hfe_is_producing : std_logic;
signal hfe_rdy_i        : std_logic;

signal lup_block        : std_logic_vector(1 downto 0);

signal gnd_bus          : std_logic_vector(31 downto 0);
signal gnd              : std_logic;
signal pwr              : std_logic;
   
component RAMB16_S18_S36
   port (
      ADDRA: IN std_logic_vector(9 downto 0);
      ADDRB: IN std_logic_vector(8 downto 0);
      DIA:   IN std_logic_vector(15 downto 0);
      DIB:   IN std_logic_vector(31 downto 0);
      DIPA:  IN std_logic_vector(1 downto 0);
      DIPB:  IN std_logic_vector(3 downto 0);
      WEA:   IN std_logic;
      WEB:   IN std_logic;
      CLKA:  IN std_logic;
      CLKB:  IN std_logic;
      SSRA:  IN std_logic;
      SSRB:  IN std_logic;
      ENA:   IN std_logic;
      ENB:   IN std_logic;
      DOA:   OUT std_logic_vector(15 downto 0);
      DOB:   OUT std_logic_vector(31 downto 0);
      DOPA:  OUT std_logic_vector(1 downto 0);
      DOPB:  OUT std_logic_vector(3 downto 0));
END component;

component dp_regflags
   generic(
      EXADDR   : integer
   );
    port(
      RESET    : in  std_logic;
      
      -- SET part
      CLK_SET  : in  std_logic;
      SET      : in  std_logic;
      ADDR_SET : in  std_logic_vector(EXADDR-1 downto 0);
      DO_SET   : out std_logic;

      -- CLR part
      CLK_CLR  : in  std_logic;
      CLR      : in  std_logic;
      ADDR_CLR : in  std_logic_vector(EXADDR-1 downto 0);
      DO_CLR   : out std_logic;

      DO_ALL   : out std_logic_vector((2**EXADDR)-1 downto 0)
    );
end component;


begin


gnd_bus &lt;= "00000000000000000000000000000000";
gnd &lt;= '0';
pwr &lt;= '1';

lup_block &lt;= LUP_ADDR(8 downto 7);  --PP

addra_i &lt;= hfe_block &amp; "00" &amp; HFE_ADDR; --PP
write_i &lt;= HFE_WEN and hfe_allocated;

HFE_RDY &lt;= hfe_rdy_i;

hfe_communication:process(HFE_CLK, RESET)
begin
   if reset = '1' then 
      hfe_rdy_i        &lt;= '0';
      hfe_allocated    &lt;= '0';
      hfe_is_producing &lt;= '0';
      hfe_block        &lt;= "00"; --PP
      hfe_block_aux    &lt;= "00"; --PP
      uh_valid         &lt;= '0';
   elsif HFE_CLK'event and HFE_CLK = '1' then
      uh_valid  &lt;= '0';
      hfe_rdy_i &lt;= '0';
      if HFE_REQ='1' then
         if hfe_is_producing='1' then
            uh_valid         &lt;= '1';
            hfe_block        &lt;= hfe_block+1;
            hfe_is_producing &lt;= '0';
            hfe_allocated    &lt;= '0';
         elsif reg_ready(conv_integer(unsigned(
	                                 hfe_block)))='0' then
            hfe_rdy_i     &lt;= '1';
            hfe_allocated &lt;= '1';
            hfe_block_aux &lt;= hfe_block;
         end if;
      elsif hfe_allocated='1' then
         hfe_is_producing&lt;='1';
      end if;
   end if;
end process;

reg_ready_proc: process(HFE_CLK,RESET)
begin
   if reset='1' then
      reg_ready &lt;= (others =&gt; '0');
   elsif HFE_CLK'event and HFE_CLK='1' then
      reg_ready &lt;= ready;
   end if;
end process;

block_ram: RAMB16_S18_S36 port map(
      ADDRA =&gt; addra_i,
      ADDRB =&gt; LUP_ADDR,
      DIA   =&gt; HFE_DOUT,
      DIB   =&gt; gnd_bus,
      DIPA  =&gt; gnd_bus(1 downto 0),
      DIPB  =&gt; gnd_bus(3 downto 0),
      WEA   =&gt; write_i,
      WEB   =&gt; gnd,
      CLKA  =&gt; HFE_CLK,
      CLKB  =&gt; LUP_CLK,
      SSRA  =&gt; gnd,
      SSRB  =&gt; gnd,
      ENA   =&gt; pwr,
      ENB   =&gt; pwr,
      DOA   =&gt; open,
      DOB   =&gt; LUP_DATA,
      DOPA  =&gt; open,
      DOPB  =&gt; open
);

flags: dp_regflags 
generic map( 
   EXADDR =&gt; 2 --PP
)
port map(
   RESET       =&gt; RESET,
   
   -- SET part
   CLK_SET     =&gt; HFE_CLK,
   SET         =&gt; uh_valid,
   ADDR_SET    =&gt; hfe_block_aux,
   DO_SET      =&gt; open,

   -- CLR part
   CLK_CLR     =&gt; LUP_CLK,
   CLR         =&gt; lup_sr_clean,
   ADDR_CLR    =&gt; lup_block,
   DO_CLR      =&gt; LUP_SR_VALID,

   DO_ALL      =&gt; ready
);


end behavioral;

</pre>

<h1>Appendix B - the source code of abstract model of LBCONN_MEM</h1>

<pre>
module \lbconn_mem_524288_13_notri (
\ADDR ,\nx1653 ,\LBLAST ,\nx1797 ,\nx1603 ,\NOT_lb_oen ,
\LBFRAME_modgen_select_12 , \data_in_reg_0_ ,\DATA_IN ,
\data_in_reg_1_ ,\data_in_reg_2_ ,\data_in_reg_3_ ,
\data_in_reg_4_ ,\data_in_reg_5_ ,\data_in_reg_6_ ,
\data_in_reg_7_ ,\data_in_reg_8_ ,\data_in_reg_9_ ,
\data_in_reg_10_ ,\data_in_reg_11_ ,\data_in_reg_12_ ,
\data_in_reg_13_ ,\data_in_reg_14_ ,\data_in_reg_15_ ,
\DATA_OUT ,\LBAD ,\RW ,\LBAS_modgen_select_11 ,\LBRW ,
\EN ,\LBCLK , LBCLK_NEXT ,\RESET ,\ARDY_modgen_select_6 ,
\SEL ,\DRDY ){
output \ADDR  : array 12..0 of boolean resolve;
\nx1653  : boolean resolve;
input \LBLAST  : boolean resolve;
\nx1797  : boolean resolve;
\nx1603  : boolean resolve;
\NOT_lb_oen  : boolean resolve;
input \LBFRAME_modgen_select_12:array 9..9 of boolean resolve;
\data_in_reg_0_  : boolean resolve;
input \DATA_IN  : array 15..0 of boolean resolve;
\data_in_reg_1_  : boolean resolve;
\data_in_reg_2_  : boolean resolve;
\data_in_reg_3_  : boolean resolve;
\data_in_reg_4_  : boolean resolve;
\data_in_reg_5_  : boolean resolve;
\data_in_reg_6_  : boolean resolve;
\data_in_reg_7_  : boolean resolve;
\data_in_reg_8_  : boolean resolve;
\data_in_reg_9_  : boolean resolve;
\data_in_reg_10_  : boolean resolve;
\data_in_reg_11_  : boolean resolve;
\data_in_reg_12_  : boolean resolve;
\data_in_reg_13_  : boolean resolve;
\data_in_reg_14_  : boolean resolve;
\data_in_reg_15_  : boolean resolve;
output \DATA_OUT  : array 15..0 of boolean resolve;
input \LBAD  : array 15..0 of boolean resolve;
\RW  : boolean resolve;
input \LBAS_modgen_select_11:array 9..9 of boolean resolve;
input \LBRW  : boolean resolve;
\EN  : boolean resolve;
input \LBCLK  : boolean resolve;
input LBCLK_NEXT : boolean resolve;
input \RESET  : boolean resolve;
input \ARDY_modgen_select_6:array 9..9 of boolean resolve;
\SEL  : boolean resolve;
input \DRDY  : boolean resolve;

gener_data: array 8..0 of boolean resolve;
bank: boolean resolve;
aux_bank: boolean resolve;
action: array 2..0 of boolean resolve;
aux_action: array 2..0 of boolean resolve;
delay: array 4..0 of boolean resolve;

 init(bank) := 1;
 init(action) := 0;
 init(gener_data) := 0;
 init(DATA_OUT) := 1;
 init(RW) := 0;
 init(delay) := 0;
 
 if (LBCLK=0 &amp;&amp; LBCLK_NEXT=1)
  {
   if (delay~=0)
    {
     next(delay) := delay - 1;
     next(DATA_OUT) := DATA_OUT;
     next(action) := action;
     next(gener_data) := gener_data;
     next(bank) := bank;
     next(RW) := RW;
    }
   else
    {
     next(delay) := 5;
     next(DATA_OUT[0]) := {0,1};
     next(DATA_OUT[2])  := {0,1};
     next(DATA_OUT[3])  := {0,1};
     next(DATA_OUT[4])  := {0,1};
     next(DATA_OUT[5])  := {0,1};
     next(DATA_OUT[6])  := {0,1};
     next(DATA_OUT[7])  := {0,1};
     next(DATA_OUT[8])  := {0,1};
     next(DATA_OUT[9])  := {0,1};
     next(DATA_OUT[10]) := {0,1};
     next(DATA_OUT[11]) := {0,1};
     next(DATA_OUT[12]) := {0,1};
     next(DATA_OUT[13]) := {0,1};
     next(DATA_OUT[14]) := {0,1};
     next(DATA_OUT[15]) := {0,1};
     aux_action[0] := {0,1};
     aux_action[1] := {0,1};
     aux_action[2] := {0,1};
     if (aux_action &gt; 5) { next(action) := 0; }
     else { next(action) := aux_action; }
     if (aux_action = 5)
      {
       next(gener_data) := 0;
       aux_bank := {0,1};
       next(bank) := aux_bank;
       next(DATA_OUT[1]) := !aux_bank;
       next(RW) := 1;
      }
     else
      {
       next(gener_data[0])  := {0,1};
       next(gener_data[1])  := {0,1};
       next(gener_data[2])  := {0,1};
       next(gener_data[3])  := {0,1};
       next(gener_data[4])  := {0,1};
       next(gener_data[5])  := {0,1};
       next(gener_data[6])  := {0,1};
       next(gener_data[7])  := {0,1};
       next(gener_data[8])  := {0,1};
       next(DATA_OUT[1])  := {0,1};
       next(bank) := bank;
       next(RW) := 0;
      }
    }
  }
 else
  {
   next(DATA_OUT) := DATA_OUT;
   next(bank) := bank;
   next(RW) := RW;
   next(gener_data) := gener_data;
   next(action) := action;
  }

ADDR := action::(bank &amp; !RW)::gener_data;
EN := 1;
SEL := 1;

}
</pre>

<!-- References -->
  <seznamknih>
    <kniha id="FormalVHDL">
      J. Holeček, T. Kratochvíla, V. Řehák, D. Šafránek, and P. Šimeček:
      <i>How to Formalize a FPGA Hardware Design.</i><br/>
      Technical report number 4/2004, CESNET, 2004.
    </kniha>

    <kniha id="VerifVHDLCombo6"> <!--viz bibtex v leb. knihovne - POUZITO -->
      T. Kratochvíla, V. Řehák, P. Šimeček:
      <i>Verification of COMBO6 VHDL Design.</i><br/>
      Technical report number 17/2003, CESNET, 2003.      
    </kniha>

    <kniha id="VHDLScampi">
      Vladimir Smotlacha:
      <i>Design of the VHDL structure of SCAMPI adapter.</i><br/>
      <tt>http://www.liberouter.org/cgi-bin2/cvsweb.cgi/
      <br/>liberouter/vhdl_design/projects/scampi_ph1/doc/
      <br/>VHDL_structure.ps</tt>
    </kniha>

    <kniha id="EditEngine">
      Tomáš Martínek:
      <i>Basic documentation of Edit Engine.</i><br/>
      <tt>http://www.liberouter.org/cgi-bin2/cvsweb.cgi/<br/>liberouter/vhdl_design/units/ee/doc/</tt>
    </kniha>

    <kniha id="LibWWW">
      Liberouter:      
      <i>Liberouter Project WWW Pages.</i><br/> 
      <tt>http://www.liberouter.org/</tt>
    </kniha>

    <kniha id="Nov04">
    Novotný J., Fučík O., Antoš D.:
    <i>Project of IPv6 Router with FPGA Hardware Accelerator.</i><br/>
    In Proceedings of Field-Programmable Logic and Applications: 
    13th International Conference FPL 2003, page 964-967, Springer Verlag, 
    2003. ISBN 3-540-40822-3.
    </kniha>

    <kniha id="SMV">
      Cadence SMV:
      <i>Cadence SMV WWW Pages.</i><br/> 
      <tt>http://www-cad.eecs.berkeley.edu/&vlnka;kenmcmil/smv/</tt>       
    </kniha>

    <kniha id="VC">
      Tomáš Kratochvíla:
      <i>Verification cookbook (Liberouter policy WWW Pages).</i><br/>
      <tt>http://www.liberouter.org/policy.html</tt>
    </kniha>

    <kniha id="VHDL">
      Ashenden Peter J.:
      <i>The VHDL Cookbook.</i><br/>
      <tt>http://tech-www.informatik.uni-hamburg.de/<br/>vhdl/doc/cookbook/VHDL-Cookbook.pdf</tt>
    </kniha>

  </seznamknih>


</zprava>
