resizevhdlalu

Addition of one 4-bit and one 3-bit inputs in VHDL


I am trying to design an ALU in VHDL with a 4 bit and a 3 bit unsigned inputs. But my attempts at resizing the input are failing, and thus the addition operation is giving 'X' as output.

This is my code:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity alu_bv is
    Port ( a : in unsigned (3 downto 0);
           b : in unsigned (2 downto 0);
           ch : in STD_LOGIC_VECTOR (2 downto 0);
           y : out unsigned (3 downto 0));
end alu_bv;

architecture Behavioral of alu_bv is
    signal c : unsigned (3 downto 0);

begin
    process(a,b,ch)
    begin
        c <= unsigned('0' & b);

        case ch is
            when "000" => y <= a + c;
            when "001" => y <= a - c;
            when "010" => y <= a + 1;
            when "011" => y <= a - 1;
            when "100" => y <= a and c;
            when "101" => y <= a or c;
            when "110" => y <= not a;
            when "111" => y <= a xor c;
            when others => NULL;
        end case;
    end process;
end Behavioral;

I have tried without typecasting when assigning to c c <= ('0' & b);

And I have tried the resize function c <= resize(b, a'length);

This was the output waveform when I ran behavioral simulation:

Hexadecimal radix: Hexadecimal Radix

Binary radix: Binary radix

Could you suggest a solution to this problem?

Edit: Someone asked to add the test bench I have used:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity alu_tb is
--  Port ( );
end alu_tb;

architecture Behavioral of alu_tb is
component  alu_bv is
    Port ( a : in unsigned (3 downto 0);
           b : in unsigned (2 downto 0);
           ch : in STD_LOGIC_VECTOR (2 downto 0);
           y : out unsigned (3 downto 0));
end component;

signal a1: unsigned (3 downto 0):="1100";
signal b1: unsigned (2 downto 0):="001";
signal ch: STD_LOGIC_VECTOR (2 downto 0):="000";
signal y1: unsigned(3 downto 0);

begin
uut:alu_bv port map(a=>a1,b=>b1,ch=>ch,y=>y1);
stim_proc: process
begin
wait for 125 ns;
ch <= "001";
wait for 125 ns;
ch <= "010";
wait for 125 ns;
ch <= "011";
wait for 125 ns;
ch <= "100";
wait for 125 ns;
ch <= "101";
wait for 125 ns;
ch <= "110";
wait for 125 ns;
ch <= "111";
wait;
end process;
end Behavioral;

Edit - Solution:
@RuudHelderman's suggestion (Adding c to rhe senstivity list) or even replacing b with c in the sensitivity works, giving the correct output process(a,c,ch)

Updated simulation waveform :

Updated simulation waveform

I have a follow-up question:
Since I am only assigning values to a and b once in the testbench and not updating them again, couldn't I remove them from the sensitivity list and keep only ch if I assign c before beginning process

This is what I mean

architecture Behavioral of alu_bv is
    signal c : unsigned (3 downto 0);

begin
    c <= ('0' & b);

    process(ch)
    begin

...

I tried this and it still gives me X as output for a + c


Solution

  • X only appears at the start, subsequent events are fine. That is because c is updated too late to be picked up by the very first execution of y <= a + c, as explained here.

    Try adding c to the sensitivity list, it will trigger the event that is necessary to update y with the latest value of c.