16-流水灯

1.流水灯

利用板载的LED灯进行流水灯的设计,让LED灯依次进行点亮,像流水一样,原理就是依次控制LED灯的IO口的高低电平的变化,让LED灯一次

2.FPGA设计

2.1 模块框图和波形

  • 本次的实验是让 led 灯依次闪亮的间隔为0.5s,也就是让 led 灯每次只亮一个,每次亮的时间为 0.5s,这样就速度就比较快了,更像“流水”的效果且肉眼还能够分辨出
  • 依次点亮板载的四个LED灯,实现流水灯的效果,两个灯之间的间隔为0.5s,LED灯一次点亮持续时间为0.5s
  • 板载LED灯低电平时点亮

  • 每个灯持续亮0.5s,需要使用计数器,计数个数为25000_0000,最大计数值为24999_999
  • 声明一个cnt变量进行计数
  • 声明一个cnt_flag产生脉冲信号,计数到最大值-1的时候产生一个周期的脉冲信号
  • led_out信号:当检测到cnt_flag信号为高电平的时候,就点亮一个灯,点亮灯的顺序:4'1110,4'1101,4'1011,4'0111,每经历一个脉冲就左移一位,但是左移是用0进行填充的,也就是说4'1110,左移变为4'1100,这样就是点亮两个灯,如何进行操作?用中间变量进行表示4'0001,4'0010'4'0100,4'1000,输出变量对其进行取反即可


  • 采用移位操作会出现问题,左移在右边进行补零,会导致每次多亮一个灯
  • 新加一个变量,表示输出信号的相反值

2.2 RTL

module water_led
#(
  parameter CNT_MAX = 24_999_999
)
(
  input wire sys_clk,
  input wire sys_rst_n,
  
  output reg [3:0] led_out
);

  reg [24:0] cnt;
  reg cnt_flag;
  reg [3:0] led_out_reg;

// cnt:计数500ms
always @ (posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    cnt <= 25'd0;
  else if (cnt == CNT_MAX)
    cnt <= 25'd0;
  else 
    cnt <= cnt + 1'b1; 

//cnt_flag:计数器计数满 500ms 标志信号
always @ (posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    cnt_flag <= 1'b0;
  else if(cnt_flag == CNT_MAX-1)
    cnt_flag <= 1'b1;
  else
    cnt_flag <= 1'b0;

// led_out_reg
always @ (posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    led_out_reg <= 4'b0001;
  else if(led_out_reg == 4'b1000 && cnt_flag == 1'b1) // 如果不加这个条件,上板之后经过一级流水,灯全部熄灭
    led_out_reg <= 4'b0001;
  else
    led_out_reg <= led_out_reg << 1;

  assign led_out = ~led_out_reg;
endmodule

2.3 Testbench

`timescale 1ns/1ns

module tb_water_led();
  reg sys_clk;
  reg sys_rst_n;
  
  wire [3:0] 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;

  water_led 
  (
    .CNT_MAX (25'd24)
  )
  water_led_inst
  (
    .sys_clk (sys_clk)
    .sys_rst_n (sys_rst_n)
    .led_out (led_out)
  )
endmodule

3.移位操作

假设被操作数是a[7:0] 8bit数据

// 逻辑右移两位
b = a >> 2'd2;
b = {2'b00,a[7:2]} ; // 用拼接符也可以表示移位操作

// 逻辑左移两位
b = a << 2'd2;
b = {a[5:0],2'b00};

posted @ 2023-06-08 21:38  Icer_Newer  阅读(149)  评论(0编辑  收藏  举报