上升沿(或下降沿)检测
如图所示,当检测到上升沿时,out会变为高电平,同时维持一个周期,然后变为低电平等待下一次检测。
只需要设定一个临时reg
类型变量来储存上一次的in值,然后在下一上升沿进行识别即可,代码如下
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] temp;
always @ (posedge clk)
begin
temp <= in; //temp始终比in晚一个周期
pedge <= ~temp & in; //当输出为1时检测到上升沿
//本题刚好与所示时序图相反,其中Q就相当于temp, D就相当于in,检测下降沿是对in取反就好。
end
endmodule
上升沿和下降沿同时检测
时序图如下
该问题比较简单,只需要稍微修改以下计算out
的表达式即可
reg [7:0] in_temp;
always @ (posedge clk)
begin
in_temp <= in;
anyedge <= in ^ in_temp;
end
end
下降沿(或上升沿)捕获
捕获的意思是,只要检测到下降沿,就使得输出信号out
一直保持高电平,直至复位信号reset
值为1(此处为同步复位)。时序图如下——
此时我们需要注意,“使out
在复位之前一直保持值为1”的方法。
module top_module (
input clk,
input reset,
input [31:0] in,
output reg [31:0] out
);
reg [31:0] in_temp;
always @(posedge clk) begin
in_temp <= in;
if(reset) out <= 0;
else begin
out <= (in_temp & ~in) | out;
end
end
endmodule
双边沿检测触发器
此时我们要构造一个触发器使其可以同时检测时钟的上升沿和下降沿,时序图如下——
由于always
中的敏感列表不支持(posedge clk or negedge
clk),因此我们可以使用两个always语句然后结合MUX实现
module top_module (
input clk,
input d,
output q
);
reg a, b;
assign q = (clk) ? a : b;
always @(posedge clk) begin
a <= d;
end
always @(negedge clk) begin
b <= d;
end
endmodule
还有以下使用XOR的方法解决,可以说是非常巧妙了。
module top_module(
input clk,
input d,
output q);
reg p, n;
// clk的上升沿
always @(posedge clk)
p <= d ^ n;
// clk的下降沿
always @(negedge clk)
n <= d ^ p;
//在上升沿时候,p=d^n, 则q=d^n^n=d;
//在下降沿时候,n=d^p, 则q=p^d^p=d;
//加载一个新值时会取消旧值。
assign q = p ^ n;
// 这样写是无法综合的
/*always @(posedge clk, negedge clk) begin
q <= d;
end*/
endmodule