开关量在检测过程中可能会产生抖动,程序需要进行必要的滤波处理。
CLK: 时钟,这里接入25M的时钟,WOBBLE_DELAY参数是抖动时间,它的值根据时钟的不同改变。
EN:检测开关。
LOGIC_IN: 开关量的输入引脚。
LOGIC_IN_MASK:开关量的屏蔽位。
LOGIC_IN_INT:开关量中断。
LOGIC_IN_STATE: 开关量的状态,仅在打开检测开关(EN)时读入的值有效。
CLEAR_INT:中断来临后,主机读取中断后写入1清中断。
module LogicInMan
#(parameter WOBBLE_DELAY = 10 * 25000)
(
CLK, EN, LOGIC_IN, LOGIC_IN_MASK, LOGIC_IN_INT, LOGIC_IN_STATE, CLEAR_INT
);
input CLK, EN;
input[7:0] LOGIC_IN;
input[7:0] LOGIC_IN_MASK;
output LOGIC_IN_INT;
output[7:0] LOGIC_IN_STATE;
inout CLEAR_INT;
reg LOGIC_IN_INT;
reg clear_int_reg;
reg[7:0] validLogicInStu;
reg[7:0] orginLogicInStu;
reg[7:0] lastLogicIn, curLogicIn;
wire[7:0] logic_in_state;
assign logic_in_state = validLogicInStu ^ orginLogicInStu;
assign LOGIC_IN_STATE = logic_in_state;
always @(posedge CLK)
begin
if(!EN)
orginLogicInStu <= validLogicInStu;
lastLogicIn <= curLogicIn;
curLogicIn <= LOGIC_IN;
end
wire time_dly;
wire start_dly;
assign start_dly = (curLogicIn == lastLogicIn)?1'b1:1'b0;
reg time_dly1, time_dly2;
wire time_dly_tig;
assign time_dly_tig = time_dly1 & ~time_dly2;
always @(posedge CLK)
begin
time_dly1 <= time_dly;
time_dly2 <= time_dly1;
end
always @(posedge CLK)
begin
if(time_dly_tig)
begin
validLogicInStu <= LOGIC_IN;
end
end
reg[31:0] count;
assign time_dly = (count == WOBBLE_DELAY)? 1'b1:1'b0;
always @(posedge CLK)
begin
if(!start_dly)
count <= 32'd0;
else
begin
if(count < WOBBLE_DELAY)
count <= count + 32'd1;
end
end
reg stu1, stu2;
wire int_tig;
assign int_tig = (stu1 != stu2 && (logic_in_state & LOGIC_IN_MASK))?1'b1:1'b0;
always @(posedge CLK)
begin
stu1 <= logic_in_state;
stu2 <= stu1;
end
always @(posedge CLK)
begin
if(!EN || clear_int_reg)
LOGIC_IN_INT <= 1'b0;
else
begin
if(int_tig)
LOGIC_IN_INT <= 1'b1;
end
end
always @(posedge CLK)
begin
if(CLEAR_INT)
clear_int_reg <= 1'b1;
else
clear_int_reg <= 1'b0;
end
assign CLEAR_INT = (!EN || clear_int_reg)?1'b0:1'bz;
endmodule
1. 程序中一直检测开关量的状态(无论是否打开检测开关),当开关量信号改变时开始记时,当信号稳定10ms后将它看作一个稳定信号。
2. 当打开检测开关时,记录下开关量的原始状态,这样做是考虑开关量常开、常闭或开关量不接的情况,以后的开关量状态与原始的开关量状态相比较(异或关系)。
3. 是否产生一个中断要与开关量屏蔽位相比较。