新人第一次写博客,该系列将不断更新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的输出进行控制。总体还是比较简单的,如果有误请大佬指出,后续将附上工程文件。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)