Shortening common idioms: bus assignment and 'prev' generation

Discussion in 'VHDL' started by Eli Bendersky, Apr 3, 2006.

  1. Hello all,

    In high level programming languages it's possible to shorten common
    programming idioms by encapsulating them into functions / modules /
    classes. It is similarly possible in simulation-aimed VHDL, but is much
    more difficult in synthesis-aimed VHDL.

    Here is one:

    some_bus(31 downto 27) <= (others => '0');
    some_bus(26) <= my_sig_3;
    some_bus(25) <= my_sig_4;
    some_bus(24 downto 20) <= (others => '0');
    some_bus(19) <= my_sig_11;
    some_bus(18 downto 2) <= (others => '0');
    some_bus(1 downto 0) <= another_bus(1 downto 0);

    I wish there sould be a way to just assign 'all zeros' to some_bus and
    then the signals to relevant bits:

    some_bus(31 downto 0) <= (others => '0');
    some_bus(26) <= my_sig_3;
    some_bus(25) <= my_sig_4;
    some_bus(19) <= my_sig_11;
    some_bus(1 downto 0) <= another_bus(1 downto 0);

    This, unfortunately, doesn't work. Setting some_bus to 'L' also doesn't
    work for synthesis (only simulation).

    Another common idiom is seeing when a signal changed:

    signal my_sig, my_sig_prev: std_logic;
    ....
    ....
    process (clk, reset_n)
    begin
    if reset_n = '0' then
    my_sig_prev <= '0';
    elsif rising_edge(clk) then
    my_sig_prev <= my_sig;
    end if;
    end process;

    And then:

    some process:
    ....
    if rising_edge(clk) then
    if my_sig_prev /= my_sig then
    ...
    ....

    How can this be shortened, in synthesis ? I find myself writing this or
    similar code (checking for a rise, or fall, of my_sig, for instance, by
    (my_sig = '0' and my_sig_prev = '1') for fall) too many times !

    Eli

    ....
     
    Eli Bendersky, Apr 3, 2006
    #1
    1. Advertising

  2. Eli Bendersky wrote:

    > I wish there sould be a way to just assign 'all zeros' to some_bus and
    > then the signals to relevant bits:
    > some_bus(31 downto 0) <= (others => '0');
    > some_bus(26) <= my_sig_3;
    > some_bus(25) <= my_sig_4;
    > some_bus(19) <= my_sig_11;
    > some_bus(1 downto 0) <= another_bus(1 downto 0);
    > This, unfortunately, doesn't work.


    It would work inside a process.

    > Another common idiom is seeing when a signal changed:
    > signal my_sig, my_sig_prev: std_logic;
    > ...
    > ...
    > process (clk, reset_n)
    > begin
    > if reset_n = '0' then
    > my_sig_prev <= '0';
    > elsif rising_edge(clk) then
    > my_sig_prev <= my_sig;
    > end if;
    > end process;
    > And then:
    > some process:
    > ...
    > if rising_edge(clk) then
    > if my_sig_prev /= my_sig then
    > ...
    > ...
    > How can this be shortened, in synthesis ?


    You only have to do this once
    in a single process design.
    See the examples here:

    http://home.comcast.net/~mike_treseler/

    -- Mike Treseler
     
    Mike Treseler, Apr 3, 2006
    #2
    1. Advertising

  3. Mike Treseler wrote:
    > Eli Bendersky wrote:
    >
    > > I wish there sould be a way to just assign 'all zeros' to some_bus and
    > > then the signals to relevant bits:
    > > some_bus(31 downto 0) <= (others => '0');
    > > some_bus(26) <= my_sig_3;
    > > some_bus(25) <= my_sig_4;
    > > some_bus(19) <= my_sig_11;
    > > some_bus(1 downto 0) <= another_bus(1 downto 0);
    > > This, unfortunately, doesn't work.

    >
    > It would work inside a process.


    Yes, but then it would also be delayed by one clock, which isn't always
    desirable. I wonder why synthesis tools don't like the 'H' value. Since
    they resolve all drivers for each signal anyway, it should be quite
    simple to implement.

    >
    > > Another common idiom is seeing when a signal changed:
    > > signal my_sig, my_sig_prev: std_logic;
    > > ...
    > > ...
    > > process (clk, reset_n)
    > > begin
    > > if reset_n = '0' then
    > > my_sig_prev <= '0';
    > > elsif rising_edge(clk) then
    > > my_sig_prev <= my_sig;
    > > end if;
    > > end process;
    > > And then:
    > > some process:
    > > ...
    > > if rising_edge(clk) then
    > > if my_sig_prev /= my_sig then
    > > ...
    > > ...
    > > How can this be shortened, in synthesis ?

    >
    > You only have to do this once
    > in a single process design.
    > See the examples here:
    >
    > http://home.comcast.net/~mike_treseler/
    >


    Interesting approach, but not to my taste, I think:

    1) It interferes with the way I understand synthesizable code. I like
    to be able to envision exactly how the hardware that's built from my
    code looks - it aids greatly in understanding complex timing demands,
    and overall I find that code written is such a way behaves very
    similarly in real life and in simulation.
    2) It is not flexible enough for large designs where usage of
    'generate' is sometimes essential to avoid duplications, and where the
    additional level of abstraction allowed by multiple processes is
    precious.
    3) I really like knowing where each signal is assigned, without looking
    around too much. When each signal has one and only one process that
    'drives' it, things are simpler to understand.

    This all is, of course, IMHO :)

    Eli
     
    Eli Bendersky, Apr 4, 2006
    #3
  4. On 4 Apr 2006 01:05:22 -0700, "Eli Bendersky" <>
    wrote:

    >Mike Treseler wrote:
    >> Eli Bendersky wrote:
    >>
    >> > I wish there sould be a way to just assign 'all zeros' to some_bus and
    >> > then the signals to relevant bits:
    >> > some_bus(31 downto 0) <= (others => '0');
    >> > some_bus(26) <= my_sig_3;
    >> > some_bus(25) <= my_sig_4;
    >> > some_bus(19) <= my_sig_11;
    >> > some_bus(1 downto 0) <= another_bus(1 downto 0);
    >> > This, unfortunately, doesn't work.

    >>
    >> It would work inside a process.

    >
    >Yes, but then it would also be delayed by one clock, which isn't always
    >desirable. I wonder why synthesis tools don't like the 'H' value. Since
    >they resolve all drivers for each signal anyway, it should be quite
    >simple to implement.


    It works inside a combinatorial process. No clock delay is generated.
    The language already does what you want in this regard. There is no
    need to change anything.

    'H' is for modeling driver strengths which is a completely independent
    concept.

    Regards,
    Allan
     
    Allan Herriman, Apr 4, 2006
    #4
  5. Eli Bendersky

    Ben Jones Guest

    "Eli Bendersky" <> wrote in message
    news:...

    > I wish there sould be a way to just assign 'all zeros' to some_bus and
    > then the signals to relevant bits:


    > some_bus(31 downto 0) <= (others => '0');
    > some_bus(26) <= my_sig_3;
    > some_bus(25) <= my_sig_4;
    > some_bus(19) <= my_sig_11;
    > some_bus(1 downto 0) <= another_bus(1 downto 0);


    some_bus <=
    ( 26 => my_sig_3,
    25 => my_sig_4,
    19 => my_sig_11,
    1 => another_bus(1),
    0 => another_bus(0),
    others => '0');

    Not ideal when you have a lot of sub-buses to map, because AFAIK you have to
    do them bit-by-bit... but is that what you had in mind?

    This notation works the same both inside and outside a process.

    -Ben-
     
    Ben Jones, Apr 4, 2006
    #5
  6. Eli Bendersky wrote:
    > Hello all,
    >
    > In high level programming languages it's possible to shorten common
    > programming idioms by encapsulating them into functions / modules /
    > classes. It is similarly possible in simulation-aimed VHDL, but is much
    > more difficult in synthesis-aimed VHDL.
    >
    > Here is one:
    >
    > some_bus(31 downto 27) <= (others => '0');
    > some_bus(26) <= my_sig_3;
    > some_bus(25) <= my_sig_4;
    > some_bus(24 downto 20) <= (others => '0');
    > some_bus(19) <= my_sig_11;
    > some_bus(18 downto 2) <= (others => '0');
    > some_bus(1 downto 0) <= another_bus(1 downto 0);
    >
    > I wish there sould be a way to just assign 'all zeros' to some_bus and
    > then the signals to relevant bits:
    >
    > some_bus(31 downto 0) <= (others => '0');
    > some_bus(26) <= my_sig_3;
    > some_bus(25) <= my_sig_4;
    > some_bus(19) <= my_sig_11;
    > some_bus(1 downto 0) <= another_bus(1 downto 0);
    >
    > This, unfortunately, doesn't work. Setting some_bus to 'L' also doesn't
    > work for synthesis (only simulation).
    >
    > Another common idiom is seeing when a signal changed:
    >
    > signal my_sig, my_sig_prev: std_logic;
    > ...
    > ...
    > process (clk, reset_n)
    > begin
    > if reset_n = '0' then
    > my_sig_prev <= '0';
    > elsif rising_edge(clk) then
    > my_sig_prev <= my_sig;
    > end if;
    > end process;
    >
    > And then:
    >
    > some process:
    > ...
    > if rising_edge(clk) then
    > if my_sig_prev /= my_sig then
    > ...
    > ...
    >
    > How can this be shortened, in synthesis ? I find myself writing this or
    > similar code (checking for a rise, or fall, of my_sig, for instance, by
    > (my_sig = '0' and my_sig_prev = '1') for fall) too many times !
    >
    > Eli
    >
    > ...
    >


    I have used the concatenation operator '&' for signal assignment outside
    a process like this
    signal some_bus : std_logic_vector(15 downto 0);
    signal another_bus : std_logic_vector(13 downto 0);
    signal a_signal : std_logic;
    signal b_signal : std_logic;

    some_bus <= (another_bus & a_signal & b_signal);

    also i _think_ this should work:
    some_bus <= ((15 downto 10) => another_bus(13 downto 8), 5 => a_signal,
    3 => '1', others => '0');

    another trick for handling wide busses is to use aliases for segments of
    your bus. Not sure about the syntax but it is something like:
    alias bus_segment(7 downto 0) is some_bus(15 downto 8);

    As far as i know, you can use the 'last_value and 'event attributes for
    your other problem.
     
    Magne Munkejord, Apr 4, 2006
    #6
  7. Eli Bendersky

    Andy Guest

    Eli Bendersky wrote:


    > 1) It interferes with the way I understand synthesizable code. I like
    > to be able to envision exactly how the hardware that's built from my
    > code looks - it aids greatly in understanding complex timing demands,
    > and overall I find that code written is such a way behaves very
    > similarly in real life and in simulation.
    > 2) It is not flexible enough for large designs where usage of
    > 'generate' is sometimes essential to avoid duplications, and where the
    > additional level of abstraction allowed by multiple processes is
    > precious.
    > 3) I really like knowing where each signal is assigned, without looking
    > around too much. When each signal has one and only one process that
    > 'drives' it, things are simpler to understand.
    >
    > This all is, of course, IMHO :)
    >
    > Eli


    I know and respect several designers that share your preferences on
    coding style WRT separate processes. I think that style stems from the
    earliest synthesis tools that could not infer storage (you had to
    instantiate registers), and therefore all of the combinatorial code was
    split up into multiple processes to keep the sensitivity lists as
    simple as possible. As you pointed out, it has its advantages.

    I am not a software person, but one reason I prefer RTL descriptions
    that use variables instead of signals is because the sequential code
    behaves like software, where the effect of order of read/write on
    variables within a process means exactly what you would think from
    reading code, whereas with signal assignments, it is irrelevent (a read
    of a signal always gets the previous value).

    If/then and for/loop constructs within processes, using globally static
    conditions/bounds, operate exactly the same as equivalent generate
    constructs for synthesis. I see no loss of flexibilty here.

    I prefer more compact, single process code (not necessarily separate
    procedures for init, update, output, etc.) rather than having the
    redundant process & clock edge code. For me it's a matter of how much
    (and how spread out) code there is to look through. I sometimes use
    separate processes to keep somewhat isolated functions separate without
    the overhead of full-up entity/architecture declarations, while still
    taking advantage of the local scoping rules on variables.

    All of this, though, is just IMHO too...

    Andy
     
    Andy, Apr 4, 2006
    #7
  8. Eli Bendersky wrote:

    > Interesting approach, but not to my taste, I think:
    > 1) It interferes with the way I understand synthesizable code. I like
    > to be able to envision exactly how the hardware that's built from my
    > code looks


    The actual hardware that's built is an
    incomprehensible netlist of look up tables,
    registers and wires. All else is abstraction.
    I like to be assured that synthesis will
    supply a netlist that works exactly the
    same as the simulation of my preferred abstraction,
    the vhdl synchronous process. Being assured
    that this same netlist will also meet my Fmax constraints
    seals the deal for me.

    > - it aids greatly in understanding complex timing demands,
    > and overall I find that code written is such a way behaves very
    > similarly in real life and in simulation.


    If that is your preference, then the overhead
    of maintaining multiple processes and the
    wiring between them is part of the bargain.

    > 2) It is not flexible enough for large designs where usage of
    > 'generate' is sometimes essential to avoid duplications, and where the
    > additional level of abstraction allowed by multiple processes is
    > precious.


    Except for the case of tri-state nodes,
    any synchronous logic description that can be
    generated from multiple processes can also
    be described by a single synchronous process
    by using variable, procedure and function declarations.

    > 3) I really like knowing where each signal is assigned, without looking
    > around too much. When each signal has one and only one process that
    > 'drives' it, things are simpler to understand.


    I prefer to use signals at the top level
    to wire up single-process entity instances.
    Port modes (in, out) provide a compile-time
    wiring check that is lacking in process to
    process wiring.

    > This all is, of course, IMHO :)


    Same here.

    -- Mike Treseler
     
    Mike Treseler, Apr 4, 2006
    #8
  9. Allan Herriman wrote:
    > On 4 Apr 2006 01:05:22 -0700, "Eli Bendersky" <>
    > wrote:
    >
    > >Mike Treseler wrote:
    > >> Eli Bendersky wrote:
    > >>
    > >> > I wish there sould be a way to just assign 'all zeros' to some_bus and
    > >> > then the signals to relevant bits:
    > >> > some_bus(31 downto 0) <= (others => '0');
    > >> > some_bus(26) <= my_sig_3;
    > >> > some_bus(25) <= my_sig_4;
    > >> > some_bus(19) <= my_sig_11;
    > >> > some_bus(1 downto 0) <= another_bus(1 downto 0);
    > >> > This, unfortunately, doesn't work.
    > >>
    > >> It would work inside a process.

    > >
    > >Yes, but then it would also be delayed by one clock, which isn't always
    > >desirable. I wonder why synthesis tools don't like the 'H' value. Since
    > >they resolve all drivers for each signal anyway, it should be quite
    > >simple to implement.

    >
    > It works inside a combinatorial process. No clock delay is generated.
    > The language already does what you want in this regard. There is no
    > need to change anything.
    >


    What should be in the sensitivity list of this process ? All of my_sig
    signals ?
     
    Eli Bendersky, Apr 6, 2006
    #9
  10. On 6 Apr 2006 07:42:03 -0700, "Eli Bendersky" <>
    wrote:

    >
    >Allan Herriman wrote:
    >> On 4 Apr 2006 01:05:22 -0700, "Eli Bendersky" <>
    >> wrote:
    >>
    >> >Mike Treseler wrote:
    >> >> Eli Bendersky wrote:
    >> >>
    >> >> > I wish there sould be a way to just assign 'all zeros' to some_bus and
    >> >> > then the signals to relevant bits:
    >> >> > some_bus(31 downto 0) <= (others => '0');
    >> >> > some_bus(26) <= my_sig_3;
    >> >> > some_bus(25) <= my_sig_4;
    >> >> > some_bus(19) <= my_sig_11;
    >> >> > some_bus(1 downto 0) <= another_bus(1 downto 0);
    >> >> > This, unfortunately, doesn't work.
    >> >>
    >> >> It would work inside a process.
    >> >
    >> >Yes, but then it would also be delayed by one clock, which isn't always
    >> >desirable. I wonder why synthesis tools don't like the 'H' value. Since
    >> >they resolve all drivers for each signal anyway, it should be quite
    >> >simple to implement.

    >>
    >> It works inside a combinatorial process. No clock delay is generated.
    >> The language already does what you want in this regard. There is no
    >> need to change anything.
    >>

    >
    >What should be in the sensitivity list of this process ? All of my_sig
    >signals ?


    another_bus is needed as well. Or you could wait for the next version
    of VHDL which allows you to have a sensitivity list that automatically
    includes all the signals needed.

    Regards,
    Allan
     
    Allan Herriman, Apr 7, 2006
    #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. =?Utf-8?B?c3RldmVuIHNjYWlmZQ==?=

    Shortening of syntax

    =?Utf-8?B?c3RldmVuIHNjYWlmZQ==?=, Jul 12, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    602
    =?Utf-8?B?c3RldmVuIHNjYWlmZQ==?=
    Jul 12, 2006
  2. Ben Charrow

    Idioms and Anti-Idioms Question

    Ben Charrow, Jun 22, 2009, in forum: Python
    Replies:
    11
    Views:
    523
    Lawrence D'Oliveiro
    Jul 4, 2009
  3. Littlefield, Tyler

    Dynamic URL shortening

    Littlefield, Tyler, Jun 15, 2011, in forum: Python
    Replies:
    0
    Views:
    559
    Littlefield, Tyler
    Jun 15, 2011
  4. Scott Thompson

    common constructor idioms

    Scott Thompson, Aug 12, 2003, in forum: Ruby
    Replies:
    3
    Views:
    108
    Dave Thomas
    Aug 12, 2003
  5. Alexey Verkhovsky

    How to disable stack-trace shortening?

    Alexey Verkhovsky, Oct 10, 2004, in forum: Ruby
    Replies:
    1
    Views:
    255
    Brian Candler
    Oct 10, 2004
Loading...

Share This Page