-
Notifications
You must be signed in to change notification settings - Fork 380
/
pwm_modulator.sv
89 lines (66 loc) · 2.11 KB
/
pwm_modulator.sv
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
//------------------------------------------------------------------------------
// pwm_modulator.sv
// Konstantin Pavlov, pavlovconst@gmail.com
//------------------------------------------------------------------------------
// INFO ------------------------------------------------------------------------
// Pulse width modulation (PWM) generator module
//
// - expecting 8-bit control signal input by default
// - system clock is 100 MHz by default
// - PWM clock is 1.5KHz by default
//
// - see also pdm_modulator.sv for pulse density modulation generator
/* --- INSTANTIATION TEMPLATE BEGIN ---
pwm_modulator #(
.PWM_PERIOD_DIV( 16 ) // 100MHz/2^16= ~1.526 KHz
.MOD_WIDTH( 8 ) // from 0 to 255
) pwm1 (
.clk( clk ),
.nrst( nrst ),
.control( ),
.pwm_out( ),
.start_strobe( ),
.busy( )
);
--- INSTANTIATION TEMPLATE END ---*/
module pwm_modulator #( parameter
CLK_HZ = 100_000_000,
PWM_PERIOD_DIV = 16, // must be > MOD_WIDTH
PWM_PERIOD_HZ = CLK_HZ / (2**PWM_PERIOD_DIV),
MOD_WIDTH = 8 // modulation bitness
)(
input clk, // system clock
input nrst, // negative reset
input [MOD_WIDTH-1:0] mod_setpoint, // modulation setpoint
output pwm_out, // active HIGH output
// status outputs
output start_strobe, // period start strobe
output busy // busy output
);
// period generator
logic [31:0] div_clk;
clk_divider #(
.WIDTH( 32 )
) cd1 (
.clk( clk ),
.nrst( nrst ),
.ena( 1'b1 ),
.out( div_clk[31:0] )
);
// optional setpoint inversion
logic [MOD_WIDTH-1:0] mod_setpoint_inv;
assign mod_setpoint_inv[MOD_WIDTH-1:0] = {MOD_WIDTH{1'b1}} - mod_setpoint[MOD_WIDTH-1:0];
// pulse generator
pulse_gen #(
.CNTR_WIDTH( MOD_WIDTH+1 )
) pg1 (
.clk( div_clk[(PWM_PERIOD_DIV-1)-MOD_WIDTH] ),
.nrst( nrst ),
.start( 1'b1 ),
.cntr_max( {1'b0, {MOD_WIDTH{1'b1}} } ),
.cntr_low( {1'b0, mod_setpoint_inv[MOD_WIDTH-1:0] } ),
.pulse_out( pwm_out ),
.start_strobe( start_strobe ),
.busy( busy )
);
endmodule