边沿检测器
边沿检测就是随着clk(时钟信号)的不断变化,当输入信号cin(暂定)发生变化时,
也就是由低电平变化到高电平或者从高电平变化到低电平时,
由rising(定义为检测上升沿)输出1表示检测到cin的上升沿(也就是由低电平到高电平)。
同理,定义一个falling(下降沿检测),当检测到下降沿时输出1。
D触发器原理
代码
module test_100(
input clk,
input cin,
output rising,
output falling,
output double //双边沿检测
);
reg reg1,reg2; //定义两个寄存器
always@(posedge clk )
begin
reg1<=cin; // reg2为前一态,reg1为当前态
reg2<=reg1;
end
assign rising=!reg2&®1; //上升沿检测 (前一态取反 与上当前态。 结果是1那就对应是检测到上升沿)
assign fallling=reg2&&!reg1; //下降沿沿检测(同理)
assign double=rising^falling; //双边沿检测(当有任意一个沿,doubel即输出高电平表示)
endmodule
仿真电路
测试文件
因为是用的ISE,其它文件是自动生成的,只需添加最后的两句always语句即可。
仿真波形
可以看到仿真成功,检测时存在有一定延时。
- List item
序列检测器
原理
也是利用D触发器,要检测4位(1101)就把分为4个寄存器中,让输入信号连续经过这四个寄存器,然后要待检测序列段与这四位的数据进行对比,相同则标记一下。
代码
module seq_detect(
input clk_i, //时钟信号
input data_in, //输入待检测信号
output flag_o //检测到后的标志
);
parameter list=4'b1101; //检测的特殊序列
reg a1,a2,a3,a4; //定义四个寄存器
always@(posedge clk_i)
begin
a1<=data_in;
a2<=a1;
a3<=a2;
a4<=a3;
end
assign flag_o=(list=={a4,a3,a2,a1})?1:0; //判断是否检测到特殊序列,如果是,结果为1,标志位出现
endmodule
仿真电路
测试文件`
module tst;
// Inputs
reg clk_i;
reg data_in;
// Outputs
wire flag_o;
// Instantiate the Unit Under Test (UUT)
seq_detect uut (
.clk_i(clk_i),
.data_in(data_in),
.flag_o(flag_o)
);
initial begin
// Initialize Inputs
clk_i = 0;
data_in = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always#10 clk_i=~clk_i;
always#20 data_in={$random}%2;
endmodule
只需要添加最后的两个always语句即可,其它由ise软件自动生成。其中最后一句是每隔20ns产生一个随机数(32位的,但这不重要)除2的余数(结果只能是1或者0)。