FPGA学习笔记(1)简单的时序逻辑电路——流水灯
编程语言为Verilog HDL
原理
(1)设计一个计数器,使开发板上的4个LED状态每500ms翻转一次。开发板上的晶振输出时钟频率为50MHz,即时钟周期为20ns。这样可以计算得出500ms = 500_000_000ns/20ns = 25_000_000,即需要计数器计数25_000_000次,也就是需要一个至少25位的计数器(225>25_000_000>224)。且每当计数次数达到需要清零并重新计数。
计数器的核心元件是触发器,基本功能是对脉冲进行计数,其所能记忆脉冲最大的数目称为该计数器的模/值。计数器常用在分频、定时等处。计数器的种类很多,按照计数方式的不同可以分为二进制计数器、十进制计数器以及任意进制计数器,按照触发器的时钟脉冲信号来源可分为同步计数器与异步计数器。按照计数增减可分为加法计数器、减法计数器以及可逆计数器。
Verilog HDL之所以被称为硬件电路描述语言,就是因为我们不是在类似C一样进行普通的编程,而是在编写一个实际的硬件电路,例如在上一讲Intel FPGA设计流程中设计的一个二选一选择器最后就是被综合称为一个真正的选择器。上面提到计数器即为加法器、比较器、寄存器以及选择器构成。
FPGA开发流程
以下是FPGA 开发的流程
- 创建Quartus Prime工程
- 编写计数器HDL描述文件
- 编写计数器测试脚本(testbench)
- 对计数器进行功能仿真
- 在Quartus Prime中执行布局布线
- 对计数器进行时序仿真
- 分配引脚并编译得到FPGA配置文件.sof
- 配置FPGA并运行
代码实现
module led_flash(
clk_50m,
rst_n,
led
);
input clk_50m;
input rst_n;
output reg [3:0]led;
reg [24:0]cnt;
parameter cnt_max =25'd24_999_999;
always@(posedge clk_50m or negedge rst_n)
if(rst_n == 0)
cnt <= 25'd0;//非阻塞赋值方式
else
if(cnt == cnt_max)
cnt<=25'd0;
else
cnt<=cnt+1'b1;
// always@(posedge clk_50m or negedge rst_n)
// if(rst_n == 0)
// led<=4'b1111;
// else if(cnt == cnt_max)
// led <= ~led;
// else
// led <= led;
always@(posedge clk_50m or negedge rst_n)
if(rst_n == 0)
led<=4'b0111;
else if(cnt == cnt_max)
led <= {led[2:0],led[3]};
else
led <= led;
endmodule
前仿真
下图为注释段闪烁LED代码的前仿真
流水灯的第二种写法
将最开始定义的output reg [3:0]led;
修改为 output [3:0]led
reg [3:0]led_r;
always@(posedge clk_50m or negedge rst_n)
if(rst_n == 0)
led_r<=4'b0001;
else if(cnt == cnt_max)begin
if(led_r == 4'b1000)
led_r <= 4'b0001; //限制条件
else
led_r <= led_r << 1; //移位
end
else
led_r <= led_r;
assign led = ~led_r;
以上就是第一次简单时序逻辑电路的学习笔记,具体代码和激励文件也已经上传。下为代码下载链接
https://download.csdn.net/download/m0_52040183/13139067