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

📄 i2c_st.v

📁 清华大学verilog hdl源码例子
💻 V
字号:


module i2c_st(  rst_l,
                clock,
                scl_tick,                
                sda_pin,
                sda,
                scl,
                scl_cnt_en,              
                i2c_rdata
		);

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

input           rst_l;              // reset
input           clock;              // mpu clock
input           scl_tick;           // 5 usec clock tick
input           sda_pin;            // i2c data muxed input

output          sda;                // i2c data
output          scl;                // i2c clock
output          scl_cnt_en;         // scl cntr enable
output  [7:0]   i2c_rdata;          // i2c read data

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

reg             sda;
reg             scl;
reg             scl_cnt_en;
reg             i2c_rdy;
reg     [7:0]   i2c_rdata;
reg     [4: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     = 5'b00000;     // state 0
parameter   en_clk   = 5'b00001;     // state 1
parameter   start1   = 5'b00010;     // state 2
parameter   dev_add1 = 5'b00011;     // state 3
parameter   ack1     = 5'b00100;     // state 4
parameter   w_add    = 5'b00101;     // state 5
parameter   ack2     = 5'b00110;     // state 6
parameter   w_data1  = 5'b00111;     // state 7
parameter   ack3     = 5'b01000;     // state 8
parameter   w_data2  = 5'b01001;     // state 9
parameter   ack4     = 5'b01010;     // state 10

parameter   dis_clk1 = 5'b01011;     // state 11
parameter   wait1    = 5'b01100;     // state 12
parameter   start2   = 5'b01101;     // state 13
parameter   dev_add2 = 5'b01110;     // state 14
parameter   ack5     = 5'b01111;     // state 15
parameter   w_add2   = 5'b10000;     // state 16                           
parameter   ack6     = 5'b10001;     // state 17   

parameter   dis_clk2 = 5'b10010;     // state 18
parameter   wait2    = 5'b10011;     // state 19
parameter   start3   = 5'b10100;     // state 20
parameter   dev_add3 = 5'b10101;     // state 21
parameter   ack7     = 5'b10110;     // state 22             
                       
parameter   r_data1  = 5'b10111;     // state 23
parameter   ack8     = 5'b11000;     // state 24
parameter   r_data2  = 5'b11001;     // state 25
parameter   ack9     = 5'b11010;     // state 26
parameter   stop1    = 5'b11011;     // state 27
parameter   stop2    = 5'b11100;     // state 27



//-------------------------------------------------------------------
// state machine
wire [7:0] wrd_add3 = 8'b10010001;
//wire [7:0] wrd_add3 = 8'b0000001;
wire [7:0] wrd_add1 = 8'h62;
wire [7:0] wrd_add2 = 8'h62;

reg [2000:0] i;
always @(posedge clock or negedge rst_l)
    if (!rst_l) 
    	begin
        i2c_state <= #1 idle;
        i <= 0;
        end
    else case(i2c_state)
    
    idle : 
        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 w_data1;

    w_data1 : if (cntr_done && scl_tick)
        i2c_state <= #1 ack3;
        
    ack3 : if (scl_tick && scl)
        i2c_state <= #1 w_data2;

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

    ack4 : if (scl_tick && scl)
	begin
        i2c_state <= #1 stop1;        
	$display($time,": finish write");	
	end
    
    stop1 : if (scl_tick && scl)
        begin
        i2c_state <= #1 dis_clk1;	      
	end
	
    dis_clk1 : if (scl_tick && scl)
        i2c_state <= #1 wait1;
        
    wait1 : if (scl_tick)
        i2c_state <= #1 start2;

    start2 : if (scl_tick)
    	begin
    	$display($time,": start wirte dev addr");
        i2c_state <= #1 dev_add2;
	end
    dev_add2 : if (cntr_done && scl_tick)
        i2c_state <= #1 ack5;
        
    ack5 : if (scl_tick && scl)    
        i2c_state <= #1 w_add2;
    w_add2 : if (cntr_done && scl_tick)
        begin
        i2c_state <= #1 ack6;      
        $display($time,": start wirte eeprom data addr"); 
        end
        
    ack6 : if (scl_tick && scl)
        i2c_state <= #1 dis_clk2;        

   dis_clk2 : if (scl_tick && scl)
        i2c_state <= #1 wait2;
        
    wait2 : if (scl_tick)        
        i2c_state <= #1 start3;
	
    start3 : if (scl_tick)
        i2c_state <= #1 dev_add3;


    dev_add3 : if (cntr_done && scl_tick)
        begin
	$display($time,": start wirte dev addr");
        i2c_state <= #1 ack7;
        end
        
    ack7 : if (scl_tick && scl)
        i2c_state <= #1 r_data1;

    r_data1 : if (cntr_done && scl_tick)
    	begin
    	$display($time,": start read comm"); 
        i2c_state <= #1 ack8;
        end
    ack8 : if (scl_tick && scl)
        i2c_state <= #1 stop2;   
        
    stop2 : if (scl_tick && scl)
        i2c_state <= #1 stop2;
                
        default : 
                i2c_state <= #1 stop2;
        
    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 == w_add2)    ||
             (i2c_state == dev_add2) ||
             (i2c_state == dev_add3) ||
             (i2c_state == w_data1)    ||
             (i2c_state == w_data2)    ||
             (i2c_state == r_data1)    ||
             (i2c_state == r_data2)              
             )   
        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 == dis_clk2 && scl_tick) 
        scl_en <= #1 1'b0;    
    else if (i2c_state == start2)
        scl_en <= #1 1'b1;
       else if (i2c_state == start3)
        scl_en <= #1 1'b1;        
    else if (i2c_state == stop1 && scl)
        scl_en <= #1 1'b0;
    else if (i2c_state == stop2 && 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 == start3)   ||
             (i2c_state == stop1)    ||
             (i2c_state == stop2)    ||
            
            ((i2c_state == dev_add1) &&        // write  address
             (bit_cntr != 3'b111)    &&        // device bit 7
             (bit_cntr != 3'b101))   ||        // device bit 5   
                      			                       
	    ((i2c_state == dev_add2) &&        // write  address
             (bit_cntr != 3'b111)    &&        // device bit 7
             (bit_cntr != 3'b101))   ||        // device bit 5                        			                       
                      			                         
            ((i2c_state == dev_add3) &&        // 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_add3[bit_cntr];
    else if((i2c_state == w_data1))             // word address
        sda <= #1 wrd_add1[bit_cntr];        
    else if((i2c_state == w_data2))             // word address
        sda <= #1 wrd_add2[bit_cntr];        
        
    else if((i2c_state == w_add2))              // word address
        sda <= #1 wrd_add3[bit_cntr];

   else if((i2c_state == ack8))              	// word address
        sda <= #1 1'b1;
    else
        sda <= #1 1'b1;




always @(posedge clock or negedge rst_l)
    if (!rst_l)
        i2c_rdata <= #1 8'b00001111;
    else if (( (i2c_state == r_data1) ||(i2c_state == r_data2) ) && scl)
        i2c_rdata[bit_cntr] <= #1 sda_pin;     

                       
assign i2c_act = ~(i2c_state == idle);
               
endmodule    

⌨️ 快捷键说明

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