原创 QEP解码器实现

2010-10-9 08:10 3629 7 7 分类: FPGA/CPLD

QEP解码


       QEP解码即将两路相位相差90度传感器信号转换为方向dir,脉冲plus,脉冲数量counter(根据方向和脉冲得出的绝对脉冲数)。


       本程序采用下表所示关系做QEP解码


 



       程序中,输入为clk,rst,a, b,输出为dir, plus, counter。程序中HITHTIME用来控制plus高电平时间。


程序如下:


/*************************************************


//module name:qepdecode


//designer:kang


//date:2010-10-08


*************************************************/


module qepdecode(


                            //input signals


                            clk,


                            rst,


                            a,


                            b,


                            //output signals


                            dir,


                            plus,


                            counter


                            );


input clk;


input rst;


input a;


input b;


 


output dir;


output plus;


output [15:0] counter;


reg dir;


reg plus;


reg [15:0] counter;


 


reg [1:0] priorba;  


reg [1:0] nowba;


reg [3:0] prioredge;


reg [3:0] nowedge;


wire [3:0] saveab;


wire [7:0] saveedge;


reg [3:0] sign;


reg cp;


reg [15:0] counter_plush;


 


parameter IDLE=4'h0;


parameter UPA=4'h1;


parameter DOWNA=4'h2;


parameter UPB=4'h3;


parameter DOWNB=4'h4;


parameter HIGHTIME=16'd0;


 


assign saveab={priorba,nowba};


assign saveedge={prioredge,nowedge};


 


//save nowstate and prior


always @(posedge clk or negedge rst)


       begin


       if(!rst)


              begin


              nowba<=2'b00;


              priorba<=2'b00;


              end


       else


              begin


              nowba<={b,a};


              priorba<=nowba;


              end


       end


 


//save the edge change of a and b


always @(posedge clk or negedge rst)


       begin


       if(!rst)


              begin


              prioredge<=IDLE;


              nowedge<=IDLE;


              cp<=0;


              end


       else


              begin


              case(saveab)


              4'b0001:begin


                            prioredge<=nowedge;


                            nowedge<=UPA;


                            cp<=1;


                            end


              4'b1011:begin


                            prioredge<=nowedge;


                            nowedge<=UPA;


                            cp<=1;


                            end


              4'b0010:begin


                            prioredge<=nowedge;


                            nowedge<=UPB;


                            cp<=1;


                            end


              4'b0111:begin


                            prioredge<=nowedge;


                            nowedge<=UPB;


                            cp<=1;


                            end


              4'b0100:begin


                            prioredge<=nowedge;


                            nowedge<=DOWNA;


                            cp<=1;


                            end


              4'b1110:begin


                            prioredge<=nowedge;


                            nowedge<=DOWNA;


                            cp<=1;


                            end


              4'b1000:begin


                            prioredge<=nowedge;


                            nowedge<=DOWNB;


                            cp<=1;


                            end


              4'b1101:begin


                            prioredge<=nowedge;


                            nowedge<=DOWNB;


                            cp<=1;


                            end


              default:cp<=0;


              endcase


              end


       end


 


//direction make


//"sign" allows direction reverse


always @(posedge clk or negedge rst)


       begin


       if(!rst)


              begin


              sign<=4'b1111;


              dir<=1;


              end


       else


              begin


              case(saveedge)


              8'h13:                           //upa and upb


                     begin     


                     dir<=1;


                     sign<=4'b1111;


                     end                                    


              8'h14:                           //upa and downb


                     begin


                     dir<=0;


                     sign<=4'b1111;


                     end                                    


              8'h12:if(sign[0])            //upa and downa


                     begin


                     dir<=!dir;


                     sign<=4'b1110;


                     end                                    


              8'h24:                           //downa and downb


                     begin


                     dir<=1;


                     sign<=4'b1111;


                     end                                    


              8'h23:                           //downa and upb


                     begin


                     dir<=0;


                     sign<=4'b1111;


                     end                                    


              8'h21:if(sign[1])            //downa and upa


                     begin


                     dir<=!dir;


                     sign<=4'b1101;      


                     end                                    


              8'h31:                           //upb and upa


                     begin


                     dir<=0;


                     sign<=4'b1111;


                     end                                    


              8'h32:                           //upb and downa


                     begin


                     dir<=1;


                     sign<=4'b1111;


                     end                                    


              8'h34:if(sign[2])            //upb and downb


                     begin


                     dir<=!dir;


                     sign<=4'b1011;


                     end                                    


              8'h42:                           //downb and downa


                     begin


                     dir<=0;


                     sign<=4'b1111;


                     end                                    


              8'h41:                           //downb and upa


                     begin


                     dir<=1;


                     sign<=4'b1111;


                     end                                    


              8'h43:if(sign[3])            //downb and upb


                     begin


                     dir<=!dir;


                     sign<=4'b0111;


                     end                                    


              default:; 


              endcase  


              end


       end


 


//counter


always @(posedge clk or negedge rst)


       begin


       if(!rst) counter<=16'h0;


       else


              if(cp)


                     if(dir) counter<=counter+1'b1;


                     else if(counter>0) counter<=counter-1'b1;


       end


 


//counter_plush


always @(posedge clk or negedge rst)


       begin


       if(!rst) counter_plush<=HIGHTIME+1'b1;


       else if(cp) counter_plush<=0;


       else counter_plush<=counter_plush+1'b1;


       end


 


//plus


always @(posedge clk or negedge rst)


       begin


       if(!rst) plus<=0;


       else if(counter_plush<=HIGHTIME) plus<=1;


       else plus<=0;


       end


 


endmodule


仿真波形


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条