Unconstrained integers and synthesis

Discussion in 'VHDL' started by Thomas Heller, Jan 29, 2011.

  1. I have written some code that uses a unconstrained integer
    and wonder how (and why) it can be synthesized. Here is the code;
    it is an SPI slave receiver which uses an unconstrained output port.
    The word size is determined by the instantiation; I connect the
    'data_out' signal to an std_logic_vector(11 downto 0).
    The code works correctly in the target device; I have not yet
    tried to simulate it.

    As I said: how is the counter instantiated? Is this valid VHLD
    or does it rely on some accidential features of xilinx implementation?
    Would it be better to define the valid range of the integer 'bitcount'?

    Thanks,
    Thomas

    <code>
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;

    entity spislave is
    Port ( sysclock : in STD_LOGIC;
    data_out : out STD_LOGIC_VECTOR;
    data_strobe : out STD_LOGIC;
    sclk : in STD_LOGIC;
    mosi : in STD_LOGIC;
    cs : in STD_LOGIC);
    end spislave;

    architecture Behavioral of spislave is

    -- universal spi slave receiver, number of bits is determined by
    instantiation.

    signal sclk_pipe : std_logic_vector(1 downto 0);
    signal data_sr : std_logic_vector(data_out'length-1 downto 0);
    signal bitcount : integer; -- <===== ?????

    begin

    process(sysclock)
    begin
    if rising_edge(sysclock) then

    sclk_pipe(0) <= sclk;
    sclk_pipe(1) <= sclk_pipe(0);

    if cs = '1' then
    -- async reset
    bitcount <= 0;
    elsif sclk_pipe = "01" then
    -- rising edge of SCLK detected: increment bitcount, shift data in
    bitcount <= bitcount + 1;
    data_sr <= data_sr(data_sr'length-2 downto 0) & mosi;

    if bitcount = data_out'length-1 then
    data_out <= data_sr(data_sr'length-2 downto 0) & mosi;
    data_strobe <= '1';
    else
    data_strobe <= '0';
    end if;

    end if;

    end if;
    end process;

    end Behavioral;
    </code>
     
    Thomas Heller, Jan 29, 2011
    #1
    1. Advertising

  2. Le 29/01/2011 17:10, Thomas Heller a écrit :
    > I have written some code that uses a unconstrained integer
    > and wonder how (and why) it can be synthesized. Here is the code;
    > it is an SPI slave receiver which uses an unconstrained output port.
    > The word size is determined by the instantiation; I connect the
    > 'data_out' signal to an std_logic_vector(11 downto 0).
    > The code works correctly in the target device; I have not yet
    > tried to simulate it.
    >
    > As I said: how is the counter instantiated? Is this valid VHLD
    > or does it rely on some accidential features of xilinx implementation?
    > Would it be better to define the valid range of the integer 'bitcount'?


    Hi
    This is perfectly legal VHDL but bad practice.
    Either your synthesis tool is dumb and it implemented a 32-bit counter,
    or it is a bit smarter than that and noticed your integer is actually a
    natural, or even that it doesn't need to count further than
    data_out'length-1.
    Anyway you'd better constrain your signal

    Nicolas
     
    Nicolas Matringe, Jan 29, 2011
    #2
    1. Advertising

  3. Thomas Heller

    rickman Guest

    On Jan 29, 12:38 pm, Nicolas Matringe <>
    wrote:
    > Le 29/01/2011 17:10, Thomas Heller a crit :
    >
    > > I have written some code that uses a unconstrained integer
    > > and wonder how (and why) it can be synthesized. Here is the code;
    > > it is an SPI slave receiver which uses an unconstrained output port.
    > > The word size is determined by the instantiation; I connect the
    > > 'data_out' signal to an std_logic_vector(11 downto 0).
    > > The code works correctly in the target device; I have not yet
    > > tried to simulate it.

    >
    > > As I said: how is the counter instantiated? Is this valid VHLD
    > > or does it rely on some accidential features of xilinx implementation?
    > > Would it be better to define the valid range of the integer 'bitcount'?

    >
    > Hi
    > This is perfectly legal VHDL but bad practice.
    > Either your synthesis tool is dumb and it implemented a 32-bit counter,
    > or it is a bit smarter than that and noticed your integer is actually a
    > natural, or even that it doesn't need to count further than
    > data_out'length-1.
    > Anyway you'd better constrain your signal
    >
    > Nicolas


    The other advantage of constraining the integer is that it can help
    you catch errors. It may seem like perfectly good code now, but if
    you make modifications and are still expecting the counter to run in a
    given range and it exceeds that range, the simulation will stop and
    tell you about the error. This can be very useful as it prevents
    things like unintended counter wraparound which can be hard to debug
    on a chip! On the other hand, if you want the counter to wrap around,
    you need to explain that clearly to the tool by using the mod operator
    when you do the addition.

    Rick
     
    rickman, Jan 29, 2011
    #3
  4. Thomas Heller

    KJ Guest

    On Jan 29, 11:10 am, Thomas Heller <> wrote:

    > As I said: how is the counter instantiated?  Is this valid VHLD
    > or does it rely on some accidential features of xilinx implementation?


    It's valid code, but you're wasting resources because synthesis will
    build a full 32 bit counter. Since your code is the SPI slave, SCLK
    and CS are primary inputs so you have no real control over how many
    SCLKs you'll actually get. You could get 12...or you could get
    12,000,000. The bitcount signal depends only on those two inputs,
    nothing else. All 32 bits will be used in the comparison because
    those upper XX bits must be checked to make sure they are indeed 0.
    Nicolas' statement "Either your synthesis tool is dumb and it
    implemented a 32-bit counter..." is incorrect. Synthesis will
    generate a full 32 bit counter (not just the 'dumb ones') and it must
    do so because that is precisely what you described (don't take my word
    for it, try it yourself and look to see that all 32 bits of bitcount
    show up...because they are ALL needed in the comparison to see if
    bitcount has hit the magic number needed).

    Instead you should make the following changes:
    - Define bitcount to be "integer range data_out'range"
    - Change when bitcount is incremented as shown below. This change
    will prevent bitcount from ever exceeding the specified range. This
    might not exactly be what you want, since bitcount will stop at
    "data_out'high-1" rather than "data_out'high", but you get the idea.
    - You might want to consider what will happen in your code if
    'data_out' is connected to a non-zero based vector (i.e. connected to
    a vector that is "111 downto 100"). Notice how I changed the compare
    value for bitcount below.

    > if bitcount = data_out'length-1 then (Not data_out'high - 1)
    > data_out <= data_sr(data_sr'length-2 downto 0) & mosi;
    > data_strobe <= '1';
    > else
    > bitcount <= bitcount + 1;
    > data_strobe <= '0';
    > end if;


    Left as an exercise for you is to work out what you want data_strobe
    to do if you do get more than the expected number of SCLKs. Although
    bitcount will stop incrementing, you might not want to keep
    data_strobe asserted in that situation. Again, maybe your system is
    masking this condition, and maybe nothing really needs to be done to
    guard against it, but you should consider the possibility and make an
    informed design decision about what to do if the SPI master generates
    more clocks than you're expecting. Here is a good case where
    simulation will allow you to really exercise 'unexpected' conditions
    so that you know what your design will actually do when those
    conditions occur.

    One should always simulate first. Synthesis should be done in
    parallel to give you additional information about your design while
    your getting the simulation correct. But the first serious synthesis
    run should occur after you get the simulation running, not the other
    way around. Doing synthesis first and simulating later is quite
    possible, many people do it, but I've found that this tends to lead to
    'fragile' designs where 'fragile' means that yes it works when the
    rest of the system behaves as expected, but when some condition that
    wasn't considered occurs, the design does something totally
    unreasonable. Better to have a robust design, many times it doesn't
    have any real device resource cost.

    > Would it be better to define the valid range of the integer 'bitcount'?


    Always define the range of any integers, without exception.

    Kevin Jennings
     
    KJ, Jan 30, 2011
    #4
  5. Thomas Heller

    KJ Guest

    On Jan 29, 12:38 pm, Nicolas Matringe <>
    wrote:

    > Either your synthesis tool is dumb and it implemented a 32-bit counter,
    > or it is a bit smarter than that and noticed your integer is actually a
    > natural, or even that it doesn't need to count further than
    > data_out'length-1.


    There is no information in the design that the synthesis tool could
    use to infer that the counter would never exceed data_out'length-1.
    The primary inputs of CS and SCLK are (presumably) off chip and come
    from some device that could very well generate lotza clockz. A full
    32 bit counter would be generated. Where bitcount is used in the
    comparison, the upper bits above data_out'high would have to be
    checked to insure that they are 0. The way bitcount is defined in the
    OP's code, there is nothing preventing bitcount from exceeding the
    range of data_out.

    > Anyway you'd better constrain your signal
    >

    Yep

    Kevin Jennings
     
    KJ, Jan 30, 2011
    #5
  6. Thomas Heller

    Dal Guest

    Why don't you have the process clocked by the serial clock then resync
    the strobe?

    This will require an additional clock domain but means your serial
    clock is not used as a flip flop input.

    Darrin



    havOn Jan 30, 3:10 am, Thomas Heller <> wrote:
    > I have written some code that uses a unconstrained integer
    > and wonder how (and why) it can be synthesized.  Here is the code;
    > it is an SPI slave receiver which uses an unconstrained output port.
    > The word size is determined by the instantiation; I connect the
    > 'data_out' signal to an std_logic_vector(11 downto 0).
    > The code works correctly in the target device; I have not yet
    > tried to simulate it.
    >
    > As I said: how is the counter instantiated?  Is this valid VHLD
    > or does it rely on some accidential features of xilinx implementation?
    > Would it be better to define the valid range of the integer 'bitcount'?
    >
    > Thanks,
    > Thomas
    >
    > <code>
    > library IEEE;
    > use IEEE.STD_LOGIC_1164.ALL;
    >
    > entity spislave is
    >      Port ( sysclock : in STD_LOGIC;
    >             data_out : out STD_LOGIC_VECTOR;
    >             data_strobe : out STD_LOGIC;
    >             sclk : in  STD_LOGIC;
    >             mosi : in  STD_LOGIC;
    >             cs : in  STD_LOGIC);
    > end spislave;
    >
    > architecture Behavioral of spislave is
    >
    > -- universal spi slave receiver, number of bits is determined by
    > instantiation.
    >
    > signal sclk_pipe : std_logic_vector(1 downto 0);
    > signal data_sr : std_logic_vector(data_out'length-1 downto 0);
    > signal bitcount : integer;   -- <===== ?????
    >
    > begin
    >
    >    process(sysclock)
    >    begin
    >      if rising_edge(sysclock) then
    >
    >        sclk_pipe(0) <= sclk;
    >        sclk_pipe(1) <= sclk_pipe(0);
    >
    >        if cs = '1' then
    >          -- async reset
    >          bitcount <= 0;
    >        elsif sclk_pipe = "01" then
    >          -- rising edge of SCLK detected: increment bitcount, shift data in
    >          bitcount <= bitcount + 1;
    >          data_sr <= data_sr(data_sr'length-2 downto 0) & mosi;
    >
    >          if bitcount = data_out'length-1 then
    >            data_out <= data_sr(data_sr'length-2 downto 0) & mosi;
    >            data_strobe <= '1';
    >          else
    >            data_strobe <= '0';
    >          end if;
    >
    >        end if;
    >
    >      end if;
    >    end process;
    >
    > end Behavioral;
    > </code>
     
    Dal, Jan 30, 2011
    #6
  7. Am 30.01.2011 10:06, schrieb Dal:
    > Why don't you have the process clocked by the serial clock then resync
    > the strobe?


    Because the way I do it there is a little noise immunity.

    > This will require an additional clock domain but means your serial
    > clock is not used as a flip flop input.


    I see no problem with that.
    Thomas
     
    Thomas Heller, Jan 30, 2011
    #7
  8. Thomas Heller

    KJ Guest

    On Jan 29, 8:52 pm, KJ <> wrote:
    Ignore part of previous post where I said "Notice how I changed the
    compare value for bitcount below", that part was correct in the OP.
    Also, the range of bitcount should be "0 to data_out'length - 1" not
    "data_out'range" to accomodate non-zero based vectors

    KJ
     
    KJ, Jan 30, 2011
    #8
  9. Thomas Heller

    Dal Guest

    Having the serial to parallel converter on the serial clock domain
    allows the serial clock to go up to (and slightly exceed) the system
    clock frequency. Not an issue if your system clock > 4xserial clock
    frequency. What is your max sclk frequency?

    It also has the advantage of not having jittery setup and hold times
    which can also be covered by STA. As this is for an FPGA having
    deterministic setup/hold is not a issue. If it were for an ASIC it
    might make characterising setup/hold a little tricky. If you use the
    same clocking method for serial transmit you would also get a jittery
    clock to output. Again, not a problem if the serial clock is slow wrt
    system clock and you don't need constant clock to out times.

    Have you got an timing constraint on the mosi pin? The pin has two
    destination flops. One should go in a IOB but the other may go into a
    slice so could suffer a longish delay. Again not a problem if serial
    clock is clock is slow and you have lots of timing margin. Still
    worth a constraint to make sure it doesn't end up on the other side of
    the device.

    I also noticed you have used "cs" synchronously.

    Darrin

    On Jan 30, 9:23 pm, Thomas Heller <> wrote:
    > Am 30.01.2011 10:06, schrieb Dal:
    >
    > > Why don't you have the process clocked by the serial clock then resync
    > > the strobe?

    >
    > Because the way I do it there is a little noise immunity.
    >
    > > This will require an additional clock domain but means your serial
    > > clock is not used as a flip flop input.

    >
    > I see no problem with that.
    > Thomas
     
    Dal, Jan 31, 2011
    #9
  10. Thomas Heller

    Andy Guest

    On Jan 29, 7:52 pm, KJ <> wrote:
    > On Jan 29, 11:10 am, Thomas Heller <> wrote:
    >
    > > As I said: how is the counter instantiated?  Is this valid VHLD
    > > or does it rely on some accidential features of xilinx implementation?

    >
    > It's valid code, but you're wasting resources because synthesis will
    > build a full 32 bit counter.  Since your code is the SPI slave, SCLK
    > and CS are primary inputs so you have no real control over how many
    > SCLKs you'll actually get.  You could get 12...or you could get
    > 12,000,000.  The bitcount signal depends only on those two inputs,
    > nothing else.  All 32 bits will be used in the comparison because
    > those upper XX bits must be checked to make sure they are indeed 0.
    > Nicolas' statement "Either your synthesis tool is dumb and it
    > implemented a 32-bit counter..." is incorrect.  Synthesis will
    > generate a full 32 bit counter (not just the 'dumb ones') and it must
    > do so because that is precisely what you described (don't take my word
    > for it, try it yourself and look to see that all 32 bits of bitcount
    > show up...because they are ALL needed in the comparison to see if
    > bitcount has hit the magic number needed).
    >
    > Instead you should make the following changes:
    > - Define bitcount to be "integer range data_out'range"
    > - Change when bitcount is incremented as shown below.  This change
    > will prevent bitcount from ever exceeding the specified range.  This
    > might not exactly be what you want, since bitcount will stop at
    > "data_out'high-1" rather than "data_out'high", but you get the idea.
    > - You might want to consider what will happen in your code if
    > 'data_out' is connected to a non-zero based vector (i.e. connected to
    > a vector that is "111 downto 100").  Notice how I changed the compare
    > value for bitcount below.
    >
    > >          if bitcount = data_out'length-1 then  (Not data_out'high - 1)
    > >            data_out <= data_sr(data_sr'length-2 downto 0) & mosi;
    > >            data_strobe <= '1';
    > >          else
    > >             bitcount <= bitcount + 1;
    > >            data_strobe <= '0';
    > >          end if;

    >
    > Left as an exercise for you is to work out what you want data_strobe
    > to do if you do get more than the expected number of SCLKs.  Although
    > bitcount will stop incrementing, you might not want to keep
    > data_strobe asserted in that situation.  Again, maybe your system is
    > masking this condition, and maybe nothing really needs to be done to
    > guard against it, but you should consider the possibility and make an
    > informed design decision about what to do if the SPI master generates
    > more clocks than you're expecting.  Here is a good case where
    > simulation will allow you to really exercise 'unexpected' conditions
    > so that you know what your design will actually do when those
    > conditions occur.
    >
    > One should always simulate first.  Synthesis should be done in
    > parallel to give you additional information about your design while
    > your getting the simulation correct.  But the first serious synthesis
    > run should occur after you get the simulation running, not the other
    > way around.  Doing synthesis first and simulating later is quite
    > possible, many people do it, but I've found that this tends to lead to
    > 'fragile' designs where 'fragile' means that yes it works when the
    > rest of the system behaves as expected, but when some condition that
    > wasn't considered occurs, the design does something totally
    > unreasonable.  Better to have a robust design, many times it doesn't
    > have any real device resource cost.
    >
    > > Would it be better to define the valid range of the integer 'bitcount'?

    >
    > Always define the range of any integers, without exception.
    >
    > Kevin Jennings


    The synthesized length of an integer type object is implementation
    dependent, but must be at least 32 bits unless optimization (e.g.
    reachability analysis) permits truncation. Every synthesis tool I know
    of implements an integer as 32 bits (prior to optimization), but that
    could change at any time, on any tool.

    There is a difference between the "size" of an unconstrained vector
    type and of a base integer type. The type Integer is NOT
    unconstrained, rather it is defined, but implementation specific, with
    a minimum required numeric value range per the LRM. An unconstrained
    vector has truly undefined length, and must be defined somewhere in
    the code (during elaboration), either by the associated signal in an
    instantiation, or by a default value specification.

    Andy
     
    Andy, Feb 3, 2011
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. walala
    Replies:
    4
    Views:
    2,121
    Ralf Hildebrandt
    Sep 8, 2003
  2. walala
    Replies:
    4
    Views:
    1,207
    Technology Consultant
    Sep 9, 2003
  3. Mohammed  A khader

    Unconstrained ports for synthesis

    Mohammed A khader, Apr 20, 2005, in forum: VHDL
    Replies:
    5
    Views:
    1,042
    Ray Andraka
    Apr 22, 2005
  4. Amal
    Replies:
    5
    Views:
    8,713
    Brandon
    Mar 8, 2006
  5. Benjamin Couillard

    Using integers for counters in synthesis

    Benjamin Couillard, Dec 8, 2010, in forum: VHDL
    Replies:
    12
    Views:
    1,087
    Benjamin Couillard
    Dec 14, 2010
Loading...

Share This Page