How would you write 3/8 demux with the WITH signal SELECT statement?
I've already done it with a CASE signal IS statement, like so (any tips for improving the code welcomed:wink:
Code:
-- [COLOR="blue"]"4"[/COLOR] as the 4th way of writing the [I]3/8 demux[/I] (1st and 2nd are IF versions)
entity demux[COLOR="blue"][B]4[/B][/COLOR]_3v8 is
Port ( a_i : in STD_LOGIC_VECTOR (2 downto 0); -- address signal
y1_o : out STD_LOGIC;
y2_o : out STD_LOGIC;
y3_o : out STD_LOGIC;
y4_o : out STD_LOGIC;
y5_o : out STD_LOGIC;
y6_o : out STD_LOGIC;
y7_o : out STD_LOGIC;
y8_o : out STD_LOGIC);
end demux4_3v8;
architecture Behavioral of demux4_3v8 is
begin
DEMUX: process(a_i)
begin
case a_i is
when "000" =>
y1_o <= '1';
when "001" =>
y2_o <= '1';
when "010" =>
y3_o <= '1';
when "011" =>
y4_o <= '1';
when "100" =>
y5_o <= '1';
when "101" =>
y6_o <= '1';
when "110" =>
y7_o <= '1';
when others =>
y8_o <= '1';
end case;
end process;
end Behavioral;
Now, how about WITH signal SELECT statement? This is, of course, wrong:
Code:
entity demux[COLOR="blue"][B]3[/B][/COLOR]_3v8 is
Port ( a_i : in STD_LOGIC_VECTOR (2 downto 0); -- address signal
y1_o : out STD_LOGIC;
y2_o : out STD_LOGIC;
y3_o : out STD_LOGIC;
y4_o : out STD_LOGIC;
y5_o : out STD_LOGIC;
y6_o : out STD_LOGIC;
y7_o : out STD_LOGIC;
y8_o : out STD_LOGIC);
end demux3_3v8;
architecture Behavioral of demux3_3v8 is
begin
with a_i select
y1_o <= '1' when "000",
y2_o <= '1' when "001",
y3_o <= '1' when "001",
-- etc.
end Behavioral;
WITH digit SELECT
segs <= "1110111" when "0000",
"0010010" when "0001",
"1011101" when "0010",
"1011011" when "0011",
"0111010" when "0100",
"1101011" when "0101",
"0101111" when "0110",
"1010010" when "0111",
"1111111" when "1000",
"1111010" when "1001",
"1101101" when others;
in the case example, you've actually generated latches. y*_o is only set to a 1 within the code. They are also different signals from each other. Nothing in the code suggests that y1_o should be '0' if y2_o is '1'. Values will default to y1_o <= y1_o.
you need to have a y1_o <= '0'; y2_o <= '0'; ... before the case statement. now when a_i changes, each unused y*_o will have a signal assignment, while the set one will have two. For non-blocking assignments, the last reached assignment is the one that will be used.
as mentioned, there is no with-select syntax for your design. y*_o needs to be a std_logic_vector, instead of 8 std_logics.
in the case example, you've actually generated latches. y*_o is only set to a 1 within the code. They are also different signals from each other. Nothing in the code suggests that y1_o should be '0' if y2_o is '1'. Values will default to y1_o <= y1_o.
you need to have a y1_o <= '0'; y2_o <= '0'; ... before the case statement. now when a_i changes, each unused y*_o will have a signal assignment, while the set one will have two. For non-blocking assignments, the last reached assignment is the one that will be used.
Is this (2 lines before case) enough to avoid "bad" latches? Be gentle, all I currently know is that latches aren't inherently "bad", but could lead to "race conditions" (if designed by a novice like me:grin.
Code:
begin
y1_o <= '0'; y2_o <= '0'; y3_o <= '0'; y4_o <= '0';
y5_o <= '0'; y6_o <= '0'; y7_o <= '0'; y8_o <= '0';
case a_i is
when "000" =>
y1_o <= '1';
when "001" =>
y2_o <= '1';
when "010" =>
y3_o <= '1';
when "011" =>
y4_o <= '1';
when "100" =>
y5_o <= '1';
when "101" =>
y6_o <= '1';
when "110" =>
y7_o <= '1';
when others =>
y8_o <= '1';
end case;
end process;
First, lucbra thanks for the correction!
So is the following OK? Would you also write demux in this way?
Code:
with a_i select
y_o <= "00000001" when "000",
"00000010" when "001",
"00000100" when "010",
"00001000" when "011",
"00010000" when "100",
"00100000" when "101",
"01000000" when "110",
"10000000" when others;