仿制HCTL-2016的旋转增量(正交)编码器计数器
最近要用到旋转增量(正交)编码器,想买HCTL-2016,找不到货源,干脆自己现学VerilogHDL,做了一个解码器,呵呵
望大家批评指正,开发环境Quartus II 7.2
//给懒人们贴上来,干脆
// ***************************************************************
//
// AB_DECODER.v Decoder for phase A and B encoder
//
// V1.00 2009-6-04
//
// Design by cqfeiyu in chongqing, all right reserved
//
// ***************************************************************
module AB_DECODER
(
DI_SYSCLK,
DI_PHASE_A,
DI_PHASE_B,
DI_PHASE_Z,
DI_ADDER,
DI_RD,
DI_OE,
DO_PULSE,
DO_DIRECT,
DO_COUNT
);
// input
//
input DI_SYSCLK;
input DI_PHASE_A;
input DI_PHASE_B;
input DI_PHASE_Z;
input DI_RD;
input DI_OE;
input [1:0] DI_ADDER;
// output
//
output DO_PULSE;
output DO_DIRECT;
output [7:0] DO_COUNT;
// register
//
reg [23:0] ENCODER_COUNT;
reg [7:0] DO_COUNT;
reg [3:0] COUNT_PHASE_A;
reg [3:0] COUNT_PHASE_B;
reg [3:0] COUNT_PHASE_Z;
reg PULSE;
reg PULSE_LAST;
reg DO_DIRECT;
reg PHASE_A;
reg PHASE_B;
reg PHASE_Z;
reg PULSE_DOUBLE;
reg PULSE_DOUBLE_LAST;
reg PHASE_A_LAST;
reg PHASE_B_LAST;
reg PHASE_Z_LAST;
reg DI_RD_LAST;
reg DO_PULSE1;
reg DO_PULSE2;
reg DO_PULSE3;
reg DO_PULSE4;
assign DO_PULSE=PULSE_LAST;
always @(posedge DI_SYSCLK) begin
COUNT_PHASE_A <= COUNT_PHASE_A << 1;
COUNT_PHASE_A[0] <= DI_PHASE_A;
COUNT_PHASE_B <= COUNT_PHASE_B << 1;
COUNT_PHASE_B[0] <= DI_PHASE_B;
COUNT_PHASE_Z <= COUNT_PHASE_Z << 1;
COUNT_PHASE_Z[0] <= DI_PHASE_Z;
end
always @(posedge DI_SYSCLK) begin
if(COUNT_PHASE_A == 4'b1111)
PHASE_A = 1'B1;
else PHASE_A = 1'B0;
PHASE_A_LAST <= PHASE_A;
DO_PULSE1 <= (!PHASE_A_LAST)& PHASE_A;
DO_PULSE2 <= PHASE_A_LAST & (!PHASE_A);
end
always @(posedge DI_SYSCLK) begin
if(COUNT_PHASE_B == 4'b1111)
PHASE_B = 1'B1;
else PHASE_B = 1'B0;
PHASE_B_LAST <= PHASE_B;
DO_PULSE3 <= (!PHASE_B_LAST)& PHASE_B;
DO_PULSE4 <= PHASE_B_LAST & (!PHASE_B);
end
always @(posedge DI_SYSCLK) begin
if(COUNT_PHASE_Z == 4'b1111)
PHASE_Z = 1'B1;
else PHASE_Z = 1'B0;
PHASE_Z_LAST <= PHASE_Z;
end
always PULSE = DO_PULSE1 | DO_PULSE2 | DO_PULSE3 | DO_PULSE4;
always @(posedge DI_SYSCLK) begin
if((DO_PULSE1 & PHASE_B) | (DO_PULSE2 & !PHASE_B) | (DO_PULSE3 & !PHASE_A) | (DO_PULSE4 & PHASE_A))DO_DIRECT<=1;
else if((DO_PULSE1 & !PHASE_B) | (DO_PULSE2 & PHASE_B) | (DO_PULSE3 & PHASE_A) | (DO_PULSE4 & !PHASE_A))DO_DIRECT<=0;
end
always @(posedge DI_SYSCLK) begin
PULSE_LAST<=PULSE;
if((PHASE_Z_LAST==1)&&(PHASE_Z==0))ENCODER_COUNT = 24'd0;
else if(PULSE_LAST)begin
if(DO_DIRECT)ENCODER_COUNT<=ENCODER_COUNT + 1'b1;
else ENCODER_COUNT<=ENCODER_COUNT- 1'b1;
end
end
always @(posedge DI_SYSCLK) begin
DI_RD_LAST<=DI_RD;
if(DI_OE==1)DO_COUNT<=8'bZ;
else if((DI_RD_LAST==0)&&(DI_RD==1))begin
case(DI_ADDER)
0: DO_COUNT<=8'd0;
1: DO_COUNT<=ENCODER_COUNT[7:0];
2: DO_COUNT<=ENCODER_COUNT[15:8];
3: DO_COUNT<=ENCODER_COUNT[23:16];
//default: DO_COUNT<=8'bZ;
endcase
end
end
endmodule |