03FPGA—led灯的显示(入门)

       学习fpga也有段时间了,但后台有几个朋友问我能不能分享一点简单入门例子,于是我打算发经典的如何控制led的例子,本文主要分享设计流程以及简单的verilog语法

       设计流程主要包括五个步骤模块设计、波形设计、编写rtl代码、仿真验证、上板验证,少部分根据设计的特殊性,有的需要进行画状态机和流程图。

1.按键控制小灯亮灭

实验目标:按下按键,小灯亮;松开按键,小灯灭。

    了解硬件设计是写代码的前提,按键按下该管脚会拉低,led灯高电平点亮。

模块设计

    模块设计:把复杂的功能进行拆分一个个独立的小模块,不仅增加模块的复用性,在后期的调试中也更简单。

波形设计

     波形设计是野火家推出独有的设计方法,我个人觉得很受用。很好的体现了FPGA内部数字电路的并行执行的特点,不了解的朋友看看。

 编写rtl代码:

     FPGA采用的是硬件描述语言,语言构成电路。这与单片机不同,后者是如何写程序(指令)控制已有电路工作。

`timescale  1ns/1ns

module led
(
    input wire  key_in,
	
	output wire  led_out

);

assign led_out = ~key_in;

endmodule

仿真验证:

     仿真验证又称测试脚本或激励,测试rtl代码中信号波形是否符合之前设计的波形。

`timescale  1ns/1ns

module tb_led();

reg    key_in;
wire   led_out;

initial key_in <= 1'b0;

always #10 key_in <= {$random} % 2;

led led_inst
(
    .key_in (key_in ),  

    .led_out(led_out)   
);

endmodule

引脚约束:

      根据硬件原理图确定按键和 led 分别与 FPGA 芯片的哪个引脚对应。

#按键
NET "key_in" LOC = U10 | IOSTANDARD = LVCMOS33;

#led灯
NET "led_out" LOC = A11 | IOSTANDARD = LVCMOS33;

上板验证:

2.一上电小灯闪烁

实验目标:一上电或按下复位按键,小灯实现闪烁,闪烁一次的时间为1秒。

rtl代码:

`timescale  1ns/1ns

module  breath_led
#(
    parameter   CNT_MAX = 25'd24_999_999
)
(
    input   wire    sys_clk     ,   
    input   wire    sys_rst_n   ,   

    output  reg      led_out
);
reg     [24:0]  cnt;    //经计算得需要25位宽的寄存器才够500ms

//cnt:计数器计数,当计数到CNT_MAX的值时清零
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 25'b0;
    else    if(cnt == CNT_MAX)
        cnt <= 25'b0;
    else
        cnt <= cnt + 1'b1;

//led_out:输出控制一个LED灯,每当计数满标志信号有效时取反
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        led_out <= 1'b0;
    else    if(cnt == CNT_MAX)
        led_out <= ~led_out;  //亮灭之间跳转
		  
endmodule

验证:

仿真验证:

`timescale  1ns/1ns

module  tb_ledflash();

reg    sys_clk                ;
reg    sys_rst_n              ;
                              
wire      led_out             ;

initial  begin
    sys_clk    = 1'b1;
    sys_rst_n = 1'b0;
	#20
    sys_rst_n = 1'b1;
	end

always #10 sys_clk = !sys_clk;   //控制一个周期20ns

ledflash 
#(
    .CNT_MAX    (25'd24     )  //改变CNT_MAX值的大小,缩短仿真时间 
)
ledflash_inst
(
       .sys_clk     (sys_clk  ) ,
       .sys_rst_n   (sys_rst_n) ,
                    
       . led_out    ( led_out )

);
endmodule

上板验证:

     效果为视频不方便展示。

3.流水灯

实验目标:每过0.5秒右移动一次

rtl代码:

`timescale  1ns/1ns
//流水灯:每过0.5s移一次
 
module  water_led
#(
    parameter CNT_MAX = 25'd24_999_999 ,    //0.5s计数最大值
	parameter CNT =  3'd3
)
(
    input   wire            clk     ,   
    input   wire            rst     ,  
	
    output  reg     [4:0]   led        

);
reg     [24:0]  cnt_500ms   ;
reg     [2:0]   cnt;


//0.5s计时器
always@(posedge clk or negedge rst)
    if(!rst)    
	    cnt_500ms <= 25'b0;
    else if(cnt_500ms == CNT_MAX)
        cnt_500ms <= 25'b0;
    else
        cnt_500ms <= cnt_500ms + 1'b1;
//cnt计数周期为4的计数器
always@(posedge clk or negedge rst)  
    if(!rst)    
	    cnt <= 3'd0;
	else if((cnt_500ms == CNT_MAX-1'b1) && (cnt == CNT))  //计数满4,清零  
	    cnt <= 3'd0;
	else if(cnt_500ms == CNT_MAX-1'b1) //时序逻辑延后了一拍,这里给他减一对齐
	    cnt <= cnt + 1'b1;
	else 
	    cnt <= cnt;
		
always@(posedge clk or negedge rst)   //case()分支语句
    if(!rst)
	    led <= 4'b0001;
	else  case (cnt)
	        3'd0:   led <= 4'b0001;
			3'd1:   led <= 4'b0010;
			3'd2:   led <= 4'b0100;
			3'd3:   led <= 4'b1000;
	       default: led <= 4'b0001;
        endcase  
		
endmodule 

验证:

`timescale  1ns/1ns

module  tb_water_led();

reg          clk   ;
reg          rst   ;
            
wire  [3:0] led    ;

initial  begin
    clk    = 1'b1;
    rst = 1'b0;
	#20
    rst = 1'b1;
	end

always #10 clk = !clk; 

water_led
#(
    .CNT_MAX    (25'd24 )  //改变CNT_MAX值的大小,缩短仿真时间 
)
water_led_inst
(
       .clk   (clk  ) ,
       .rst   (rst) ,
                    
       .led   (led)

);
endmodule

仿真验证: 

 

上板验证:

     效果为视频不方便展示。

总结:

1.仿真就是测试rtl代码的正确性,编写整个系统的输入信号使其满足rtl代码的需求,就可以查看其内部逻辑的正确性。reg型表示的寄存器类型,reg相当于存储单元,具记忆功能; wire的本质是一条没有逻辑的连线,也就是说输入时什么输出也就是什么,无记忆功能。我们要对输入信号进行初始化、赋值故输入一般使用 reg,输出随输入变化故使用 wire。

说明:

       本人使用的是野火家Xilinx Spartan6系列开发板及配套教程,以上内容如有疑惑或错误欢迎评论区指出,或者移步B站观看野火家教学视频。

开发软件:ise14.7     仿真:modelsim 10.5 

如需上述资料私信或留下邮箱

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡0糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值