赞
踩
一、概述
众所周知,在我们学习任何一款硬件,不管是单片机MCU,DSP以及其他的一系列硬件在内的最开始接触的都是LED流水灯的实现,这就和我们在学习编程时的输出“Hello World”一样,我们在学习FPGA的过程当中也是要从LED流水灯开始学起。
在FPGA开发中我们不管是实现什么功能,基本上都是需要使用计数器作为基础,这里也不例外。
二、设计代码的编写
- //模块定义
- module led(
- input rst_n,
- input clk,
- output reg [3:0] led_out
- );
-
-
- //参数定义
- parameter TIME_500ms= 25_000_000;
- //内部信号定义
- reg [24:0] cnt;//计数500ms所需要的二进制位数
- wire add_cnt;//计数器开启条件
- wire end_cnt;//计数器结束条件
- reg [3:0] state_n;
- //计数器实现功能,0.5秒技术
- always @(posedge clk or negedge rst_n)begin
- if(!rst_n)begin
- cnt<=0;
- end
- else if(add_cnt)begin
- if(end_cnt)
- cnt<=0;
- else
- cnt<=cnt+1;
- end
- else
- cnt<=0;
- end
- assign add_cnt=1'b1;
- assign end_cnt=add_cnt && cnt ==(TIME_500ms-1);
-
- always @(posedge clk or negedge rst_n)begin
- if(!rst_n)
- led_out<=4'b0011;
- else if(end_cnt)begin
- led_out<={led_out[2:0],led_out[3]};
- end
- else
- led_out<=led_out;
- end
- endmodule

在这个代码中我们需要注意的就是使用拼接符实现LED灯的循环移动led_out<={led_out[2:0],led_out[3]};这句代码实现的就是将最高位和最低位进行不断交换。
三、测试文件的编写
- //定义时间尺度
- `timescale 1ns/1ps
- module led_tb();
-
- //重定义
- defparam led_inst.TIME_500ms = 25;
- //内部变量定义
- reg clk;
- reg rst_n;
- wire [3:0] led_out;
-
- //模块实例化
- led led_inst(
- /*input */ .rst_n (rst_n ),
- /*input */ .clk (clk ),
- /*output reg [3:0] */ .led_out (led_out )
- );
-
- //时钟
- parameter CLK_CLY =20;
- initial clk=0;
- always #(CLK_CLY/2) clk=~clk;
-
- //复位
- initial begin
- rst_n =1'b0;
- #(CLK_CLY*2);
- #3;
- rst_n =1'b1;
- end
- //激励
-
- endmodule

因为这里我们设置的周期是ms计数,相比于硬件本身的20ns来说非常大,所在我在测试文件中对于周期做了一个重定义——defparam led_inst.TIME_500ms = 25;在测试文件中的重定义不会影响设计文件中的值,所以可以放心使用。
四、波形仿真
在波形图中我们可以看到LED灯从 0001——1000进行不断的循环流水。
四、下板验证
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。