VHDL library of ProASIC3 gates

Hard macros and "tiles" of Actel/Microsemi's ProASIC3 so I can design compatible and optimised code without the proprietary libraries

Similar projects worth following
This is a collection of VHDL files that re-implement the gates of a FPGA family, which is close to ASIC structures and that I use to evaluate ASICs.

Actel/Microsemi/Microchip provides official definitions and delays for very accurate simulation but these are proprietary files and I don't need such a precision at the early stages of prototyping.

I replace these files with mine so I can make truly Free and Open Source designs, which can later be ported to ASIC technology.

This is a work in progress that gets updates when needed by my designs, please forgive the many holes.

The VHDL code is portable '93 but only GHDL scripts (not mcode) are provided.

This project is "more or less related" to  #Shared Silicon  and aims to better prepare and prototype designs in FPGA before committing to ASIC tapeout. I'm currently using this library for the #YGREC8

Lately, Christos joined forces and opened new perspectives and applications for this library, for test/validation/fuzzing through the injection of faults. It enables the verification of test benches and other critical tools, for fault-tolerant circuits, wafer-stepper test vectors...

Currently I'm working on the 2nd version of the library.

From the README.txt :


This is a "Free" collection of 3-input gates and some additional ProASIC3-specific modules, used to design my processors.

See the license/ directory for the AGPLv3 terms of distribution.

The proasic3/ directory contains all the gates and modules, rewritten to simulate the real tiles and hard macros.

It depends on the delay/ directory that defines a propagation time for all the tiles.

You'll find an example in the INC8/ directory, that implements an 8-bits increment unit using only 3-inputs gates and with a well-defined latency.


As of 20190819, the v2 supports these tiles and hard macros:



and2    and2a   and2b   nand2   nand2a  nand2b  nor2    nor2a   nor2b   or2     or2a    or2b    xnor2   xor2

and3    and3a   and3b   and3c   ao1     ao12    ao13    ao14    ao15    ao16    ao17    ao18    ao1a    ao1b    ao1c    ao1d    ao1e    aoi1    aoi1a   aoi1b   aoi1c   aoi1d   aoi5    ax1     ax1a    ax1b    ax1c    ax1d    ax1e    axo1    axo2    axo3    axo5    axo6    axo7    axoi1   axoi2   axoi3   axoi4   axoi5   axoi7   maj3    maj3x   maj3xi  min3    min3x   min3xi  mx2     mx2a    mx2b    mx2c    nand3   nand3a  nand3b  nor3    nor3a   nor3b   nor3c   oa1     oa1a    oa1b    oa1c    oai1    or3     or3a    or3b    or3c    xa1     xa1a    xa1b    xa1c    xai1    xai1a   xo1     xo1a    xor3    xnor3   zor3    zor3i

DFN0     DFN1     DFI0     DFI1    
DFN0C0   DFN1C0   DFI0C0   DFI1C0  
DFN0C1   DFN1C1   DFI0C1   DFI1C1
DFN0E0   DFN1E0   DFI0E0   DFI1E0
DFN0E1   DFN1E1  ...

Read more »


Many enhancements ! meta-levels and other goodies...

x-compressed-tar - 32.71 kB - 08/13/2019 at 21:59



GND/VCC + "non-binary" logic cone detection

x-compressed-tar - 7.66 kB - 08/11/2019 at 15:42



now with sequential gates

x-compressed-tar - 6.75 kB - 08/10/2019 at 21:47



a better working version of the new system

x-compressed-tar - 6.61 kB - 08/09/2019 at 20:24



incomplete preview of the new system, for debugging only

x-compressed-tar - 3.51 kB - 08/09/2019 at 04:19


View all 10 files

  • Typo...

    Yann Guidon / YGDESa day ago 0 comments

    While reviewing and re-checking the gates versus the handbook, I finally spotted that I made a mistake with xo6 which is in fact axo6. This is fixed in the next release, along with a couple of missing gates. The latches are not included yet though.

    I try to focus on packaging, integration and testing, though the perspective of v3 is alluring and I try to clear the path towards this even better system.

  • v2.1

    Yann Guidon / YGDES4 days ago 0 comments

    The v2 is already a significant breakthrough but instead of packaging/testing/integrating, I consider adding even more powerful features, in particular to provide an even better function ! I don't want to merely check if/how test vectors cover a design, now I want to generate these test vectors !

    I have the stem of the algorithm but the system requires some more "updates" and I have to solve some thorny VHDLities : so many things are possible AND impossible, it's sometimes like a maze...

    Anyway, I now add a "hidden port" to ALL the gates, to allow automatic discovery of the DUT's netlist, which is one of the required features to build the TVG algorithm.

    Update : in fact, no need of a hidden port, I might have found a more elegant solution. We'll see when v2 is operational.

  • v2 beta needs tests !

    Yann Guidon / YGDES08/13/2019 at 22:25 0 comments

    There's a new archive and it's amazing !



    Where do I start ...

    So now it has all the DFx gates (64 of them !), all the logic gates (1, 2 and 3-inputs macros) and and... oh well, POWERFUL features to probe and analyse a circuit...

    You get BOTH the "fast" (simple) gates and the "trace" versions, and you can select which gate will be logged. Either use a "VHDL configuration" or change the source code to affect an architecture to selected gates !

    The "fast" cells are just like the previous version. Fast and simple.

    The "trace" cells have the same function BUT also support multi-values signals ! The '0'/'1' levels are the basic "binary" system, but if at least one output is 'L' or 'H', then the output will adopt the 'L'/'H' levels ! And any other input value will be copied to the output and propagated to the rest of the circuit.

    All the cells (except for now the DFF) work with a lookup table and the testbench can alter one bit of one the lookup table.

    • In "alter" mode, the selected bit is flipped and the selected gate's function is changed. This is useful to verify that your BIST or test vector can catch ALL possible faults (not just stuck or broken wires).
    • In "trace" mode, the selected LUT bit is not flipped but changed from '0'/'1' binary level to 'L'/'H' meta level, to observe the effect of this given LUT entry over the output(s).

    A few features are still missing, for example we can't change the LUT when the simulation is started... DFFs are not alterable yet, either, but it's not critical.

    Many tools, tests and examples shoud be written but this release is really a game-changer !!! Download it and try it !

  • v2 with sequential gates

    Yann Guidon / YGDES08/10/2019 at 21:50 0 comments

    I added the code to generate all the 15 DFN1* gates.


    lt needs some more polishing and some gates are still missing but it's just a few days of work...

    I'm already wondering how I will implement the alteration of the DFFs.

  • early success with v2

    Yann Guidon / YGDES08/10/2019 at 14:51 0 comments

    The system starts to work !

    With the most fundamental problems "mostly solved", I can see my new code working in a promising manner.

    Here is the new README.txt :

    file README.txt
    created sam. août 10 16:03:22 CEST 2019
    WHAT :
    The new version of the PA3 gates library is more compact
    and provides much more insight into the logic's dynamic behaviour.
    Configuration relies a lot on the runtime generics option of the
    recent GHDL simulator, with the -g command line parameter.
    WHY :
    This tool enhances the classic ProASIC3 gates library
    for design verification and "Design For Test".
    It helps build test vectors and prove they can catch all the possible faults.
    It also helps ensure that a complex boolean function has
    no "blind spot" with unused intermediary combinations.
    A non-boolean value can be injected and propagated through
    the logic gates, to highlight the "logic cone" of the circuit,
    which can greatly help during debug/development.
    HOW :
    The provided script generates the big files with all
    the definitions, then runs a couple of tests (three XOR2 chained)
    as a self-test as well as demonstration of the use of the
    new extra features of this library.
    * VHDL source code only needs to include :
    Library proasic3;
        use proasic3.all;
    (just like before)
    * The top level simulation file must include these 2 generics :
      generic (
        gate_select_number: integer := 0;
        bit_select_number: integer := -1
    The default values do nothing, but when they are changed,
    the selected gate is affected/altered.
    These values can be changed post-elaboration by GHDL's command line.
    * A clock signal is required for sampling the gates' states
    (avoiding false results due to transients)
      signal clock : std_logic := '0';
    * The clock and the generics are fed into an entity
    that does some of the dirty work behind the scene:
      rg: entity register_generics port map(
           gate_select_number => gate_select_number,
           bit_select_number => bit_select_number,
           clock => clock);
    When "clock" changes to value '1' then the values of all the detected gates
    are sampled and the histogram is updated.
    The histogram is shown when  "clock" changes to value 'X'.
    TODO :
      - "fast" option without instrumentation
      - sequential gates
      - tiny gates (1 and 0 input)
      - restrict the gates that will be sampled or altered.
      - sed scripts to filter the outputs
    NOFIX :
      - coarse timing (everybody has 1ns latency)
      - 2^31 simulation cycles maximum

    The archive is going live soon...

  • v2 in progress

    Yann Guidon / YGDES08/09/2019 at 20:39 0 comments

    It was not easy but i have a first proof of concept for the code !

    It is far from being the most elegant or efficient but it works. A 2-stages compilation system creates the whole collection of gates and their definitions, the result is provided in the archive in case you can't run the generation script.

    It covers the alteration of a given bit of the lookup table of a given gate. The access works with a number system: the program lists all the alterable gates and provides their path along with an index, that is reused to address the gate. It should be pretty easy to use in a script.

    The delay system should also be redesigned. Probably with real data from the datasheets, though this is pointless without information about the routing delays...

    The sequential gates are missing too, and the smaller gates are still absent...

  • Lookup tables !

    Yann Guidon / YGDES08/08/2019 at 08:55 0 comments

    I finally took the time to write the first code ! And I get the following LUT8s :

     and3 :    10000000
     and3a :   00001000
     and3b :   00000010
     and3c :   00000001
     ao1 :     11101010
     ao12 :    01101101
     ao13 :    11010100
     ao14 :    11010110
     ao15 :    00101001
     ao16 :    01000010
     ao17 :    10000110
     ao18 :    01001101
     ao1a :    10101110
     ao1b :    11010101
     ao1c :    01011101
     ao1d :    10101011
     ao1e :    01010111
     aoi1 :    00010101
     aoi1a :   01010001
     aoi1b :   00101010
     aoi1c :   01010100
     aoi1d :   10101000
     aoi5 :    11100111
     ax1 :     10100110
     ax1a :    01011001
     ax1b :    10101001
     ax1c :    01101010
     ax1d :    01010110
     ax1e :    10010101
     axo1 :    11100110
     axo2 :    01101110
     axo3 :    01110110
     axo5 :    10011101
     xo6 :     10111001
     axo7 :    01100111
     axoi1 :   00011001
     axoi2 :   10010001
     axoi3 :   10001001
     axoi4 :   00100110
     axoi5 :   01100010
     axoi7 :   10011000
     maj3 :    11101000
     nand3 :   01111111
     nand3a :  11110111
     nand3b :  11111101
     nor3 :    00000001
     nor3a :   00010000
     nor3b :   01000000
     nor3c :   10000000
     oa1 :     10101000
     oa1a :    10001010
     oa1b :    01010100
     oa1c :    01000101
     oai1 :    01010111
     or3 :     11111110
     or3a :    11101111
     or3b :    10111111
     or3c :    01111111
     xa1 :     00101000
     xa1a :    10000010
     xa1b :    00010100
     xa1c :    01000001
     xo1 :     10111110
     xo1a :    11101011
     xor3 :    10010110
     xnor3 :   01101001
     zor3 :    10000001
     zor3i :   01111110

    The necessary source code is not as difficult as I imagined, though it requires some method. There are some obvious duplicates but it's a different problem.

    All the code must be re-tested after this rewrite because I have caught a few inconsistencies...

  • Let's generate (most) files

    Yann Guidon / YGDES06/17/2019 at 09:20 0 comments

    If you remember the log What if we generated the files for each gate ?  you know I discarded the idea of generating the gates with a script.

    Well, after a few days of sitting on this setback, I decided that there were enough "low hanging fruits", and the advantages are good enough, to justify writing some code to generate those gates. The trick is to keep the system simple and small enough that it doesn't create more problems than it solves.

    The first change is to create 4 types of combinatorial gates, depending on the number of inputs. The sequential gates (latches, flip-flops) will be ignored for now.

    4 types means there are dealing with 4 sizes of lookup tables : 1, 2, 4 and 8 entries. Ideally we would use only one size (8 entries) and an extra size parameter (stored somewhere) gives the range, or something... but since VHDL arrays already has 'range-related attributes, we can infer the actual type. The perturbation logic would be something like :

    index = Random() mod Table'Length;
    table(index) <= table(index) xor '1';

    The lookup table array is std_logic_vector because it helps with something else : coverage. If one element of the table is set to 'X' then the value will (ideally) propagate to the output, showing that this entry is sensitive to a given test vector. The universal gate must be modified:

    if (a='X') or (b='X') or (c='X') then
        return 'X';
    end if;

    We can go even further because each input gets compared sequentially to create the index :

    variable i : integer := 0;
    if a = '1' then
        index := 1;
        if a /= '0' then
            return a;
        end if;
    end if;

    Then the same code is copy-pasted-modified for b and c, depending on the number of inputs (and names) of the gates.

    Sounds like a plan... 

    Now that we can deal with a flexible size of lookup table, we can define the corresponding type :

      subtype LookupType1  is std_logic_vector( 0 downto 0);
      subtype LookupType2  is std_logic_vector( 1 downto 0);
      subtype LookupType4  is std_logic_vector( 3 downto 0);
      subtype LookupType8  is std_logic_vector( 7 downto 0);

     Then we can sort the gates according to their inputs :

    • no input : GND VCC  (CLKBUFF is an exception with the implicit input from a pin)
    • 1 input : INV CLKINT (CLKINT wouldn't be used in a portable design anyway)
    • 2 inputs :  AND2 AND2A NAND2 NOR2 NOR2A NOR2B OR2 OR2A OR2B NOR2 XNOR2 XOR2 (some functions would be redundant)
    • 3 inputs with modified input signal names :  MX2 MX2A MX2B MX2C


  • What if we generated the files for each gate ?

    Yann Guidon / YGDES06/12/2019 at 00:35 0 comments

    There are about 100 files of the gate_* form. They are quite hard to manage, though the collection has grown organically and slowly... but if we want to modify them globally, it becomes painful and tedious. Errors could creep into the code and be hard to spot...

    Most gates follow a simple pattern : 3 inputs, one output, one boolean function to apply. It seems very easy to script.

    Then, there are some gates with a different naming scheme, such as the MUXx gates. OK, so let's have, for each gate, an array of strings with the names of the input signals.

    Then, there are gates with only 2, 1 (INV) and even 0 inputs (GND...) so a different/smaller lookup function is required.

    And then, there are the sequential gates... Complexity gets out of control because there are many variations that change the code. That part will be a lot harder to script.

    Then there is this crucial question : what language to use ? VHDL is perfectly capable of performing the generation, as it can access files and process character strings. It's good because there would be a single language, and the generation can be performed only once in a while. However it's not the MOST appropriate language. I'd do it in JavaScript if it was easier to use on the command line... C is not a contender and I'm not keen on Python. It would be awkward in bash as well...

  • What about coverage ?

    Yann Guidon / YGDES06/11/2019 at 22:06 0 comments

    As this library exceeds the initial limited scope, new perspectives emerge. It's good to have a library that replicates the historical Actel gates, it's awesome to inject faults, but now, what about we collect stats about the gates activities ?

    Actel/MicroSemi/Microchip already does something similar during simulation to estimate power consumption but my idea is different : IF I'm going to alter a logic gate by 1 bit, then I need to know if this input combination really has a use. IF I can detect that an input combination is not used in practice, it could help simplify the gate for example. And it would also mean that it's useless to alter this bit.

    So it's a "coverage" test, that gathers a histogram of the meaningful input combinations and helps direct test vectors toward rarely-seen cases (while the common cases are usually degenerate and are often covered "along" when the rare cases are tested)

    Testing coverage requires a good testbench that stimulates all the inputs and intermediate signals.

    Then, the testbench runs with all the gates tooled with a histogram (that could saturate at 255 or 64Ki). The trick is to sample these input values when the clock is about to change because the delta cycles will add transients with meaningless values. It makes the implementation harder because we don't want to add an additional clock input to each gate... but VHDL or VHPI can do wonders.

    At each sampling point, the inputs of each gate are collected into a number (0 to 7) that serves as an index into the histogram, where one bin is incremented.

    After the run, the histogram is collected and sorted, lowest bins first : these are the ones that the test vectors must "hit" with one test vector. If possible the test vector also hits more "low bins" to increase efficiency and reduce the number of test vectors (and testing time).

    How a test vector can be created from a given target configuration is not yet easy or examined...


    The list of vectors can then be used to enhance the testbench (or make another, hopefully shorter). Null bins are not used and thus are not tested because they would create a "false fail" condition. However the null bins are useful to detect design defects.

View all 16 project logs

  • 1
    Get and install GHDL

    get it there :

    also read

    Be sure to not use the MCODE version... The GCC and LLVM backends seem to work well.

  • 2

    under Linux :

    tar xzvf A3Ptiles.20190412.tgz
    cd A3P/
  • 3
    Use in your project

    Use the INC8 example to setup your scripts and include the proper paths to the files.

View all 3 instructions

Enjoy this project?



Yann Guidon / YGDES wrote 08/08/2019 at 10:36 point

Damnit I found a wrong declaration for NAND2, with 3 inputs in PA3_components.vhdl :-/

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/02/2018 at 19:24 point


so far, I need the following gates for INC8 :


I haven't looked yet at your library of CMOS cells at #Shared Silicon ...

  Are you sure? yes | no

SHAOS wrote 12/02/2018 at 23:54 point

What is "AX1"? My INV, AND2 and AND3 were "silicon proven"

I have XOR2 and NXOR2 too, but I didn't test them in silicon yet

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2018 at 04:31 point

From the files :

architecture rtl of AX1 is
  Y <= (A and B) xor C after gate_delay;
end rtl;

so it's a XOR2 with one input being the result of AND2. The absence of output buffer of AND2 makes the combined gate faster.

  Are you sure? yes | no

SHAOS wrote 12/03/2018 at 04:34 point

so I guess it could be built out of AND2 and XOR2 then :)

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2018 at 05:11 point

It could but it would use more surface and be slower.

That's why it's interesting to design and analyse the logic with A3P : if you limit yourself to basic gates, you miss some useful optimisations.

This library of cells helps me design tighter circuits and when they are stable and optimised, I can then focus on the CMOS library to implement the required functions (if they are not available yet).

And your role becomes clear at this point ;-)

  Are you sure? yes | no

SHAOS wrote 12/03/2018 at 06:32 point

I don't think custom implementation of AND-XOR will be much smaller or faster of a simple combination of AND and XOR, may be just a little bit... 

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2018 at 12:03 point

This little bit could make a significant difference :-)

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2018 at 12:31 point

the merging saves the space of the intermediate buffer, as well as the interconnect between AND2 and XOR2.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates