[笔记].小练Verilog版本PWM驱动步进电机
0赞
发表于 4/26/2011 4:46:52 PM
阅读(10918)
硬件: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