Search code examples
genericsvhdl

what is #define equivalent in VHDL


what is the equivalent of #define, #ifdef and #ifndef in VHDL?

I want to use generics as #define, and change the design according to them. as a simple example: define a string generic and use it to determine if the clock is single or differential.

generic (
  something : boolean := FALSE;
  CLK_MODE : string := "SINGLE_ENDED"
);

Now, How to change the logic according to the generics? one can of course write 2 possible logic descriptions with a simple if statement but then both will be synthesized (although only one is really used).

Also, Is it possible to change the ports according to the generic? for the CLK example, 2 in ports are needed for differential clock but only one is needed for single ended clock. how to enable or disable the second port according to the generic?


Solution

  • One way to synthesize different hardware circuits depending on a condition is using a generic with an if-generate statement. In the example below, when the generic ARITHMETIC_OPERATION_IS_ADD is true, an adder is generated. When it is false, a subtractor is generated.

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity conditional_hardware is
        generic (
            ARITHMETIC_OPERATION_IS_ADD: boolean := true
        );
        port (
            a, b: in unsigned(7 downto 0);
            y: out unsigned(7 downto 0)
        );
    end;
    
    architecture example of conditional_hardware is
    begin
    
        adder: if ARITHMETIC_OPERATION_IS_ADD generate
            y <= a + b;
        end generate;
    
        subtractor: if not ARITHMETIC_OPERATION_IS_ADD generate
            y <= a - b;
        end generate;
    
    end;
    

    Note: if you really want it, there are VHDL preprocessors that work much as their C++ counterparts. For instance, take a look at http://vhdlpp.sourceforge.net/README.

    For a very good and comprehensive introduction to the fundamentals of reusable VHDL, I highly recommend VLSI Technology's whitepaper Coding Tips and Techniques for Synthesizeable, Reusable VHDL.

    It's been a while since I last used LVDS, so the following may be out of date. For outputs, you can assign complementary values to two output pins:

    diff_out_p <= my_signal;
    diff_out_n <= not my_signal;
    

    Then, on your project settings file, assign them to a differential pair, and set the output standard to LVDS or whatever you use.

    For inputs, my tool manual recommends instantiating a primitive. This primitive has two inputs and one output. You should connect the inputs to a differential pair, and use the output in your VHDL code (<data_out> in the example below).

    library altera; 
    use altera.altera_primitives_components.all; 
    
    lvds_input_buffer : ALT_INBUF_DIFF
    generic map (
        IO_STANDARD => "LVDS",
        LOCATION => "IOBANK_1A",
        ENABLE_BUS_HOLD => "off",
        WEAK_PULL_UP_RESISTOR => "off"
    )  port map ( 
        i => <data_in_pos>,
        ibar => <data_in_neg>,
        o => <data_out>
    );