Search code examples
vhdlmodelsim

Delay in Simulation of Output with regard to Input


I am making a MultiLevel Car Parking system module with consist of common entry and exit, The idea is that, when I get input stimulus from signal car entry or car exit, It will check the car's Type and then the output should display the level reserved for the particular type where, the car should go, If the slots reserves for particular type is full then the display should output as such. The code gets stimulated through the output gets displayed only after the next clock cycle after the input stimulus is given.

I have tried using a different if-else block for counting operations and also with different process using a flag, and tried to change it to different if-else blocks, but it's still the same. I am beginner to vhdl the execution of statements is quite confusing, and online search is of little help, please help me where did I go wrong?

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.Numeric_std.all; 
            use work.Parking_Package.all;

entity CarPark is 
port(     clk :in std_logic;
      rst : in std_logic;
      car_in : in std_logic;
      Car_out : in std_logic;
      Ent_car_type : car_type;
          Ext_car_type : car_type;
      Status : out level
    );
end CarPark;

architecture behave of CarPark is 
signal count : counter;
begin         
SLOT_CHECKING: process(rst,clk)
begin 
        if(rst= '1')then
    count <= (others => 0);
    Status <= FULL;

        elsif(rising_edge(clk))then
    if(car_in )then       
                     case(Ent_car_type)is                                    
    when Admin =>                                            
                    if(count(Admin) < 5) then                                                
                            Status <= L1;                                                
                            count(Admin) <= count(Admin) +1;
        else
                         Status <= FULL;                                 
                    end if;
    when Staff =>
         if(count(Staff) < 5) then
            Status <= L2;
            count(Staff) <= count(Staff) + 1;
        else
          Status <= FULL;
               end case;                                                                         
            end if;
      elsif(car_out)then                                 
            case(Ext_car_type)is                                     
        when Admin =>                                            
                            if(count(Admin) >0) then
               Status <= L1a;
               count(Admin) <= count(Admin) - 1;
            else
               count(Admin)<= 0;                  
            end if;
        when Staff =>
            if(count(Staff) >0) then
                Status <= L2a;
                count(Staff) <= count(Staff) - 1;
            else
                count(Staff) <= 0;  
            end if;
     end process;
 end behave;

The user defined packages is given below

library ieee;
        use ieee.std_logic_1164.all;
        use ieee.Numeric_std.all;
package Parking_Package is

     type car_type is (Admin, Staff);

     type level is (L1, L2a, FULL);

     type counter is array (Staff downto Admin) of integer range 0 to 22;

     end Parking_Package;

package body Parking_Package is

end Parking_Package;

After initializing using reset, I give input of car_in as 1 and car_type as Admin, The output gets displayed as L1 in the Next Clock and if I force the value of car_type as staff, The corresponding output is simulated in the next clock cycle.

![ScreenShot Simulation] https://i.sstatic.net/9e8Gg.jpg


Solution

  • Firstly, some comments :

    • Your application (MultiLevel Car Parking) is not very adapted to VHDL language. It's too high level. Your coding style is a bit object oriented (type and variable names).
    • There are syntax errors in your code (I assume you already know it because You achieve to have a simulation screen).
    • The behavior that you expect on the first clock cycle implies that your output will be the product of combinational logic. It's better to have outputs directly from flip flops.

    Then the code that you can use to have the expected behavior with 2 process (One purely sequential, the other purely combinational) :

        signal current_count        : counter;
        signal next_count           : counter;
        signal current_status       : level;
        signal next_status          : level;
    
    begin
    
        SEQ : process(rst_tb, clk_tb)
        begin
    
            if (rst_tb = '1') then
    
                current_count   <= (others => 0);
                current_status  <= FULL;
    
            elsif (rising_edge(clk_tb)) then
    
                current_count   <= next_count;
                current_status  <= next_status;
    
            end if;
    
         end process;
    
         SLOT_CHECKING : process(current_count, current_status, car_in, car_out, Ent_car_type, Ext_car_type)
         begin
    
            next_count  <= current_count;
            next_status <= current_status;
    
            if (car_in = '1') then       
    
                case (Ent_car_type) is
    
                    when Admin =>                                            
                        if (current_count(Admin) < 5) then                                                
                            next_status         <= L1;                                                
                            next_count(Admin)   <= current_count(Admin) + 1;
                        else
                            next_status         <= FULL;                                 
                        end if;
    
                    when Staff =>
                        if (current_count(Staff) < 5) then
                            next_status         <= L2;
                            next_count(Staff)   <= current_count(Staff) + 1;
                        else
                            next_status         <= FULL;                                                                       
                        end if;
    
                end case;
    
            elsif (car_out = '1') then    
    
                case (Ext_car_type) is  
    
                    when Admin =>                                            
                        if (current_count(Admin) > 0) thenremarques
                            next_status         <= L1a;
                            next_count(Admin)   <= current_count(Admin) - 1;
                        else
                            next_count(Admin)   <= 0;                  
                        end if;
    
                    when Staff =>
                        if (current_count(Staff) > 0) then
                            next_status         <= L2a;
                            next_count(Staff)   <= current_count(Staff) - 1;
                        else
                            next_count(Staff)   <= 0;  
                        end if;
    
                end case;
    
             end if;
    
        end process;
    
        count   <= next_count   ;
        Status  <= next_status  ;
    

    Warning, with this code the outputs are directly from combinational logic : It's not recommended but it is the only way to get the behavior you expect.

    If this application is only a practise, I advice you too to take another example more adapted to VHDL : filter, SPI communication, processing unit, ...