Alias array / array of aliases

Discussion in 'VHDL' started by Colin Beighley, Oct 5, 2011.

  1. Hello,

    I'm looking to do something like the following.

    --code-

    signal signal_a, signal b : unsigned(3 downto 0);

    type registers is array 0 to 1 of unsigned(3 downto 0);

    alias my_regs : registers is (signal_a,signal_b);

    --end code--

    So essentially I have a bunch of signals in a module and want to group
    them as an array of registers using aliases. The other way around is
    possible - declaring the array of registers as signals and then
    declaring the individual signals using aliases. However, I can't do it
    as I've shown, at least not using Xilinx's tools. Any suggestions?

    Thanks,
    Colin
     
    Colin Beighley, Oct 5, 2011
    #1
    1. Advertising

  2. Colin Beighley wrote:
    > Hello,
    >
    > I'm looking to do something like the following.
    >
    > --code-
    >
    > signal signal_a, signal b : unsigned(3 downto 0);
    >
    > type registers is array 0 to 1 of unsigned(3 downto 0);
    >
    > alias my_regs : registers is (signal_a,signal_b);
    >
    > --end code--
    >
    > So essentially I have a bunch of signals in a module and want to group
    > them as an array of registers using aliases. The other way around is
    > possible - declaring the array of registers as signals and then
    > declaring the individual signals using aliases. However, I can't do it
    > as I've shown, at least not using Xilinx's tools. Any suggestions?


    I'm not sure why you want to use an alias for this. Why not use something like:

    declaration:
    SIGNAL my_regs : registers;

    concurrent assignment:
    my_regs <= (signal_a, signal_b);

    ? (exact syntax not checked, but I'm sure you get the idea :) )

    Kind regards,

    Pieter Hulshoff
     
    Pieter Hulshoff, Oct 6, 2011
    #2
    1. Advertising

  3. Colin Beighley

    Gabor Guest

    Pieter Hulshoff wrote:
    > Colin Beighley wrote:
    >> Hello,
    >>
    >> I'm looking to do something like the following.
    >>
    >> --code-
    >>
    >> signal signal_a, signal b : unsigned(3 downto 0);
    >>
    >> type registers is array 0 to 1 of unsigned(3 downto 0);
    >>
    >> alias my_regs : registers is (signal_a,signal_b);
    >>
    >> --end code--
    >>
    >> So essentially I have a bunch of signals in a module and want to group
    >> them as an array of registers using aliases. The other way around is
    >> possible - declaring the array of registers as signals and then
    >> declaring the individual signals using aliases. However, I can't do it
    >> as I've shown, at least not using Xilinx's tools. Any suggestions?

    >
    > I'm not sure why you want to use an alias for this. Why not use something like:
    >
    > declaration:
    > SIGNAL my_regs : registers;
    >
    > concurrent assignment:
    > my_regs <= (signal_a, signal_b);
    >
    > ? (exact syntax not checked, but I'm sure you get the idea :) )
    >
    > Kind regards,
    >
    > Pieter Hulshoff
    >


    I've run into similar situations. The problem is that concurrent
    assignments are one-way. What if I'm using these signals to
    connect inout ports of sub-modules? Usually this gets painful
    when you need to use a generate loop.

    -- Gabor
     
    Gabor, Oct 7, 2011
    #3
  4. I don't use aliases because they are invisible in simulation.
    If you want an array of registers, you will need to declare
    a type and subtype as shown below. This has nothing to
    do with Xilinx tools. It is the vhdl language.

    -- Mike Treseler

    package stack_pkg is
    constant reg_len_c : positive := 32;
    constant array_len_c : positive := 32;
    subtype reg_t is std_logic_vector(reg_len_c-1 downto 0);
    type regs_t is array (0 to array_len_c-1) of reg_t;
    constant reg_init_c : reg_t := (others => '0');
    end package stack_pkg;
     
    Mike Treseler, Oct 9, 2011
    #4
  5. It's not quite as elegant as I had hoped, but here's what I've been
    doing.

    Leveraging the resolved nature of the std_logic (and hence slv,
    signed, and unsigned), I'm putting a procedure at the end of my
    sequential assignment process for the state machine of the module that
    does the address based IO. In each clock cycle the companion
    combinatorial process decides the values that will be assigned to the
    registers in the procedure update_regs, and then if the external logic
    wants to write to a register the value written to that register will
    resolve to the external logic's value.

    I tend to use the resolution capabilities of std_logic and derived
    types pretty heavily in this way, does anyone have any comment on best
    practices in this regard?

    Note - it's easy to use signals in the module that are of greater /
    smaller length than the data bus, you just need to be careful with
    your conversions to signed/unsigned know what you're doing with the
    unused bits. If they're greater you have to use more than 1 address,
    for instance unused bits + MSb's at addr X and LSb's at addr X + 1.

    --CODE--
    entity module is
    port(
    CLK,RST : in std_logic;

    REG_ADDR : in unsigned(1 downto 0);
    REG_WR : in std_logic;
    REG_DATA_IN : in std_logic_vector(3 downto 0);
    REG_DATA_OUT : out std_logic_vector(3 downto 0)
    );
    end entity;

    architecture behavioral of module is
    signal sig_a_signed : signed(3 downto 0);
    signal sig_b_slv : std_logic_vector(3 downto 0);
    signal sig_c_unsigned : unsigned(3 downto 0);
    begin

    sequential_assignments : process(RST,CLK)
    procedure reset_regs;
    procedure update_regs;

    procedure register_io is
    begin
    case to_integer(REG_ADDR) is
    when 0 =>
    if REG_WR = '1' then sig_a_signed <= signed(REG_DATA_IN); end
    if;
    REG_DATA_OUT <= std_logic_vector(sig_a_signed);
    when 1 =>
    if REG_WR = '1' then sig_b_slv <= REG_DATA_IN; end if;
    REG_DATA_OUT <= sig_b_slv;
    when 2 =>
    if REG_WR = '1' then sig_c_unsigned <= unsigned(REG_DATA_IN);
    end if;
    REG_DATA_OUT <= std_logic_vector(sig_c_unsigned);
    when others =>
    REG_DATA_OUT <= (others => '-');
    end case;
    end procedure;
    begin
    if RST = '1' then
    reset_regs;
    elsif rising_edge(CLK) then
    update_regs;
    register_io;
    end if;
    end process sequential_assignments;

    end architecture;
    --END CODE--
     
    Colin Beighley, Oct 11, 2011
    #5
  6. Note that in the last post I didn't include the combinatorial process
    or flesh out the reset or update procedures, as I thought it was
    unnecessary to explain.
     
    Colin Beighley, Oct 11, 2011
    #6
  7. Colin Beighley

    KJ Guest

    On Oct 11, 1:45 pm, Colin Beighley <> wrote:
    > It's not quite as elegant as I had hoped, but here's what I've been
    > doing.
    >
    > Leveraging the resolved nature of the std_logic (and hence slv,
    > signed, and unsigned), I'm putting a procedure at the end of my
    > sequential assignment process for the state machine of the module that
    > does the address based IO.


    Your example does not demonstrate any use of 'the resolved nature of
    the std_logic', what you have will work just as well with the
    unresolved type std_ulogic. That's OK, I wouldn't recommend using
    'the resolved nature of the std_logic' in any code intended to be
    synthesized...certainly not for addressable registers.

    > In each clock cycle the companion
    > combinatorial process decides the values that will be assigned to the
    > registers in the procedure update_regs, and then if the external logic
    > wants to write to a register the value written to that register will
    > resolve to the external logic's value.
    >


    What you've described here (about 'resolve to the external logic's
    value') is not what you've shown in your code. Your example code
    simply shows addressable registers...and you should ask yourself why
    you think you need a separate combinatorial process, the clocked
    process you have is all you need...much cleaner.

    > I tend to use the resolution capabilities of std_logic and derived
    > types pretty heavily in this way, does anyone have any comment on best
    > practices in this regard?
    >


    1. You're not using the resolution capabilities of std_logic...I'm not
    sure why you think you are. I'm guessing that since you have an
    'update_regs' (not shown) and it probably updates the same signals as
    'register_io' that you think this is using resolved logic. If that's
    the case then you're mistaken, the 'register_io' procedure is simply
    higher priority than 'update_regs' since it will have the final word.
    This is not intended as a criticism of your code, just that your
    terminology about using resolved logic is not correct. Resolved logic
    has to do with multiple drivers of a signal...and a single process
    (even with multiple procedures) can never create multiple drivers of
    any signal.

    2. If you were making use of the resolution capabilities of std_logic
    in your example code and that code was intended to be synthesized,
    that would be a mistake. Since you're not, your code looks OK.

    > Note - it's easy to use signals in the module that are of greater /
    > smaller length than the data bus, you just need to be careful with
    > your conversions to signed/unsigned know what you're doing with the
    > unused bits. If they're greater you have to use more than 1 address,
    > for instance unused bits + MSb's at addr X and LSb's at addr X + 1.
    >


    I tend to define a record that defines all of the bits that are
    writable whether they are used to control anything or not like this...
    type t_THIS_PORT is record
    Reserved: std_ulogic_vector(31 downto 24);
    Pointer: std_ulogic_vector(23 downto 0);
    end record t_THIS_PORT;

    Next I define a pair of functions called 'to_std_ulogic_vector' and
    'from_std_ulogic_vector' that work with this record type and do
    exactly what the name suggests.

    Repeat this for all read/write registers.

    Now the register updates (such as your 'sig_a_signed <=
    signed(REG_DATA_IN);') become 'sig_a <=
    from_std_ulogic_vector(REG_DATA_IN'). By itself, this isn't really
    much different than what you have, but it also cleanly takes care of
    things like bit widths not matching the external updater as well as
    when you have ports with lot of bit fields and you want to change
    those definitions around a bit. In my case, all I would change is the
    code inside the 'to_std_ulogic_vector' and 'from_std_ulogic_vector'
    functions and re-synthesize. In fact, if all that is changing is the
    widths/bit locations of existing fields (i.e. not adding/removing any
    fields), then all I update is the record definition without touching
    the source code for the function at all. No having to hunt through
    and places where bit 9 needs to be used rather than bit 8 to control
    something.

    Kevin Jennings
     
    KJ, Oct 12, 2011
    #7
  8. Colin Beighley wrote:

    > --CODE--
    > entity module is
    > port(
    > CLK,RST : in std_logic;
    >
    > REG_ADDR : in unsigned(1 downto 0);
    > REG_WR : in std_logic;
    > REG_DATA_IN : in std_logic_vector(3 downto 0);
    > REG_DATA_OUT : out std_logic_vector(3 downto 0)
    > );
    > end entity;
    >
    > architecture behavioral of module is
    > signal sig_a_signed : signed(3 downto 0);
    > signal sig_b_slv : std_logic_vector(3 downto 0);
    > signal sig_c_unsigned : unsigned(3 downto 0);
    > begin
    >
    > sequential_assignments : process(RST,CLK)
    > procedure reset_regs;
    > procedure update_regs;
    >
    > procedure register_io is
    > begin
    > case to_integer(REG_ADDR) is
    > when 0 =>
    > if REG_WR = '1' then sig_a_signed <= signed(REG_DATA_IN); end
    > if;
    > REG_DATA_OUT <= std_logic_vector(sig_a_signed);
    > when 1 =>
    > if REG_WR = '1' then sig_b_slv <= REG_DATA_IN; end if;
    > REG_DATA_OUT <= sig_b_slv;
    > when 2 =>
    > if REG_WR = '1' then sig_c_unsigned <= unsigned(REG_DATA_IN);
    > end if;
    > REG_DATA_OUT <= std_logic_vector(sig_c_unsigned);
    > when others =>
    > REG_DATA_OUT <= (others => '-');
    > end case;
    > end procedure;
    > begin
    > if RST = '1' then
    > reset_regs;
    > elsif rising_edge(CLK) then
    > update_regs;
    > register_io;
    > end if;
    > end process sequential_assignments;
    >
    > end architecture;
    > --END CODE--


    This code does not make any sense to me. In procedure register_io you drive
    a new value to say sig_a_signed. At the same moment, you drive the value of
    sig_a_signed to REG_DATA_OUT. But that is the *old* value of sig_a_signed.
    The new value appears on sig_a_signed only after a delta delay.

    Have you simulated this code? Admittedly, I have not, other than reading the
    code and perform some mental simulation.

    As KJ already pointed out, there isn't any resolving involved in this code.
    That was the thing that made me look at your code in the first place.

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
     
    Paul Uiterlinden, Oct 12, 2011
    #8
  9. Colin Beighley

    KJ Guest

    On Oct 12, 5:14 am, Paul Uiterlinden <> wrote:
    >
    > This code does not make any sense to me. In procedure register_io you drive
    > a new value to say sig_a_signed. At the same moment, you drive the value of
    > sig_a_signed to REG_DATA_OUT. But that is the *old* value of sig_a_signed..
    > The new value appears on sig_a_signed only after a delta delay.
    >


    I believe that the 'REG_*' interface signals represent a typical read/
    write interface to some external processor. Presumably that processor
    would need the ability to read from registers hence the 'REG_DATA_OUT
    <= ...' statements. Putting this inside the clocked process presumes
    that the processor is expected to wait one clock cycle after setting
    the address before REG_DATA_OUT would be valid. Far better to have an
    explicit read command and wait (or acknowledge) handshake signals for
    an interface definition, but that's off topic.

    Kevin Jennings
     
    KJ, Oct 12, 2011
    #9
  10. Thanks for the advice, guys! My understanding of resolved signals was
    that you could do multiple assignments within a process to a signal
    and that only the last one would take affect. Is this not an attribute
    specific only to resolved signals? I have simulated this and it seems
    to work fine, is there a reason I shouldn't synthesize a design like
    this?
     
    Colin Beighley, Oct 12, 2011
    #10
  11. Colin Beighley

    KJ Guest

    On Oct 12, 1:07 pm, Colin Beighley <> wrote:
    > Thanks for the advice, guys! My understanding of resolved signals was
    > that you could do multiple assignments within a process to a signal
    > and that only the last one would take affect.


    Remove the word 'resolved' from your sentence and your sentence will
    be correct.

    > Is this not an attribute
    > specific only to resolved signals?


    No, it is true for all signals.

    > I have simulated this and it seems
    > to work fine, is there a reason I shouldn't synthesize a design like
    > this?


    I didn't see anything wrong in the method demonstrated by your example
    code. Should synthesize just fine.
     
    KJ, Oct 12, 2011
    #11
  12. Again, thanks for the advice, KJ. I guess I should read up on resolved
    signals.
     
    Colin Beighley, Oct 12, 2011
    #12
  13. Colin Beighley

    Tricky Guest

    On Oct 12, 9:48 pm, Colin Beighley <> wrote:
    > Again, thanks for the advice, KJ. I guess I should read up on resolved
    > signals.


    resolution functions need to be defined for a type. The only resolved
    type in VHDL is std_logic. This allows std_logic to be driven from
    multiple processes. The main use of this is to simulate tri-state
    busses.

    with a resolution function, you can do this in your code (outside of a
    process)

    a <= '1';
    a <= '0';

    and when you simulate it you get 'X'

    if you tried this with a std_ulogic, it would give you an error when
    you compiled the code (before you even got to the simulation) because
    std_ulogic is not resolved, and multiple drivers are banned.
     
    Tricky, Oct 14, 2011
    #13
    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. Roedy Green

    enum aliases

    Roedy Green, Jun 26, 2005, in forum: Java
    Replies:
    5
    Views:
    3,929
    Roedy Green
    Jun 30, 2005
  2. Kevin
    Replies:
    5
    Views:
    2,193
    Jack Klein
    Feb 6, 2004
  3. Michael Surette

    superuser access to aliases database file

    Michael Surette, Nov 26, 2003, in forum: Python
    Replies:
    0
    Views:
    305
    Michael Surette
    Nov 26, 2003
  4. mp
    Replies:
    24
    Views:
    844
    Floyd L. Davidson
    May 3, 2006
  5. grocery_stocker
    Replies:
    9
    Views:
    816
    grocery_stocker
    May 24, 2008
Loading...

Share This Page