FPGA,实现LED灯的亮灭

前言

FPGA实现LED灯的闪烁实验。

一、具体实验

1.模块实现

`timescale 1ns / 1ps


module led_flash(

    Clk,
    Reset_n,  //n代表低电平(negative)复位
    Led
    );
    input Clk;
    input Reset_n;
    output Led;
    
    reg [24:0]counter;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        counter <= 0;
        Led <= 0;
    end    
    else if(counter ==24999999)begin  500ms/20ns=500000000/20=25000000-1=24999999
        Led <= !Led;
        counter <=0;
    end
    else
        counter <= counter +1'd1;
    
    
    
endmodule

always@(posedge Clk or negedge Reset_n)
pos积极地(positive),edge边缘
neg消极的(negative),整体:时钟的上升沿或者复位信号的下降沿。
在这里插入图片描述
这里有个缺少begin end的错误。begin end的作用就相当于C语言里面的()括号,不然就执行一条语句,编译器会产生疑问。

1)非阻塞赋值解释

counter <= 0; 这是一个非阻塞赋值语句
非阻塞赋值的主要特点是,所有在同一仿真时刻的非阻塞赋值语句会同时被计算,但它们的更新会发生在仿真时刻的末尾。这与阻塞赋值(使用=运算符)不同,阻塞赋值会立即更新变量的值,并且在下一条语句执行前阻止其他语句的执行。
意味着在当前的仿真时刻,counter的新值会被计算为0,但这个更新不会立即发生。而是在当前仿真时刻的所有操作(包括所有非阻塞赋值语句的计算)都完成后,counter的值才会被更新为0。
非阻塞赋值在描述并行或同时发生的硬件行为时非常有用,比如描述数字逻辑电路中的并行更新。在描述如流水线、状态机等硬件时,非阻塞赋值也是非常重要的。

Xilinx FPGA的D触发器结构,是使用高电平复位能够节约一定的资源,这里使用低电平复位是为了符合开发板上的常态为高电平的按键作为复位按键的功能使用。

这里推荐分开写,能够方便代码的修改调试,和逻辑综合器的硬件综合。

    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter ==25000000-1)
        counter <=0;
    else
        counter <= counter +1'd1;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        Led <= 0;
    end    
    else if(counter ==25000000-1)
        Led <= !Led;

分开写的部分代码。计数分为三种情况,一种是复位按下,一种是计数寄到了24999999,一种是正常的技术状态每次加1。

2)疑问

既然Reset_n复位和counter ==25000000-1对应相同的 counter <=0;的逻辑,那么二者可不可以合并呢?
答案是:不可以,复位逻辑对应D触发器的专门的复位端口,需要专门写出来,不能够与其他的条件合并。

2.激励部分

`timescale 1ns/1ps

module led_flash_tb();
   reg Clk;
   reg Reset_n;
   wire Led;  //为什么Led应该是wire类型的
   
    
   led_flash led_flash(

    .Clk(Clk),
    .Reset_n(Reset_n),  
    .Led(Led)
    );
    
    initial Clk = 1;  //初始化时钟Clk信号为逻辑高电平
    always #10 Clk = !Clk;  //每隔10ns翻转一次,模拟时钟的周期。
    
    initial begin  //模拟初始化的过程
        Reset_n = 0;  //Reset_n初始化为0
        #201;         //过了201ns,Reset_n被置1
        Reset_n = 1;
        #2000000000;  //2s对应的ns数,9个0。 等待2s的时间,模拟一个持续2秒的复位信号。
        
        
    end

endmodule

提问, wire Led; 为什么Led应该是wire类型的
解释:wire类型通常用于表示输出信号或连接到其他模块的信号。这里Led连接的是led_flash的输出部分,所以应该是wire,起连接的作用,而不是以output led的形式作为一个独立的输出信号。

3.问题解释

在这里插入图片描述
这是counter ==25000000得到的结果,发现结果并不是以500ms为半周期,一秒闪烁一次。
这个问题和计数值的设置有关
计数4次
4
0-1
1-2
2-3
3-0
0-1

计数到4
0-1
1-2
2-3
3-4
4-0 计数到4需计5次,计数4次需要4次、计到3. Counter是计数的个数,比计到的数多一个,所以是24999999.

在这里插入图片描述

将counter ==24999999得到正确的结果。

总结

这就是对LED闪烁的全部仿真内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值