首页 > 其他 > 详细

24LC64_IIC_verilog控制读写

时间:2021-06-13 00:47:03      阅读:35      评论:0      收藏:0      [点我收藏+]

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            =        4d00;
        parameter        START_1            =        4d01;
        parameter        SEND_D_ADDR        =        4d02;
        parameter        ACK_1            =        4d03;
        parameter        SEND_B_ADDR_H    =        4d04;
        parameter        ACK_2            =        4d05;
        parameter        SEND_B_ADDR_L    =        4d06;
        parameter        ACK_3            =        4d07;
        parameter        WR_DATA            =        4d08;
        parameter        ACK_4            =        4d09;
        parameter        START_2            =        4d10;
        parameter        SEND_RD_ADDR    =        4d11;
        parameter        ACK_5            =        4d12;
        parameter        RD_DATA            =        4d13;
        parameter        N_ACK            =        4d14;
        parameter        STOP            =        4d15;
        
        parameter        CNT_1MHZ        =        8d49;
        
        
        
        
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        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)
                                     )    ? 1b1 :1b0;


        
        assign        iic_sda        =    (sda_ctrl == 1b1)    ?    1bz : sda    ;
        assign        D_ADDR_DATA        =    8b1010_0000;
        assign        B_ADDR_H_DATA    =    8b0000_0100;
        assign        B_ADDR_L_DATA    =    8b0000_0110;
    //    assign        WR_DATA_DATA    =    8‘b0101_1010;
        assign        RD_ADDR_DATA    =    8b1010_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    <=     8d0;
        else if(current_state !=    IDLE)
            begin
                if(clk_1mhz_cnt    <    CNT_1MHZ    )
                    clk_1mhz_cnt    <=    clk_1mhz_cnt    +     1b1;
                else
                    clk_1mhz_cnt    <=    8d0            ;
            end
        else
            clk_1mhz_cnt    <= 8d0;



        always@(posedge sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            write_flag    <=     1b1;
        else if(flag == 1b1)
            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    <=     1b0;
        else    if((current_state ==    STOP)&&(cnt_byte    == 8d1)&&(clk_1mhz_cnt    == CNT_1MHZ)&&(clk_1mhz_bit    == 8d3))
            flag    <=        1b1;
        else
            flag    <=     1b0;    


            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            clk_1mhz_bit    <= 8d0;
        else if(current_state !=    IDLE)
            begin
                if(clk_1mhz_cnt    ==    CNT_1MHZ)
                    begin
                        if(clk_1mhz_bit    <    8d3)
                            clk_1mhz_bit    <=    clk_1mhz_bit    +     1b1;
                        else
                            clk_1mhz_bit    <=    8d0    ;
                    end
                else
                    clk_1mhz_bit    <=    clk_1mhz_bit;
            end
        else
            clk_1mhz_bit    <= 8d0;            
            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            cnt_byte    <= 8d0;
        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    <=    8d7)
                    begin
                        if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit    ==    8d3))
                            cnt_byte    <=    cnt_byte    +     1b1;
                        else
                            cnt_byte    <=    cnt_byte    ;
                    end
                else
                    cnt_byte    <=    8d0;
            end
        else if(current_state ==    STOP)    
            begin
                if(cnt_byte    <=    12d2000)
                    begin
                        if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit    ==    8d3))
                            cnt_byte    <=    cnt_byte    +     1b1;
                        else
                            cnt_byte    <=    cnt_byte    ;
                    end
                else
                    cnt_byte    <=    8d0;
            end
        else
            cnt_byte    <= 8d0;                            
            



//~~~~~~~~~~~~~~~~~~~~~~~~~~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 == 1b1)||(read_flag    ==    1b1))
                                        next_state    =    START_1;
                                    else
                                        next_state    =    IDLE;
                                
                START_1            :    if((clk_1mhz_cnt == CNT_1MHZ  )&&(clk_1mhz_bit == 8d3))
                                        next_state    =    SEND_D_ADDR;
                                    else
                                        next_state    =    START_1;
                
                SEND_D_ADDR        :    if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte    ==    8d7)&&(clk_1mhz_bit == 8d3))
                                        next_state    =    ACK_1;
                                    else
                                        next_state    =    SEND_D_ADDR;
                                
                ACK_1            :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8d3)&&(ack         == 1b0))
                                        next_state    =    SEND_B_ADDR_H;
                                    else
                                        next_state    =    ACK_1;

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

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

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

                ACK_3            :    if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8d3)&&(ack         == 1b0))
                                        begin
                                            if(write_flag == 1b1)
                                                next_state    =    WR_DATA;
                                            else if((read_flag == 1b1))
                                                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    ==    8d7)&&(clk_1mhz_bit == 8d3))
                                        next_state    =    ACK_4;
                                    else
                                        next_state    =    WR_DATA;

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

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

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

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

                STOP            :    if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8d3)&&(cnt_byte    ==    12d2000))
                                        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    <= 1b1;
        else if(current_state ==    START_1)
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d2))
                    iic_sck    <= 1b0;
                else
                    iic_sck    <= iic_sck;
            end
        else if(current_state ==    STOP)
            begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d0)&&(cnt_byte == 8d0))
                    iic_sck    <= 1b1;
                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 == 8d0))
                    iic_sck    <= 1b1;
                else if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d2))
                    iic_sck    <= 1b0;
                else
                    iic_sck    <= iic_sck;
            end    
        else
            iic_sck    <= 1b1;
        
    


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

        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            rd_data        <= 8d06;
        else if(current_state == RD_DATA)
                begin
                if((clk_1mhz_cnt    ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d3)&&(cnt_byte == 8d7))
                    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        <= 1b1;
        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 == 8d1))
                    ack    <= iic_sda    ;
                else
                    ack    <= ack;
            end
        else
            ack        <= 1b1;    
            
            
        always@(posedge    sys_clk or negedge sys_rst_n)
        if(!sys_rst_n)
            sda    <= 1b1;
        else if(current_state ==    START_1)
            begin
                if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d0))
                    sda    <= 1b0;
                else
                    sda    <= sda;
            end
        else if(current_state ==    START_2)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= 1b1;
                else if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d1))
                    sda    <= 1b0;
                else
                    sda    <= sda;
            end
        else if(current_state ==    N_ACK)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= 1b1;
                else
                    sda    <= sda;
            end
        else if(current_state ==    STOP)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0)&&(cnt_byte == 8d0))
                    sda    <= 1b0;
                else if((clk_1mhz_cnt ==    CNT_1MHZ)&&(clk_1mhz_bit == 8d2)&&(cnt_byte == 8d0))
                    sda    <= 1b1;
                else
                    sda    <= sda;
            end
        else if(current_state ==    SEND_D_ADDR)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= D_ADDR_DATA[(4d7 - cnt_byte)];
                else
                    sda    <= sda;
            end
        else if(current_state ==    SEND_B_ADDR_H)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= B_ADDR_H_DATA[(4d7 - cnt_byte)];
                else
                    sda    <= sda;
            end    
        else if(current_state ==    SEND_B_ADDR_L)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= B_ADDR_L_DATA[(4d7 - cnt_byte)];
                else
                    sda    <= sda;
            end    
        else if(current_state ==    WR_DATA)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= WR_DATA_DATA[(4d7 - cnt_byte)];
                else
                    sda    <= sda;
            end        
        else if(current_state ==    SEND_RD_ADDR)
            begin
                if((clk_1mhz_cnt ==    1b0)&&(clk_1mhz_bit == 8d0))
                    sda    <= RD_ADDR_DATA[(4d7 - cnt_byte)];
                else
                    sda    <= sda;
            end
        else
            sda    <= 1b1;

















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        =    1b1;
                sys_rst_n    =    1b0;
                # 36000;
                sys_rst_n    =    1b1;    


/*                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;
                sda_link        =    1‘b0;
                sda_ack        <=    1‘b0;                //ack3
                #4000;
                sda_link        =    1‘b1;                //ack up
                sda_ack        <=    1‘b1;    
                #36000;
                sda_link        =    1‘b0;
                sda_ack        <=    1‘b0;                //ack5
                #4000;
                sda_link        =    1‘b0;                //ack up
                sda_ack        <=    1‘b1;    
                #8000;
                sda_ack        <=    1‘b0;    
                #8000;
                sda_ack        <=    1‘b1;
                #8000;
                sda_ack        <=    1‘b0;
                #8000;
                sda_link        =    1‘b1;
                #4000;
                sda_link        =    1‘b1;                //ack up
                sda_ack        <=    1‘b1;    

*/



    
            end





always #10 sys_clk = ~sys_clk;



 eeprom_iic ee_u0
(
        .sys_clk            (sys_clk),
        .sys_rst_n        (sys_rst_n),
        
        .iic_sck            (iic_sck),
        .iic_sda            (iic_sda)
);

 M24LC64 M24LC64(
        .A0(1b0), 
        .A1(1b0),
        .A2(1b0),
        .WP(1b0),
        .SDA(iic_sda), 
        .SCL(iic_sck), 
        .RESET(!sys_rst_n)
        );



endmodule

24LC64_IIC_verilog控制读写

原文:https://www.cnblogs.com/258empire/p/14878786.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!