24LC64_IIC_verilog控制读写

Posted 小白白笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了24LC64_IIC_verilog控制读写相关的知识,希望对你有一定的参考价值。

PS:EEPROM单次写时间比较长,24LC64要5ms,才能进行读操作,否则不会响应地址,示波器观察的。

1‘给出单次写仿真图1;(sda上面的蓝色是主从三态门切换时候,未知态,实测波形,也会有小尖峰出现)

2’给出单次读仿真图2;

3‘给出main代码;(用quartus的issp观察数据的)

4’给出testbench代码;(添加了24LC64的verilog模型,读数据不能显示,显示的高阻态)

 

图一

 

 

图2

 

 

main代码

module eeprom_iic
(
        input            sys_clk,
        input            sys_rst_n,
        
        output    reg        iic_sck,
        inout    wire    iic_sda
);

        reg            [3:0]        current_state;
        reg            [3:0]        next_state;
        reg            [7:0]        clk_1mhz_cnt;
        reg                        flag;    
        reg            [7:0]        clk_1mhz_bit;
        reg            [11:0]        cnt_byte;
        reg                        sda;

        reg                        write_flag;
        wire                        read_flag;        
        reg                        ack;
        reg            [7:0]        rd_data_reg;
        reg            [7:0]        rd_data;





        wire                    sda_ctrl;
        wire        [7:0]        D_ADDR_DATA;
        wire        [7:0]        B_ADDR_H_DATA;
        wire        [7:0]        B_ADDR_L_DATA;
        wire        [7:0]        WR_DATA_DATA;
        wire        [7:0]        RD_ADDR_DATA;
        
        
        


//~~~~~~~~~~~~~~~~~~~~~~~~~~parameter~~~~~~~~~~~~~~~~~~~~~~

        parameter        IDLE            =        4\'d00;
        parameter        START_1            =        4\'d01;
        parameter        SEND_D_ADDR        =        4\'d02;
        parameter        ACK_1            =        4\'d03;
        parameter        SEND_B_ADDR_H    =        4\'d04;
        parameter        ACK_2            =        4\'d05;
        parameter        SEND_B_ADDR_L    =        4\'d06;
        parameter        ACK_3            =        4\'d07;
        parameter        WR_DATA            =        4\'d08;
        parameter        ACK_4            =        4\'d09;
        parameter        START_2            =        4\'d10;
        parameter        SEND_RD_ADDR    =        4\'d11;
        parameter        ACK_5            =        4\'d12;
        parameter        RD_DATA            =        4\'d13;
        parameter        N_ACK            =        4\'d14;
        parameter        STOP            =        4\'d15;
        
        parameter        CNT_1MHZ        =        8\'d49;
        
        
        
        
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        assign        sda_ctrl    =    ((current_state == ACK_1)||(current_state == ACK_2)||
                                     (current_state == ACK_3)||(current_state == ACK_4)||
                                     (current_state == ACK_5)||(current_state == RD_DATA)
                                     )    ? 1\'b1 :1\'b0;


        
        assign        iic_sda        =    (sda_ctrl == 1\'b1)    ?    1\'bz : sda    ;
        assign        D_ADDR_DATA        =    8\'b1010_0000;
        assign        B_ADDR_H_DATA    =    8\'b0000_0100;
        assign        B_ADDR_L_DATA    =    8\'b0000_0110;
    //    assign        WR_DATA_DATA    =    8\'b0101_1010;
        assign        RD_ADDR_DATA    =    8\'b1010_0001;
        
        
            unnamed u000 (
        .source (WR_DATA_DATA), // sources.source
        .probe  (rd_data)   //  probes.probe
    );


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        always@(posedge sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            clk_1mhz_cnt    <=     8\'d0;
        else if(current_state !=    IDLE)
            begin
                if(clk_1mhz_cnt    <    CNT_1MHZ    )
                    clk_1mhz_cnt    <=    clk_1mhz_cnt    +     1\'b1;
                else
                    clk_1mhz_cnt    <=    8\'d0            ;
            end
        else
            clk_1mhz_cnt    <= 8\'d0;



        always@(posedge sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            write_flag    <=     1\'b1;
        else if(flag == 1\'b1)
            write_flag    <=        ~ write_flag;
        else
            write_flag    <= write_flag;

 
        assign    read_flag    = ~ write_flag;


        always@(posedge sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            flag    <=     1\'b0;
        else    if((current_state ==    STOP)&&(cnt_byte    == 8\'d1)&&(clk_1mhz_cnt    == CNT_1MHZ)&&(clk_1mhz_bit    == 8\'d3))
            flag    <=        1\'b1;
        else
            flag    <=     1\'b0;    


            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            clk_1mhz_bit    <= 8\'d0;
        else if(current_state !=    IDLE)
            begin
                if(clk_1mhz_cnt    ==    CNT_1MHZ)
                    begin
                        if(clk_1mhz_bit    <    8\'d3)
                            clk_1mhz_bit    <=    clk_1mhz_bit    +     1\'b1;
                        else
                            clk_1mhz_bit    <=    8\'d0    ;
                    end
                else
                    clk_1mhz_bit    <=    clk_1mhz_bit;
            end
        else
            clk_1mhz_bit    <= 8\'d0;            
            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            cnt_byte    <= 8\'d0;
        else if((current_state ==    SEND_D_ADDR)||(current_state ==    SEND_B_ADDR_H)||
                (current_state ==    SEND_B_ADDR_L)||(current_state ==    WR_DATA)||
                (current_state ==    SEND_RD_ADDR)||(current_state ==    RD_DATA)        )    
            begin
                if(cnt_byte    <=    8\'d7)
                    begin
                        if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit    ==    8\'d3))
                            cnt_byte    <=    cnt_byte    +     1\'b1;
                        else
                            cnt_byte    <=    cnt_byte    ;
                    end
                else
                    cnt_byte    <=    8\'d0;
            end
        else if(current_state ==    STOP)    
            begin
                if(cnt_byte    <=    12\'d2000)
                    begin
                        if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit    ==    8\'d3))
                            cnt_byte    <=    cnt_byte    +     1\'b1;
                        else
                            cnt_byte    <=    cnt_byte    ;
                    end
                else
                    cnt_byte    <=    8\'d0;
            end
        else
            cnt_byte    <= 8\'d0;                            
            



//~~~~~~~~~~~~~~~~~~~~~~~~~~fsm~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        always@(posedge     sys_clk or negedge    sys_rst_n)
        if(!sys_rst_n)
            current_state    <=     IDLE     ;
        else
            current_state    <=     next_state;
            
        
        always@(*)
        begin
            case(current_state)
                
                IDLE            :    if((write_flag == 1\'b1)||(read_flag    ==    1\'b1))
                                        next_state    =    START_1;
                                    else
                                        next_state    =    IDLE;
                                
                START_1            :    if((clk_1mhz_cnt == CNT_1MHZ  )&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    SEND_D_ADDR;
                                    else
                                        next_state    =    START_1;
                
                SEND_D_ADDR        :    if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    ACK_1;
                                    else
                                        next_state    =    SEND_D_ADDR;
                                
                ACK_1            :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack         == 1\'b0))
                                        next_state    =    SEND_B_ADDR_H;
                                    else
                                        next_state    =    ACK_1;

                SEND_B_ADDR_H:    if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    ACK_2;
                                    else
                                        next_state    =    SEND_B_ADDR_H;

                ACK_2            :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack         == 1\'b0))
                                        next_state    =    SEND_B_ADDR_L;
                                    else
                                        next_state    =    ACK_2;

                SEND_B_ADDR_L:    if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    ACK_3;
                                    else
                                        next_state    =    SEND_B_ADDR_L;

                ACK_3            :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack         == 1\'b0))
                                        begin
                                            if(write_flag == 1\'b1)
                                                next_state    =    WR_DATA;
                                            else if((read_flag == 1\'b1))
                                                next_state    =    START_2;
                                            else
                                                next_state    =    ACK_3;
                                        end
                                    else
                                        next_state    =    ACK_3;

                WR_DATA        :    if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    ACK_4;
                                    else
                                        next_state    =    WR_DATA;

                ACK_4            :    if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(ack         == 1\'b0))
                                        next_state    =    STOP;
                                    else
                                        next_state    =    ACK_4;    

                START_2        :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    SEND_RD_ADDR;
                                    else
                                        next_state    =    START_2;
                
                SEND_RD_ADDR:    if((clk_1mhz_cnt == CNT_1MHZ)&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    ACK_5;
                                    else
                                        next_state    =    SEND_RD_ADDR;
                                        
                ACK_5            :    if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(ack         == 1\'b0))
                                        next_state    =    RD_DATA;
                                    else
                                        next_state    =    ACK_5;

                RD_DATA        :    if((clk_1mhz_cnt == CNT_1MHZ)&&(cnt_byte    ==    8\'d7)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    N_ACK;
                                    else
                                        next_state    =    RD_DATA;

                N_ACK            :    if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3))
                                        next_state    =    STOP;
                                    else
                                        next_state    =    N_ACK;

                STOP            :    if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(cnt_byte    ==    12\'d2000))
                                        next_state    =    IDLE;
                                    else
                                        next_state    =    STOP;
                                        
                default            :        next_state    =    IDLE;
            endcase
        end


    
    

        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            iic_sck    <= 1\'b1;
        else if(current_state ==    START_1)
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2))
                    iic_sck    <= 1\'b0;
                else
                    iic_sck    <= iic_sck;
            end
        else if(current_state ==    STOP)
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0)&&(cnt_byte == 8\'d0))
                    iic_sck    <= 1\'b1;
                else
                    iic_sck    <= iic_sck;
            end        
        else if((current_state !=    IDLE)&&(current_state !=    START_1)&&(current_state !=    STOP))
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0))
                    iic_sck    <= 1\'b1;
                else if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2))
                    iic_sck    <= 1\'b0;
                else
                    iic_sck    <= iic_sck;
            end    
        else
            iic_sck    <= 1\'b1;
        
    


        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            rd_data_reg        <= 8\'d0;
        else if(current_state == RD_DATA)
                begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit <= 8\'d7)&&(clk_1mhz_bit == 8\'d1))
                    rd_data_reg    <= {rd_data_reg[6:0],iic_sda};
                else
                    rd_data_reg        <= rd_data_reg;
            end
        else
            rd_data_reg        <= 8\'d0;        
    

        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            rd_data        <= 8\'d06;
        else if(current_state == RD_DATA)
                begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(cnt_byte == 8\'d7))
                    rd_data    <= rd_data_reg;
                else
                    rd_data        <= rd_data;
            end
        else
            rd_data        <= rd_data;    

    

        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            ack        <= 1\'b1;
        else if((current_state == ACK_1)||(current_state == ACK_2 )||(current_state == ACK_3 )
                ||(current_state == ACK_4 )||(current_state == ACK_5 ))
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&& (clk_1mhz_bit == 8\'d1))
                    ack    <= iic_sda    ;
                else
                    ack    <= ack;
            end
        else
            ack        <= 1\'b1;    
            
            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            sda    <= 1\'b1;
        else if(current_state ==    START_1)
            begin
                if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= 1\'b0;
                else
                    sda    <= sda;
            end
        else if(current_state ==    START_2)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= 1\'b1;
                else if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d1))
                    sda    <= 1\'b0;
                else
                    sda    <= sda;
            end
        else if(current_state ==    N_ACK)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= 1\'b1;
                else
                    sda    <= sda;
            end
        else if(current_state ==    STOP)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0)&&(cnt_byte == 8\'d0))
                    sda    <= 1\'b0;
                else if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2)&&(cnt_byte == 8\'d0))
                    sda    <= 1\'b1;
                else
                    sda    <= sda;
            end
        else if(current_state ==    SEND_D_ADDR)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= D_ADDR_DATA[(4\'d7 - cnt_byte)];
                else
                    sda    <= sda;
            end
        else if(current_state ==    SEND_B_ADDR_H)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= B_ADDR_H_DATA[(4\'d7 - cnt_byte)];
                else
                    sda    <= sda;
            end    
        else if(current_state ==    SEND_B_ADDR_L)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= B_ADDR_L_DATA[(4\'d7 - cnt_byte)];
                else
                    sda    <= sda;
            end    
        else if(current_state ==    WR_DATA)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= WR_DATA_DATA[(4\'d7 - cnt_byte)];
                else
                    sda    <= sda;
            end        
        else if(current_state ==    SEND_RD_ADDR)
            begin
                if((clk_1mhz_cnt ==    1\'b0)&&(clk_1mhz_bit == 8\'d0))
                    sda    <= RD_ADDR_DATA[(4\'d7 - cnt_byte)];
                else
                    sda    <= sda;
            end
        else
            sda    <= 1\'b1;

















endmodule

 

testbench

`timescale 1ns/1ns


module    eeprom_iic_tb;
            
            reg        sys_clk;
            reg        sys_rst_n;
            

            
            
            wire        iic_sck;
            wire        iic_sda;

    /*        reg        sda_link;
            reg        sda_ack;
            assign    iic_sda = (sda_link == 1\'b1) ? 1\'bz : sda_ack;
    */    


            initial
            begin
                sys_clk        =    1\'b1;
                sys_rst_n    =    1\'b0;
                # 36000;
                sys_rst_n    =    1\'b1;    


/*                sda_link        =    1\'b1;
                sda_ack        <=    1\'b1;
                # 36000;
                sys_rst_n    =    1\'b1;        
                #36020;
                sda_link        =    1\'b0;                //ack1        
                sda_ack        <=    1\'b0;
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;                
                #32000;
                sda_link        =    1\'b0;                //ack2
                sda_ack        <=    1\'b0;    
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;                
                #32000;
                sda_link        =    1\'b0;
                sda_ack        <=    1\'b0;                //ack3
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;        
                #32000;
                sda_link        =    1\'b0;
                sda_ack        <=    1\'b0;                //ack4
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;        
            
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    
                #52000;
                sda_link        =    1\'b0;
                sda_ack        <=    1\'b0;                //ack1
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;
                #32000;
                sda_link        =    1\'b0;
                sda_ack        <=    1\'b0;                //ack2
                #4000;
                sda_link        =    1\'b1;                //ack up
                sda_ack        <=    1\'b1;    
                #32000;
       

以上是关于24LC64_IIC_verilog控制读写的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在 CREF JavaCard 模拟器的控制台中测试读写 APDU 时收到输入数据长度!= Lc 或 SW1 SW2: 6700?

IIC读写AT24C02代码2——串口命令控制多页读写

LC_24. Swap Nodes in Pairs

Linux查看磁盘读写

如何将其转换为 32 位架构 ARM 程序集

Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime(代码片