【深度教学2】手把手带你学会用EP4CE6F17C8实现FPGA流水灯

一、电路模块

 1、LED

开发板板载了4个用户LED发光二极管。4 个用户LED部分的原理图如下图所示,当 FPGA的引脚输出为逻辑 0时,LED会熄灭。输出为逻辑1时,LED被点亮。

其实物图如下所示。

LED的引脚分配见下表。

2、时钟晶振

开发板板载了一个50MHz的有源晶振,为系统提供时钟。

其实物图如下所示。

时钟输出引脚分配见下表。

3、按键

开发板板载了4个独立按键,其中有3个用户按键(KEY1~KEY3),1个功能按键(RESET)。按键按下为低电平(0),释放为高电平(1),4个按键的原理图如下图所示。本例中只使用了RESET键。

其实物图如下所示。

按键的引脚分配见下表。

二、实验代码

本例实现4位LED的流水灯,输出使用4个发光管led1~led4。代码使用Verilog编写,如下。

module led4_shift ( 
    input    clk,            //板载50HMz系统时钟
    input rst_n,             //复位按键
    output reg[3:0] led      //4个LED
 );
 
reg [27:0] timer;            //定义时钟计数器
    
//4秒循环计数
always@(posedge clk or negedge rst_n)    //敏感信号为时钟上沿或复位下沿
begin
    if (rst_n == 1'b0)                     //低电平复位
    timer <= 28'd0;                        //复位时时钟计数器清零
    else if (timer == 28'd199_999_999)     //时钟计数器到达4秒时
        timer <= 28'd0;                    //时钟计数器清零
    else
        timer <= timer + 28'd1;            //时钟计数器加1,即来一次时钟脉冲加一次
end

//LED控制
always@(posedge clk or negedge rst_n)    //敏感信号为时钟上沿或复位下沿
begin
    if (rst_n == 1'b0)                    //低电平复位时LED全灭
        led <= 4'b0000;
    else if (timer == 28'd49_999_999)     //时钟到1秒时,LED0点亮
        led <= 4'b0001; 
    else if (timer == 28'd99_999_999)     //时钟到2秒时,LED1点亮
        led <= 4'b0010;
    else if (timer == 28'd149_999_999)    //时钟到3秒时,LED2点亮
        led <= 4'b0100; 
    else if (timer == 28'd199_999_999)    //时钟到4秒时,LED3点亮
        led <= 4'b1000;
end
endmodule

代码也可以写成如下的方式。

module led4_shift ( 
    input    clk,            //板载50HMz系统时钟
    input rst_n,             //复位按键
    output reg[3:0] led      //4个LED
 );
 
reg [25:0] timer;            //定义时钟计数器
reg [2:0] sec;               //定义秒计数器
    
//4秒循环计数
always@(posedge clk or negedge rst_n)    //敏感信号为时钟上沿或复位下沿
begin
    if (rst_n == 1'b0)                      //低电平复位
    begin
        timer <= 26'd0;                     //复位时时钟计数器及秒计数器清零
        sec <= 3'd0;
    end
     else if (timer == 26'd49_999_999)      //时钟计数器到达1秒时
     begin
        timer <= 26'd0;                     //时钟计数器清零
        sec <= sec + 3'd1;                  //秒计数器加1
    end
     else if(sec == 3'd4)                   //秒计数器加到4时恢复零
        sec <= 3'd0;
    else
        timer <= timer + 26'd1;             //时钟计数器加1,即来一次时钟脉冲加一次
end

//LED控制
always@(posedge clk or negedge rst_n)    //敏感信号为时钟上沿或复位下沿
begin
    if (rst_n == 1'b0)                      //低电平复位时LED全灭
        led <= 4'b0000;
    else if (sec == 3'd1)                   //时钟到1秒时,LED0点亮
        led <= 4'b0001; 
    else if (sec == 3'd2)                   //时钟到2秒时,LED1点亮
        led <= 4'b0010;
    else if (sec == 3'd3)                   //时钟到3秒时,LED2点亮
        led <= 4'b0100; 
    else if (sec == 3'd4)                   //时钟到4秒时,LED3点亮
        led <= 4'b1000;
end
endmodule

三、代码说明

1、always语句为过程语句,用于引导顺序语句,设计模块中的任何顺序语句都必须放在过程语句结构中。在@之后的括号中,列出所有输入敏感信号。在always语句中申明的变量必须为reg类型,不能使用wire类型。
begin与end之间为顺序块语句,仅限于用在always引导的过程语句结构中(assign中不能使用块语句)。
2、“<=”属于非阻塞赋值符号(“=”属于阻塞型赋值),只能用于顺序语句中,不能在assign引导的并行语句中。即assign中只能使用“=”赋值,而always中可以两种("="和"<=")都使用,但在同一过程中对同一变量赋值,两种不允许混用。而且,在许多情况下,不同的赋值符号将导致不同的电路结构和逻辑功能的综合结果。注意,对同一个变量的赋值不能出现在两个以上的always语句中。
3、条件判断if语句必须放在由always引导的顺序结构中。数字常量要指明位宽及使用的进制方式,如4'b0001,4表示位宽为4,b表示使用二进制,后面的数字要符合位宽。
4、同一结果可以有多种程序设计形式,以消耗逻辑器件最少为佳。

四、实验步骤

FPGA开发的详细步骤请参见“基于EP4CE6F17C8的FPGA开发流程(以半加器为例)”一文,本例只对一同之处进行说明。

本例工程放在D:\EDA_FPGA\Exam_2文件夹下,工程名称为Exam_2。模块文件名称为led4_shift.v,并设置为顶层实体。其余步骤与“基于EP4CE6F17C8的FPGA开发流程”中的一样。

接下来看管脚约束,本例中不仅使用了4个LED,还引入了时钟晶振和复位按钮,具体的端口分配如下图所示。

对于未用到的引脚设置为三态输入方式,多用用途引脚全部做为普通I/O端口,电压设置为3.3-V LVTTL(与”基于EP4CE6F17C8的FPGA开发流程“中的一样)。需要注意,程序中的每个端口都必须为其分配管脚,如果系统中存在未分配的I/O,软件可能会进行随机分配,这将造成不可预料的后果,存在烧坏FPGA芯片的风险。

接下来对工程进行编译,编译完成后,可查看一下逻辑器件的消耗情况,第一种代码的消耗如下图所示。

第二种代码的消耗如下图所示。

可以看到,第二种方式要消耗掉更多的器件。另外,还可以点击菜单Tools->Netlist Viewers->RTL Viewer,查看一下生成的RTL电路图。

最后进行程序下载,并查看结果。

根据前面的程序,初始化时4个led均为熄灭状态,1秒后led0点亮其余熄灭,再过1秒后led1点亮其余熄灭,再过1秒后led2点亮其余熄灭,再过1秒后led3点亮其余熄灭, 再过1秒后led0再次被点亮其余熄灭,如此循环,如下面4张图片所示。

当按下RESET键时,所示LED均熄灭。如下图所示。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值