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

📄 i2c_st.v

📁 RD1006--I2C与存储器的IP 代码及说明文档
💻 V
字号:
//----------------------------------------------------------------------------
// 
//  Name:  i2c_st.v   
// 
//  Description: Statemachine module of the I2C serial controller
// 
//  $Revision: 1.0 $          
//  
//  Copyright 2004 Lattice Semiconductor Corporation.  All rights reserved.
//
//----------------------------------------------------------------------------
// Permission:
//
//   Lattice Semiconductor grants permission to use this code for use
//   in synthesis for any Lattice programmable logic product.  Other
//   use of this code, including the selling or duplication of any
//   portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL or Verilog source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Lattice Semiconductor provides no warranty
//   regarding the use or functionality of this code.
//----------------------------------------------------------------------------
//
//    Lattice Semiconductor Corporation
//    5555 NE Moore Court
//    Hillsboro, OR 97124
//    U.S.A
//
//    TEL: 1-800-Lattice (USA and Canada)
//    408-826-6000 (other locations)
//
//    web: http://www.latticesemi.com/
//    email: techsupport@latticesemi.com
// 
//----------------------------------------------------------------------------
`timescale 1 ns /  100 ps

/*
This module provides the state machine for the I2C interface.
*/

module i2c_st(  rst_l,
                clock,
                scl_tick,
                i2c_go,
                wrd_add,
                sda_pin,
                sda,
                scl,
                scl_cnt_en,
                i2c_rdy,
                i2c_act,
                i2c_rdata,
                ack_err);

//-------------------------------------------------------------------
// port list

input           rst_l;              // reset
input           clock;              // mpu clock
input           scl_tick;           // 5 usec clock tick
input           i2c_go;             // start i2c cycle
input   [7:0]   wrd_add;            // i2c address
input           sda_pin;             // i2c data muxed input

output          sda;                // i2c data
output          scl;                // i2c clock
output          scl_cnt_en;         // scl cntr enable
output          i2c_rdy;            // i2c ready
output          i2c_act;            // i2c cycle active
output  [7:0]   i2c_rdata;          // i2c read data
output          ack_err;            // ack error

//-------------------------------------------------------------------
// registers

reg             sda;
reg             scl;
reg             scl_cnt_en;
reg             i2c_rdy;
reg     [7:0]   i2c_rdata;

reg     [3:0]   i2c_state;

reg     [2:0]   bit_cntr;

reg             scl_en;
reg             en_cntr;
reg             cntr_done;
reg             ack_err;

wire            i2c_act;

//-------------------------------------------------------------------
// parameters

parameter   idle     = 4'b0000;     // state 0
parameter   en_clk   = 4'b0001;     // state 1
parameter   start1   = 4'b1100;     // state C
parameter   dev_add1 = 4'b1000;     // state 8
parameter   ack1     = 4'b0100;     // state 4
parameter   w_add    = 4'b1010;     // state A
parameter   ack2     = 4'b0101;     // state 5
parameter   wait1    = 4'b0011;     // state 3
parameter   dis_clk1 = 4'b1111;     // state F
parameter   start2   = 4'b1101;     // state D
parameter   dev_add2 = 4'b1001;     // state 9
parameter   ack3     = 4'b0110;     // state 6
parameter   data     = 4'b1011;     // state B
parameter   ack4     = 4'b0111;     // state 7
parameter   stop1    = 4'b1110;     // state E

//-------------------------------------------------------------------
// state machine

always @(posedge clock or negedge rst_l)
    if (!rst_l) 
        i2c_state <= #1 idle;
        
    else case(i2c_state)
    
    idle : if (i2c_go) 
        i2c_state <= #1 en_clk;
        
    en_clk : if (scl_tick)
        i2c_state <= #1 start1;
            
    start1 : if (scl_tick)
        i2c_state <= #1 dev_add1;
             
    dev_add1 : if (cntr_done && scl_tick)
        i2c_state <= #1 ack1;
       
    ack1 : if (scl_tick && scl)
        i2c_state <= #1 w_add;   
        
    w_add : if (cntr_done && scl_tick)
        i2c_state <= #1 ack2;
                
    ack2 : if (scl_tick && scl)
        i2c_state <= #1 dis_clk1;
        
    dis_clk1 : if (scl_tick && scl)
        i2c_state <= #1 wait1;
        
    wait1 : if (scl_tick)
        i2c_state <= #1 start2;

    start2 : if (scl_tick)
        i2c_state <= #1 dev_add2;

    dev_add2 : if (cntr_done && scl_tick)
        i2c_state <= #1 ack3;
        
    ack3 : if (scl_tick && scl)
        i2c_state <= #1 data;

    data : if (cntr_done && scl_tick)
        i2c_state <= #1 ack4;

    ack4 : if (scl_tick && scl)
        i2c_state <= #1 stop1;
        
    stop1 : if (scl_tick && scl)
        i2c_state <= #1 idle;
                
        default : 
                i2c_state <= #1 idle;
        
    endcase
     
//-------------------------------------------------------------------
// bit counter

always @(posedge clock or negedge rst_l)
    if (!rst_l)
        bit_cntr <= #1 3'b111;
    else if (en_cntr && scl && scl_tick)
        bit_cntr <= #1 bit_cntr - 1;
        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        cntr_done <= #1 1'b0;
    else if (bit_cntr == 3'b0 && scl)
        cntr_done <= #1 1'b1;
    else
        cntr_done <= #1 1'b0;
        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        en_cntr <= #1 1'b0;
    else if ((i2c_state == dev_add1) ||
             (i2c_state == w_add)    ||
             (i2c_state == dev_add2) ||
             (i2c_state == data))
        en_cntr <= #1 1'b1;
    else if (cntr_done)
        en_cntr <= #1 1'b0;
        
//-------------------------------------------------------------------
// scl generation

// enable clock divider
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        scl_cnt_en <= #1 1'b0;
    else if (i2c_state == en_clk)
        scl_cnt_en <= #1 1'b1;
    else if (i2c_state == idle)
        scl_cnt_en <= #1 1'b0;
        
// enables tick divider        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        scl_en <= #1 1'b0;
    else if (i2c_state == start1)
        scl_en <= #1 1'b1;
    else if (i2c_state == dis_clk1 && scl_tick) 
        scl_en <= #1 1'b0;
    else if (i2c_state == start2)
        scl_en <= #1 1'b1;
    else if (i2c_state == stop1 && scl)
        scl_en <= #1 1'b0;

// tick divider        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        scl <= #1 1'b1;
    else if (scl_en && scl_tick)
        scl <= #1 ~scl;   

//-------------------------------------------------------------------
// sda generation

always @(posedge clock or negedge rst_l)
    if (!rst_l)
        sda <= #1 1'b1;     
    else if ((i2c_state == start1)   ||         // starts
             (i2c_state == start2)   ||
             (i2c_state == stop1)    ||
            ((i2c_state == dev_add1) &&         // write  address
             (bit_cntr != 3'b111)    &&         // device bit 7
             (bit_cntr != 3'b101))   ||         // device bit 5
            ((i2c_state == dev_add2) &&         // read address
             (bit_cntr != 3'b111)    &&         // device bit 7
             (bit_cntr != 3'b101)    &&         // device bit 5
             (bit_cntr != 3'b000)))             // read bit
        sda <= #1 1'b0; 
    else if((i2c_state == w_add))               // word address
        sda <= #1 wrd_add[bit_cntr];
    else
        sda <= #1 1'b1;

always @(posedge clock or negedge rst_l)
    if (!rst_l)
        i2c_rdata <= #1 8'b0;
    else if ((i2c_state == data) && scl)
        i2c_rdata[bit_cntr] <= #1 sda_pin;
    else if (i2c_go)
        i2c_rdata <= #1 8'b0;
        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        i2c_rdy <= #1 1'b0;
    else if ((i2c_state == stop1) && scl)
        i2c_rdy <= #1 1'b1;
    else if (i2c_go)
        i2c_rdy <= #1 1'b0;
        
always @(posedge clock or negedge rst_l)
    if (!rst_l)
        ack_err <= #1 1'b0;
    else if (((i2c_state == ack1)  || 
              (i2c_state == ack2)  ||
              (i2c_state == ack3)) && scl && sda_pin)
        ack_err <= #1 1'b1;
    else if (i2c_go)
        ack_err <= #1 1'b0;
        
               
assign i2c_act = ~(i2c_state == idle);
               
endmodule    

//------------------------------- E O F -------------------------------------- 

⌨️ 快捷键说明

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