新人第一次写博客,该系列将不断更新fpga相关知识。有错误的地方希望大佬们可以指出,互相学习,提高水平。谢谢大家。
文章目录- FPGA学习系列
- 前言
- 一、原理
- 二.代码
- 总结
前言
我使用的是vivado,在编程部分应该就IP核的创建和quartusii不一样,模块代码是可以通用的。后面也会放出工程链接,也会有quartusii和vivado的工程。附带modelsim的仿真文件。
一、原理(这里是达芬奇pro的原理图)
LED0~LED3S是FPGA的引脚,很明显当FPGA输出高电平时三极管导通,而FPGA输出电压大约为1.35V所以二极管导通所以点亮led,当FPGA输出低电平时三极管截止,灯灭。
本次我将实现间隔0.5s的流水灯,一共四个灯,系统频率50Mhz,也就是一个周期时20ns,所以要实现0.5s的间隔,相当于要0.5s/20ns个时钟周期,即25000000个时钟周期。
二.代码代码如下:
module water_led #( parameter CNT_MAX=25'd25_000_000 ) ( input wire sys_clk , //系统时钟 input wire sys_rst_n , //系统复位 output reg [3:0] led //输出流水灯 ); reg [24:0] cnt ; //间隔计数 reg [1:0] led_crtl ; //流水灯状态 //计数到最大值清0 减1 是因为从0开始计数 always@(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt <= 25'd0; else if(cnt == CNT_MAX - 1'b1) cnt <= 25'd0; else cnt <= cnt + 1'b1; end //每计数到最大值的时候 led_crtl+1 表示亮下一个灯 其余情况不变 always@(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) led_crtl <= 2'd0; else if(cnt == CNT_MAX - 1'b1) led_crtl <= led_crtl + 1'b1; else led_crtl <= led_crtl; end //流水灯逻辑 判断led_crtl的值 亮不同的灯 always@(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) led <= 4'd0; else begin case(led_crtl) 2'b00 : led <= 4'b0001; 2'b01 : led <= 4'b0010; 2'b10 : led <= 4'b0100; 2'b11 : led <= 4'b1000; default : led<=4'b0000; endcase end endmodule
至此,就是一个简单流水灯工程,我是利用一个led_crtl相当于状态机来表示led的亮灭情况。
之所以一开始使用parameter定义CNT_MAX可以方便以后调用模块的时候,方便参数的修改。
cnt的位宽可以利用电脑自带的计算器去计算。如下.
看BIN一共25位,所以是25位宽
总结该工程比较简单,一个计数器进行计数,还有一个led_crtl的状态标志位,对led的输出进行控制。总体还是比较简单的,如果有误请大佬指出,后续将附上工程文件。



