Search code examples
vhdl

Process sensitivity list vhdl


I have the following problem:

I have a simple entity driven by a single process:

LIBRARY IEEE;
USE ieee.std_logic_1164.ALL;            
USE ieee.std_logic_unsigned.ALL;        
USE ieee.std_logic_arith.ALL;

entity somma_CDC is
                Port 
                    (
                    
                        A                       : in    std_logic;                                  
                        B                       : in    std_logic;                                  
                        Reset                   : in    std_logic;                                  
                        Internal_Carry_enable   : in    std_logic;                                  
                        S                       : out   std_logic                                   
                    
                    );
end somma_CDC;

architecture Behavioral_somma_CDC of somma_CDC is

signal Internal_Carry: std_logic;

begin
    somma_CDC:process (Reset,A,B) 
                    begin
                    
                        if Reset = '1' 
                            then
                                Internal_Carry <= '0';
                                
                        else 
                                S <= A XOR B XOR Internal_Carry ;
                                if (Internal_Carry_enable = '1')
                                    then
                                    Internal_Carry <= (A AND B) OR (Internal_Carry AND A) OR (Internal_Carry AND B) ;
                                end if;
                        end if;
                        
                    end process;
end architecture;
                    

In practice, it is very similar to a full adder. Ideally, the block diagram should look like this:

pic.

My problem arises when in the cycles following the first, I find the values of the operands equal. In this case, the process does not activate and therefore fails to calculate the case in which A = 1, B = 1, Carry_In = 1. There is a clock signal in my system, but the clock goes faster than the input data change. If I put the clock in the sensitivity list I get wrong results, as the carry "propagates" in the wrong way. I tried without using the sensitivity list and putting a wait for "X" time, with "X" the minimum time for changing operands A and B. It works, but it depends on something that can always change in a project. Is there another way to activate this process?


Solution

  • TL;DR: Add Internal_Carry to your sensitivity list.

    Edit: As @Tricky pointed out, Internal_Carry_enable should be in the sensitivity list as well.

    Full Answer:

    I think the problem here is that you may miss understood how to use the sensitivity list. You are using it as C like programming, where the process would be reading reset, A and B as inputs.

    But in vhdl every signal in the sensitivity list is a trigger that must change its value in order for the process to be rerun again.

    So, the main problem here is the signal Internal_Carry. Since it is not in the sensitivity list, the signal S wont respond as Internal_Carry change to a new value after the first run. You would need to change either reset, A or B to see the effects of Internal_Carry from the last run.

    There are other problems in your code, but not related to this.

    1. Internal_Carry is a latch since you didnt assign any default value to it (which value should it holds if reset is not 0 and Internal_Carry_enable is not 1?).

    2. You may need to take a look in the differences between combinational and sequential logic, since you wrote about clock in an adder circuit. If you add a clock the assignment of a value to a signal will generate a register, while a process without a clock in its sensitivity list will be purely combinational.