Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

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);
share|improve this question
add comment

3 Answers

up vote 4 down vote accepted

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;
share|improve this answer
    
I've done this myself and it was supported by ModelSIM and Xilinx ISE. –  Aaron D. Marasco Dec 23 '12 at 0:02
add comment

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).

share|improve this answer
    
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? –  NickHalden Dec 22 '12 at 23:02
    
Seems to work fine in Quartus. –  akohlsmith Dec 23 '12 at 0:36
    
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. –  Brian Drummond Dec 23 '12 at 10:04
    
@BrianDrummond no, I don't ever use std_logic_arith. std_logic_1164 and numeric_std only. –  akohlsmith Dec 23 '12 at 15:04
add comment
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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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