2
\$\begingroup\$

I have code below for a counter that sets an output bit high or low depending on the count value being compared with a reference value. It is used to generate a PWM signal.

During simulation, the PWM_Output bit is always high as I think the Count_Value signal in never incremented inside the if statement.

Any ideas as to why this PWM_Output bit is not toggling? (Sorry, I am unsure how to get the code in one snippet, maybe someone who knows how will edit the question).

Below is the code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.Data_Sizes_Package.all;

entity PWM_Counter_and_Comparator is

    Generic
    (
        Max_Counter_Value : integer := 20
    );

    Port
    (
        PWM_Comparison_Value    : in std_logic_vector(27 downto 0);
        Clock                   : in std_logic;
        Run_Reset               : in std_logic;
        PWM_Output              : out std_logic
    );

end PWM_Counter_and_Comparator;

architecture Behavioral of PWM_Counter_and_Comparator is

    signal PWM_Comparison_Value_int : integer range 0 to Max_Counter_Value;
    signal Count_Value : integer range 0 to Max_Counter_Value;

begin

    PWM_Comparison_Value_int <= conv_integer(unsigned(PWM_Comparison_Value));

    process(Clock, Run_Reset)
    begin

        if Run_Reset = '0' then
            Count_Value <= 0;

            if Count_Value = Max_Counter_Value then
                Count_Value <= 0;

                if (Run_Reset = '1') and (Count_Value < PWM_Comparison_Value_int) then
                    Count_Value <= Count_Value + 1;
                end if;

            end if;

        end if;

    end process;

    process(Clock , Run_Reset)

    begin

        if (Count_Value < PWM_Comparison_Value_int) and (Run_Reset = '1') then
            PWM_Output <= '1';
        else
            PWM_Output <= '0';
        end if;

    end process;

end Behavioral;
\$\endgroup\$
8
  • 2
    \$\begingroup\$ Where is your clock event statement inside the processes?(or rising edge) \$\endgroup\$ Commented Feb 21, 2021 at 21:06
  • 1
    \$\begingroup\$ Also are you sure: you want to write a nested if structure? Check where to write end if of your conditions. \$\endgroup\$ Commented Feb 21, 2021 at 21:11
  • 1
    \$\begingroup\$ You can write elsif after your reset condition. If reset doesnt occur, your counter count up until your period. \$\endgroup\$ Commented Feb 21, 2021 at 21:19
  • 1
    \$\begingroup\$ Your code enters last 2 blocks only first condition if true. This means reset state. \$\endgroup\$ Commented Feb 21, 2021 at 21:22
  • 1
    \$\begingroup\$ İ'm mobile now. I cant write any code now. But look this link please. You can use sync process with clock, you dont need reset in the sensivity list. vhdlwhiz.com/clocked-process \$\endgroup\$ Commented Feb 21, 2021 at 21:28

2 Answers 2

4
\$\begingroup\$

Your if statements are nested, so if Run_Reset = '1', the entire process is skipped, and if Run_Reset = '0', the counter is reset and the increment code is skipped. The counter can never take on any other value than zero.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks Simon, I see now what my mistake is. So if you want 3 separate (non-nested) if statements within a process, does the (end if;) have to be before the next if statement is written? \$\endgroup\$
    – David777
    Commented Feb 22, 2021 at 7:30
  • 1
    \$\begingroup\$ @David777, yes, or in your case since all of them assign to the same signal and only the last assignment before the wait statement (implicit in the sensitivity list) is executed, you want to use elsif. \$\endgroup\$ Commented Feb 22, 2021 at 11:15
  • \$\begingroup\$ Ah ok, but you mention 'wait' statement? Is this something that happens within a process body? \$\endgroup\$
    – David777
    Commented Feb 22, 2021 at 18:45
  • 1
    \$\begingroup\$ @David777, if a process has a sensitivity list, the language pretends that the process body has a loop around it, that waits until a signal in the sensitivity list has an event. I.e. process(reset, clk) is begin ... end process; is equivalent to process is begin loop wait until reset'event or clk'event; ... end loop; end process; \$\endgroup\$ Commented Feb 22, 2021 at 18:58
1
\$\begingroup\$

Consider using the standard libraries numeric_std and numeric_std_unsigned instead of std_logic_arith and std_logic_unsigned.

The below example is the standard form for a clocked process with an asynchronous reset for VHDL-2008. I'm not sure what PWM comparator logic you require, so I'll let you decide what to put:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.numeric_std_unsigned.all;  -- Standard library.
--use work.Data_Sizes_Package.all;

entity PWM_Counter_and_Comparator is

    Generic
    (
        Max_Counter_Value : integer := 20
    );

    Port
    (
        PWM_Comparison_Value    : in std_logic_vector(27 downto 0);
        Clock                   : in std_logic;
        Reset                   : in std_logic;
        PWM_Output              : out std_logic
    );

end PWM_Counter_and_Comparator;

architecture Behavioral of PWM_Counter_and_Comparator is

    signal Count_Value : integer range 0 to Max_Counter_Value;

begin

    process(all)  -- For VHDL-2008, use all to replace the sensitivity list.
    begin

        if Reset then  -- Asynchronous reset condition.

            Count_Value <= 0;
            PWM_Output <= '0';

        elsif rising_edge(Clock) then  -- Synchronous logic

            if Count_Value = Max_Counter_Value then
                Count_Value <= 0;
                PWM_Output <= not PWM_Output;  -- Outputs are readable in VHDL-2008.
                                               -- Toggles the output every time Count_Value equals Max_Counter_Value.
                                               -- I'm not sure if this was your intent, so I'll leave it up to you to decide.
            else
                Count_Value <= Count_Value + 1;
            end if;

        end if;

    end process;

end Behavioral;
\$\endgroup\$
3
  • \$\begingroup\$ I'm pretty sure that the PWM_Comparison_Value is supposed to control the PWM wave uptime. \$\endgroup\$
    – IanJ
    Commented Feb 21, 2021 at 23:40
  • \$\begingroup\$ Thanks tim. Yeah this was not my intent but I get the point. I'll change to suit my own logic. What do you mean by 'all' in the process sensitivity list? Does this include all inputs that are defined in the entity? \$\endgroup\$
    – David777
    Commented Feb 22, 2021 at 7:28
  • 1
    \$\begingroup\$ @David777, all means all of the signals that are read in the process. Historically, sensitivity lists used to cause lots of bugs due to simulator-synthesis mismatches, but that's now a thing of the past. When all is used, modern simulators read through the process to find out which signals are being read, then infer the sensitivity list from that. Antiquated simulators would rely on the sensitivity list whereas synthesisers rely on what's in the process leading to a mismatch if there is a mistake in the sensitivity list that doesn't match what is in the process. \$\endgroup\$
    – tim
    Commented Feb 22, 2021 at 12:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.