<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        FPGA讀寫EEPROM

        作者:Qstone   來源:Qstone的空間   點擊數:  更新時間:2014年06月08日   【字體:

         module i2c(clk,rst,data_in,scl,sda,wr_input,rd_input,lowbit,en,seg_data);

         
        input clk,rst;
        output scl;//I2C時鐘線
        inout  sda;//I2C數據線
        input[3:0] data_in;//撥碼開關輸入想寫入EEPROM的數據
        input wr_input;//要求寫的輸入
        input rd_input;//要求讀的輸入
        output lowbit; //輸出一個低電平給矩陣鍵盤的某一行
        output[1:0] en;//數碼管使能
        output[7:0] seg_data;//數碼管段數據
        reg[7:0] seg_data;
         
         
        reg scl;
        reg[1:0] en;
         
        reg[7:0] seg_data_buf;
        reg[11:0] cnt_scan;
        reg sda_buf;//sda輸入輸出數據緩存
        reg link;   //sda輸出標志
        reg phase0,phase1,phase2,phase3;//一個scl時鐘周期的四個相位階段,將一個scl周期分為4段
        //phase0對應scl的上升沿時刻,phase2對應scl的下降沿時刻,phase1對應從scl高電平的中間時刻,phase2對應從scl低電平的中間時刻,
        reg[7:0] clk_div;//分頻計數器
        reg[1:0] main_state;
        reg[2:0] i2c_state;//對i2c操作的狀態
        reg[3:0] inner_state;//i2c每一操作階段內部狀態
        reg[19:0] cnt_delay;//按鍵延時計數器
        reg start_delaycnt;//按鍵延時開始
        reg[7:0] writeData_reg,readData_reg;//要寫的數據的寄存器和讀回數據的寄存器
        reg[7:0] addr;//被操作的EEPROM字節的地址
         
        parameter div_parameter=100;// 分頻系數,AT24C02最大支持400K時鐘速率
         
        parameter start=4'b0000, //開始
         first=4'b0001, //第1位
         second=4'b0010,//第2位
         third=4'b0011, //第3位
         fourth=4'b0100, //第4位
         fifth=4'b0101, //第5位
         sixth=4'b0110, //第6位
         seventh=4'b0111, //第7位
         eighth=4'b1000, //第8位
         ack=4'b1001,   //確認位
         stop=4'b1010; //結束位
        parameter ini=3'b000, //初始化EEPROM狀態
         sendaddr=3'b001, //發送地址狀態
         write_data=3'b010, //寫數據狀態?
         read_data=3'b011, //讀數據狀態
         read_ini=6'b100; //發送讀信息狀態
         
        assign lowbit=0;
        assign sda=(link)? sda_buf:1'bz;
         
        always@(posedge clk or negedge rst)
        begin
        if(!rst)
        cnt_delay<=0;
        else begin
        if(start_delaycnt) begin
        if(cnt_delay!=20'd800000)
        cnt_delay<=cnt_delay+1;
        else
        cnt_delay<=0;
        end
        end
        end
         
        always@(posedge clk or negedge rst)
        begin
        if(!rst) begin
        clk_div<=0;
        phase0<=0;
        phase1<=0;
        phase2<=0;
        phase3<=0;
        end
        else begin
        if(clk_div!=div_parameter-1)
        clk_div<=clk_div+1;
        else
        clk_div<=0;
        if(phase0)
        phase0<=0;
        else if(clk_div==99) 
        phase0<=1;
        if(phase1)
        phase1<=0;
        else if(clk_div==24)
        phase1<=1;
        if(phase2)
        phase2<=0;
        else if(clk_div==49)
        phase2<=1;
        if(phase3)
        phase3<=0;
        else if(clk_div==74)
        phase3<=1;
        end
        end
         
         
        ///////////////////////////EEPROM操作部分/////////////
        always@(posedge clk or negedge rst)
        begin
        if(!rst) begin
        start_delaycnt<=0;
        main_state<=2'b00;
        i2c_state<=ini;
        inner_state<=start;
        scl<=1;
        sda_buf<=1;
        link<=0;
        writeData_reg<=5;
        readData_reg<=0;
        addr<=10;
        end
        else begin
        case(main_state)
        2'b00: begin  //等待讀寫要求
        writeData_reg<=data_in;
        scl<=1;
        sda_buf<=1;
        link<=0;
        inner_state<=start;
        i2c_state<=ini;
        if((cnt_delay==0)&&(!wr_input||!rd_input))
        start_delaycnt<=1;
        else if(cnt_delay==20'd800000) begin
        start_delaycnt<=0;
        if(!wr_input)
        main_state<=2'b01;
        else if(!rd_input)
        main_state<=2'b10;
        end
        end
        2'b01: begin  //向EEPROM寫入數據
        if(phase0)
        scl<=1;
        else if(phase2)
        scl<=0;
        case(i2c_state)
        ini: begin   //初始化EEPROM
        case(inner_state)
        start: begin
        if(phase1) begin
        link<=1;
        sda_buf<=0;
        end
        if(phase3&&link) begin
        inner_state<=first;
        sda_buf<=1;
        link<=1;
        end
        end
        first: 
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=second;
        end
        second:
        if(phase3) begin
        sda_buf<=1;
        link<=1;
        inner_state<=third;
        end
        third:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=3'b000;
        end
        if(phase3) begin
        link<=1;
        sda_buf<=addr[7];
        inner_state<=first;
        i2c_state<=sendaddr;
        end
        end
        endcase
        end
        sendaddr: begin  //送相應字節的地址
        case(inner_state)
        first: 
        if(phase3) begin
        link<=1;
        sda_buf<=addr[6];
        inner_state<=second;
        end
        second:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[5];
        inner_state<=third;
        end
        third:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[4];
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[3];
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[2];
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[1];
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[0];
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=3'b000;
        end
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[7];
        inner_state<=first;
        i2c_state<=write_data;
        end
        end
        endcase
        end
        write_data: begin //寫入數據
        case(inner_state)
        first: 
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[6];
        inner_state<=second;
        end
        second:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[5];
        inner_state<=third;
        end
        third:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[4];
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[3];
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[2];
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[1];
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        link<=1;
        sda_buf<=writeData_reg[0];
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=2'b00;
        end
        else if(phase3) begin
        link<=1;
        sda_buf<=0;
        inner_state<=stop;
        end
        end
        stop: begin
        if(phase1)
        sda_buf<=1;
        if(phase3) 
        main_state<=2'b00;
        end
        endcase
        end
        default:
        main_state<=2'b00;
        endcase
        end
        2'b10: begin  //讀EEPROM
        if(phase0)
        scl<=1;
        else if(phase2)
        scl<=0;
        case(i2c_state)
        ini: begin   //初始化EEPROM
        case(inner_state)
        start: begin
        if(phase1) begin
        link<=1;
        sda_buf<=0;
        end
        if(phase3&&link) begin
        inner_state<=first;
        sda_buf<=1;
        link<=1;
        end
        end
        first: 
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=second;
        end
        second:
        if(phase3) begin
        sda_buf<=1;
        link<=1;
        inner_state<=third;
        end
        third:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=2'b00;
        end
        if(phase3) begin
        link<=1;
        sda_buf<=addr[7];
        inner_state<=first;
        i2c_state<=sendaddr;
        end
        end
        endcase
        end
        sendaddr: begin  //送相應要讀字節的地址
        case(inner_state)
        first: 
        if(phase3) begin
        link<=1;
        sda_buf<=addr[6];
        inner_state<=second;
        end
        second:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[5];
        inner_state<=third;
        end
        third:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[4];
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[3];
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[2];
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[1];
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        link<=1;
        sda_buf<=addr[0];
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=2'b00;
        end
        if(phase3) begin
        link<=1;
        sda_buf<=1;
        inner_state<=start;
        i2c_state<=read_ini;
        end
        end
        endcase
        end
        read_ini: begin  //發出讀要求
        case(inner_state)
        start: begin
        if(phase1) begin
        link<=1;
        sda_buf<=0;
        end
        if(phase3&&link) begin
        inner_state<=first;
        sda_buf<=1;
        link<=1;
        end
        end
        first: 
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=second;
        end
        second:
        if(phase3) begin
        sda_buf<=1;
        link<=1;
        inner_state<=third;
        end
        third:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fourth;
        end
        fourth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=fifth;
        end
        fifth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=sixth;
        end
        sixth:
        if(phase3) begin
        sda_buf<=0;
        link<=1;
        inner_state<=seventh;
        end
        seventh:
        if(phase3) begin
        sda_buf<=1;
        link<=1;
        inner_state<=eighth;
        end
        eighth:
        if(phase3) begin
        link<=0;
        inner_state<=ack;
        end
        ack: begin
        if(phase0) 
        sda_buf<=sda;
        if(phase1) begin
        if(sda_buf==1) 
        main_state<=2'b00;
        end
        if(phase3) begin
        link<=0;
        inner_state<=first;
        i2c_state<=read_data;
        end
        end
        endcase
        end
        read_data: begin  //讀出數據
        case(inner_state)
        first: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=second;
        end
        second: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=third;
        end
        third: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=fourth;
        end
        fourth: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=fifth;
        end
        fifth: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=sixth;
        end
        sixth: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=seventh;
        end
        seventh: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3)
        inner_state<=eighth;
        end
        eighth: begin
        if(phase0)
        sda_buf<=sda;
        if(phase1) begin
        readData_reg[7:1]<=readData_reg[6:0];
        readData_reg[0]<=sda;
        end
        if(phase3) 
        inner_state<=ack;
        end
        ack: begin
        if(phase3) begin
        link<=1;
        sda_buf<=0;
        inner_state<=stop;
        end
        end
        stop: begin
        if(phase1) 
        sda_buf<=1;
        if(phase3) 
        main_state<=2'b00;
        end
        endcase
        end
        endcase
        end
        endcase
         end
        end
        ///////////////////////////數碼管顯示部分/////////////
        always@(posedge clk or negedge rst)
        begin
        if(!rst) begin
        cnt_scan<=0;
        en<=2'b10;
        end
        else begin
        cnt_scan<=cnt_scan+1;
        if(cnt_scan==12'hfff)
        en<=~en;
        end
        end
         
        always@(writeData_reg or readData_reg or en)
        begin
        case(en)
        2'b10:
        seg_data_buf=writeData_reg;
        2'b01:
        seg_data_buf=readData_reg;
        default:
        seg_data_buf=0;
        endcase
        end
         
        always@(seg_data_buf)
        begin
        case(seg_data_buf)
        8'b0000_0000:
        seg_data=8'b0000_0011;
        8'b0000_0001:
        seg_data=8'b1001_1111;
        8'b0000_0010:
        seg_data=8'b0010_0101;
        8'b0000_0011:
        seg_data=8'b0000_1101;
        8'b0000_0100:
        seg_data=8'b1001_1001;
        8'b0000_0101:
        seg_data=8'b0100_1001;
        8'b0000_0110:
        seg_data=8'b0100_0001;
        8'b0000_0111:
        seg_data=8'b0001_1111;
        8'b0000_1000:
        seg_data=8'b0000_0001;
        8'b0000_1001:
        seg_data=8'b0001_1001;
        8'b0000_1010:
        seg_data=8'b0001_0001;
        8'b0000_1011:
        seg_data=8'b1100_0001;
        8'b0000_1100:
        seg_data=8'b0110_0011;
        8'b0000_1101:
        seg_data=8'b1000_0101;
        8'b0000_1110:
        seg_data=8'b0110_0001;
        8'b0000_1111:
        seg_data=8'b0111_0001;
        default:
        seg_data=8'b1111_1111;
        endcase
        end
        endmodule 
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮