Can a signal be resolved as 'most recent event wins'?

Discussion in 'VHDL' started by Iwo Mergler, Sep 17, 2007.

  1. Iwo Mergler

    Iwo Mergler Guest

    Hi,

    This is an exercise in simplifying port maps in
    testbench code.

    I'm trying to use a record as a bus with signals
    going in opposite directions. Is this possible
    in VHDL?

    Something like this:

    type mytype is
    record
    cmd : with_the_flow type;
    busy : against_the_flow type;
    end record;

    The idea is to have this record be an in-signal
    for entity A and an out-signal for entity B.
    Which makes signal.busy an out signal for entity
    A and an in-signal for entity B.

    I'm fairly sure that no such thing exists in VHDL.

    To solve the problem, I tried to describe the
    record as a resolved bus. The idea is to declare the
    bus as inout signals for both entities and fix the
    multiple driver problem by resolving the individual
    record elements.

    Entities A & B know which end of the bus they represent,
    so only A ever drives signal.busy and only B ever drives
    signal.cmd.

    I think the problem boils down to having to resolve such
    that the most recent assignment wins. Typical resolution
    functions will look at the signal values, I would like
    to look at the signal attributes.

    Unfortunately, I don't seem to be able to get at the
    attributes of the component signals of the record, only
    the attributes of the record itself:

    package test is
    type cmd_t is (idle,read,write);
    type operation_t is
    record
    cmd : cmd_t;
    busy : boolean;
    end record;
    type op_vector is array (integer range <>) of operation_t;
    function op_resolve(ov : in op_vector) return operation_t;
    subtype op_t is op_resolve operation_t;
    end test;

    package body test is
    function op_resolve(ov : in op_vector) return operation_t is
    variable f2p_i : integer := 0;
    variable p2f_i : integer := 0;
    variable result : operation_t;
    begin
    -- Current assignment wins
    for i in ov'range loop -- OK
    if ov(i).cmd'event then -- This breaks
    f2p_i := i;
    end if;
    if ov(i).busy'event then
    p2f_i := i;
    end if;
    end loop;
    result.cmd := ov(f2p_i).cmd;
    result.busy := ov(p2f_i).busy;
    return result;
    end function op_resolve;
    end package body;

    The compiler says

    Model Technology ModelSim ALTERA vcom 6.1g Compiler 2006.08 Aug 12 2006
    -- Loading package standard
    -- Compiling package test
    -- Compiling package body test
    -- Loading package test
    ** Error: Z:/resolving.vhd(27): Attribute "event" requires a static signal
    prefix.
    ** Error: Z:/resolving.vhd(30): Attribute "event" requires a static signal
    prefix.
    ** Error: Z:/resolving.vhd(39): VHDL Compiler exiting

    Is there a way to get at the record member attributes?

    Kind regards,

    Iwo
    Iwo Mergler, Sep 17, 2007
    #1
    1. Advertising

  2. Mike Treseler, Sep 17, 2007
    #2
    1. Advertising

  3. Iwo Mergler

    Jim Lewis Guest

    Iwo,
    I do this by individually resolving the elements of
    the record. The easy way to do this is to assign
    the driving value of a port to an identity value when
    it is not being driven. The obvious example is to drive
    a 'Z' for a std_logic element of the record.

    For other types, you can write a resolution function by
    deciding that 0 makes a good identity element.
    The package ResolutionPkg.vhd shows two different ways
    to do this (I generally use resolved):
    http://www.synthworks.com/papers/ResolutionPkg.vhd

    Cheers,
    Jim



    > Hi,
    >
    > This is an exercise in simplifying port maps in
    > testbench code.
    >
    > I'm trying to use a record as a bus with signals
    > going in opposite directions. Is this possible
    > in VHDL?
    >
    > Something like this:
    >
    > type mytype is
    > record
    > cmd : with_the_flow type;
    > busy : against_the_flow type;
    > end record;
    >
    > The idea is to have this record be an in-signal
    > for entity A and an out-signal for entity B.
    > Which makes signal.busy an out signal for entity
    > A and an in-signal for entity B.
    >
    > I'm fairly sure that no such thing exists in VHDL.
    >
    > To solve the problem, I tried to describe the
    > record as a resolved bus. The idea is to declare the
    > bus as inout signals for both entities and fix the
    > multiple driver problem by resolving the individual
    > record elements.
    >
    > Entities A & B know which end of the bus they represent,
    > so only A ever drives signal.busy and only B ever drives
    > signal.cmd.
    >
    > I think the problem boils down to having to resolve such
    > that the most recent assignment wins. Typical resolution
    > functions will look at the signal values, I would like
    > to look at the signal attributes.
    >
    > Unfortunately, I don't seem to be able to get at the
    > attributes of the component signals of the record, only
    > the attributes of the record itself:
    >
    > package test is
    > type cmd_t is (idle,read,write);
    > type operation_t is
    > record
    > cmd : cmd_t;
    > busy : boolean;
    > end record;
    > type op_vector is array (integer range <>) of operation_t;
    > function op_resolve(ov : in op_vector) return operation_t;
    > subtype op_t is op_resolve operation_t;
    > end test;
    >
    > package body test is
    > function op_resolve(ov : in op_vector) return operation_t is
    > variable f2p_i : integer := 0;
    > variable p2f_i : integer := 0;
    > variable result : operation_t;
    > begin
    > -- Current assignment wins
    > for i in ov'range loop -- OK
    > if ov(i).cmd'event then -- This breaks
    > f2p_i := i;
    > end if;
    > if ov(i).busy'event then
    > p2f_i := i;
    > end if;
    > end loop;
    > result.cmd := ov(f2p_i).cmd;
    > result.busy := ov(p2f_i).busy;
    > return result;
    > end function op_resolve;
    > end package body;
    >
    > The compiler says
    >
    > Model Technology ModelSim ALTERA vcom 6.1g Compiler 2006.08 Aug 12 2006
    > -- Loading package standard
    > -- Compiling package test
    > -- Compiling package body test
    > -- Loading package test
    > ** Error: Z:/resolving.vhd(27): Attribute "event" requires a static signal
    > prefix.
    > ** Error: Z:/resolving.vhd(30): Attribute "event" requires a static signal
    > prefix.
    > ** Error: Z:/resolving.vhd(39): VHDL Compiler exiting
    >
    > Is there a way to get at the record member attributes?
    >
    > Kind regards,
    >
    > Iwo
    >
    Jim Lewis, Sep 17, 2007
    #3
  4. Iwo Mergler wrote:

    > Hi,
    >
    > This is an exercise in simplifying port maps in
    > testbench code.
    >
    > I'm trying to use a record as a bus with signals
    > going in opposite directions. Is this possible
    > in VHDL?


    Yes, by the use of a proper resolution function and handshake mechanism this
    is possible.

    See http://groups.google.com/group/comp.lang.vhdl/msg/095574c4e8034cd8

    It shows quite some similarities with your approach.

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
    Paul Uiterlinden, Sep 17, 2007
    #4
  5. Iwo Mergler

    Iwo Mergler Guest

    Iwo Mergler wrote:
    > Hi,
    >
    > This is an exercise in simplifying port maps in
    > testbench code.

    <snip>

    Mike, Jim, Paul,

    thank you very much for the pointers. All three responses
    together solve my problem.

    Jim's suggestion, as implemented in Paul's example shows
    resolution by signal value. I now know that an undriven
    signal assumes a default value, the leftmost element in
    an enumeration. This solves my problem - I can resolve
    the signals this way.

    Mike, what you describe as remote procedures is exactly
    what I'm trying to do. I was under the illusion that
    the idea was so clever that there was no need to research
    other people's solutions. I feel suitably chastised. :)

    This is a bus simulator for use in a testbench. It is
    implemented as a package with a whole bunch of bus
    activity procedures and an entity which is the actual
    bus driver. They communicate over an inout signal which
    is my record. The procedures contain handshake waits with
    the bus driver which effectively 'block' the procedure
    calls for the duration of the bus sequence.

    The resulting testbench looks roughly like this:

    ....
    use work.mypackage.all;
    ....
    architecture tb of testbench is
    ....
    component thebusexerciser is
    port (
    -- global
    clk : in std_logic;
    reset : in std_logic;
    op : inout bus_op_t;

    -- bus interface
    ...
    );
    end component;

    signal op : bus_op_t;

    ....
    begin
    master : thebusexerciser
    port map (
    ...
    op => op;
    ...
    );
    ...
    simulation : process
    variable data : bus_data_t;
    begin
    wait(5); -- waits 5 clock cycles after reset.
    bus_write(op,0x"00000000",0x"DEADBEEF");
    while bus_read(op,0x"00000008") = 0x"00000000" loop
    null; -- polling
    end loop;
    data := bus_read(op,0x"00000004");
    if data /= 0x"12345678" then
    scream_in_terror;
    end if;
    ...
    end process;

    etc.

    The idea is to use a simple sequential process to coordinate
    the busmaster with other parts of the testbench.

    Kind regards,

    Iwo
    Iwo Mergler, Sep 18, 2007
    #5
  6. Iwo Mergler wrote:

    > The resulting testbench looks roughly like this:
    >
    > ...
    > use work.mypackage.all;
    > ...
    > architecture tb of testbench is
    > ...
    > component thebusexerciser is
    > port (
    > -- global
    > clk : in std_logic;
    > reset : in std_logic;
    > op : inout bus_op_t;
    >
    > -- bus interface
    > ...
    > );
    > end component;
    >
    > signal op : bus_op_t;
    >
    > ...
    > begin
    > master : thebusexerciser
    > port map (
    > ...
    > op => op;
    > ...
    > );
    > ...
    > simulation : process
    > variable data : bus_data_t;
    > begin
    > wait(5); -- waits 5 clock cycles after reset.
    > bus_write(op,0x"00000000",0x"DEADBEEF");
    > while bus_read(op,0x"00000008") = 0x"00000000" loop
    > null; -- polling
    > end loop;
    > data := bus_read(op,0x"00000004");
    > if data /= 0x"12345678" then
    > scream_in_terror;
    > end if;
    > ...
    > end process;
    >
    > etc.
    >
    > The idea is to use a simple sequential process to coordinate
    > the busmaster with other parts of the testbench.


    Yup, that's the way I use it.

    A problem that is see with your example is in this piece:

    while bus_read(op,0x"00000008") = 0x"00000000" loop
    null; -- polling
    end loop;

    Subprogram bus_read clearly is a function and it must have a wait statement
    inside (or calls another procedure with a wait statement). That is a
    combination that is not possible in VHDL. So bus_read should be a
    procedure.

    The result value should either be returned via an out or inout mode
    parameter of bus_read, or it could be retrieved from signal op with a
    second function, like get_data.

    I use the latter solution, because the first solution tends to clutter the
    bus_read procedure with a lot of parameters. And if you want to make them
    optional, you end up with a whole lot of overloaded procedures.

    So my solution would be:

    bus_read(op, 0x"00000008");
    poll: while get_data(op) = 0x"00000000" loop
    bus_read((op, 0x"00000008");
    end loop poll;

    bus_read(op, 0x"00000004");
    if get_data(op) /= 0x"12345678" then
    scream_in_terror;
    end if;

    The duplicated read in the poll part can be avoided with an exit statement

    poll: loop
    bus_read((op, 0x"00000008");
    exit poll when get_data(op) /= 0x"00000000";
    end loop poll;

    Or if you don't like exit statements, with an extra boolean variable:

    variable poll_end: boolean;
    ...
    while not poll_end loop
    bus_read((op, 0x"00000008");
    poll_end := get_data(op) /= 0x"00000000";
    end loop;

    Or with a loop-until construct, which VHDL unfortunately does not have...

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
    Paul Uiterlinden, Sep 18, 2007
    #6
  7. Iwo Mergler

    Jim Lewis Guest

    Iwo,
    > Mike, what you describe as remote procedures is exactly
    > what I'm trying to do. I was under the illusion that
    > the idea was so clever that there was no need to research
    > other people's solutions. I feel suitably chastised. :)


    Been teaching this in our VHDL Testbench classes since the
    late 90's. At that time mainly focused on std_logic.

    A paper on applying this technique to both subblocks and
    chips (and hence not writing duplicating tests at both
    levels) is posted here:
    http://www.synthworks.com/papers/

    under the title:
    "Accelerating Verification Through Pre-Use of
    System-Level Testbench Components"

    I did not start using integer, time, and real resolution
    functions until last fall. Ironically Paul U had posted
    something about them earlier and I had missed it and instead
    I had to learn it in a less direct way. So me too, I wish
    I had been collaborating more and sooner.

    My current plan is to make more of our packages publicly
    available in some form - time permitting.

    Cheers,
    Jim Lewis
    SynthWorks VHDL Training
    Jim Lewis, Sep 18, 2007
    #7
  8. Iwo Mergler wrote:

    > Mike, what you describe as remote procedures is exactly
    > what I'm trying to do. I was under the illusion that
    > the idea was so clever that there was no need to research
    > other people's solutions. I feel suitably chastised. :)


    The idea is from Jonathan Bromley.
    I just coded the simplest possible example.
    But I'm happy that it made sense to you.

    > This is a bus simulator for use in a testbench. It is
    > implemented as a package with a whole bunch of bus
    > activity procedures and an entity which is the actual
    > bus driver. They communicate over an inout signal which
    > is my record. The procedures contain handshake waits with
    > the bus driver which effectively 'block' the procedure
    > calls for the duration of the bus sequence.


    Do your procedures use signals
    or process variables to retain
    state information?

    > The resulting testbench looks roughly like this:


    Thanks for the outline. Looks interesting.
    Maybe you can make us a small example when
    you get it all worked out.

    All the verification gurus like the client-server
    architecture arbitrating multiple processes,
    so it sounds like you are on a solid track.

    I prefer to use a single test process
    where the only signals are the wires to the UUT.
    But I'm an over-the-top procedural guy.

    Good luck on your project.

    -- Mike Treseler
    Mike Treseler, Sep 18, 2007
    #8
  9. Iwo Mergler

    Iwo Mergler Guest

    Paul Uiterlinden wrote:

    > Iwo Mergler wrote:
    >
    >> The resulting testbench looks roughly like this:
    >>
    >> ...
    >> use work.mypackage.all;
    >> ...
    >> architecture tb of testbench is
    >> ...
    >> component thebusexerciser is
    >> port (
    >> -- global
    >> clk : in std_logic;
    >> reset : in std_logic;
    >> op : inout bus_op_t;
    >>
    >> -- bus interface
    >> ...
    >> );
    >> end component;
    >>
    >> signal op : bus_op_t;
    >>
    >> ...
    >> begin
    >> master : thebusexerciser
    >> port map (
    >> ...
    >> op => op;
    >> ...
    >> );
    >> ...
    >> simulation : process
    >> variable data : bus_data_t;
    >> begin
    >> wait(5); -- waits 5 clock cycles after reset.
    >> bus_write(op,0x"00000000",0x"DEADBEEF");
    >> while bus_read(op,0x"00000008") = 0x"00000000" loop
    >> null; -- polling
    >> end loop;
    >> data := bus_read(op,0x"00000004");
    >> if data /= 0x"12345678" then
    >> scream_in_terror;
    >> end if;
    >> ...
    >> end process;
    >>
    >> etc.
    >>
    >> The idea is to use a simple sequential process to coordinate
    >> the busmaster with other parts of the testbench.

    >
    > Yup, that's the way I use it.
    >
    > A problem that is see with your example is in this piece:
    >
    > while bus_read(op,0x"00000008") = 0x"00000000" loop
    > null; -- polling
    > end loop;
    >
    > Subprogram bus_read clearly is a function and it must have a wait
    > statement inside (or calls another procedure with a wait statement). That
    > is a combination that is not possible in VHDL. So bus_read should be a
    > procedure.
    >
    > The result value should either be returned via an out or inout mode
    > parameter of bus_read, or it could be retrieved from signal op with a
    > second function, like get_data.
    >
    > I use the latter solution, because the first solution tends to clutter the
    > bus_read procedure with a lot of parameters. And if you want to make them
    > optional, you end up with a whole lot of overloaded procedures.
    >
    > So my solution would be:
    >
    > bus_read(op, 0x"00000008");
    > poll: while get_data(op) = 0x"00000000" loop
    > bus_read((op, 0x"00000008");
    > end loop poll;
    >
    > bus_read(op, 0x"00000004");
    > if get_data(op) /= 0x"12345678" then
    > scream_in_terror;
    > end if;
    >


    Thanks for solving my next problem. :)
    I added a results array to my state record and implemented your suggestion.

    Kind regards,

    Iwo
    Iwo Mergler, Sep 20, 2007
    #9
  10. Iwo Mergler

    Iwo Mergler Guest

    Mike Treseler wrote:
    > Iwo Mergler wrote:
    >> This is a bus simulator for use in a testbench. It is
    >> implemented as a package with a whole bunch of bus
    >> activity procedures and an entity which is the actual
    >> bus driver. They communicate over an inout signal which
    >> is my record. The procedures contain handshake waits with
    >> the bus driver which effectively 'block' the procedure
    >> calls for the duration of the bus sequence.

    >
    > Do your procedures use signals
    > or process variables to retain
    > state information?


    Signals. I admit I didn't think of using process variables.
    Is there an advantage in doing so?

    Kind regards,

    Iwo
    Iwo Mergler, Sep 20, 2007
    #10
  11. Iwo Mergler wrote:

    > Mike Treseler wrote:
    >>
    >> Do your procedures use signals
    >> or process variables to retain
    >> state information?

    >
    > Signals. I admit I didn't think of using process variables.
    > Is there an advantage in doing so?


    Variables are easier to use (no delta needed to see the updated value),
    consume about ten times less memory than signals (important for modeling
    memories) and consume less processor power (variables do not have an event
    queue to be maintained).

    In short: only use signals for communication between processes. For data
    that stays in a process and need not be visible outside it, use variables.

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
    Paul Uiterlinden, Sep 20, 2007
    #11
    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?QWxleCBTLg==?=

    Code being Debugged is not most recent

    =?Utf-8?B?QWxleCBTLg==?=, Jan 31, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    285
    =?Utf-8?B?QWxleCBTLg==?=
    Feb 1, 2005
  2. Ken McCrory

    Text box losing most recent Text value

    Ken McCrory, Mar 9, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    441
    Patrick Olurotimi Ige
    Mar 10, 2005
  3. Jan Faerber
    Replies:
    16
    Views:
    582
    Jan Faerber
    Jan 23, 2005
  4. Nova's Taylor
    Replies:
    7
    Views:
    674
    Peter Hansen
    Jun 19, 2004
  5. Richard Heathfield

    Re: Most recent C and C++ standards documents ?

    Richard Heathfield, May 20, 2006, in forum: C Programming
    Replies:
    2
    Views:
    274
    Robert Gamble
    May 20, 2006
Loading...

Share This Page