Close
0%
0%

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...


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 20190328 I have implemented these tiles and hard macros:

AND2A AND2 AND3A AND3B AND3C AND3 AO1A AO1 AOI1D AX1 AX1A AX1B AX1C AX1D AX1E AXO1 CLKBUFF CLKINT DFN1E1C0 DFN1E1C1 DFN1E1 DFN1 FIFO512x8 INV MAJ3 MX2A MX2C MX2 NAND2 NAND3A NAND3B NAND3 NOR2A NOR2 NOR3A NOR3B NOR3 OA1A OA1B OA1C OR2 OR2A OR3A OR3B OR3 RAM4K9 XA1A XA1 XNOR2 XNOR3 XO1 XOR2 XOR3

as well as an "inferred" dual-port RAM block that matches the A3P chips.

More gates from Christos (20190411):

AO12 AO13 AO14 AO15 AO16 AO17 AO18 AO1B AO1C AO1D AO1E AOI1A AOI1B AOI1C AOI1 AOI5  AXO2 AXO3 AXO5 AXO6 AXO7 AXOI1 AXOI2 AXOI3 AXOI4 AXOI5 AXOI7 DFN1C0 DFN1C1 DFN1E0C0 DFN1E0C1 DFN1E0P0 DFN1E0P1 DFN1E0 DFN1E1P0 DFN1E1P1 DFN1P0 DFN1P1 GND MX2B NOR2B NOR3C OAI1 OR2B OR3C VCC XA1B XA1C XO1A ZOR3I ZOR3

ALL THESE FILES ARE PROVIDED AS IS AND ARE NOT A COMPLETE SUBSTITUTE TO THE OFFICIAL FILES. I DIDN'T TEST MOST OF THEM! USE AT YOUR OWN RISKS!

Check the log 1. definition of the gates for the boolean equations of each gate.


These files are written to help simulate designs optimised for the ProASIC3 family using GHDL without forcing the user to install the Actel/Microsemi toolsuite. Some of my designs (such as the YASEP and YGREC) are written as a behavioural/RTLfile and some parts require architecture-specific versions (for speed !)that must be checked for equivalence with the higher-level description.

I provide the gates used by my own designs but more are also included, "just in case" they are needed.

This library is for convenience, hence accuracy is bad in certain aspects. ALWAYS refer to the latest versions of the files provided by Actel/Microsemi/Microchip !

Why bother ?

The A3P family is quite old and slow by today's standards. It's also a mature family with well understood behaviour but more importantly, as the name implies, it's also very close to ASIC design rules. ASIC design is the real goal.

My design workflow is roughly :

  1. design the general architecture and define the units
  2. design and test individual units in RTL, check functionality
  3. break the unit(s) down to individual 3-input gates and map to A3P tiles
  4. test equivalence with RTL and estimate performance
  5. check on FPGA (for fun !)
  6. given the list of used tiles types, design/import/adapt identical ASIC cells and place/route the ASIC

So the "obsolete" Actel/Microsemi gates are just one intermediary step toward designing totally free ASICs.


Logs:
1. definition of the gates
2. More gates !
3. An unexpected boost
4. Project created on OHWR !
5. Generalised fault injection
6. Generalised fault injection - part deux
7. What about coverage ?
8. What...

Read more »

A3Ptiles.20190412.tgz

50 more gates from Christos and a bugfix

x-compressed-tar - 80.27 kB - 04/11/2019 at 22:50

Download

A3Ptiles.20190330.tgz

Some more gates and fixes

x-compressed-tar - 78.34 kB - 03/29/2019 at 23:19

Download

pa3_libguide_ug_.pdf

"IGLOO, ProASIC3, SmartFusion and Fusion Macro Library Guide for Software v10.1" ©2013 Actel/Microsemi

Adobe Portable Document Format - 1.21 MB - 03/29/2019 at 22:56

Preview
Download

A3Ptiles.20190104.tgz

Newer, better version

x-compressed-tar - 77.46 kB - 01/04/2019 at 05:04

Download

A3Ptiles.tgz

The archive of gates, with license and example.

application/x-compressed-tar - 39.90 kB - 12/02/2018 at 13:07

Download

  • 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;
    else
        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 NOR2 NOR2A NOR2B OR2 OR2A OR2B NOR2  XOR2 (there are 10 names so some functions would be redundant)
    • 3 inputs : 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 AXO2 AXO3  AXO5 XO6 AXO7 AXOI1  AXOI2 AXOI3 AXOI4 AXOI5 AXOI7 MAJ3 NAND2 NAND3 NAND3A NAND3B NOR3 NOR3A NOR3B NOR3C OA1 OA1A OA1B  OA1C OAI1 OR3 OR3A OR3B OR3C XA1 XA1A XA1B XA1C XO1 XO1A XOR3 XNOR3 ZOR3 ZOR3I
    • 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.

  • Generalised fault injection - part deux

    Yann Guidon / YGDES06/10/2019 at 19:17 0 comments

    The idea progresses while I gather the necessary ingredients for the new version of the library. At this moment I consider getting rid of all the C and VHPI code because VHDL already contains all the required features, I think.

    Let's start with the fundamental feature, that evaluates the gate's function. It must be short, simple, efficient, fast. We work with SLV8 (std_logic_vector(7 downto 0)) as the boolean function table.

    subtype FunctTableType is std_logic_vector( 7 downto 0);

    The input signal A has the least significant effect on the index, so we have the linear relationship :

    CBAIndex
    0000
    0011
    0102
    0113
    1004
    1015
    1106
    1117

    OR3 is coded as "11111110" and AND3 as "10000000".

    From there, it's very easy to look it up :

    function TableLookup(
       A : std_logic ;
       B : std_logic ;
       C : std_logic ;
       Table : FunctTableType)
    return std_logic is
      variable index : integer := 0;
    begin
      if A = '1' then index := 1;         end if;
      if B = '1' then index := index + 2; end if;
      if C = '1' then index := index + 4; end if;
      return Table(index);
    end function;

    There. No C code required.

    Then the body of the gate's entity applies this function to the corresponding table.

    entity AND3 is
      port( A, B, C : in std_logic;
                  Y : out std_logic);
    end AND3;
    
    architecture rtl of AND3 is
      constant Table : FuncTableType := "10000000";
    begin
      Y <= TableLookup(A, B, C, Table) after gate_delay;
    end rtl;

    Nothing complex, here, either, though I have moved the constant for a separated declaration, instead of a mere inline mention. That's where the hinge of the system resides.


    First, we must initialise the function table.

    Initially I wanted it to be initialised in the gate file itself. It would make the system self-contained, reducing confusion and complexity. Then I realised that the initialisation (and table creation) would be computed, again and again, for every gate in the DUT. It's not an issue for the example INC8 unit but imagine a huge processor... So it's best to create all the tables once and for all, before everything. And since I don't want to do it by hand, some code is required (even though it will take more dev time, huh huh huh).

    I want to reduce the duplication of code as much as possible and at that moment, it is VERY tempting to create only one entity/architecture, with a function table provided as a generic but this would break the compatibility with the historical ACTEL files. As a consequence, the collection of gate files will continue to exist...

    However the constants can be precomputed in the package.

    Library ieee;
        use ieee.std_logic_1164.all;
    
    package proasic3 is
      subtype FunctTableType is std_logic_vector( 7 downto 0);
      type A3PTileName is (
        AND2, AND2A, 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, CLKINT, DFN1, DFN1C0, DFN1C1, DFN1E0,
        DFN1E0C0, DFN1E0C1, DFN1E0P0, DFN1E0P1, DFN1E1, DFN1E1C0,
        DFN1E1C1, DFN1E1P0, DFN1E1P1, DFN1P0, DFN1P1, INV, MAJ3, MX2, 
        MX2A, MX2B, MX2C, NAND2, NAND3A, NAND3B, NAND3, NOR2A, NOR2, 
        NOR2B, NOR3, NOR3A, NOR3B, NOR3C, OA1A, OA1B, OA1C, OAI1, OR2, 
        OR2A, OR2B, OR3, OR3A, OR3B, OR3C, XA1, XA1A, XA1B, XA1C, XNOR2, 
        XNOR3, XO1, XO1A, XOR2, XOR3, ZOR3, ZOR3I);
    
      function Create_Table(f : A3PTileName) return FunctTableType;
      function TableLookup( A, B, C : std_logic; Table : FunctTableType) return std_logic;
    
      constant A3P_AND3 : FunctTableType := Create_Table(AND3);
    
      ...
      component AND3     port(A, B, C : in std_logic; Y : out std_logic); end component;
      ...
    
    end proasic3;
    
    package body ygrec8_def is
      function TableLookup(
         A, B, C : std_logic ;
         Table : FunctTableType)
      return std_logic is
        variable index : integer := 0;
      begin
     if A = '1' then index := 1;...
    Read more »

  • Generalised fault injection

    Yann Guidon / YGDES06/07/2019 at 19:40 0 comments

    Christos has modified the original DFF gates to inject faults and evaluate/validate the fault-tolerant memory cells used by the CERN.

    Meanwhile, I created this library to help with ASIC design, which is a different beast and methodology. I have no bit-flip issue (at least, directy) but "Design For Test" requires the design and evaluation of testing methods, such as BIST (at chip power-on) and post-factory pass/fail (for binning). A brand new fabbed chip must be thoroughly tested to ensure ALL the gates and wires work correctly under nominal conditions and a test rig must include all the necessary test vectors.

    This is a different fault model, because the changes (usually) don't occur at run time. However the software structure is almost the same, and the fault can be set during startup at random (or under guidance from command line parameters), instead of while simulating.

    The faults can be summarized to a simple model : stuck to 0 or stuck to 1. The wires could also be broken, thus float and pick up some neighbouring signal, but it can still be simplified down to : "not getting the expected value".

    But how do you change a logic gate ? And how to keep things simple ? And how do we ensure only THAT gate (or a list thereof) is altered ? Well, a good understanding of GHDL and VHDL can do wonders :-D


    There are tens of logic gates but they all have the same overall structure : 1, 2 or 3 inputs, then some "computation", then one output.

    It's easy to stick the output to 0 or 1 (or even invert it though it's not useful) but it wouldn't be perfectly complete (because there could be faults inside the gate where the changes are conditional) and we can do even better.

    The "computation" part can be a performed by a single table lookup. For 3 inputs, the output can be defined by 2^3=8 bits, the description fits in a byte. Each type of gate can thus be implemented as one call to a generic C function in VHPI, with the following parameters :

    • A input
    • B input
    • C input
    • lookup table

    For now the library implements each gate as a direct boolean computation, it will take some effort to convert all the gates and check them for accuracy but it's not difficult.

    The lookup table is usually represented as a string of bits, which is seen as a character string in VHDL. It's not convenient at all so the lookup table needs to be converted to "integer" in a way or another. The gate is easy to alter : simply flip (XOR) one bit of the lookup table.

    To prevent conversion problems, and since the gates' functions are already defined and tested, the boolean function can be transformed into an actual VHDL function, that is passed/called by another function, to scan the inputs and create a "generic" during elaboration. This way, we don't have to calculate anything by hand. I'll have to find how to pass a function to another in VHDL... or something like that.


    Now we need something else : we need to address each gate, to apply a fault only to one. We need to index/register all the gates to cover, and give each an ID. By default, ID=0 and no fault is applied.

    But we also need to locate WHICH gate is faulted, because giving an arbitrary number won't be useful if it can't be matched with the code.

    Furthermore, we don't want to have to modify the code and the system MUST register the gates independently, automatically.

    Fortunately, VHDL already forces code to include labels to entities. There must be a way to get it, pass it to the generic definition and then to some C code that will perform some filtering.

    I will reuse some of the tricks I have implemented for the framebuffer interface, with generics initialised with the return value of a C function that provides new values each time.


    It's only the first thoughts and there are still many little details to check...

    Read more »

  • Project created on OHWR !

    Yann Guidon / YGDES05/11/2019 at 20:02 0 comments

    https://ohwr.org/project/microsemi-lib

    It seems the CERN people are exploiting and even expanding the library. We need to agree on a few conventions to keep all our projects compatible.

    A new feature appeared, where errors are injected in flip-flops to test high-reliability redundant designs, using the VHPI interface and external C code. I don't think I'll use this feature because I'm not concerned by rad-hard designs :-)

    The gates library might be extended to other FPGA families though it is out of my own scope.

    On the one hand, I'm losing some control over the development of the library. On the other, everybody benefits from this consolidation and expansion, where more features are added and cross-tested, and I already have the features I needed initially. The rest is just a bonus ;-)

    So that's further proof that, when done correctly, Free Software and Open Source are amazing :-)

  • An unexpected boost

    Yann Guidon / YGDES04/11/2019 at 13:43 0 comments

    It was a big surprise to receive an email from one of the good folks at CERN.

    Even more a surprise when the email says that this library is used for post-synthesis simulation with GHDL !

    Even better is the contribution that fills the blanks and adds about 50 missing gates !

    It will take a while but the main archive will be updated and will now have much broader use, it will do much more than my own designs but for others who need to replace or even bypass the proprietary tools from Actel/Microsemi/Microchip. GHDL again shows its incredible strengths and now there is a new bridge to the FPGA workflow world !

    Many thanks to all the people who make those great contributions to the free and open design tools :-)

  • More gates !

    Yann Guidon / YGDES01/04/2019 at 01:39 0 comments

    I'm adding MAJ3AXO1 as well as some AX1x gates. The definition of the guide is not consistent with the naming so beware ! AX1 should be (A and B) xor C but the manual says it is AX1C. This should be checked with the actual tools so until then, put warnings everywhere...

    Give me some time to update, check and upload the new archive...


    I just confirmed that the manual definition matches with the generated bitstream. I dumped the EDIF of some test code and collected the following equations :
    AX1E  "!((A & B) ^ C)"
    AX1D  "!((!A & !B) ^ C)"
    AX1C  "(A & B) ^ C"
    AX1B  "(!A & !B) ^ C"
    AX1A  "!((!A & B) ^ C)"
    AX1   "(!A & B) ^ C"

    So I must update the INC8 code...

  • definition of the gates

    Yann Guidon / YGDES12/03/2018 at 05:06 0 comments

    Updated 20190328
    Updated 20190411 : 50 more gates !


    For those who are not familiar with the Actel nomenclature, I have included below the definition of the gates that are implemented so far. This is not exhaustive and I might have omitted many gates because I don't need them (but Christos added more).

    Of course, some definitions are redundant (by swapping pins or inverting functions and levels: for example NAND2 = OR2C) but they are practical and it is optimised later (with aliases ?).

    gate_AND2.vhdl:       Y <= A and B after gate_delay;
    gate_AND2A.vhdl:      Y <= (not A) and B after gate_delay;
    gate_AND3.vhdl:       Y <= (A and B) and C after gate_delay;
    gate_AND3A.vhdl:      Y <= ((not A) and B) and C after gate_delay;
    gate_AND3B.vhdl:      Y <= ((not A) and (not B)) and C after gate_delay;
    gate_AND3C.vhdl:      Y <= ((not A) and (not B)) and (not C) after gate_delay;
    gate_AO1.vhdl:        Y <= (A and B) or C after gate_delay;
    gate_AO12.vhdl:       Y <= ((not A) and B) or ((not A) and (not C)) or (B and (not C)) or (A and (not B) and C) after gate_delay;
    gate_AO13.vhdl:       Y <= (A and B) or (A and (not C)) or (B and (not C)) after gate_delay;
    gate_AO14.vhdl:       Y <= (A and B) or (A and (not C)) or (B and (not C)) or ((not A) and (not B) and C) after gate_delay;
    gate_AO15.vhdl:       Y <= (A and (not B) and C) or ((not A) and B and C) or ((not A) and (not B) and (not C)) after gate_delay;
    gate_AO16.vhdl:       Y <= (A and B and (not C)) or ((not A) and (not B) and C) after gate_delay;
    gate_AO17.vhdl:       Y <= (A and B and C) or ((not A) and B and (not C)) or ((not A) and (not B) and C) after gate_delay;
    gate_AO18.vhdl:       Y <= ((not A) and B) or ((not A) and (not C)) or (B and (not C)) after gate_delay;
    gate_AO1A.vhdl:       Y <= ((not A) and B) or C after gate_delay;
    gate_AO1B.vhdl:       Y <= (A and B) or (not C) after gate_delay;
    gate_AO1C.vhdl:       Y <= ((not A) and B) or (not C) after gate_delay;
    gate_AO1D.vhdl:       Y <= ((not A) and (not B)) or C after gate_delay;
    gate_AO1E.vhdl:       Y <= ((not A) and (not B)) or (not C) after gate_delay;
    gate_AOI1.vhdl:       Y <= not ( (A and B) or C ) after gate_delay;
    gate_AOI1A.vhdl:      Y <= not ( ((not A) and B) or C ) after gate_delay;
    gate_AOI1B.vhdl:      Y <= not ( (A and B) or (not C) ) after gate_delay;
    gate_AOI1C.vhdl:      Y <= not ( ((not A) and (not B)) or C ) after gate_delay;
    gate_AOI1D.vhdl:      Y <= not ( ((not A) and (not B)) or (not C) ) after gate_delay;
    gate_AOI5.vhdl:       Y <= not ( ((not A) and B and C) or (A and (not B) and (not C)) ) after gate_delay;
    gate_AX1.vhdl:        Y <= ((not A) and B) xor C after gate_delay; -- /!\
    gate_AX1A.vhdl:       Y <= not (((not A) and B) xor C) after gate_delay; -- beware of definition and inversion !
    gate_AX1B.vhdl:       Y <= ((not A) and (not B)) xor C after gate_delay;  -- beware of definition !
    gate_AX1C.vhdl:       Y <= (A and B) xor C after gate_delay; -- /!\ mistaken with AX1 in the guide ?
    gate_AX1D.vhdl:       Y <= not(((not A) and (not B)) xor C) after gate_delay;
    gate_AX1E.vhdl:       Y <= not((A and B) xor C) after gate_delay;
    gate_AXO1.vhdl:       Y <= (A and B) or (B xor C) after gate_delay;
    gate_AXO2.vhdl:       Y <= ((not A) and B) or (B xor C) after gate_delay;
    gate_AXO3.vhdl:       Y <= (A and (not B)) or (B xor C) after gate_delay;
    gate_AXO5.vhdl:       Y <= ((not A) and B) or ((not B) xor C) after gate_delay;
    gate_AXO6.vhdl:       Y <= (A and (not B)) or ((not B) xor C) after gate_delay;
    gate_AXO7.vhdl:       Y <= ((not A) and (not B)) or (B xor C) after gate_delay;
    gate_AXOI1.vhdl:      Y <= not ((A and B) or (B xor C)) after gate_delay;
    gate_AXOI2.vhdl:      Y <= not (((not A) and B) or (B xor C)) after gate_delay;
    gate_AXOI3.vhdl:      Y <= not ((A and (not B)) or (B xor C)) after gate_delay;
    gate_AXOI4.vhdl:      Y <= not ((A and B) or ((not B) xor C)) after gate_delay;
    gate_AXOI5.vhdl:      Y <= not (((not A) and B) or ((not B) xor C)) after gate_delay;
    gate_AXOI7.vhdl:      Y <= not (((not A) and (not B)) or (B xor C)) after gate_delay;
    gate_CLKINT.vhdl:     Y <= A after gate_delay; (just a buffer)
    gate_DFN1.vhdl:       Q<=D after gate_delay; (always enabled)
    gate_DFN1C0.vhdl:     Q<=D after gate_delay;
    gate_DFN1C1.vhdl: Q<=D after gate_delay;
    ...
    Read more »

View all 9 project logs

  • 1
    Get and install GHDL

    get it there : https://github.com/ghdl/ghdl/releases

    also read http://ghdl.free.fr/

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

  • 2
    Test

    under Linux :

    wget https://cdn.hackaday.io/files/1625946956421696/A3Ptiles.20190412.tgz
    tar xzvf A3Ptiles.20190412.tgz
    cd A3P/
    ./runme.sh
  • 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?

Share

Discussions

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

@SHAOS 

so far, I need the following gates for INC8 :

 INV  XOR2  AX1 AND3  AND2

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
begin
  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