⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irda_check.v

📁 红外通讯作为一种简便的无线通讯技术在电子设备中具有广泛的应用
💻 V
字号:
////////////////////////////////////////////////////////////////////////////////
//                __     ___ _               ___ ____                         //
//                \ \   / (_) |__   ___  ___|_ _/ ___|                        //
//                 \ \ / /| | '_ \ / _ \/ __|| | |                            //
//                  \ V / | | |_) |  __/\__ \| | |___                         //
//                   \_/  |_|_.__/ \___||___/___\____|                        //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
// 	   Copyright (C) 2003-2006 VibesIC, Inc.   All rights reserved.           //
//----------------------------------------------------------------------------//
// This source code is provided by VibesIC,and be verified on VibesIC FPGA    //
// development kit. The source code may be used and distributed without       //
// restriction provided that this copyright statement is not removed from the //
// file and that any derivative work contains the original copyright notice   //
// and the associated disclaimer.                                             //
//----------------------------------------------------------------------------//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED     //
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF       //
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE//
// AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     //
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,//
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,OR PROFITS; //
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   //
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR    //
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF     //
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                 //
//----------------------------------------------------------------------------//
// 本设计由威百仕( VibesIC )提供,并在其产品中验证通过,您可以在此基础上修改,//
// 复制并分发,但请您保留版权声明部分。我们并不承诺本设计可以用做商业产品,同时//
// 我们不保证设计的通用性。为了方便更新以及修改请保留设计的版本信息,并对自行 //
// 修改部分添加足够的注释。对设计如有其他建议,请到网站进行讨论。              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//  Company:       www.richic.com                                             //
//  Company bbs:   www.edacn.net                                              //
//  Engineer:      alex_yang                                                  //
//                                                                            //
//  Target Device: XC3S400-PQ208                                              //
//  Tool versions: Simulation:    ModelSim SE 6.2a                            //
//                 Synthesis:     XST(ise8.1...sp3)                           //
//                 Place&Routing: ISE8.1...sp3                                //
//                 Others tools:  UltraEdit-32 12.10a                         //
//  Create Date:   2006-9-6 12:29                                             //
//  Description:                                                              //
//                                                                            //
//  LOG:                                                                      //
//       1. Revision 1.0 (Initial version)  2006-9-6 12:29    alex_yang       //
//                                                                            //
//       2. Revision 1.1  2006-12-20 16:09   alex_yang                        //
//          Modify for VX-SP306                                               //
////////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ns

module irda_check (clk, rst_n, irda, irda_data);
  input   clk;
  input   rst_n;
  input   irda;
  output  irda_data;
  
  reg [15:0] irda_data;    // save irda data,than send to 7 segment led
  reg [31:0] get_data;     // use for saving 32 bytes irda data
  reg [5:0]  data_cnt;     // 32 bytes irda data counter
  reg [2:0]  cs,ns;
  reg error_flag;          // 32 bytes data期间,数据错误标志

  parameter   IDLE       = 3'b000,
              LEADER_9   = 3'b001,
              LEADER_4   = 3'b010,
              DATA_STATE = 3'b100;

  //----------------------------------------------------------------------------
  reg irda_reg0;       //为了避免亚稳态,避免驱动多个寄存器,这一个不使用。
  reg irda_reg1;       //这个才可以使用,以下程序中代表irda的状态
  reg irda_reg2; //为了确定irda的边沿,再打一次寄存器,以下程序中代表irda的前一状态
  wire irda_neg_pulse; //确定irda的下降沿
  wire irda_pos_pulse; //确定irda的上升沿
  wire irda_chang;     //确定irda的跳变沿
    
  always @ (posedge clk) //在此采用跟随寄存器
    if(!rst_n)
      begin
        irda_reg0 <= 1'b0;
        irda_reg1 <= 1'b0;
        irda_reg2 <= 1'b0;
      end
    else
      begin
        irda_reg0 <= irda;
        irda_reg1 <= irda_reg0;
        irda_reg2 <= irda_reg1;
      end 
      
  assign irda_chang = irda_neg_pulse | irda_pos_pulse;
  assign irda_neg_pulse = irda_reg2 & (~irda_reg1);
  assign irda_pos_pulse = (~irda_reg2) & irda_reg1;

  //----------------------------------------------------------------------------
  //设计分频和计数部分:从PT2222的规范中我们发现最小的电平保持时间是0.56ms,而
  //我们在进行采样时,一般都会对最小的电平采样16次。也就是说要对0.56ms最少采样16
  //次。
  //              0.56ms/16=35us 
  //在开发板上自带的主频为50MHz,即时钟周期为20ns,所以我们需要的分频次数为:
  //              35000/20=1750
  //在设计中我们利用了两个counter,一个counter用于计1750次时钟主频;
  //一个counter用于计算分频之后,同一种电平所scan到的点数,这个点数最后会用来判断
  //是leader的9ms 还是4.5ms,或是数据的 0 还是 1。
  //----------------------------------------------------------------------------
  reg [10:0] counter;  //分频1750次
  reg [8:0]  counter2; //计数分频后的点数
  wire check_9ms;  // check leader 9ms time
  wire check_4ms;  // check leader 4.5ms time
  wire low;        // check  data=0 time
  wire high;       // check  data=1 time
  
  always @ (posedge clk)
    if (!rst_n)
      counter <= 11'd0;
    else if (irda_chang)  //irda电平跳变了,就重新开始计数
      counter <= 11'd0;
    else if (counter == 11'd1750)
      counter <= 11'd0;
    else
      counter <= counter + 1'b1;
   
  always @ (posedge clk)
    if (!rst_n)
      counter2 <= 9'd0;
    else if (irda_chang)  //irda电平跳变了,就重新开始计点
      counter2 <= 9'd0;
    else if (counter == 11'd1750)
      counter2 <= counter2 +1'b1;

  assign check_9ms = ((217 < counter2) & (counter2 < 297)); //257
  assign check_4ms = ((88 < counter2) & (counter2 < 168));  //128
  assign low  = ((6 < counter2) & (counter2 < 26));         // 16
  assign high = ((38 < counter2) & (counter2 < 58));        // 48

  //----------------------------------------------------------------------------
  // generate statemachine
  always @ (posedge clk)
    if (!rst_n)
      cs <= IDLE;
    else 
      cs <= ns;
      
  always @ ( * )
    case (cs)
      IDLE: 
        if (~irda_reg1) 
          ns = LEADER_9;
        else
          ns = IDLE;
      LEADER_9:
        if (irda_pos_pulse)   //leader 9ms check
          begin
            if (check_9ms)
              ns = LEADER_4;
            else
              ns = IDLE;
          end
        else  //完备的if---else--- ;防止生成latch
          ns =LEADER_9;
      LEADER_4:
        if (irda_neg_pulse)  // leader 4.5ms check
          begin
            if (check_4ms)
              ns = DATA_STATE;
            else
              ns = IDLE;
          end
        else
          ns = LEADER_4;
      DATA_STATE:
        if ((data_cnt == 6'd32) & irda_reg2 & irda_reg1)
          ns = IDLE;
        else if (error_flag)
          ns = IDLE;
        else
          ns = DATA_STATE;
      default:
        ns = IDLE;
    endcase

  //状态机中的输出,用时序电路来描述
  always @ (posedge clk)
    if (!rst_n)
      begin
        data_cnt <= 6'd0;
        get_data <= 32'd0;
        error_flag <= 1'b0;
      end
    else if (cs == IDLE)
      begin
        data_cnt <= 6'd0;
        get_data <= 32'd0;
        error_flag <= 1'b0;
      end
    else if (cs == DATA_STATE)
      begin
        if (irda_pos_pulse)  // low 0.56ms check
          begin
            if (!low)  //error
              error_flag <= 1'b1;
          end
        else if (irda_neg_pulse)  //check 0.56ms/1.68ms data 0/1
          begin
            if (low)
              get_data[0] <= 1'b0;
            else if (high)
              get_data[0] <= 1'b1;
            else
              error_flag <= 1'b1;
              
            get_data[31:1] <= get_data[30:0];
            data_cnt <= data_cnt + 1'b1;
          end
      end

  always @ (posedge clk)
    if (!rst_n)
      irda_data <= 16'd0;
    else if ((data_cnt ==6'd32) & irda_reg1)
      irda_data <= get_data[15:0];
    
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -