FPGA开发——实现流水灯的设计

一、概述

众所周知,在我们学习任何一款硬件,不管是单片机MCU,DSP以及其他的一系列硬件在内的最开始接触的都是LED流水灯的实现,这就和我们在学习编程时的输出“Hello World”一样,我们在学习FPGA的过程当中也是要从LED流水灯开始学起。

在FPGA开发中我们不管是实现什么功能,基本上都是需要使用计数器作为基础,这里也不例外。

二、设计代码的编写

//模块定义
module  led(
    input rst_n,
    input clk,
    output reg [3:0]  led_out
);


//参数定义
parameter TIME_500ms= 25_000_000;
//内部信号定义
reg [24:0]  cnt;//计数500ms所需要的二进制位数
wire        add_cnt;//计数器开启条件
wire        end_cnt;//计数器结束条件
reg  [3:0]  state_n;
//计数器实现功能,0.5秒技术
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt<=0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt<=0;
        else
            cnt<=cnt+1;
    end
    else
        cnt<=0; 
end
assign add_cnt=1'b1;
assign end_cnt=add_cnt && cnt ==(TIME_500ms-1);

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        led_out<=4'b0011;
    else if(end_cnt)begin
        led_out<={led_out[2:0],led_out[3]};
    end 
    else
        led_out<=led_out;
end 
endmodule

在这个代码中我们需要注意的就是使用拼接符实现LED灯的循环移动led_out<={led_out[2:0],led_out[3]};这句代码实现的就是将最高位和最低位进行不断交换。

三、测试文件的编写

//定义时间尺度
`timescale 1ns/1ps
module led_tb();

//重定义
defparam  led_inst.TIME_500ms = 25;
//内部变量定义
reg clk;
reg rst_n;
wire [3:0] led_out;

//模块实例化
led led_inst(
    /*input              */ .rst_n    (rst_n     ),
    /*input            */ .clk      (clk       ),
    /*output reg [3:0] */ .led_out  (led_out   )
);

//时钟
parameter CLK_CLY =20;
initial clk=0;
always  #(CLK_CLY/2) clk=~clk;

//复位
initial begin
    rst_n =1'b0;
    #(CLK_CLY*2);
    #3;
    rst_n =1'b1;
end 
//激励

endmodule

因为这里我们设置的周期是ms计数,相比于硬件本身的20ns来说非常大,所在我在测试文件中对于周期做了一个重定义——defparam  led_inst.TIME_500ms = 25;在测试文件中的重定义不会影响设计文件中的值,所以可以放心使用。

四、波形仿真

在波形图中我们可以看到LED灯从 0001——1000进行不断的循环流水。

四、下板验证

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是FPGA模块化设计实现流水灯的步骤: 1. 时钟产生模块:使用Verilog中的always块和#延迟语句来生成时钟信号。例如,以下代码将生成一个50MHz的时钟信号: ```verilog always #10 clk = ~clk; ``` 2. 移位模块:使用Verilog中的shift语句实现移位操作。例如,以下代码将实现一个向左移位的操作: ```verilog assign shift_out = {shift_in[6:0], 1'b0}; ``` 3. LED驱动模块:使用Verilog中的assign语句将移位模块的输出连接到LED驱动器。例如,以下代码将实现一个LED驱动器: ```verilog assign led = shift_out; ``` 4. 模式切换模块:使用Verilog中的always块和case语句来实现模式切换。例如,以下代码将实现两种不同的模式: ```verilog always @(posedge clk) begin case (mode) 2'b00: shift_in <= {shift_in[5:0], 1'b0}; 2'b01: shift_in <= {1'b0, shift_in[6:1]}; endcase end ``` 在这个例子中,模式切换模块将根据mode信号选择不同的移位模式。 5. 将所有模块组合在一起:使用Verilog中的module语句将所有模块组合在一起。例如,以下代码将组合所有模块: ```verilog module top_module ( input clk, input [1:0] mode, output reg [6:0] led ); reg [6:0] shift_in; wire [6:0] shift_out; // 时钟产生模块 always #10 clk = ~clk; // 移位模块 assign shift_out = {shift_in[6:0], 1'b0}; // LED驱动模块 assign led = shift_out; // 模式切换模块 always @(posedge clk) begin case (mode) 2'b00: shift_in <= {shift_in[5:0], 1'b0}; 2'b01: shift_in <= {1'b0, shift_in[6:1]}; endcase end endmodule ``` 以上是FPGA模块化设计实现流水灯的步骤,你可以根据自己的需求自定义流水间隔和模式个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

电子小芯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值