计数器
功能实现:
- 时钟:50MHz,每10ns翻转一次
- 复位:高电平时复位,从零重新计数,异步复位(复位的触发可与时钟不同步)
- 计数:从0开始计数,计数到7后,清零重新计
参数设置:
参数名称 | 参数内容 |
---|---|
Count_Num | 计数范围为 0 ~ Count_Num - 1 |
Width | Count_Num 的位宽 |
代码:
module counter #(parameter Count_Num = 8, parameter Width = $clog2(Count_Num))(
input wire CLK,
input wire RST,
output reg [Width-1:0] cnt
);
// 自动加一,复位或计满时置零,
always @(posedge CLK or posedge RST) begin
if(RST == 1'b1) begin
cnt <= 1'b0;
end
else if(cnt == Count_Num - 1'b1) begin
cnt <= 1'b0;
end
else begin
cnt <= cnt + 1'b1;
end
end
endmodule
TestBench 代码:
`timescale 1ns / 1ps
module tb_counter(
);
reg CLK;
reg RST;
wire [2:0] cnt;
// 初始化CLK和RST
initial begin
CLK <= 1'b1;
RST <= 1'b1;
#20;
RST <= 1'b0;
#35;
RST <= 1'b1;
#10;
RST <= 1'b0;
end
always #10 CLK = ~CLK;
initial begin
$timeformat(-9, 0, "ns", 6);
$monitor("@time %t:cnt = %d", $time, cnt);
end
// 实例模块
counter #(
.Count_Num (8)
)tb_counter(
.CLK (CLK),
.RST (RST),
.cnt (cnt)
);
endmodule
波形:
监视器输出:
边沿检测
对应野火FPGA视频的第十七讲——触摸按键控制LED灯。
功能实现:
- 时钟:50MHz,每10ns翻转一次
- 复位:异步复位,高电平时 IN_1、IN_2 置一
- 下边沿检测:检测 IN 的下降沿
时序图分析:
- IN_1 是将 IN 同步到时钟信号上
- IN_2 是 IN_1 的延迟一拍结果,是 IN_1 的滞后,代表 IN 的上一时刻
- 当 IN_1 为低 IN_2 为高时,代表 IN 的上一时刻为高,下一时刻为低,即为下降沿
- 若以 OUT 来标志下降沿的到来,OUT 需要根据 IN_1 和 IN_2 的状态来赋值
- 若 OUT 通过组合(assign)方式赋值,那么每当 IN_1 和 IN_2 的状态满足判定条件的时候,OUT 就会实时地发生变化
- 若 OUT 通过时序方式赋值,那么 OUT 会在下一个时钟周期进行赋值,其变化会相对组合方式延迟一拍
代码:
module EdgeDetection(
input wire CLK,
input wire RST,
input wire IN,
output wire OUT_1,
output reg OUT_2
);
reg IN_1;
reg IN_2;
// 边沿检测
always@(posedge CLK or posedge RST) begin
if(RST == 1'b1) begin
IN_1 <= 1'b1;
IN_2 <= 1'b1;
end
else begin
IN_1 <= IN;
IN_2 <= IN_1;
end
end
// 通过组合方式给OUT_1赋值
assign OUT_1 = ((IN_1 == 1'b0) && (IN_2 == 1'b1));
// 通过时序方式给OUT_2赋值
always@(posedge CLK or posedge RST) begin
if(RST == 1'b1) begin
OUT_2 <= 1'b0;
end
else if((IN_1 == 1'b0) && (IN_2 == 1'b1)) begin
OUT_2 <= 1'b1;
end
else begin
OUT_2 <= 1'b0;
end
end
endmodule
TestBench 代码:
`timescale 1ns / 1ps
module tb_EdgeDetection(
);
reg CLK;
reg RST;
reg IN;
wire OUT_1;
wire OUT_2;
// 初始化CLK和RST
initial begin
CLK <= 1'b0;
RST <= 1'b1;
#40;
RST <= 1'b0;
end
always #10 CLK = ~CLK;
// 初始化IN
initial begin
IN <= 1'b1;
#60;
IN <= 1'b0;
#70;
IN <= 1'b1;
#50;
IN <= 1'b0;
#30;
IN <= 1'b1;
end
// 实例模块
EdgeDetection tb_EdgeDetection(
.CLK(CLK),
.RST(RST),
.IN(IN),
.OUT_1(OUT_1),
.OUT_2(OUT_2)
);
endmodule
波形: