3
\$\begingroup\$

I've been having a common reoccurring issue when I write VHDL code. I end up writing code similar to this (as an example):

ENTITY registerfile IS
    PORT(VX : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
         RS1: IN  STD_LOGIC_VECTOR(3 DOWNTO 0));
END registerfile;

ARCHITECTURE rtl OF registerfile IS
    TYPE FeedbackSignal IS ARRAY(15 DOWNTO 0) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
    SIGNAL V_F : FeedbackSignal;
BEGIN
    PROCESS(RS1, V_F)
    BEGIN
        CASE RS1 IS
            WHEN "0000" =>
                VX <= V_F(0);
            WHEN "0001" =>
                VX <= V_F(1);
            WHEN "0010" =>
                VX <= V_F(2);
            WHEN "0011" =>
                VX <= V_F(3);
            WHEN "0100" =>
                VX <= V_F(4);
            WHEN "0101" =>
                VX <= V_F(5);
            WHEN "0110" =>
                VX <= V_F(6);
            WHEN "0111" =>
                VX <= V_F(7);
            WHEN "1000" =>
                VX <= V_F(8);
            WHEN "1001" =>
                VX <= V_F(9);
            WHEN "1010" =>
                VX <= V_F(10);
            WHEN "1011" =>
                VX <= V_F(11);
            WHEN "1100" =>
                VX <= V_F(12);
            WHEN "1101" =>
                VX <= V_F(13);
            WHEN "1110" =>
                VX <= V_F(14);
            WHEN "1111" =>
                VX <= V_F(15);
            WHEN OTHERS =>
                VX <= (OTHERS => 'Z');
        END CASE;
    END PROCESS;
END rtl;

Assume V_F is connected to an internal register or something similar. I feel like this is extremely repetitive, and I can't seem to figure out a better way. Is there a more concise way similar to something like:

VX <= V_F(RS1);
\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

I have resolved this issue myself in a different, more compact way.

I have essentially used the following:

PROCESS(RS1, V_F)
BEGIN
    VX <= V_F(TO_INTEGER(UNSIGNED(RS1)));
END PROCESS;
\$\endgroup\$
1
  • \$\begingroup\$ I've done this myself and it was supported by ModelSIM and Xilinx ISE. \$\endgroup\$ Dec 23, 2012 at 0:02
2
\$\begingroup\$

It looks like this is one of those occasions where a loop works very well:

if (RS1 > 15) then
    VX <= (others => 'Z';
end if;

for i in 0 to 15 loop
    if RS1 = i then
        VX <= V_F(i);
    end if;
end loop

I've used these constructs for expanding 8-bit FIFOs to 32-bit data buses and also for implementing register reads for arrays of similar components (e.g. 8 identical serial ports with their register sets in a contiguous block of I/O memory).

\$\endgroup\$
4
  • \$\begingroup\$ Oooh not a bad idea. I don't think your code works as is though. Wouldn't you need to convert i to a 4 bit STD_LOGIC_VECTOR? \$\endgroup\$
    – NickHalden
    Dec 22, 2012 at 23:02
  • 1
    \$\begingroup\$ Seems to work fine in Quartus. \$\endgroup\$
    – akohlsmith
    Dec 23, 2012 at 0:36
  • \$\begingroup\$ If it "works", that means you're using those non-standard STD_LOGIC_ARITH libraries and you'll never quite be sure of what you're getting or why... Use numeric_std, and declare RS1 as unsigned. The loop is a very useful technique, but unnecessary in this specific case; you can use TO_INTEGER and address the bits directly. \$\endgroup\$
    – user16324
    Dec 23, 2012 at 10:04
  • \$\begingroup\$ @BrianDrummond no, I don't ever use std_logic_arith. std_logic_1164 and numeric_std only. \$\endgroup\$
    – akohlsmith
    Dec 23, 2012 at 15:04
0
\$\begingroup\$
VX <= V_F(RS1);

won't work since vector indicies must be determinable at compile-time (for concurrent statements).

Instead, the most compact way of describing the behaviour you want is to use sequential statements. Look at Kohlsmith's suggestion.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.