First post, etc.

Discussion in 'VHDL' started by Jerry Coffin, Nov 14, 2004.

  1. Jerry Coffin

    Jerry Coffin Guest

    Hi All,

    I'm one of those software guys, but a couple of weeks ago I bought one
    of Xilinx's $99.95 development boards to play with. Though I've seen
    hints at the idea that I should be able to write code like 'x <= a
    /b;' to do division, when I've tried to synthesize that, I only get
    error messages.

    Lacking that, I whipped up some code that seems to work, and thought
    I'd post it in the hopes that 1) somebody else might find it useful,
    and 2) people who know more about VHDL than I do (which is probably
    just about everybody) might critique it and offer whatever advice they
    think would be helpful/useful/whatever (and although this is my first
    post here, I've posted for years on various newsgroups
    where...um...robust discusions are normal, so don't worry too much
    about hurting my feelings or anything like that...).

    Right now, this is hard-coded for 16-bit operands; I haven't yet
    looked into
    how to parameterize that, but it certainly ought to be pretty simple.

    For anybody who's into technicalities, this is a simple radix-2
    divider. It
    will normally take roughly 2N clock cycles to complete a division,
    where N is the difference in size between the (set bits in) the two
    operands.

    Anyway, on with the code:

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
    use IEEE.numeric_std.ALL;

    entity divider is
    Port(CLK : in std_Logic;
    reset : in std_Logic;
    numer : in std_logic_vector(15 downto 0);
    denom : in std_logic_vector(15 downto 0);
    result : out std_logic_vector(15 downto 0);
    remainder: out std_logic_vector(15 downto 0);
    done : out std_logic);
    end divider;

    architecture Behavioral of divider is
    constant zero: std_logic_vector(15 downto 0) := "0000000000000000";
    constant one : std_logic_vector(16 downto 0) :=
    "00000000000000001";
    begin
    divide : process(clk, numer, denom) is

    variable curr_mag : std_logic_vector(16 downto 0);
    variable partial : std_Logic_vector(16 downto 0);
    -- variable subtrahend : std_logic_vector(15 downto 0);
    -- variable magnitude : std_logic_vector(15 downto 0);
    variable modulus : std_logic_vector(15 downto 0);
    variable res : std_logic_vector(15 downto 0);
    type states is (idle, init, lshift, rshift, subs);
    variable state : states;
    variable difference : std_logic_vector(15 downto 0);

    begin
    if (CLK = '1' and CLK'event) then
    if ( reset = '1') then
    state := init;
    else
    case state is
    when init =>
    curr_mag := one;
    partial(15 downto 0) := denom;
    partial(16) := '0';
    state := lshift;
    when lshift =>
    if (numer >= partial) then
    partial(16 downto 1) := partial(15 downto 0);
    partial(0) := '0';
    curr_mag(16 downto 1) := curr_mag(15 downto 0);
    curr_mag(0) := '0';
    else
    state := rshift;
    end if;
    when rshift =>
    -- subtrahend := partial(16 downto 1);
    -- magnitude := curr_mag(16 downto 1);
    state := subs;
    modulus := numer;
    res := zero;
    when subs =>

    -- For more speed at the expense of greater area, use the
    commented-out lines.
    -- In the case of two sets of two above, just un-comment them. For
    those below,
    -- un-comment them, and comment-out the simlar lines immediately below
    them.
    -- The differences in both speed and area are fairly substantial -- at
    least
    -- with the tools I'm using (Xilinx WebPack ISE) -- I'd be interested
    to know
    -- whether more expensive tools know how to optimize this sort of
    thing
    -- automatically.

    -- This is another place a better tool might optimize automatically.
    My
    -- first stab at this bit of code was:
    -- if ( modulus >= subtrahend) then
    -- modulus := modulus - subtrahend;
    -- but that consumes quite a bit more space, basically doing the
    subtraction
    -- twice.
    -- difference := modulus - subtrahend;
    difference := modulus - partial(16 downto 1);
    if (difference >= 0) then
    modulus := difference;
    -- res := res or magnitude;
    res := res or curr_mag(16 downto 1);
    end if;
    -- subtrahend(14 downto 0) := subtrahend(15 downto 1);
    -- subtrahend(15) := '0';
    partial(15 downto 1) := partial(16 downto 2);
    partial(16) := '0';
    -- magnitude(14 downto 0) := magnitude(15 downto 1);
    -- magnitude(15) := '0';
    curr_mag(15 downto 1) := curr_mag(16 downto 2);
    curr_mag(16) := '0';
    -- if ( magnitude = zero) then
    if (curr_mag(16 downto 1) = zero) then
    remainder <= modulus;
    result <= res;
    done <= '1';
    state := idle;
    end if;
    when others =>
    end case;
    end if;
    end if;
    end process;
    end Behavioral;

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Nov 14, 2004
    #1
    1. Advertising

  2. Jerry Coffin wrote:
    > Hi All,
    >
    > I'm one of those software guys, but a couple of weeks ago I bought one
    > of Xilinx's $99.95 development boards to play with. Though I've seen
    > hints at the idea that I should be able to write code like 'x <= a
    > /b;' to do division, when I've tried to synthesize that, I only get
    > error messages.
    >
    > Lacking that, I whipped up some code that seems to work, and thought
    > I'd post it in the hopes that 1) somebody else might find it useful,
    > and 2) people who know more about VHDL than I do (which is probably
    > just about everybody) might critique it and offer whatever advice they
    > think would be helpful/useful/whatever (and although this is my first
    > post here, I've posted for years on various newsgroups
    > where...um...robust discusions are normal, so don't worry too much
    > about hurting my feelings or anything like that...).



    Just a few personal observations:

    1) In stead of using "if clk = '1' and clk'event" (by the way: the
    paranthesis are not needed, this is not C ;-) ), I'd rather write
    "wait until clk = '1'" or "wait until rising_edge(clk)". I just do not
    like "if .. end if" statements spanning a lot of lines if that is not
    needed.

    2) For the same reason I would put the reset part at the end of the process:

    if ( reset = '1') then
    state := init;
    end if;

    3) In stead of writing:

    partial(16 downto 1) := partial(15 downto 0);
    partial(0) := '0';

    you could write this in a single line:

    partial := partial(15 downto 0) & '0';

    For the rest: for a software guy your code looks pretty good to me! ;-)
    I did not look at the algorithm is self.

    One thing though: I don't see signal "done" being set to '0' anywhere. I
    suppose this should be done in state init.

    OK, another thing: I see that state init is left unconditionally.
    Shouldn't there be some kind of request signal?

    Yikes, another thing! Do not use std_logic_arith and std_logic_unsigned
    (and certainly not both at the same time). Use numeric_std instead. It
    is standardized properly, the other two are not.

    Now that I said this, I now see that you use "if difference >=0 then".
    By using std_logic_unsigned this is false only for value zero. I guess
    you should have used package std_logic_signed instead. But again: rather
    use package numeric_std and delcare difference to be of type signed(15
    downto 0).

    Paul.
     
    Paul Uiterlinden, Nov 15, 2004
    #2
    1. Advertising

  3. Paul Uiterlinden wrote:

    > Now that I said this, I now see that you use "if difference >=0 then".
    > By using std_logic_unsigned this is false only for value zero.


    Errr, always true, for any value. An unsigned is >= 0 per definition.

    Paul.
     
    Paul Uiterlinden, Nov 15, 2004
    #3
  4. Jerry Coffin

    Jerry Coffin Guest

    Paul Uiterlinden <> wrote in message news:<cn9mr3$14b$>...

    [ ... ]

    > 1) In stead of using "if clk = '1' and clk'event" (by the way: the
    > paranthesis are not needed, this is not C ;-) ), I'd rather write
    > "wait until clk = '1'" or "wait until rising_edge(clk)". I just do not
    > like "if .. end if" statements spanning a lot of lines if that is not
    > needed.


    I tried that, but apparently other things need to change as well to
    make that work -- when I try this by itself, I get an error message
    saying I can't have both a wait statement and signal sensitivity
    specified as part of the process declaration. I haven't tried to
    eliminate the latter to see exactly what else would need to change if
    I did that though...

    > 2) For the same reason I would put the reset part at the end of the process:
    >
    > if ( reset = '1') then
    > state := init;
    > end if;


    Seems reasonable.

    > 3) In stead of writing:
    >
    > partial(16 downto 1) := partial(15 downto 0);
    > partial(0) := '0';
    >
    > you could write this in a single line:
    >
    > partial := partial(15 downto 0) & '0';


    Ah, thank you. Undoubtedly the books I have mention that somewhere,
    but if so I haven't run across it yet (though I have a tendency read
    more or less randomly rather than working through them sequentially,
    so I shouldn't be surprised at missing a few things).

    > One thing though: I don't see signal "done" being set to '0' anywhere. I
    > suppose this should be done in state init.


    Oops, you're quite right.

    > OK, another thing: I see that state init is left unconditionally.
    > Shouldn't there be some kind of request signal?


    Maybe -- I had written it with a "start" signal, but basically it
    ended up as simply the complement of the reset signal.

    Another possibility would be to eliminate the init state entirely, and
    just carry out all the 'init' actions directly in response to the
    reset signal. At the moment, I left it as part of the state machine
    proper, but I'm honestly not sure how much real difference that makes.

    > Yikes, another thing! Do not use std_logic_arith and std_logic_unsigned
    > (and certainly not both at the same time). Use numeric_std instead. It
    > is standardized properly, the other two are not.
    >
    > Now that I said this, I now see that you use "if difference >=0 then".
    > By using std_logic_unsigned this is false only for value zero. I guess
    > you should have used package std_logic_signed instead. But again: rather
    > use package numeric_std and delcare difference to be of type signed(15
    > downto 0).


    Hmm....I may have to spend a bit more time in the books to entirely
    understand this -- I'd assumed that comparisons on a particular type
    would always be done the same way, and that including the other
    packages would simply add other types with operators to work on them.

    Thanks for your comments -- some for their direct content and
    (particularly) the last for pointing out an area I clearly need to
    study more closely.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Nov 15, 2004
    #4
  5. Jerry Coffin

    rickman Guest

    Jerry Coffin wrote:
    >
    > Paul Uiterlinden <> wrote in message news:<cn9mr3$14b$>...
    >
    > [ ... ]
    >
    > > 1) In stead of using "if clk = '1' and clk'event" (by the way: the
    > > paranthesis are not needed, this is not C ;-) ), I'd rather write
    > > "wait until clk = '1'" or "wait until rising_edge(clk)". I just do not
    > > like "if .. end if" statements spanning a lot of lines if that is not
    > > needed.

    >
    > I tried that, but apparently other things need to change as well to
    > make that work -- when I try this by itself, I get an error message
    > saying I can't have both a wait statement and signal sensitivity
    > specified as part of the process declaration. I haven't tried to
    > eliminate the latter to see exactly what else would need to change if
    > I did that though...


    Yes, you can't have both. If you use a wait, you remove the sensitivity
    list. But I don't recommend that. The if rising_edge(clk) is a
    standard form that nearly all synthesis will recognize while not all
    tools recognize a wait.

    Also, you only need the clock in your sensitivity list. None of the
    other signals are capable of affecting the state of the output other
    than when clock changes. So you don't need any other signals in the
    list.

    > > 2) For the same reason I would put the reset part at the end of the process:
    > >
    > > if ( reset = '1') then
    > > state := init;
    > > end if;

    >
    > Seems reasonable.


    Funny, I am a hardware designer who has has some training in software.
    I was taught (and still prefer) to put the short conditions ahead of the
    long ones since it is much easier to read over them. I always put the
    short reset in front of the rest.


    > Hmm....I may have to spend a bit more time in the books to entirely
    > understand this -- I'd assumed that comparisons on a particular type
    > would always be done the same way, and that including the other
    > packages would simply add other types with operators to work on them.
    >
    > Thanks for your comments -- some for their direct content and
    > (particularly) the last for pointing out an area I clearly need to
    > study more closely.


    The type std_logic_vector as defined in the ieee standard, does not have
    comparison operators other than '='. In order to use the other
    comparisons, you need to either use one of the ...signed/...unsigned
    libraries which is not recommended, or use numeric_std and make the
    signal a signed or unsigned type. Then the operator is defined.

    --

    Rick "rickman" Collins


    Ignore the reply address. To email me use the above address with the XY
    removed.

    Arius - A Signal Processing Solutions Company
    Specializing in DSP and FPGA design URL http://www.arius.com
    4 King Ave 301-682-7772 Voice
    Frederick, MD 21701-3110 301-682-7666 FAX
     
    rickman, Nov 15, 2004
    #5
  6. rickman wrote:
    > Yes, you can't have both. If you use a wait, you remove the sensitivity
    > list. But I don't recommend that. The if rising_edge(clk) is a
    > standard form that nearly all synthesis will recognize while not all
    > tools recognize a wait.


    Really? Surely tools do recognize "wait until clk = '1'" as the first
    statement in a process? If they do not, I would not care to use those tools!

    >>>2) For the same reason I would put the reset part at the end of the process:
    >>>
    >>> if ( reset = '1') then
    >>> state := init;
    >>> end if;

    >
    > Funny, I am a hardware designer who has has some training in software.
    > I was taught (and still prefer) to put the short conditions ahead of the
    > long ones since it is much easier to read over them. I always put the
    > short reset in front of the rest.


    And I usually put the normal operation of the code first, followed by
    the other stuff such as reset. There's something to be said for both
    strategies. :)

    Paul.
     
    Paul Uiterlinden, Nov 16, 2004
    #6
  7. Jerry Coffin wrote:
    >
    > Hmm....I may have to spend a bit more time in the books to entirely
    > understand this -- I'd assumed that comparisons on a particular type
    > would always be done the same way, and that including the other
    > packages would simply add other types with operators to work on them.


    Of course I should have mentioned the FAQ:
    http://www.eda.org/comp.lang.vhdl/

    And in particular in this case:
    http://www.eda.org/comp.lang.vhdl/FAQ1.html#4.8

    Paul.
     
    Paul Uiterlinden, Nov 16, 2004
    #7
  8. Jerry Coffin

    Alan Fitch Guest

    "rickman" <> wrote in message
    news:...
    <snip>
    > The type std_logic_vector as defined in the ieee standard, does not

    have
    > comparison operators other than '='. In order to use the other
    > comparisons, you need to either use one of the ...signed/...unsigned
    > libraries which is not recommended, or use numeric_std and make the
    > signal a signed or unsigned type. Then the operator is defined.
    >


    Hi Rick, sorry to be pedantic :), but enumerated types (such as
    std_logic)
    do have implicit comparison operators defined. They are defined such
    that
    the value that occurs to the right in the type declaration is greater
    than a value that occurs left of it.

    Thus '1' is > '0'.

    For comparison of vectors (such as std_logic_vector), the comparison
    operator will do comparison using this ordering from left to right
    of the array. However if the arrays are different sizes, "funny
    things"
    will happen.

    So

    a) if your arrays are the same length
    b) you "think" of the contents as unsigned numbers
    c) the vectors only contain '0' and '1'

    the relational operators will work, and synthesise correctly.

    However if you "think" of the contents as signed, or the lengths
    are different, or you've got e.g. 'L' mixed with '0', horrible
    (but well-defined) things will happen.

    Having said that, I am just being pedantic - of course you should
    use an arithmetic package, preferably numeric_std.

    Regarding another comment (by someone I've snipped out) about the
    use of both std_logic_arith and std_logic_unsigned, this is often
    necessary as certain functions that you want to have when using
    std_logic_signed or std_logic_unsigned are only available in
    std_logic_arith - another good reason for preferring numeric_std,
    which has a cleaner design,

    regards
    Alan

    --
    Alan Fitch
    Consultant

    DOULOS - Developing Design Know-how
    VHDL * Verilog * SystemC * Perl * Tcl/Tk * Verification * Project
    Services

    Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24
    1AW, UK
    Tel: +44 (0)1425 471223 mail:

    Fax: +44 (0)1425 471573 Web:
    http://www.doulos.com

    The contents of this message may contain personal views which are not
    the
    views of Doulos Ltd., unless specifically stated.
     
    Alan Fitch, Nov 17, 2004
    #8
    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. Robin Cull
    Replies:
    5
    Views:
    406
    Andrew Dalke
    Jul 31, 2003
  2. Daniel Joyce

    Python Audio (Alpy, Fastaudio, Etc Etc)

    Daniel Joyce, Sep 16, 2003, in forum: Python
    Replies:
    1
    Views:
    925
    Markus Wankus
    Sep 16, 2003
  3. Replies:
    2
    Views:
    321
  4. Theron NightStar

    first prog - first post

    Theron NightStar, Jul 11, 2005, in forum: C++
    Replies:
    4
    Views:
    303
    Jon Bell
    Jul 14, 2005
  5. Kevin Walzer

    Re: PIL (etc etc etc) on OS X

    Kevin Walzer, Aug 1, 2008, in forum: Python
    Replies:
    4
    Views:
    407
    Fredrik Lundh
    Aug 13, 2008
Loading...

Share This Page