野火FPGA跟练(一)——计数器、边沿检测


计数器

功能实现:

  1. 时钟:50MHz,每10ns翻转一次
  2. 复位:高电平时复位,从零重新计数,异步复位(复位的触发可与时钟不同步)
  3. 计数:从0开始计数,计数到7后,清零重新计

在这里插入图片描述参数设置:

参数名称参数内容
Count_Num计数范围为 0 ~ Count_Num - 1
WidthCount_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灯。

功能实现:

  1. 时钟:50MHz,每10ns翻转一次
  2. 复位:异步复位,高电平时 IN_1、IN_2 置一
  3. 下边沿检测:检测 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

波形:
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值