-
Notifications
You must be signed in to change notification settings - Fork 2
/
pwm.v
92 lines (79 loc) · 2.53 KB
/
pwm.v
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
`timescale 1ns/10ps
/*
pwm.v
(C) 2021-07-08 Samuel B Powell
Pulse width modulation with spread-spectrum mode.
When SpreadSpectrum is zero, the output is asserted when the internal counter
is less than the duty cycle value. The flicker period in this case is the full
counter period: flicker_period = clock_period * pow(2, Bits)
When SpreadSpectrum is n > 0, the high n bits of the counter are reversed and rotated
to be the least significant bits before comparing to the duty cycle value. This
decreases the minimum flicker period of the output to:
flicker_period = clock_period * pow(2, Bits - SpreadSpectrum)
E.g. Bits = 3, duty_cycle = 5 (62.5%)
SpreadSpectrum = 0
count: 000 001 010 011 100 101 110 111
out: 1 1 1 1 1 0 0 0
SpreadSpectrum = 1 (splits the total period into 2)
count: 000 010 100 110 | 001 011 101 111
out: 1 1 1 0 | 1 1 0 0
SpreadSpectrum = 2 (splits the total period into 4)
count: 000 100 | 010 110 | 001 101 | 011 111
out: 1 1 | 1 0 | 1 0 | 1 0
//Instantiation template
module pwm #(
.Bits(8),
.ActiveHigh(1),
.SpreadSpectrum(7) // 0 <= SpreadSpectrum < Bits
)(
.clk(), // in
.reset(), // in: synchronous, on posedge clk
.enable(), // in
.set_duty(), // in
.duty_cycle(), // in [Bits]: latched on posedge clk when set_duty is asserted
.out() //out: modulated when enable is asserted
);
*/
module pwm #(
parameter Bits = 8,
parameter ActiveHigh = 1,
parameter SpreadSpectrum = 1
)(
input wire clk,
input wire reset,
input wire enable,
input wire set_duty,
input wire [Bits:0] duty_cycle,
output reg out
);
reg [Bits-1:0] state, state_spread;
reg [Bits:0] duty;
reg comp;
integer i;
always @* begin
//the LSBs of state_spread are the reversed MSBs of state
for(i = 0; i < SpreadSpectrum; i = i + 1)
state_spread[i] = state[Bits - 1 - i];
//the MSBs of state_spread are the LSBs of state
for(i = SpreadSpectrum; i < Bits; i = i + 1)
state_spread[i] = state[i - SpreadSpectrum];
//compare
comp = (state_spread < duty);
end
always @(posedge clk) begin
if(reset) begin
state <= 0;
duty <= 0;
out <= ~|ActiveHigh;
end else begin
if(set_duty) begin
duty <= duty_cycle;
end
if(enable) begin
state <= state + 1;
out <= ~(comp ^ (|ActiveHigh));
end
end
end
endmodule