Search code examples
vhdlcounter

How to set a value at moduleEN - VHDL


I've this code:

library IEEE;

use IEEE.std_logic_1164.all;

entity Controller is
port (
    CLK : in std_logic;
    OutENABLE : out std_logic_vector (2 downto 0);
    ModuleRESET : in std_logic;
    ModuleENABLE : in std_logic
);
end Controller;

architecture Controller_archi of Controller is
    signal Counter : integer range 0 to 4200 := 0;

    begin
        process (CLK, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                OutENABLE <= (others => '0');
                Counter <= 0;
            elsif rising_edge(CLK) then
                if ModuleENABLE = '1' then
                    Counter <= Counter + 1;
                    case Counter is
                        when 0 =>
                            OutENABLE <= "001";
                        when 450 =>
                            OutENABLE <= "010";
                        when 900 =>
                            OutENABLE <= "100";
                        when 1350 =>
                            OutENABLE <= "001";
                            Counter <= 0;
                        when others =>
                    end case;
                else
                    OutENABLE <= "000";
                end if;
            end if;
        end process;

end Controller_archi;

But it's not working like I need.

What I need:

  • When ModuleENABLE goes '1' instantly OutENABLE goes "001" and not at first rising_edge(CLK) (Now, in this code, if ModuleENABLE goes '1' OutENABLE doesn't change from "000" to "001", it change to "001" after first rising_edge(CLK))
  • Counter go up when rising_edge(CLK) and OutENABLE it's updated every CLK event. (Now, in this code, counter go up when rising_edge(CLK) but OutENABLE it's updated when rising_edge(CLK) and not when CLK goes up and goes down)

So I've modified code to do that:

library IEEE;
use IEEE.std_logic_1164.all;

entity Controller is
port (
    CLK : in std_logic;
    OutENABLE : out std_logic_vector (2 downto 0);
    ModuleRESET : in std_logic;
    ModuleENABLE : in std_logic
);
end Controller;

architecture Controller_archi of Controller is
    signal Counter : integer range 0 to 4200 := 0;

    begin
        process (CLK, ModuleENABLE, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                OutENABLE <= (others => '0');
                Counter <= 0;
            elsif ModuleENABLE = '1' then
                if rising_edge(CLK) then
                    Counter <= Counter + 1;
                end if;
                    case Counter is
                        when 0 =>
                            OutENABLE <= "001";
                        when 450 =>
                            OutENABLE <= "010";
                        when 900 =>
                            OutENABLE <= "100";
                        when 1350 =>
                            OutENABLE <= "001";
                            Counter <= 0;
                        when others =>
                    end case;
             else
                 Counter <= 0;
                 OutENABLE <= "000";
             end if;
        end process;

end Controller_archi;

Now code work like I need in ModelSim, but when I synthesize it or compile it and simulate again it doesn't work.

My question is:

  • What it's wrong with second code and how I can fix it?

  • If I can't fix second code how I can modify first code to work like I need?


Solution

  • What it's wrong with second code and how I can fix it?

    Your synthesis tool is fussy about how the clock and reset lines are connected. You have to use a structure like:

            if ModuleRESET = '0' then
               ...
            elsif rising_edge(CLK) then
    

    or the synthesis tool cannot recognise the clock and reset lines.

    If I can't fix second code how I can modify first code to work like I need?

    You need to move "OutENABLE" outside of the first process, and into a process of its own. From what you've said, OutENABLE should not be a register - it should be a combinatorial function of Counter, ModuleRESET and ModuleENABLE. Try this.

        process (CLK, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                Counter <= 0;
            elsif rising_edge(CLK) then
                if ModuleENABLE = '1' then
                    Counter <= Counter + 1;
                    case Counter is
                        when 1350 =>
                           Counter <= 0;
                        when others =>
                           null;
                    end case;
                end if;
            end if;
        end process;
    
        process (Counter, ModuleRESET, ModuleEnable)
        begin
            OutENABLE <= "000";
            if ModuleRESET = '1' and ModuleENABLE = '1' then
                case Counter is
                    when 0 .. 449 =>
                        OutENABLE <= "001";
                    when 450 .. 899 =>
                        OutENABLE <= "010";
                    when 900 .. 1349 =>
                        OutENABLE <= "100";
                    when others =>
                        OutENABLE <= "001";
                end case;
            end if;
        end process;