OpenCores
URL https://opencores.org/ocsvn/signal_waveform_generator/signal_waveform_generator/trunk

Subversion Repositories signal_waveform_generator

[/] [signal_waveform_generator/] [trunk/] [hw/] [sources/] [PwmController/] [sources/] [PwmController.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ldalmasso
------------------------------------------------------------------------
2
-- Engineer:    Dalmasso Loic
3
-- Create Date: 28/01/2025
4
-- Module Name: PwmController
5
-- Description:
6
--      PWM Controller with configurable PWM Resolution (in bits), PWM Signal Output Frequency (Hz) and PWM Signal Output Frequency Error Range (Hz).
7
--              The size of the Duty Cycle input is 1-bit greater than the PWM Resolution to handle 100% Duty Cycle.
8
--              The Duty Cyle value is dynamic but the new value will be applied only at the end of the PWM Duty Cycle Period (when Next Duty Cycle Trigger is enable).
9
--              User MUST carefully select generic parameters to satisfy PWM Output Frequency & Accuracy. Otherwise, assertion will be throw.
10
--              User can fix a Range of valid PWM Frequency Output.
11
--
12
-- Generics
13
--              sys_clock: System Input Clock Frequency (Hz)
14
--              pwm_resolution: PWM Resolution (Bits)
15
--              signal_output_freq: PWM Signal Output Frequency (Hz)
16
--              signal_output_freq_error: Range of PWM Signal Output Error Range (Hz)
17
-- Ports
18
--              Input   -       i_sys_clock: System Input Clock
19
--              Input   -       i_reset: Reset ('0': No Reset, '1': Reset)
20
--              Input   -       i_duty_cycle: Duty Cycle to apply (Value Range: [0;2^pwm_resolution])
21
--              Output  -       o_next_duty_cycle_trigger: Next Duty Cycle Trigger ('0': No Trigger, '1': Trigger Enable)
22
--              Output  -       o_pwm: PWM Output
23
------------------------------------------------------------------------
24
 
25
LIBRARY IEEE;
26
USE IEEE.STD_LOGIC_1164.ALL;
27
USE IEEE.NUMERIC_STD.ALL;
28
 
29
ENTITY PwmController is
30
 
31
GENERIC(
32
        sys_clock: INTEGER := 100_000_000;
33
        pwm_resolution: INTEGER := 8;
34
        signal_output_freq: INTEGER := 7;
35
        signal_output_freq_error: INTEGER := 1
36
);
37
 
38
PORT(
39
        i_sys_clock: IN STD_LOGIC;
40
    i_reset: IN STD_LOGIC;
41
        i_duty_cycle: IN UNSIGNED(pwm_resolution downto 0);
42
        o_next_duty_cycle_trigger: OUT STD_LOGIC;
43
        o_pwm: OUT STD_LOGIC
44
);
45
 
46
END PwmController;
47
 
48
ARCHITECTURE Behavioral of PwmController is
49
 
50
------------------------------------------------------------------------
51
-- Constant Declarations
52
------------------------------------------------------------------------
53
-- System Clock Period
54
constant SYSTEM_CLOCK_PERIOD: REAL := real(1) / real(sys_clock);
55
 
56
-- PWM Resolution Max Value
57
constant PWM_RESOLUTION_MAX_VALUE: INTEGER := 2**pwm_resolution;
58
 
59
-- PWM Duty Cycle Frequency
60
constant PWM_DUTY_CYCLE_FREQUENCY: INTEGER := INTEGER( PWM_RESOLUTION_MAX_VALUE * signal_output_freq);
61
 
62
-- PWM Max Clock Divider
63
constant PWM_MAX_CLOCK_DIVIDER: INTEGER := INTEGER( real(1) / (real(PWM_RESOLUTION_MAX_VALUE) * SYSTEM_CLOCK_PERIOD * real(PWM_DUTY_CYCLE_FREQUENCY) ) );
64
 
65
------------------------------------------------------------------------
66
-- Signal Declarations
67
------------------------------------------------------------------------
68
-- PWM Clock Divider & Clock Enable
69
signal pwm_clock_divider: INTEGER range 0 to PWM_MAX_CLOCK_DIVIDER := 0;
70
signal pwm_clock_enable: STD_LOGIC := '0';
71
 
72
-- PWM Counter
73
signal pwm_counter: UNSIGNED(pwm_resolution-1 downto 0) := (others => '0');
74
 
75
-- Duty Cycle Input Register
76
signal duty_cycle_reg: UNSIGNED(pwm_resolution downto 0) := (others => '0');
77
 
78
------------------------------------------------------------------------
79
-- Module Implementation
80
------------------------------------------------------------------------
81
begin
82
 
83
        --------------------------------------------------
84
        -- PWM Frequency Output Configuration Assertion --
85
        --------------------------------------------------
86
        process
87
        variable duty_cycle: real;
88
        variable signal_output_freq_min: real;
89
        variable signal_output_freq_max: real;
90
        variable signal_output_freq_actual: real;
91
        begin
92
                duty_cycle := ( real(1) / ( real(PWM_RESOLUTION_MAX_VALUE) * SYSTEM_CLOCK_PERIOD * (real(PWM_MAX_CLOCK_DIVIDER) + 1.0) ) );
93
                signal_output_freq_min := real(signal_output_freq) - real(signal_output_freq_error);
94
                signal_output_freq_max := real(signal_output_freq) + real(signal_output_freq_error);
95
                signal_output_freq_actual := ( duty_cycle / real(PWM_RESOLUTION_MAX_VALUE) );
96
 
97
                assert (signal_output_freq_min <= signal_output_freq_actual) and (signal_output_freq_actual <= signal_output_freq_max)
98
                report
99
                                "PWM Module Configuration Failure !" & LF &
100
                                "Signal Output Freq Min: " & real'image(real(signal_output_freq_min)) & LF &
101
                                "Signal Output Freq Max: " & real'image(real(signal_output_freq_max)) & LF &
102
                                "Actual Signal Output Freq: " & real'image(real(signal_output_freq_actual))
103
                severity FAILURE;
104
                wait;
105
        end process;
106
 
107
        -----------------------
108
        -- PWM Clock Divider --
109
        -----------------------
110
        process(i_sys_clock)
111
        begin
112
                if rising_edge(i_sys_clock) then
113
 
114
                        -- Reset PWM Clock Divider
115
                        if (i_reset = '1') or (PWM_MAX_CLOCK_DIVIDER = 0) or (pwm_clock_divider = PWM_MAX_CLOCK_DIVIDER -1) then
116
                                pwm_clock_divider <= 0;
117
 
118
                        -- Increment PWM Clock Divider
119
                        else
120
                                pwm_clock_divider <= pwm_clock_divider +1;
121
                        end if;
122
                end if;
123
        end process;
124
 
125
        -----------------------
126
        -- PWM Clock Enable --
127
        -----------------------
128
        process(i_sys_clock)
129
        begin
130
                if rising_edge(i_sys_clock) then
131
 
132
                        -- Reset PWM Clock Enable
133
                        if (i_reset = '1') then
134
                                pwm_clock_enable <= '0';
135
 
136
                        -- PWM Clock Enable
137
                        elsif (PWM_MAX_CLOCK_DIVIDER = 0) or (pwm_clock_divider = PWM_MAX_CLOCK_DIVIDER -1) then
138
                                pwm_clock_enable <= '1';
139
 
140
                        -- PWM Clock Disable
141
                        else
142
                                pwm_clock_enable <= '0';
143
                        end if;
144
                end if;
145
        end process;
146
 
147
        -----------------
148
        -- PWM Counter --
149
        -----------------
150
        process(i_sys_clock)
151
        begin
152
                if rising_edge(i_sys_clock) then
153
 
154
                        -- Reset PWM Counter
155
                        if (i_reset = '1') then
156
                                pwm_counter <= (others => '0');
157
 
158
                        -- PWM Clock Enable
159
                        elsif (pwm_clock_enable = '1') then
160
 
161
                                -- Increment PWM Counter
162
                                pwm_counter <= pwm_counter + 1;
163
 
164
                        end if;
165
                end if;
166
        end process;
167
 
168
        ------------------------------
169
        -- Duty Cycle Input Handler --
170
        ------------------------------
171
        process(i_sys_clock)
172
        begin
173
                if rising_edge(i_sys_clock) then
174
 
175
                        -- Reset or PWM Clock Enable and End of PWM Counter
176
                        if (i_reset = '1') or ((pwm_clock_enable = '1') and (pwm_counter = PWM_RESOLUTION_MAX_VALUE -1)) then
177
                                duty_cycle_reg <= i_duty_cycle;
178
                        end if;
179
 
180
                end if;
181
        end process;
182
 
183
        -----------------------------
184
        -- Next Duty Cycle Trigger --
185
        -----------------------------
186
        process(i_sys_clock)
187
        begin
188
                if rising_edge(i_sys_clock) then
189
 
190
                        -- PWM Clock Enable and End of PWM Counter
191
                        if (pwm_clock_enable = '1') and (pwm_counter = PWM_RESOLUTION_MAX_VALUE -1) then
192
                                o_next_duty_cycle_trigger <= '1';
193
 
194
                        else
195
                                o_next_duty_cycle_trigger <= '0';
196
                        end if;
197
 
198
                end if;
199
        end process;
200
 
201
        ----------------
202
        -- PWM Output --
203
        ----------------
204
        process(i_sys_clock)
205
        begin
206
                if rising_edge(i_sys_clock) then
207
 
208
                        -- Reset PWM Output
209
                        if (i_reset = '1') then
210
                                o_pwm <= '0';
211
 
212
                        -- PWM Clock Enable
213
                        elsif (pwm_clock_enable = '1') then
214
 
215
                                -- Reset PWM Output
216
                                if (pwm_counter >= duty_cycle_reg) then
217
                                        o_pwm <= '0';
218
 
219
                                -- Set PWM Output
220
                                else
221
                                        o_pwm <= '1';
222
                                end if;
223
                        end if;
224
 
225
                end if;
226
        end process;
227
 
228
end Behavioral;

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.