|
似乎坛子里做光电编码器相关项目的兄弟还不少,发个FPGA实现的90度相位差A、B两相脉冲计数的程序上来(Z相被54了).
看了几个兄弟的写法,似乎都有点问题,乱说几点:
1、四倍频是必须的,这个跟编码器的结构有关
2、初始状态可能不是 A=0,B=0,(对于伺服电机尤其如此)
3、适当的隔离和滤波也是必须的
刚开始的时候接手摇编码器,计数器值老是有差。接伺服电机就更夸张,计数都计到天上去了.
纠结了两天才弄成,在伺服电机上和手摇编码器上测了一段时间没发现问题(阿弥陀佛).
FSM实现,个人觉得不是最优的方法,请高手指点.
FSM主状态转换图:
![](http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_574663.JPG)
总共13个状态,全画出来烦死,知道意思就好:) (原文件名:coderFSM.JPG)
源程序:
/*******************************************************************
** Company :
** Project Name :
** Author :
** Creation Date : 2010.07
** Version Number : 1.0
**
** Description :
**
**
**
** Revision History :
**
** Date Initials Modification
**
**
**********************************************************************/
module coder_counter(
clk, //system clock
en, //enable(low active)
load, //asynchronous load signal(high active)
diff_a, //A phasic pulse input
diff_b, //B phasic pulse input
load_data, //asynchronous load data
counter, //counter data
err //counter error signal(high active)
);
/*****************************************************************************
* Parameter Declarations *
*****************************************************************************/
parameter DATA_WIDTH = 32;
parameter IDLE='d0,ALBL_ADD='d1,ALBL_SUB='d2,ALBL='d3,AHBL_ADD='d4,AHBL_SUB='d5,AHBL='d6,
AHBH_ADD='d7,AHBH_SUB='d8,AHBH='d9,ALBH_ADD='d10,ALBH_SUB='d11,ALBH='d12,ERR='d13;
/*****************************************************************************
* Port Declarations *
*****************************************************************************/
input clk,en,load,diff_a,diff_b;
input [DATA_WIDTH-1:0]load_data;
output reg[DATA_WIDTH-1:0]counter;
output reg err;
/*****************************************************************************
* Internal wires and registers Declarations *
*****************************************************************************/
reg [3:0]state,n_state;
//wire reset_n = ~load;
wire [1:0]signal = {diff_b,diff_a};
/*****************************************************************************
* Finite State Machine *
*****************************************************************************/
always@(posedge clk or posedge load)
begin
if(load)
state <= IDLE;
else
state <= n_state;
end
always@(en or signal or state)
begin
case(state)
IDLE:
begin
if(en == 1)
n_state <= IDLE;
else
begin
case(signal)
'b00:n_state <= ALBL;
'b01:n_state <= AHBL;
'b10:n_state <= ALBH;
'b11:n_state <= AHBH;
endcase
end
end
ALBL_ADD:n_state <= ALBL;
ALBL_SUB:n_state <= ALBL;
ALBL://00
begin
case(signal)
'b00:n_state <= ALBL;
'b01:n_state <= AHBL_ADD;
'b10:n_state <= ALBH_SUB;
'b11:n_state <= ERR;
endcase
end
AHBL_ADD:n_state <= AHBL;
AHBL_SUB:n_state <= AHBL;
AHBL://01
begin
case(signal)
'b00:n_state <= ALBL_SUB;
'b01:n_state <= AHBL;
'b10:n_state <= ERR;
'b11:n_state <= AHBH_ADD;
endcase
end
AHBH_ADD:n_state <= AHBH;
AHBH_SUB:n_state <= AHBH;
AHBH://11
begin
case(signal)
'b00:n_state <= ERR;
'b01:n_state <= AHBL_SUB;
'b10:n_state <= ALBH_ADD;
'b11:n_state <= AHBH;
endcase
end
ALBH_ADD:n_state <= ALBH;
ALBH_SUB:n_state <= ALBH;
ALBH://10
begin
case(signal)
'b00:n_state <= ALBL_ADD;
'b01:n_state <= ERR;
'b10:n_state <= ALBH;
'b11:n_state <= AHBH_SUB;
endcase
end
ERR:n_state <= ERR;
default:n_state <= IDLE;
endcase
end
always@(posedge clk)
begin
case(state)
IDLE:
begin
counter <= load_data;
err <= 0;
end
ALBL_ADD:
begin
counter <= counter + 1'b1;
err <= 1'b0;
end
ALBL_SUB:
begin
counter <= counter - 1'b1;
err <= 1'b0;
end
ALBL:
begin
counter <= counter;
err <= 1'b0;
end
AHBL_ADD:
begin
counter <= counter + 1'b1;
err <= 1'b0;
end
AHBL_SUB:
begin
counter <= counter - 1'b1;
err <= 1'b0;
end
AHBL:
begin
counter <= counter;
err <= 1'b0;
end
AHBH_ADD:
begin
counter <= counter + 1'b1;
err <= 1'b0;
end
AHBH_SUB:
begin
counter <= counter - 1'b1;
err <= 1'b0;
end
AHBH:
begin
counter <= counter;
err <= 1'b0;
end
ALBH_ADD:
begin
counter <= counter + 1'b1;
err <= 1'b0;
end
ALBH_SUB:
begin
counter <= counter - 1'b1;
err <= 1'b0;
end
ALBH:
begin
counter <= counter;
err <= 1'b0;
end
ERR:
begin
counter <= counter;
err <= 1'b1;
end
default:
begin
counter <= counter;
err <= err;
end
endcase
end
endmodule
程序文件:
增量式光电编码器计数器verilog程序ourdev_574664.rar(文件大小:1K) (原文件名:coder_counter.rar) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|