前言:
Hello world ! 这句代码大家都很熟悉吧,作为学习C语言的开始,逐渐的进入代码的世界。那么对于硬件来说,点灯也就是梦的开始,无论是单片机还是FPGA等等。有句话说得好,当你学会点灯的时候那么你就已经开始入门了哈哈哈。当然,硬件的话不比得软件,想要真正的入门还得通过不断地学习,打好基础,才能走得更远,加油吧,未来的硬件工程师们!
环境:
开发平台:vivado 2020.1
语言:verilog
开发板:Xilinx ZYNQ 7010
点亮led:
首先是去直接点灯,测试一下led是否能被点亮
verilog代码:
组合逻辑
module test(
input wire sysclk ,
input wire rst_n ,
output wire [3:0] led
);
assign led = 4'b1111;
endmodule
时序逻辑
`timescale 1ns / 1ps
module test(
input wire sysclk ,
input wire rst_n ,
output reg [3:0] led
);
always @(posedge sysclk)
if(!rst_n)
led <= 4'b0000;
else
led <= 4'b1111;
endmodule
仿真代码:
`timescale 1ns / 1ps
module text_tb();
reg sysclk ;
reg rst_n ;
wire [3:0] led ;
initial begin
sysclk = 0;
rst_n = 0;
#101
rst_n = 1;
end
always #10 sysclk = ~sysclk;
test test_u(
. sysclk ( sysclk ) ,
. rst_n ( rst_n ) ,
. led ( led )
);
endmodule
仿真结果:
组合逻辑
这里的话用的assign赋值语句,之前的文章里也提到过,组合逻辑的话是没有时钟的参与,因此板子现象是上电后led就会全亮
时序逻辑:
这里的话是用的always赋值语句,在复位拉高有效后,时钟上升沿采集到了高信号,led就立即从熄灭状态跳转到全亮
1s流水灯:
verilog代码:
`timescale 1ns / 1ps
module test(
input wire sysclk ,//系统时钟
input wire rst_n ,//复位
output reg [3:0] led
);
parameter delay = 50_000_000;//1s内部晶振次数
reg [26:0] cnt;//计数器,记录是否达到一秒
//1s计时器
always @(posedge sysclk)
if(!rst_n)
cnt <= 0;
else if(cnt == delay - 1)
cnt <= 0;
else
cnt <= cnt + 1;
//流水灯赋值
always @(posedge sysclk)
if(!rst_n)
led <= 4'b0001;
else if(cnt == delay - 1)
led <= {led[0],led[3:1]};
else
led <= led;
endmodule
这里的话相对于前面的点灯来说,它需要多添加一个计时器,也就是来记录晶振次数是否达到1s,这个板卡的时钟频率是50MHz,用我们之前的那个周期公式 T=1/f,就可以算出它的晶振次数是50_000_000这么多。然后这里对流水灯赋值,是采用的拼接符号,将低位拼接到高位,形成一个流动的现象,这里的话还有很多其它的方法,大家可以自行探索
仿真代码:
这个仿真代码和点亮led那个一样,都可以使用
仿真结果:
写仿真的时候,可以将时钟稍微改小一点,不然会跑很长时间,这里已经被我改小了,仿真的话主要是看能否实现功能
这里led初始是4‘b0001,当复位拉高后,cnt开始计数,时钟晶振是500
cnt计时器的话,每计到499就清零,led就发生跳转,因为cnt从0开始算,到499就刚好是500
最终的话仿真就是一个这样的现象,呈现出一个流动的状态。上板的话需要注意将时钟改回去,不然的话你会发现led跳动得很快,甚至以肉眼是无法看见现象的,并且需要跑综合后绑定管脚,再生成bit流后才可以上板
1s翻转灯:
verilog代码:
`timescale 1ns / 1ps
module test(
input wire sysclk ,//系统时钟
input wire rst_n ,//复位
output reg [3:0] led
);
parameter delay = 50_000_000;//1s内部晶振次数
reg [26:0] cnt;//计数器,记录是否达到一秒
//1s计时器
always @(posedge sysclk)
if(!rst_n)
cnt <= 0;
else if(cnt == delay - 1)
cnt <= 0;
else
cnt <= cnt + 1;
//翻转灯赋值
always @(posedge sysclk)
if(!rst_n)
led <= 4'b0011;
else if(cnt == delay - 1)
led <= ~led;
else
led <= led;
endmodule
这个翻转灯的话和流水灯是特别相似的,这样的话我们的端口定义和计时器这些都不需要改动,只需要对翻转灯赋值这里,将len的赋值给改一下,这里我是直接用的逻辑取反符号,也可以使用拼接符这些,方法挺多的,大家也可以自己去尝试
仿真代码:
仿真代码也是之前使用的那个,在没有添加新端口的时候,都可以使用
仿真结果:
这里的话最终结果就是led灯两个之间进行翻转的一个现象,上板的话记得将时间改到自己需要的一个时间,需要0.5s或者2s这些,都可以用T=1/f这个公式去算出你所需要的一个时钟
总结:
本次的话就是主要去介绍关于点亮led的一些常见例程,其实还有很多关于led的例程,但其实都是差不多的,感兴趣的话可以去试试,有错误的地方希望大家能够指出,谢谢!