Xilinx FPGA:vivado状态机实现花式跑马灯

一、实验要求

(1)两个按键分别控制led灯的样式和速度,样式分为流水灯和翻转灯,速度分为0.5s/1s/1.5s/2s四个挡位。

(2)分别对两个按键进行按键消抖。

二、状态图

三、程序设计

(1)状态机模块

`timescale 1ns / 1ps
module fancy_led(
       input                    sys_clk          ,//系统时钟 
       input                    rst_n            ,//系统复位 

       input                    key_flag_1       ,//key_1按键消抖后产生的标志信号,根据此标志信号完成状态跳转
       input                    key_flag_2       ,//key_2按键消抖后产生的标志信号,根据此标志信号完成状态跳转
       
       input        [3:0]       led_water        ,//从流水灯模块输出
       input        [3:0]       led_jump         ,//从翻转灯模块输出                         
       output   reg [3:0]       led              ,//被赋值输出的变量                         
       output   reg[31:0]       TIME              //定义一个时间变量,输入给led_water和led_jump
    );
   
   //定义现态、次态

    reg                     [2:0]      cur_state;  //现态
    reg                     [2:0]      next_state; //次态
                               
    parameter              TIME_0_5s  = 32'd25_000_000     ;
    parameter              TIME_1s    = 32'd50_000_000     ;
    parameter              TIME_1_5s  = 32'd75_000_000     ;
    parameter              TIME_2s    = 32'd10_000_000_0   ;                  
  
  //定义空闲状态
  
    localparam              IDLE       = 9'b0000            ;
    
  //定义流水灯的四个状态
 
    localparam              water_0_5s = 9'b0001            ;
    localparam              water_1s   = 9'b0010            ;
    localparam              water_1_5s = 9'b0011            ;
    localparam              water_2s   = 9'b0100            ;

  //定义翻转灯的四个状态
    localparam              jump_0_5s = 9'b0101            ;
    localparam              jump_1s   = 9'b0110            ;
    localparam              jump_1_5s = 9'b0111            ;
    localparam              jump_2s   = 9'b1000            ;

  //状态机第一段:描述现态和次态的关系
  always@(posedge sys_clk)
       if(!rst_n)
         cur_state <= IDLE        ;
         else
         cur_state <= next_state  ;
   
  //状态机第二段: 描述现态和次态的触发
  
  //key_flag_1改变样式 key_flag_2改变速度
  always@(*)
        case(cur_state)
        IDLE       :   
                      begin
                      if(key_flag_1)
                      next_state = water_0_5s  ;
                      else if(key_flag_2)
                      next_state = jump_0_5s   ;
                      else
                      next_state = cur_state   ;                       
                      end
        water_0_5s :   
                      begin
                      if(key_flag_2)
                      next_state = water_1s    ;
                      else if (key_flag_1)
                      next_state = jump_0_5s   ;
                      else
                      next_state = cur_state   ;                       
                      end
        water_1s   :   
                      begin
                      if(key_flag_2)
                      next_state <= water_1_5s  ;
                      else if(key_flag_1)
                      next_state <= jump_0_5s   ;
                      else
                      next_state <= cur_state   ;       
                      end
        water_1_5s :   
                      begin
                      if(key_flag_2)
                      next_state <= water_2s    ;
                      else if(key_flag_1)
                      next_state <= jump_0_5s   ;
                      else
                      next_state <= cur_state   ;         
                      end
        water_2s   :   
                      begin
                      if(key_flag_2)
                      next_state <= water_0_5s  ;
                      else if(key_flag_1)
                      next_state <= jump_0_5s   ;
                      else
                      next_state <= cur_state   ;          
                      end
        jump_0_5s  :   
                      begin
                      if(key_flag_2)
                      next_state <= jump_1s      ;
                      else if(key_flag_1)
                      next_state <= water_0_5s   ;
                      else
                      next_state <= cur_state    ;         
                      end
        jump_1s    :   
                      begin
                      if(key_flag_2)                     
                      next_state <= jump_1_5s    ; 
                      else if(key_flag_1)                
                      next_state <= water_0_5s   ; 
                      else                         
                      next_state <= cur_state    ;      
                      end
        jump_1_5s  :   
                      begin
                      if(key_flag_2)                     
                      next_state <= jump_2s      ; 
                      else if(key_flag_1)                
                      next_state <= water_0_5s   ; 
                      else                         
                      next_state <= cur_state    ;       
                      end
        jump_2s    :   
                      begin
                      if(key_flag_2)                     
                      next_state <= jump_0_5s    ; 
                      else if(key_flag_1)                
                      next_state <= water_0_5s   ; 
                      else                         
                      next_state <= cur_state    ;       
                      end
        
     
        endcase       
  
  
  
  //状态机第三段 ,关键信号赋值
  
    always@(posedge sys_clk)
    
          case(cur_state)
          IDLE      : 
                           led <= 4'b1111 ;  
                     
          water_0_5s : begin     
         
                           led <= led_water    ;
                           TIME <= TIME_0_5s   ;
       
                       end
  
          water_1s   : begin                     
                                                 
                           led <= led_water    ;   
                           TIME <= TIME_1s     ; 
                                                 
                       end                       
                      
          water_1_5s : begin                     
          
                           led <= led_water    ;   
                           TIME <= TIME_1_5s   ; 
               
                       end                       
                                           
          water_2s   : begin                     
          
                           led <= led_water    ; 
                           TIME <= TIME_2s     ; 
             
                       end   

          jump_0_5s :  begin                    
          
                           led  <= led_jump    ;
                           TIME <= TIME_0_5s   ;  
              
                       end                      
                                   
          jump_1s   :  begin                         
          
                           led  <= led_jump    ;     
                           TIME <= TIME_1s     ;     
          
                       end                           
                       
          jump_1_5s :  begin                         
          
                           led  <= led_jump    ;     
                           TIME <= TIME_1_5s   ;     
          
                       end                           
                        
          jump_2s   :  begin                         
          
                           led  <= led_jump    ;     
                           TIME <= TIME_2s     ;     
          
                       end 
                       
                       
          endcase                          
                    
  
  

endmodule

(2)流水灯模块

`timescale 1ns / 1ps

module led_water(
input                   sys_clk       ,
input                   rst_n         ,
input       [31:0]      TIME          ,
output    reg[3:0]     led_water     
    );
    
//parameter         TIME_1s=26'd50_000_000     ;//定义流水灯计时器\翻转灯计时器最大值
 reg      [26:0]          count    ;
//流水灯和翻转灯的1s计时器

always@(posedge sys_clk)
      if(!rst_n)
      count <= 0   ;
      else if(count == TIME-1 )
      count <= 0   ;
      else
      count <= count +1;
      
always@(posedge  sys_clk)
      if(!rst_n)
        led_water <= 4'b0001 ;
      else if(  count == TIME-1 )
        led_water <={led_water[0],led_water[3:1]} ;
      else 
        led_water <=led_water;

endmodule

(3)翻转灯模块

`timescale 1ns / 1ps

module led_jump(
input                   sys_clk       ,   
input                   rst_n         ,   
input       [31:0]      TIME          ,   
output    reg[3:0]     led_jump     
    );
    
//parameter         TIME_1s=26'd50_000_000     ;//定义流水灯计时器\翻转灯计时器最大值
 reg      [26:0]          count_2    ;
//翻转灯的1s计时器

always@(posedge sys_clk)
      if(!rst_n)
      count_2 <= 0   ;
      else if(count_2 == TIME-1 )
      count_2 <= 0   ;
      else
      count_2 <= count_2 +1;
      
always@(posedge  sys_clk)
      if(!rst_n)
        led_jump <= 4'b0110    ;
      else if( count_2 == TIME-1 )
        led_jump <=~led_jump ;
      else 
        led_jump <=led_jump ;

endmodule

(4)按键消抖模块

`timescale 1ns / 1ps
module key_1_debounce(
     input            sys_clk    ,  
     input            rst_n      ,
     input            key_1      ,
     output   wire    key_flag_1 
    );
   
    parameter         TIME_20ms = 19'd10_000_0  ;
     reg    [19:0]     cnt_key_1                  ;

   
   always@(posedge sys_clk)
        if(!rst_n)
          cnt_key_1 <= 0   ;
          else if( key_1 == 0 )begin
               if(cnt_key_1== TIME_20ms -1)
                  cnt_key_1<= cnt_key_1  ;
                  else
                  cnt_key_1 <= cnt_key_1 +1  ;
          end
          else
                  cnt_key_1 <= 0        ;
                  
                  
   assign key_flag_1 = (cnt_key_1 == TIME_20ms -2)? 1:0       ; 
   
             
       
  endmodule
`timescale 1ns / 1ps
module key_2_debounce(
     input            sys_clk    ,  
     input            rst_n      ,
     input            key_2      ,
     output   wire    key_flag_2     //长久的使能信号
    
    );
   
    parameter         TIME_20ms = 19'd10_000_0  ;
     reg    [19:0]     cnt_key_2                   ;

   
   always@(posedge sys_clk)
        if(!rst_n)
          cnt_key_2 <= 0   ;
          else if( key_2 == 0 )begin
               if(cnt_key_2 == TIME_20ms -1)
                  cnt_key_2 <= cnt_key_2  ;
                  else
                  cnt_key_2 <= cnt_key_2 +1  ;
          end
          else
                  cnt_key_2 <= 0        ;
                  
                  
   assign key_flag_2 = (cnt_key_2 == TIME_20ms -2)? 1:0       ; 

  endmodule

四、block块设计

生成的顶层代码:

//Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2020.1 (win64) Build 2902540 Wed May 27 19:54:49 MDT 2020
//Date        : Thu Jun  6 18:40:01 2024
//Host        : LAPTOP-A2IQ2GRP running 64-bit major release  (build 9200)
//Command     : generate_target block_fancy_led_wrapper.bd
//Design      : block_fancy_led_wrapper
//Purpose     : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps

module block_fancy_led_wrapper
   (key_1_0,
    key_2_0,
    led_0,
    rst_n_0,
    sys_clk_0);
  input key_1_0;
  input key_2_0;
  output [3:0]led_0;
  input rst_n_0;
  input sys_clk_0;

  wire key_1_0;
  wire key_2_0;
  wire [3:0]led_0;
  wire rst_n_0;
  wire sys_clk_0;

  block_fancy_led block_fancy_led_i
       (.key_1_0(key_1_0),
        .key_2_0(key_2_0),
        .led_0(led_0),
        .rst_n_0(rst_n_0),
        .sys_clk_0(sys_clk_0));
endmodule

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值