I am trying to understand and work with a design using multiple processes. It is a simple program, split in three processes:
- Counter (Count_proc)
- A PWM duty cycle counter process (PWM_target_counter)
- Output process (PWM_output)
The program should use the first process to count to a limit "FREQ_PWM_COUNTER_MAX". When this limit is reached, another process should increment a variable "pwm_target". The last process will set the output according to "pwm_target".
The program should make a moving duty cycle with a frequency of 50Hz.
The code should simply increment the duty cycle continuously from 0% to 100% and start over again. And it is this duty cycle I want to output.
The program is tested in real hardware and I get at the output(s) just a single pulse of 10ns each 5ms.
I could properly get it to work in a single process, but I want to learn how to use several processes. Any help or hints are appreciated?
entity PWM_Counter is
Generic (
INPUT_CLK : integer :=100000000; --100 MHz
PWM_FREQ : integer := 50); --PWM frequency 50 Hz
Port (
Pwm_Out : out std_logic;
Debug : out std_logic;
Clk : in std_logic);
end PWM_Counter;
architecture Behavioral of PWM_Counter is
--Constants
constant FREQ_PWM_COUNTER_MAX : integer := INPUT_CLK/PWM_FREQ; --Initialize frequency counts based on input clock frequency and wanted PWM frequency
--Signal
signal pwm_value : std_logic := '0'; --Signal to hold pwm_value
signal debug_value : std_logic := '0';
signal counter : integer range 0 to FREQ_PWM_COUNTER_MAX := 0; --Frequency counter
signal pwm_target : integer range 0 to FREQ_PWM_COUNTER_MAX :=0; --Contain the duty cycle target value for the counter
signal counter_output : std_logic := '0';
begin
Pwm_Out <= pwm_value;
Debug <= debug_value;
Count_proc : process(Clk)
begin
if rising_edge (Clk) then
if(counter = FREQ_PWM_COUNTER_MAX) then
counter <= 0;
counter_output <= '1';
debug_value <= '1';
else
counter <= counter + 1;
debug_value <= '0';
end if;
end if;
end process;
PWM_target_counter : process(counter_output)
begin
if rising_edge(counter_output) then
if (pwm_target < FREQ_PWM_COUNTER_MAX) then
pwm_target <= pwm_target + 1;
else
pwm_target <= 0;
end if;
end if;
end process;
PWM_output : process(Clk)
begin
if rising_edge(Clk) then
if (counter < pwm_target) then
pwm_value <= '1';
else
pwm_value <= '0';
end if;
end if;
end process;
end Behavioral;
Just to try, I managed to make it into a single process.
entity PWM_Counter is
Generic (
INPUT_CLK : integer :=100000000; --100 MHz
PWM_FREQ : integer := 50); --PWM frequency 50 Hz
Port (
Pwm_Out : out std_logic;
Debug : out std_logic;
Clk : in std_logic;
Reset : in std_logic);
end PWM_Counter;
architecture Behavioral of PWM_Counter is
--Constants
constant FREQ_PWM_COUNTER_MAX : integer := INPUT_CLK/PWM_FREQ; --Initialize frequency counts based on input clock frequency and wanted PWM frequency
constant PWM_DUTY_CYCLE_STEP : integer := 1000;
constant PWM_STEP : integer := FREQ_PWM_COUNTER_MAX/PWM_DUTY_CYCLE_STEP;
--Signal
signal pwm_value : std_logic := '0'; --Signal to hold pwm_value
signal debug_value : std_logic := '0';
signal counter : integer range 0 to FREQ_PWM_COUNTER_MAX := 0; --Frequency counter
signal pwm_counter : integer range 0 to FREQ_PWM_COUNTER_MAX :=0; --Contain the duty cycle target value for the counter
signal pwm_target : integer range 0 to FREQ_PWM_COUNTER_MAX*PWM_DUTY_CYCLE_STEP :=0; --Contain the duty cycle target value for the counter
begin
Pwm_Out <= pwm_value;
Debug <= debug_value;
PWM_Output : process(Clk)
begin
if rising_edge (Clk) then
if (Reset = '0') then
if (counter = FREQ_PWM_COUNTER_MAX) then
counter <= 0;
pwm_value <= '1';
debug_value <= '1';
if ( pwm_target = FREQ_PWM_COUNTER_MAX) then
pwm_target <= 0;
pwm_counter <= 0;
else
pwm_counter <= pwm_counter + 1;
pwm_target <= pwm_counter*PWM_STEP;
end if;
elsif (counter < FREQ_PWM_COUNTER_MAX) then
counter <= counter + 1;
if (counter < pwm_target) then
pwm_value <= '1';
debug_value <= '1';
else
pwm_value <= '0';
debug_value <= '0';
end if;
end if;
else
counter <= 0;
pwm_counter <= 0;
pwm_target <= 0;
pwm_value <= '0';
debug_value <= '0';
end if;
end if;
end process;
end Behavioral;
But at least for me it seems more complicated (even though it actually do work now.)