I've got the definite impression that we are not on the same page when we talk about what it means for something to be 'standardized'. The usage I'm talking about is that something 'standardized' if it is interchangable with something else that accomplishes that same function but not necessarily in the same way. Although the fifo functionality is pretty low level, since you suggested it I'll use it for the example....it will also be a good indicator of exactly what I mean about the lack of standardization even on something that is easy to describe.
Copied below (without permission of the authors but only done for demonstration purposes) are the entity definitions for 'lpm_fifo' (an EIA standard) and 'sync_fifo' (Mike Tressler standard). Keeping mind what it is that a fifo is supposed to do (the function) and the intended USER of the fifo who has to deal with the interface to that function (i.e. signals and generics on the entity) let's peruse these two.
Both have generics for specifying width of the fifo...but can't agree on the name of that generic parameter.
Both have generics for specifying the depth of the fifo....but again can't agree on the name of that generic parameter. Both are bad from the standpoint of the user since Mike makes you specify depth as an address length (which is really log2(depth)) and lpm_fifo makes you use two parameters (the depth and log2(depth)). Each has their own unique way of not really telling you that their parameters really are simply log2(depth).
Lpm_fifo allows you an option (Lpm_Showahead) for having the output show up as soon as it is available or only after in response to the read command. sync_fifo has no similar option. Having used fifos for a number of years I can say that both forms are generally useful depending on the application and performance requirements so in that regard sync_fifo is less useful than lpm_fifo.
Lpm_fifo has some mystery parameters (lpm_type and lpm_hint) that are intended to be used to pass information further down the tool chain. From the standpoint of a user of the fifo, they just clutter up the interface and are no value. sync_fifo has nothing comparable so in that regard it is better tham lpm_fifo. LPM intended those to be used to pass info on to the fitter in some way but those strings are all going to be 'vendor specific' so no kudos there.
Users of a fifo need to reset it, write to it and read from it. Again here there is no naming consistency on any of the signals with the exception of the 'full' and 'empty' status outputs. sync_fifo also has some two forms of reset (rst and init) that apparently Mike has found to be useful that the rest of the industry has not seen to be of enough value to include. Maybe sync_fifo is more useful because of this...or maybe it was a band-aid for a particular nitch problem but in most cases I would likely end up tying them to the same signal or tying one of them to '0'. lpm_fifo also has two forms of reset (async and sync); I won't rant on the dubious value of async resets maybe some find value to it.
Although 'full' and 'empty' outputs are usually all that most users of a fifo will need, there are more than a few occasions where more status is needed. 'sync_fifo' does not provide anything, 'lpm_fifo' goes to the other extreme and provides a raw dump of the count. What is generally more useful would be to have a number of flag outputs where the depth where the flag gets triggered can be specified by a generic value (like half full, three quarters full, .98% full, etc.) Give both a failing mark on this for not giving much thought to how fifos really get used.
Users of fifos tend to think of 'writing' and 'reading' the fifo, not 'pushing' and 'popping' it as sync_fifo does. In fact 'push' and 'pop' give the implication of a stack (which is a "last in first out" memory) not a fifo (which is "first in, first out") which would make one question whether you're even using the right function so demerits to sync_fifo on that one.
So now that the long winded critique of two definitions of a fifo has been completed, so what? Why does any of this matter? Mike would probably agree that his 'sync_fifo' could very well have been implemented with the exact same set of parameter and signal names as lpm_fifo but he chose not to. So what is the impact of that decision? Well, if you want to switch from lpm_fifo over to Mike's sync_fifo because maybe it is so much better you've got a bunch of editing to do (every usage of lpm_fifo)...and yet sync_fifo implements the EXACT SAME FUNCTION. Even worse, maybe you'd just like to evaluate that supposed performance improvement.
You're not getting anything more, and maybe you're simply trying to figure out if you get better performance using Mike's implementation but you've got a bit of effort in front of you to do that evaluation. Why? Because the interface to these two things that implement the EXACT SAME FUNCTION are completely different. Which is the situation that we're in today. Some FPGA vendors support the one sorry standard that exists (LPM) but are not doing much to improve it and move up the ladder to more higher level functions while one large FPGA vendor (namely 'X') does not directly support it that one standard...but they do provide their own unique way to implement the EXACT SAME FUNCTION.
Peter Alfke goes off on his rant about his X's hard coded fifo runs at 550 MHZ but doesn't seem to grasp the fact that he is talking about performance and that that hard coded fifo is implementing the EXACT SAME FUNCTION. I find it hard to believe that the Xilnx tool set could not, once it encountered the entity called 'lpm_fifo' that it could plop in that hard coded block. Maybe there are some usage restrictions that would prevent that hard coded block from always being instantiated but hey, isn't that what synthesis is supposed to figure out? How to best implement the specified function? Perhaps Peter can explain to everyone how the interface to that Xilinx hard coded fifo differs in some fundamental manner that the interface to that EXACT SAME FUNCTION could not be the same.
Last, I would like to thank Mike for making available his code on his web site. His example designs are a definite 'good' thing. My comparisons of Mike's fifo implementation to LPM fifo is not meant to imply that his is any way worse just that it goes to show you that even with something simple, agreement on the interface to the EXACT SAME FUNCTION differs for no rational reason. Mike being able to reuse 'sync_fifo' wherever he needs fifo functionality though is no different than any other FPGA vendor pushing their 'standard'.
Look at the IC industry and how they can standardize on things and fairly ask yourself why IP can't follow that model. Hint: The answer is not "Well IP is not the same as ICs".....if you analyze it rationally I think you'll see that the answer is more along the lines of "Well dang, it really could be standardized and still come out with new stuff as well as improve on old stuff".
KJ
------------- entity LPM_FIFO generic ( LPM_WIDTH : natural; -- MUST be greater than 0 LPM_WIDTHU : natural := 1; -- MUST be greater than 0 LPM_NUMWORDS : natural; -- MUST be greater than 0 LPM_SHOWAHEAD : string := "OFF"; LPM_TYPE : string := L_FIFO; LPM_HINT : string := "UNUSED"); port ( DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); CLOCK : in std_logic; WRREQ : in std_logic; RDREQ : in std_logic; ACLR : in std_logic := '0'; SCLR : in std_logic := '0'; Q : out std_logic_vector(LPM_WIDTH-1 downto 0); USEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0); FULL : out std_logic; EMPTY : out std_logic); end LPM_FIFO;
entity sync_fifo is generic (dat_length : natural := 16; add_length : natural := 8 -- 7 for 127x16 8 for 255x16 );
port (clk : in std_ulogic; rst : in std_ulogic; -- powerup init of pointers, flags init : in std_ulogic; -- synch init of pointers, flags -- (but not data) push : in std_ulogic; -- data_i latched on edge after push -- ok to push and pop at same time pop : in std_ulogic; -- hold one tick, read data_q while low data_i : in std_logic_vector(dat_length-1 downto 0); data_q : out std_logic_vector(dat_length-1 downto 0); -- readback full : out std_ulogic; empty : out std_ulogic);
end sync_fifo;