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

Subversion Repositories pwm

[/] [pwm/] [trunk/] [RTL/] [PWM.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 m99
/*Author: Zhuxu
2
        m99a1@yahoo.cn
3
Pulse Width Generators/timers with 16-bit main counter.
4
Period or timers target number is controlled by register [15:0]period.
5
Duty cycle is controlled by register [15:0]DC.
6
Clock used for PWM signal generation can be switched between Wishbone Bus clock and external clock. It is down clocked first.
7
o_pwm outputs PWM signal or timers interrupt.
8
 
9
control register [7:0]ctrl:
10
bit 0:  When set, external clock is chosen for PWM/timer. When cleared, wb clock is used for PWM/timer.
11
bit 1:  When set,  PWM is enabled. When cleared,  timer is enabled.
12
bit 2:  When set,  PWM/timer starts. When cleared, PWM/timer stops.
13
bit 3:  When set, timer runs continuously. When cleared, timer runs one time.
14
bit 4:  When set, o_pwm enabled.
15
bit 5:  timer interrupt bit     When it is written with 0, interrupt request is cleared.
16
bit 6:  When set, a 16-bit external signal i_DC is used as duty cycle. When cleared, register DC is used.
17
bit 7:  When set, counter reset for PWM/timer, it's output and bit 5 will also be cleared. When changing from PWM mode to timer mode reset is needed before timer starts.
18
*/
19
module  PWM(
20
//wishbone slave interface
21
input   i_wb_clk,
22
input   i_wb_rst,
23
input   i_wb_cyc,
24
input   i_wb_stb,
25
input   i_wb_we,
26
input   [15:0]i_wb_adr,
27
input   [15:0]i_wb_data,
28
output  [15:0]o_wb_data,
29
output  o_wb_ack,
30
 
31
input   i_extclk,
32
input   [15:0]i_DC,
33
input   i_valid_DC,
34
output  o_pwm
35
 
36
);
37
 
38
////////////////////control logic////////////////////////////
39
parameter       adr_ctrl=0,
40
                adr_divisor=2,
41
                adr_period=4,
42
                adr_DC=6;
43
reg     [7:0]ctrl;
44
reg     [15:0]period;
45
reg     [15:0]DC;
46
reg     [15:0]divisor;   //for down clocking. If(divisor==0)To=Ti;       else To=Ti/divisor;
47
integer i;
48
wire    write;
49
assign  write=i_wb_cyc&i_wb_stb&i_wb_we;
50
assign  o_wb_ack=i_wb_stb;
51
always@(posedge i_wb_clk or posedge i_wb_rst)
52
        if(i_wb_rst)begin
53
                ctrl[4:0]<=0;
54
                ctrl[7:6]<=0;
55
                DC<=0;
56
                period<=0;
57
                divisor<=0;
58
        end
59
        else if(write)begin
60
                case(i_wb_adr)
61
                        adr_ctrl:begin
62
                                ctrl[4:0]<=i_wb_data[4:0];
63
                                ctrl[7:6]<=i_wb_data[7:6];
64
                        end
65
                        adr_divisor:divisor<=i_wb_data;
66
                        adr_period:period<=i_wb_data;
67
                        adr_DC:DC<=i_wb_data;
68
                endcase
69
        end
70
 
71
//interrupt bit control
72
wire    pwm;
73
assign  pwm=ctrl[1];
74
reg     [1:0]state;
75
reg     clrint;         //signal to pwm/timer  logic
76
wire    ack_clrint;     //signal from pwm/timer  logic
77
wire    int;            //signal from pwm/timer  logic
78
always@(posedge i_wb_clk or posedge i_wb_rst)
79
        if(i_wb_rst)begin
80
                ctrl[5]<=0;
81
                state<=0;
82
                clrint<=0;
83
        end
84
        else begin
85
                case(state)
86
                        1:begin
87
                                if(write)begin
88
                                        if(i_wb_data[7])begin
89
                                                ctrl[5]<=0;
90
                                                state<=0;
91
                                        end
92
                                        else if(!i_wb_data[5])begin
93
                                                ctrl[5]<=0;
94
                                                if(!pwm)begin
95
                                                        clrint<=1;
96
                                                        state<=2;
97
                                                end
98
                                                else state<=0;
99
                                        end
100
                                end
101
                        end
102
                        2:if(ack_clrint)begin
103
                                clrint<=0;
104
                                state<=0;
105
                        end
106
                        default:begin
107
                                if(!pwm)ctrl[5]<=int;
108
                                if(int)state<=1;
109
                        end
110
                endcase
111
        end
112
 
113
 
114
///////////////////////////////////////////////////////////
115
 
116
//////down clocking for pwm/timer///////////////////
117
wire    clk_source;
118
wire    eclk,oclk;
119
assign  clk_source=ctrl[0]?i_extclk:i_wb_clk;
120
down_clocking_even      down_clocking_even_0(
121
clk_source,
122
(!i_wb_rst),
123
{1'b0,divisor[15:1]},
124
eclk
125
);
126
down_clocking_odd       down_clocking_odd_0(
127
clk_source,
128
(!i_wb_rst),
129
{1'b0,divisor[15:1]},
130
oclk
131
);
132
wire    clk;
133
assign  clk=divisor[0]?oclk:eclk;
134
///////////////////////////////////////////////////////
135
 
136
/////////////////main counter //////////////////////////
137
reg     [15:0]ct;
138
reg     pts;    //PWM signal or timer interrupt signal
139
reg     [15:0]extDC;
140
wire    [15:0]DC_1;
141
assign  DC_1=ctrl[6]?extDC:DC;  //external or internal duty cycle toggle
142
wire    [15:0]period_1;
143
assign  period_1=(period==0)?0:(period-1);
144
reg     switch_ack_clrint;
145
wire    state_timer;
146
assign  state_timer=ctrl[3];
147
wire    rst_ct;
148
assign  rst_ct=i_wb_rst|ctrl[7];
149
assign  int=pwm?0:pts;
150
assign  ack_clrint=switch_ack_clrint?clrint:0;
151
always@(posedge clk or posedge rst_ct)
152
        if(rst_ct)begin
153
                pts<=0;
154
                ct<=0;
155
                switch_ack_clrint<=0;
156
                extDC<=0;
157
        end
158
        else begin
159
        if(i_valid_DC)extDC<=i_DC;
160
        if(switch_ack_clrint&&(!clrint))switch_ack_clrint<=0;
161
        if(ctrl[2])begin
162
                case(pwm)
163
                        1:begin
164
                                if(ct>=period_1)ct<=0;
165
                                else ct<=ct+1;
166
 
167
                                if(ct<DC_1)pts<=1;
168
                                else pts<=0;
169
                        end
170
                        0:begin
171
 
172
                                case(state_timer)
173
                                        0:begin
174
                                                if(clrint)switch_ack_clrint<=1;
175
                                                if(ct>=period_1)begin
176
                                                        if(clrint)begin
177
                                                                pts<=0;
178
                                                                ct<=0;
179
                                                        end
180
                                                        else pts<=1;
181
 
182
                                                end
183
                                                else ct<=ct+1;
184
                                        end
185
                                        1:begin
186
                                                if(ct>=period_1)begin
187
                                                        pts<=1;
188
                                                        ct<=0;
189
                                                end
190
                                                else begin
191
                                                        if(clrint)begin
192
                                                                switch_ack_clrint<=1;
193
                                                                pts<=0;
194
                                                        end
195
                                                        ct<=ct+1;
196
                                                end
197
                                        end
198
                                endcase
199
                        end
200
                endcase
201
        end
202
        else if(clrint)begin
203
                switch_ack_clrint<=1;
204
                if(!pwm)begin
205
                        pts<=0;
206
                        ct<=0;
207
                end
208
        end
209
        end
210
//////////////////////////////////////////////////////////
211
 
212
assign  o_pwm=ctrl[4]?pts:0;
213
assign  o_wb_data=      i_wb_adr==adr_ctrl?{8'h0,ctrl}:
214
                        i_wb_adr==adr_divisor?divisor:
215
                        i_wb_adr==adr_period?period:
216
                        i_wb_adr==adr_DC?DC:0;
217
 
218
 
219
endmodule

powered by: WebSVN 2.1.0

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