[笔记].小练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
posted @ 2011-04-16 01:49  _安德鲁  阅读(4418)  评论(2编辑  收藏  举报