zoukankan      html  css  js  c++  java
  • 红外解码编码学习----verilog

        在设计中运用红外遥控器可以很好的解决按键缺少的问题,还可以方便的控制产品。

       红外发射部分

        红外发射管:

            

      判断红外发射管的好坏

    电路原理图:

     

     接收部分:

         

    传输的NEC协议

     

    本实验电路:

         

       verilog 程序:

         发送程序:       

      
        
        /********************************Copyright**************************************                           
        **----------------------------File information--------------------------
        ** File name  :IR_send.v  
        ** CreateDate :2015.06
        ** Funtions   :红外信号的发送程序,发送格式:引导码+8bit用户码+8bit用户反码(或者用户反码)+8bit数据码+8bit用户反码+结束码
        ** Operate on :M5C06N3L114C7
        ** Copyright  :All rights reserved. 
        ** Version    :V1.0
        **---------------------------Modify the file information----------------
        ** Modified by   :
        ** Modified data :        
        ** Modify Content:
        *******************************************************************************/
         
        module  IR_send  (
                   clk,
                   rst_n,
                   
                             key_1,
                             key_2,
                             
                             IR_out,
                             led_1,
                             led_2,
                             led_3,
                             led_4
                             
    //                          testdata
                     );
         input          clk;    //24M/20m
         input          rst_n;
         
         input          key_1; 
         input          key_2;
         
         output         IR_out;
         
         output  reg    led_1;
         output  reg    led_2;
       output       led_3;
         output       led_4;
         
    //     output  [7;0]  testdata;
         //-------------------//
    
        `define     CLK_20M
    //    `define     CLK_24M    
    //    `define     CLK_50M
    
    
     `ifdef      CLK_20M
                 parameter t_38k    = 10'd526;
                 parameter t_38k_half = 10'd263;
                 parameter t_9ms    = 18'd179999;
                 parameter t_4_5ms  = 17'd89999;
                 parameter t_13_5ms = 19'd269999;
                 parameter t_560us  = 14'd11199;
                 parameter t_1_12ms = 15'd22399;
                 parameter t_1_68ms = 16'd33599;
                 parameter t_2_24ms = 16'd44799;
          `endif
            
         `ifdef      CLK_24M
                 parameter t_38k    = 10'd630;
                 parameter t_38k_half = 10'd315;
                 parameter t_9ms    = 18'd215999;
                 parameter t_4_5ms  = 17'd107999;
                 parameter t_13_5ms = 19'd323999;
                 parameter t_560us  = 14'd13439;
                 parameter t_1_12ms = 15'd26879;
                 parameter t_1_68ms = 16'd40319;
                 parameter t_2_24ms = 16'd53759;
          `endif
            
         `ifdef      CLK_50M
                 parameter t_38k    = 11'd1315;
                 parameter t_38k_half = 10'd657;
                 parameter t_9ms    = 19'd449999;
                 parameter t_4_5ms  = 18'd224999;             
                 parameter t_13_5ms = 20'd674999;
                 parameter t_560us  = 15'd27999;
                 parameter t_1_12ms = 16'd55999;             
                 parameter t_1_68ms = 17'd83999;             
                 parameter t_2_24ms = 17'd111999;
          `endif    
            
         parameter DATA_USER = 8'h00;
         
         //---------------------------------//
          //分频38Khz时钟
          reg  [10:0]   cnt1;
            wire         clk_38k;
            always @(posedge clk or negedge rst_n)
             begin
              if(!rst_n)
               begin
                   cnt1 <= 0;
                end
              else if(cnt1 == t_38k)
                begin
                   cnt1 <= 0;
                end
                else cnt1 <= cnt1 + 1;
             end
      assign  clk_38k = (cnt1<t_38k_half)?1:0;
     //-------------------------------------------//
     
    //    wire         key_1_flg;
    //        wire         key_2_flg;
    //      key_shake   U1(
    //            .clk_100M(clk),
    //            .rst_n(rst_n),
    //           
    //            .key_in(key_1),
    //            .key_out(key_1_flg)
    //             );
    //                         
    //        key_shake  U2(
    //            .clk_100M(clk),
    //            .rst_n(rst_n),
    //           
    //            .key_in(key_2),
    //            .key_out(key_2_flg)
    //             );
       reg   [2:0]      key_1_flag;
         wire             key_1_neg;
         wire             key_1_pos;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               key_1_flag <= 3'b000;
            end
          else 
            begin
               key_1_flag <= {key_1_flag[1:0],key_1};
            end
          end
        assign key_1_pos = (key_1_flag[2:1]== 2'b01);
        
        
         reg   [2:0]      key_2_flag;
         wire             key_2_neg;
         wire             key_2_pos;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               key_2_flag <= 3'b000;
            end
          else 
            begin
               key_2_flag <= {key_2_flag[1:0],key_2};
            end
          end
        assign key_2_pos = (key_2_flag[2:1] == 2'b01);
        
     //------------------------------------------//     
        parameter  IDEL       = 3'D0;        //初始化状态,等待发送命令
            parameter  START      = 3'D1;        //开始发送引导码 
            parameter  SEND_USER  = 3'D2;        //发送用户码
            parameter  SEND_UNUSER= 3'D3;        //发送用户反码
            parameter  SEND_DATA  = 3'D4;        //发送数据
            parameter  SEND_UNDATA= 3'D5;        //发送数据反码
            parameter  FINISH     = 3'D6;        //发送结束码
            parameter  FINISH_1   = 3'D7;        //发送结束
        reg   [2:0]     state;
        reg             start_en;
            wire            start_over;
            reg             zero_en;
            wire            zero_over;
            reg             one_en;
            wire            one_over;
             reg             finish_en;
            wire            finish_over;
            reg             sendover;
            reg   [7:0]     shiftdata;
            reg   [3:0]     i;
            reg   [7:0]     DATA;
            always @(posedge clk or negedge rst_n)
             begin
              if(!rst_n)
               begin
                  state <= IDEL;
                        start_en <= 0;
                        zero_en <= 0;
                        one_en <= 0;
                        finish_en <= 0;
                        sendover <= 0;
                        shiftdata <= 0; 
                        i <= 0;
                        DATA <= 8'D0;
                        
                        led_1 <= 1;
                        led_2 <= 1;                    
                end
              else 
                begin
                   case(state)
                         IDEL:
                            begin
                              start_en <= 0;
                                    zero_en <= 0;
                                    one_en <= 0;
                                    finish_en <= 0;
                                    sendover <= 0; 
                                    shiftdata <= 0;
                                    i <= 0;
                                    DATA <= 8'd0;
                                    
                                    if(key_1_pos)
                                      begin
                                        state <= START;    
                                            DATA <= 8'd1;
                                        end
                                     else if(key_2_pos)
                                         begin
                                                state <= START;    
                                                DATA <= 8'd2;
                                            end
                                    else state <= IDEL;
                             end
                          START:              //发送引导码
                               begin
                                         
                                     if(start_over)    
                                       begin                                         
                                             start_en <= 0;
                                             state <= SEND_USER;    
                                             shiftdata <= DATA_USER;
                                          end
                                     else 
                                          begin
                                             start_en <= 1;
                                             state <= START;     
                                          end     
                                end
                            SEND_USER:
                              begin
    //                                    led_3 <= 1;
                                        if((i==7)&&(one_over||zero_over))  //结束位
                                            begin
                                                  i <=0;    
                                          shiftdata <= ~DATA_USER;
                                                  state <= SEND_UNUSER;
                                                    one_en <= 0;
                                                  zero_en <= 0;
                                             end
                                        else
                                          begin                                                
                                                if(zero_over||one_over)   //1bit发送结束
                                                  begin
                                                    i <= i + 1;
                                                         one_en <= 0;
                                                         zero_en <= 0;
                                                     end
                                                else if(shiftdata[i])
                                                    begin
                                                         one_en <= 1;       
                                                     end
                                                else if(!shiftdata[i]) zero_en <= 1;
                                              else 
                                                    begin
                                                     i <= i ;
                                                         one_en <= one_en;
                                                         zero_en <= zero_en;
                                                     end    
                                           end
                                 end
                            SEND_UNUSER:
                               begin
                                        led_1 <= ~led_1;     
                                     if((i==7)&&(one_over||zero_over))  //结束位
                                            begin
                                                  i <=0;                                                 
                                                  state <= SEND_DATA;
                                                    shiftdata <= DATA;
                                                    one_en <= 0;
                                                    zero_en <= 0;
                                                    
                                             end
                                        else
                                          begin                                        
                                                if(zero_over||one_over)   //1bit发送结束
                                                  begin
                                                     i <= i + 1;
                                                         one_en <= 0;
                                                         zero_en <= 0;
                                                     end
                                                else if(shiftdata[i])
                                                    begin
                                                         one_en <= 1;       
                                                     end
                                                else if(!shiftdata[i]) zero_en <= 1;
                                              else 
                                                    begin
                                                     i <= i ;
                                                         one_en <= one_en;
                                                         zero_en <= zero_en;
                                                     end    
                                           end     
                                         
                                    end
                            SEND_DATA:
                               begin
                                         led_2 <= ~led_2    ;
                                        if((i==7)&&(one_over||zero_over))  //结束位
                                            begin
                                                  i <=0;                                                  
                                                  state <= SEND_UNDATA;
                                                    shiftdata <= ~DATA;
                                                    one_en <= 0;
                                                    zero_en <= 0;
                                             end
                                        else
                                          begin                                                
                                                if(zero_over||one_over)   //1bit发送结束
                                                  begin
                                                    i <= i + 1;
                                                         one_en <= 0;
                                                         zero_en <= 0;
                                                     end
                                                else if(shiftdata[i])
                                                    begin
                                                         one_en <= 1;       
                                                     end
                                                else if(!shiftdata[i]) zero_en <= 1;
                                              else 
                                                    begin
                                                     i <= i ;
                                                         one_en <= one_en;
                                                         zero_en <= zero_en;
                                                     end    
                                           end 
                                                                              
                                    end
                        SEND_UNDATA:
                            begin
                                        
                                    if((i==7)&&(one_over||zero_over))  //结束位
                                            begin
                                                  i <=0;    
                                                  shiftdata <= 0;
                                                  state <= FINISH;
                                                    one_en <= 0;
                                                    zero_en <= 0;
                                             end
                                        else
                                          begin                                            
                                                if(zero_over||one_over)   //1bit发送结束
                                                  begin
                                                     i <= i + 1;
                                                         one_en <= 0;
                                                         zero_en <= 0;
                                                     end
                                                else if(shiftdata[i])
                                                    begin
                                                         one_en <= 1;       
                                                     end
                                                else if(!shiftdata[i]) zero_en <= 1;
                                              else 
                                                    begin
                                                     i <= i ;
                                                         one_en <= one_en;
                                                         zero_en <= zero_en;
                                                     end    
                                           end         
                                        
                                    end
                            FINISH:
                               begin
                                        if(finish_over)    
                                        begin
                                             finish_en <= 0;
                                             state <= FINISH_1;     
                                          end
                                       else 
                                          begin
                                             finish_en <= 1;
                                             state <= FINISH;     
                                          end      
                                         
                                     end
                            FINISH_1:
                                  begin
                                                
                                          sendover <= 1;
                                            state <= IDEL;
                                            
                                  end
                                                    
                          default: state <= IDEL;
                        endcase
                end
              end
                
            
            
      //----------------------------------------------//
         //引导码,9ms载波加4.5ms空闲
         reg    [19:0]     cnt2;
         wire              start_flag;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               cnt2 <= 0;
            end
          else if(start_en)
            begin
              if(cnt2 >= t_13_5ms)  cnt2 <= t_13_5ms+1;        
                else cnt2 <= cnt2 + 1;
                end
            else cnt2  <= 0;         
         end
        assign start_over = (cnt2 == t_13_5ms)?1:0;    
        assign start_flag = (start_en&&(cnt2 <= t_9ms))?1:0;
        
      //----------------------------------------------//
         //比特0, 560us载波 + 560us空闲
         reg    [15:0]     cnt3;
         wire              zero_flag;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               cnt3 <= 0;
            end
          else if(zero_en)
            begin
              if(cnt3 >= t_1_12ms)  cnt3 <= t_1_12ms+1;        
                else cnt3 <= cnt3 + 1;
                end
            else cnt3  <= 0;         
         end
        assign zero_over = (cnt3 == t_1_12ms)?1:0;    
        assign zero_flag = (zero_en&&(cnt3 <= t_560us))?1:0;
        
       //----------------------------------------------//
         //比特1, 560us载波 + 1.68ms空闲
         reg    [16:0]     cnt4;
         wire              one_flag;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               cnt4 <= 0;
            end
          else if(one_en)
            begin
              if(cnt4 >= t_2_24ms)  cnt4 <= t_2_24ms+1;        
                else cnt4 <= cnt4 + 1;
                end
            else cnt4  <= 0;         
         end
        assign one_over = (cnt4 == t_2_24ms)?1:0;    
        assign one_flag = (one_en&&(cnt4 <= t_560us))?1:0;
        
        //----------------------------------------------//
         //结束码, 560us载波 
         reg    [14:0]     cnt5;
         wire              finish_flag;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
               cnt5 <= 0;
            end
          else if(finish_en)
            begin
              if(cnt5 >= t_560us)  cnt5 <= t_560us+1;        
                else cnt5 <= cnt5 + 1;
                end
            else cnt5  <= 0;         
         end
        assign finish_over = (cnt5 == t_560us)?1:0;    
        assign finish_flag = (finish_en&&(cnt5 <= t_560us))?1:0;
        
     //-----------------------------------//
     wire   ir_out;
     assign ir_out = start_flag||zero_flag||one_flag||finish_flag;
     assign IR_out = ir_out&&clk_38k;
     
     assign led_3 = i[1];
     assign led_4 = i[0];
     
        endmodule
        
    View Code

    接收程序:  

     
      
        /********************************Copyright**************************************                           
        **----------------------------File information--------------------------
        ** File name  :ir_resive.v  
        ** CreateDate :2015.06
        ** Funtions   : 中断接收程序。结束数据为:引导码+用户码+用户反码+数据码+数据反码。
        ** Operate on :M5C06N3L114C7
        ** Copyright  :All rights reserved. 
        ** Version    :V1.0
        **---------------------------Modify the file information----------------
        ** Modified by   :
        ** Modified data :        
        ** Modify Content:
        *******************************************************************************/
         
         module  IR_resive  (
                   clk,
                   rst_n,
                   
                             ir_in,
                                                      
                             led_error,
                             
                             led_5,
                             led_6,
                             led_7,
                             
                             test_data
                     );
         input          clk;
         input          rst_n;
         
         input          ir_in;
         
         output         led_error;
         
         output        led_5;
         output        led_6;
         output         led_7;
         
         
         output  [7:0]  test_data;
         //---------------------------------------------//
           reg    [2:0]    ir_in_reg;
             wire            ir_in_pos;
             wire            ir_in_neg;
             wire            ir_in_change;
             always @(posedge clk or negedge rst_n)
             begin
              if(!rst_n)
               begin
                   ir_in_reg <= 3'b111;
                end
              else 
                begin
                  ir_in_reg <= {ir_in_reg[1:0],ir_in}; 
                end
              end
            assign     ir_in_pos = (ir_in_reg[2:1] == 2'b01)?1:0;
            assign     ir_in_neg = (ir_in_reg[2:1] == 2'b10)?1:0;
            assign  ir_in_change = ir_in_pos|ir_in_neg;
            
         //------------------------------------//
         //设计分频和计数部分:从1838T的 技术手册中,可以得出最小的脉冲持续时间为500us,在采样时可以对最小的电平采样16次,即对500us采样16次,
       //则每次的采样间隔时间是  500us/16=31.25us     时钟频率为FCLK = X MHZ, 则最小采样计数为:N =31.25*X,
         //然后再用一个计数器计数同一电平的采样计数时间。
         //最后判断是leader的9ms 还是4.5ms,或是数据的 0 还是 1。
         //--------------------------------------------------------//
             `define     FCLK_20M 
    //         `define     FCLK_24M `
             
             `ifdef    FCLK_20M
              parameter   t_31_25us = 10'd625;
                    parameter   t_100k = 200;
                `endif    
                
                `ifdef    FCLK_24M
              parameter   t_31_25us = 10'd750; //
                    parameter   t_100k = 240;
                `endif
                
                `ifdef    FCLK_50M
              parameter   t_31_25us = 11'd1562; //
                    parameter   t_100k = 500;
                `endif
                
                  parameter   t_low_H = 26;
                    parameter   t_low_L = 13;      //16                
                    parameter   t_high_H=67;       //54  1.7MS左右    
                    parameter   t_high_L=35 ;                  
                    parameter   t_9ms_H   =9'd398;   //288
                    parameter   t_9ms_L   =9'd278;
                    parameter   t_4_5ms_H =9'd154;   //144
                    parameter   t_4_5ms_L =9'd134;
            
                    parameter   t_watch  = 9'd500;   //定时,计数达到500,则已经跑飞,
    
                    parameter   t_1s     = 16'd31999;
    
    
            
            //---------------------------------------------// 
             reg              idel_flag;     
             reg     [10:0]    cnt;
             always @(posedge clk or negedge rst_n)
             begin
              if(!rst_n)
               begin
                  cnt <= 0;
                end
                else if(idel_flag) cnt <= 0;        //空闲状态,不再变化
              else if(ir_in_change)  cnt <= 0;
              else if(cnt == t_31_25us) cnt <= 0;            
                else cnt<= cnt + 1;
             end
                
         reg    [8:0]        cnt1;
         always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
              cnt1 <= 0;
            end
            else if(idel_flag) cnt1 <= 0;
          else if(ir_in_change)  cnt1 <= 0;
          else if(cnt == t_31_25us) cnt1 <= cnt1 + 1;
            else cnt1 <= cnt1;
         end
         
         
               wire          t_9ms_flag;
                wire          t_4_5_ms_flag;
                wire          short_flag;     //短电平,可是高电平也可以是低电平
                wire          long_flag;      //长电平,肯定是高电平  
                assign  t_9ms_flag = ((cnt1 > t_9ms_L)&&(cnt1 < t_9ms_H));
                assign  t_4_5_ms_flag = ((cnt1 > t_4_5ms_L)&&(cnt1 < t_4_5ms_H));
                assign  long_flag = ((cnt1 > t_high_L)&&(cnt1 < t_high_H));
                assign  short_flag = ((cnt1 > t_low_L)&&(cnt1 < t_low_H));
                
                wire          watchdog;
                assign  watchdog =  (cnt1 > t_watch)?1:0;
        //---------------------------------------------//
        parameter   IDEL    = 4'd0;
        parameter   L_9MS   = 4'd1;
        parameter   L_4_5MS = 4'd2;
        parameter   DATA_R  = 4'd4;
        parameter   FINISH_R= 4'd8;
        
       reg      [3:0]      state;
         reg      [31:0]     shiftdata;
         reg      [5:0]      n;
         reg                 error_flag;
         reg                 r_over;
         reg      [31:0]     rdata;
     always @(posedge clk or negedge rst_n)
     begin
      if(!rst_n)
       begin
          state <= IDEL;
                shiftdata <= 0;
                n <= 0;
                error_flag <= 0;
                rdata <= 0;
                r_over<= 0;
                idel_flag <= 0;
                
    //            led_5 <= 1;
    //            led_6 <= 1;
        end
    //  else  if(watchdog) state <= IDEL;
        else 
        begin
          case(state)
                 IDEL:
                   begin
                             
                          idel_flag <= 1;   //空闲状态
                            shiftdata <= 0;
                      n <= 0;
                      error_flag <= 0; 
                            r_over<= 0;
                            if(ir_in_reg[1] ==0) 
                             begin
                                 state <= L_9MS;  //检测到拉低数据线
                                 idel_flag <= 0;
                              end
                            else  state <= IDEL;
                        end
                L_9MS:        //9ms为低电平,数据线拉高时结束
                  begin
    //                    led_5 <= 0;
                        if(watchdog) state <= IDEL;                        
                        else if(ir_in_pos)    
                         begin 
                             if(t_9ms_flag)  state <= L_4_5MS;
                             else 
                                 begin
                                     state <= IDEL;
                                     error_flag <= 1;
                                    end
                          end    
                        else   state <= L_9MS;
                     end
                L_4_5MS:
                  begin
                     if(watchdog) state <= IDEL;        
                        else if(ir_in_neg)    
                         begin 
                             if(t_4_5_ms_flag)  state <= DATA_R;
                             else 
                                 begin
                                     state <= IDEL;
                                     error_flag <= 1;
                                    end
                          end    
                        else   state <= L_4_5MS;    
                 end
                DATA_R:
                  begin
    //                    led_6 <= 0;
                     if(watchdog) state <= IDEL;        
                   else if((n == 32)&&(ir_in_reg[2:1] == 2'b11))  state <= FINISH_R;
                     else if(ir_in_pos)    
                         begin 
                             if(short_flag)  state <= DATA_R;
                             else 
                                 begin
                                     state <= IDEL;
                                     error_flag <= 1;
                                    end
                          end    
                     else if(ir_in_neg)
                         begin
                                n<= n + 1;
                                if(short_flag) shiftdata[n] <= 0;        //从低位到高位依次接收,这样数据的位置是 相反的
                                else if(long_flag)  shiftdata[n] <= 1;  //从原来的{用户码,用户反码,数据,数据反码}变为{数据反码,数据,用户反码,用户码}
                                else                                     //所以要调整数据位置
                                    begin
                                     state <= IDEL;
                                     error_flag <= 1;
                                    end    
                        end                     
                        else   state <= DATA_R;                            
                  end
                FINISH_R:
                  begin
                        r_over <= 1;    
                        rdata <= {shiftdata[7:0],shiftdata[15:8],shiftdata[23:16],shiftdata[31:24]};               //调整位置
                        state <= IDEL;
                     end
                default:state <= IDEL;
             endcase     
        end
      end
        
         //---------------------------------------------//
         assign led_5 = (rdata[15:8] == 8'h01)?0:1; 
         assign led_6 = (rdata[15:8] == 8'h02)?0:1;
       assign led_7 = (rdata[31:24] == 8'h00)?0:1;
         assign test_data = rdata[15:8];
    //  assign test_data = {error_flag,t_4_5_ms_flag,ir_in_change,ir_in_reg[1],state[3:0]};
        endmodule
        
        
        
    View Code        

        按键消抖(与以前有修改):    

    /********************************Copyright**************************************                           
    **----------------------------File information--------------------------
    ** File name  :key_shake.v  
    ** CreateDate :2015.03
    ** Funtions   : 按键的消抖操作:在复位之后的100us内,不响应按键的操作,在之后有按键按下后,有20ms的延迟,之后输出按键输出.
    ** Operate on :M5C06N3L114C7
    ** Copyright  :All rights reserved[F]. 
    ** Version    :V1.0
    **---------------------------Modify the file information----------------
    ** Modified by   :    
    ** Modified data :             2015.04                            2015.06
    ** Modify Content:V1.1:clk-->clk_100M, 常数声明放到一起,便于修改。     增加实用20Mclk,并将输出修改为连续高电平
    *******************************************************************************/
     
     module  key_shake (
               clk_100M,
               rst_n,
               
                key_in,
                key_out
                 );
     input          clk_100M;            //100Mhz
     input          rst_n;
     
     input          key_in;
     output         key_out;
     
     //--------------------------------------
     
     //在复位之后的100us内,不响应按键的操作
     
    //  `define   CLK_100M
        `define   CLK_20M
        
     `ifdef  CLK_100M
                parameter    t_100us  = 14'd9999;
                parameter    t1ms = 17'd99999;       //定时1ms 
                parameter    t_20ms = 5'd20;
      `endif
     
      `ifdef  CLK_20M
                parameter    t_100us  = 14'd1999;
                parameter    t1ms = 17'd19999;       //定时1ms 
                parameter    t_20ms = 5'd20;
      `endif
        
      reg    [13:0]   cnt;
        reg             key_en;         //复位之后允许按键输入标志
     always @(posedge clk_100M or negedge rst_n)
     begin
      if(!rst_n)
       begin
          cnt <= 0;
                key_en <=0;
        end
      else 
        begin
          if(cnt == t_100us)
                  begin
                       key_en <= 1;
                     end
           else
                  begin
                        key_en <= 0; 
                       cnt <= cnt + 1;
                  end
        end
      end
     
     //--------------------------------------------------
     wire         HtoL_flag;         //下降沿标志
     wire         LtoH_flag;         //上升沿标志
     reg   [2:0]   key_reg;
     always @(posedge clk_100M or negedge rst_n)
     begin
      if(!rst_n)
       begin
          key_reg <= 3'b111;            //默认没按下状态为高,按下之后为低.反之则为3'b000;
        end
      else 
        begin
          key_reg <= {key_reg[1:0],key_in};  
        end
      end
        
     assign HtoL_flag = key_en?(key_reg[2:1] == 2'b10):0;            //下降沿检测,一个时钟的高电平
     assign LtoH_flag = key_en?(key_reg[2:1] == 2'b01):0;               //上升沿检测,一个时钟的高电平  
    //---------------------------------------------
     reg          cnt_en;                 //计数使能标志
    
     reg   [16:0]  cnt2; 
     always @(posedge clk_100M or negedge rst_n)
     begin
      if(!rst_n)
       begin
          cnt2 <= 17'd0;
        end
      else if((cnt_en)&&(cnt2 == t1ms))
        begin
          cnt2 <= 17'd0;
        end
        else if(cnt_en)
        begin
          cnt2 <= cnt2 + 17'd1;
        end    
        else 
              cnt2 <= 17'd0;    
      end
        
     reg   [4:0]   cnt3; 
     always @(posedge clk_100M or negedge rst_n)
     begin
      if(!rst_n)
       begin
           cnt3 <= 5'd0;
        end
      else if((cnt_en)&&(cnt2 == t1ms))
        begin
                if(cnt3 == t_20ms )
                   cnt3 <= t_20ms;
                else
             cnt3 <= cnt3 + 1;                              
        end
        else if(!cnt_en)
           cnt3 <= 5'd0;        
      end
        
    //----------------------------------
    //按键状态机
        reg  [2:0]  i;
        reg      key_down;        //按键按下标志
        reg      key_up;          //按键释放标志  
        always @(posedge clk_100M or negedge rst_n)
         begin
          if(!rst_n)
           begin
                    key_down <= 0;
                    key_up <= 0;
                    i <= 0;
                    cnt_en <= 0;
            end
          else 
            begin
              case(i)
                     'd0:
                        begin
                                 key_down <= 0;
                           key_up <= 0;    
                          if(HtoL_flag) i <= 'd1;         //检测到按下
                                else if(LtoH_flag) i <= 'd2;    //检测到释放按键
                                else  i  <= 'd0;
                         end
                        'd1:
                          begin
                                if(cnt3 == t_20ms )
                                  begin
                                     if(!key_in)                  //检测到按键依然被按下
                                       begin
                                           key_down <= 1;            //按键按下成功
                                           i <= 'd3;
                                           cnt_en <= 0;
                                          end
                                        else
                                           begin
                                            key_down <= 0; 
                                             i <= 'd0;
                                             cnt_en <= 0;        
                                             end
                                     end
                                 else
                                   cnt_en <= 1;
                                end
                        'd2:
                          begin
                                if(cnt3 == t_20ms )
                                  begin
                                        if(key_in)                  //检测到按键被释放
                                       begin
                                           key_up <= 1;             //按键释放成功
                                           i <= 'd4;
                                           cnt_en <= 0;
                                          end
                                        else
                                            begin
                                               key_up <= 0;  
                                             i <= 'd0;
                                             cnt_en <= 0;        
                                             end
                                     end
                                 else
                                   cnt_en <= 1;
                                end
                        'd3:
                          begin
                                                     if(key_in)    
                                                       begin                             
                                 key_down <= 0;            
                                 i <= 'd0;  
                                                          end
                                                        else 
                                                             i <= 'd3;
                             end 
                                            'd4:
                                                begin
                                                     if(!key_in)    
                                                       begin                             
                                 key_up <= 0;            
                                 i <= 'd0;  
                                                          end
                                                        else 
                                                             i <= 'd4;        
                                                end
                      default:i <= 'd0;    
                    endcase            
            end
          end
            
     assign      key_out = key_down;         //当按键被按下有效时
    // assign   key_out = key_up;         //当按键被释放后才有效时
    endmodule
    View Code

        将两个程序合在一起的顶层文件:

       

      
        /********************************Copyright**************************************                           
        **----------------------------File information--------------------------
        ** File name  :IR_TOP.v  
        ** CreateDate :2015.06
        ** Funtions   : 中断的顶层文件
        ** Operate on :M5C06N3F256C7
        ** Copyright  :All rights reserved. 
        ** Version    :V1.0
        **---------------------------Modify the file information----------------
        ** Modified by   :
        ** Modified data :        
        ** Modify Content:
        *******************************************************************************/
         
        module  IR_TOP  (
                   clk,
                   rst_n,
                   
                             ir_in,
                             ir_out,
                             
                             key_1,
                             key_2,
                             
                             led_d1,
                             led_d2,
                             led_d3,
                             led_d4,
                             led_d5,
                             led_d6,
                             led_d7,
                             led_d8,
                                                      
                             test_data
                     );
         input          clk;
         input          rst_n;
         
         input          key_1;
         input          key_2;
              
         input          ir_in;
         output         ir_out;
         
         output         led_d1;
         output         led_d2;
         output         led_d3;
         output         led_d4;
         output         led_d5;
         output         led_d6;
         output         led_d7;
         output         led_d8;
              
         output  [7:0]  test_data;
         
         //---------------------------------------------//
          wire         key_1_flag;
            wire         key_2_flag;
          key_shake   U1(
                .clk_100M(clk),
                .rst_n(rst_n),
               
                .key_in(key_1),
                .key_out(key_1_flag)
                 );
                             
            key_shake  U2(
                .clk_100M(clk),
                .rst_n(rst_n),
               
                .key_in(key_2),
                .key_out(key_2_flag)
                 );
                             
          wire  [7:0]   data_t;
                                 
          IR_send  u1(
                   .clk(clk),
                   .rst_n(rst_n),
                   
                             .key_1(key_1_flag),
                             .key_2(key_2_flag),
                             
                             .IR_out(ir_out),
                             .led_1(led_d1),
                             .led_2(led_d2),
                             .led_3(led_d3),
                             .led_4(led_d4)
                     ); 
                                 
          IR_resive  u2(
                   .clk(clk),
                   .rst_n(rst_n),
                   
                             .ir_in(ir_in),
                                                      
                             .led_error(led_d8),
                             
                             .led_5(led_d5),
                             .led_6(led_d6),
                             .led_7(led_d7),
                             .test_data(data_t)
                     );
         //---------------------------------------------//
         assign  test_data = data_t;
        endmodule
        
        
    View Code 

      仿真图:

       接收仿真图:

         

       发送仿真图:

      

  • 相关阅读:
    heat模板
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode819.Most Common Word最常见的单词
    Leetcode819.Most Common Word最常见的单词
    Leetcode783.Minimum Distance Between BST Nodes二叉搜索树结点最小距离
  • 原文地址:https://www.cnblogs.com/fhyfhy/p/4556979.html
Copyright © 2011-2022 走看看