-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathpwm.vhd
167 lines (145 loc) · 5.65 KB
/
pwm.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
--**********************************************************************
-- Copyright (c) 2011-2014 by XESS Corp <http://www.xess.com>.
-- All rights reserved.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 3.0 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library. If not, see
-- <http://www.gnu.org/licenses/>.
--**********************************************************************
--*********************************************************************
-- Modules for generating repetitive or single pulses.
--*********************************************************************
library IEEE, XESS;
use IEEE.std_logic_1164.all;
use XESS.CommonPckg.all;
package PulsePckg is
--*********************************************************************
-- PWM module.
--*********************************************************************
component Pwm is
port (
clk_i : in std_logic; -- Input clock.
duty_i : in std_logic_vector; -- Duty-cycle input.
pwm_o : out std_logic -- PWM output.
);
end component;
--**********************************************************************
-- Generate a triggered pulse with a lockout interval after the trigger.
--**********************************************************************
component PulseGen is
generic (
FREQ_G : real; -- Clock frequency (MHz).
LOCKOUT_TIME_G : real; -- Lockout time after trigger (us).
PULSE_WIDTH_G : real -- Pulse duration (us).
);
port (
clk_i : in std_logic; -- Input clock.
trigger_i : in std_logic; -- Pulse trigger.
lockout_o : out std_logic; -- Lockout indicator.
pulse_o : out std_logic -- Output pulse.
);
end component;
end package;
--*********************************************************************
-- PWM module.
--*********************************************************************
library IEEE, UNISIM, XESS;
use IEEE.MATH_REAL.all;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use UNISIM.vcomponents.all;
use XESS.CommonPckg.all;
use XESS.PulsePckg.all;
entity Pwm is
port (
clk_i : in std_logic; -- Input clock.
duty_i : in std_logic_vector; -- Duty-cycle input.
pwm_o : out std_logic -- PWM output.
);
end entity;
architecture arch of Pwm is
constant MAX_DUTY_C : std_logic_vector(duty_i'range) := (duty_i'range => ONE);
signal timer_r : natural range 0 to 2**duty_i'length-1;
begin
process(clk_i)
begin
if rising_edge(clk_i) then
pwm_o <= LO;
timer_r <= timer_r + 1;
if timer_r < TO_INTEGER(unsigned(duty_i)) then
pwm_o <= HI;
end if;
end if;
end process;
end architecture;
--**********************************************************************
-- Generate a triggered pulse with a lockout interval after the trigger.
--**********************************************************************
library IEEE, XESS;
use IEEE.MATH_REAL.all;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use XESS.CommonPckg.all;
entity PulseGen is
generic (
FREQ_G : real; -- Clock frequency (MHz).
LOCKOUT_TIME_G : real; -- Lockout time after trigger (us).
PULSE_WIDTH_G : real -- Pulse duration (us).
);
port (
clk_i : in std_logic; -- Input clock.
trigger_i : in std_logic; -- Pulse trigger.
lockout_o : out std_logic; -- Lockout indicator.
pulse_o : out std_logic -- Output pulse.
);
end entity;
architecture arch of PulseGen is
signal prevTrigger_r : std_logic;
begin
process(clk_i)
constant LOCKOUT_TIME_C : natural := integer(round(FREQ_G * LOCKOUT_TIME_G));
constant PULSE_WIDTH_C : natural := integer(round(FREQ_G * PULSE_WIDTH_G));
variable lockoutCnt_v : natural range 0 to LOCKOUT_TIME_C;
variable pulseCnt_v : natural range 0 to PULSE_WIDTH_C;
begin
if rising_edge(clk_i) then
-- The pulse output is high as long as the pulse counter is
-- non-zero. Once the pulse counter decrements to zero, the
-- pulse output is lowered and the counter decrements stop.
if pulseCnt_v /= 0 then
pulse_o <= HI;
pulseCnt_v := pulseCnt_v - 1;
else
pulse_o <= LO;
end if;
-- The lockout output is active as long as the lockout counter
-- is non-zero. Once the lockout counter decrements to zero, the
-- lockout output is deactivated and the counter decrements stop.
-- After the lockout expires, triggers will once again be accepted.
-- A rising edge on the trigger will cause another lockout and will
-- start the generation of an output pulse.
if lockoutCnt_v /= 0 then
lockout_o <= HI;
lockoutCnt_v := lockoutCnt_v - 1;
else
lockout_o <= LO;
if trigger_i = HI and prevTrigger_r = LO then
lockoutCnt_v := LOCKOUT_TIME_C;
pulseCnt_v := PULSE_WIDTH_C;
pulse_o <= HI;
end if;
end if;
prevTrigger_r <= trigger_i;
end if;
end process;
end architecture;