[笔记].小练Verilog版本PWM驱动步进电机
硬件:MAX II EPM240T100C5
软件:Quartus II 10.0
step_motor.v
module step_motor
//#(parameter RPM50 = 40, RPM300 = 6)
#(parameter RPM50 = 1000, RPM300 = 3)
(
// global clock and asyn reset
input CLOCK_50,
input RST_N,
// step motor interface
output wire ENA,
output wire PUL,
output wire DIR,
//test
output wire PIN_64
);
//assign PIN_64 = pwm_out;
localparam SUBDIVISION = 64;
function integer log2(input integer n);
integer i;
for(i=0; 2**i <=n; i=i+1) log2=i+1;
endfunction
// generate 6KHz tick
localparam DIV_50M_INTO_6K = 8333 / SUBDIVISION;
reg [log2(DIV_50M_INTO_6K):1] cnt0; // 0~8332
always@(posedge CLOCK_50)
if(DIV_50M_INTO_6K-1 == cnt0) cnt0 <= 0;
else cnt0 <= cnt0 + 1'b1;
wire tick_6KHz = (DIV_50M_INTO_6K-1 == cnt0) ? 1 : 0;
// generate pulse signal at low frequency
localparam DIV_1SEC = 50_000_000; // 10Hz
reg [log2(DIV_1SEC):1] cnt1;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) cnt1 <= 0;
else if (cnt1 == DIV_1SEC - 1) cnt1 <= 0;
else cnt1 <= cnt1 + 1;
reg [log2(RPM50):1] period;
reg acc_dec;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) begin
period <= RPM50;
//acc_dec <= 0;
end
else if(cnt1 == DIV_1SEC - 1) begin
//if(period == RPM300) acc_dec <= ~acc_dec;
//if(acc_dec) begin
if(period == RPM300) period <= RPM50;
else period <= period - 1;
//end
//period <= RPM50;
//else period <= period - 1;
end
wire adjust_enable = (cnt1 == DIV_1SEC - 1) ? 1 : 0;
/* PWM */
wire pwm_out;
pwm_generator #(.N(log2(RPM50)), .START_SPEED(RPM50)) pwm_generator_inst
(
// global clock and asyn reset
.CLOCK_50(CLOCK_50),
.RST_N(RST_N),
// clock enable tick
.clock_enable(tick_6KHz),
// PWM interface
.adjust_enable(adjust_enable),
.period(period),
.pwm_out(pwm_out)
);
assign PUL = pwm_out;
assign ENA = 1;
assign DIR = 0;
endmodule
pwm_generator.v
module pwm_generator
#(parameter N=10, START_SPEED = 100)
(
// global clock and asyn reset
input CLOCK_50,
input RST_N,
// clock enable tick
input clock_enable,
// PWM interface
input adjust_enable,
input [N:1] period,
output reg pwm_out
);
reg [N:1] period_r;
reg [N:1] pulse_width_r;
// pass the parameter
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) begin
period_r <= START_SPEED;
pulse_width_r <= START_SPEED >> 1;
end
else if(adjust_enable) begin
period_r <= period;
pulse_width_r <= period >> 1;
end
// counter
reg [N:1] cnt;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) cnt <= 0;
else if(clock_enable) begin
if(cnt == period_r) cnt <= 0;
else cnt <= cnt + 1'b1;
end
// generate pulse
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) pwm_out <= 0;
else if(clock_enable) begin
if(cnt < pulse_width_r) pwm_out <= 1;
else pwm_out <= 0;
end
endmodule


浙公网安备 33010602011771号