# VHDL Logic Simplification

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


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;

• I've done this myself and it was supported by ModelSIM and Xilinx ISE. Commented Dec 23, 2012 at 0:02

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

• 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? Commented Dec 22, 2012 at 23:02
• Seems to work fine in Quartus. Commented Dec 23, 2012 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.
– user16324
Commented Dec 23, 2012 at 10:04
• @BrianDrummond no, I don't ever use std_logic_arith. std_logic_1164 and numeric_std only. Commented Dec 23, 2012 at 15:04
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.