最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

Verilog程序8、I2C通信协议

来源:动视网 责编:小OO 时间:2025-09-25 03:15:51
文档

Verilog程序8、I2C通信协议

接口定义状态机:状态机涉及的变量有:        reg[3:0]cstate;        regsda_r;        regsda_link;        reg[3:0]num;        reg[7:0]db_r;        reg[7:0]read_data;没有仿真、没有下载测试。解决方法:可以从杨老师那里自己焊一个板子来试验。`timescale1ns/1ps///////////////////////////////////////////////////
推荐度:
导读接口定义状态机:状态机涉及的变量有:        reg[3:0]cstate;        regsda_r;        regsda_link;        reg[3:0]num;        reg[7:0]db_r;        reg[7:0]read_data;没有仿真、没有下载测试。解决方法:可以从杨老师那里自己焊一个板子来试验。`timescale1ns/1ps///////////////////////////////////////////////////


接口定义

状态机:

状态机涉及的变量有:

        reg [3:0] cstate;

        reg sda_r;

        reg sda_link;

        reg [3:0] num;

        reg [7:0] db_r;

        reg [7:0] read_data;

没有仿真、没有下载测试。解决方法:可以从杨老师那里自己焊一个板子来试验。

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date:    09:36:37 11/15/2010

// Design Name:

// Module Name:    i2c

// Project Name:

// Target Devices:

// Tool versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//////////////////////////////////////////////////////////////////////////////////

module i2c(clk,rst_n,bu1,bu2,scl,sda,out_data);

        input clk,rst_n,bu1,bu2;                //bu1:按下执行写入.bu2:按下执行读取.

        output scl;

        output [7:0] out_data;

        inout sda;

        

        //按键部分

        reg [19:0] cnt_20ms;            //20ms的定时器

        reg bu1_r,bu2_r;

        

        always @(posedge clk or negedge rst_n)

        if(!rst_n)

                cnt_20ms <= 1'b0;

        else

                cnt_20ms <= cnt_20ms + 1'd1;

        

        

        always @(posedge clk or negedge rst_n)

                if(!rst_n)

                begin

                        bu1_r <= 1'b0;

                        bu1_r <= 1'b0;

                end

                else if(cnt_20ms == 20'hf_ffff)

                begin

                        bu1_r <= bu1;

                        bu2_r <= bu2;

                end     

        

        //分频中的计数

        reg [8:0] cnt_delay;

        reg [2:0] cnt;

        

        always @(posedge clk or negedge rst_n)

                if(!rst_n)

                        cnt_delay <= 1'd0;

                else if(cnt_delay == 9'd499)

                        cnt_delay <= 1'd0;

                else

                        cnt_delay <= cnt_delay+1;

                        

        //获取捕捉的点

        always @(posedge clk or negedge rst_n)

                if(!rst_n)

                        cnt <= 3'd5;

                else

                begin

                        case(cnt_delay)

                                9'd125: cnt <= 3'd1;            //高电片的中间时刻

                                9'd249: cnt <= 3'd2;            //下降沿

                                9'd375: cnt <= 3'd3;            //低电平的中间时刻

                                9'd499: cnt <= 3'd0;            //上升沿

                                default: cnt <= 3'd5;

                        endcase

                end

        `define scl_pos (cnt == 3'd0)

        `define scl_high (cnt == 3'd1)

        `define scl_neg (cnt == 3'd2)

        `define scl_low (cnt == 3'd3)

        

        //EEPRom时钟的产生

        reg scl_r;

        

        always @(posedge clk or negedge rst_n)

                if(!rst_n)

                        scl_r <= 3'd0;

                else if(`scl_pos)

                        scl_r <= 3'd1;

                else if(`scl_neg)

                        scl_r <= 3'd0;

        assign scl = scl_r;             

        

        //写入iic的地址和数据

        `define DEVICE_READ 8'b1010_0001

        `define DEVICE_WRITE 8'b1010_0000

        `define WRITE_DATA 8'b1101_0001

        `define BYTE_ADDR 8'b0000_0011

        

        reg [7:0] db_r;         //数据寄存器,存放要发送的地址或数据

        reg [7:0] read_data;

        

        //写入、?慈?iic的状态机

        parameter IDLE   = 4'd0;

        parameter START1 = 4'd1;

        parameter ADD1   = 4'd2;

        parameter ACK1   = 4'd3;

        parameter ADD2   = 4'd4;

        parameter ACK2   = 4'd5;

        parameter START2 = 4'd6;

        parameter ADD3   = 4'd7;

        parameter ACK3   = 4'd8;

        parameter DATA   = 4'd9;

        parameter ACK4   = 4'd10;

        parameter STOP1  = 4'd11;

        parameter STOP2  = 4'd12;

        

        reg [3:0] cstate;

        reg sda_r;

        reg sda_link;

        reg [3:0] num;          //用来计量地址或数据的位数

        

        always @(posedge clk or negedge rst_n)

                if(!rst_n)

                begin

                        cstate <= IDLE;

                        sda_r <= 1'b1;

                        sda_link <= 1'b0;

                        num <= 4'd0;

                        read_data <= 8'd0;

                end

                else

                begin

                        case(cstate)

                                IDLE:

                                begin

                                        sda_link <= 1'b1;

                                        sda_r <= 1'b1;

                                        if(bu1 || bu2)

                                        begin

                                                db_r <= `DEVICE_WRITE;

                                                cstate <= START1;

                                        end

                                        else

                                                cstate <= IDLE;

                                end

                                START1:

                                begin

                                        if(`scl_high)

                                        begin

                                                sda_link <= 1'b1;

                                                sda_r <= 0;             //产生下降沿,产生起始信号

                                                cstate <= ADD1;

                                                num <= 1'b0;

                                        end

                                        else

                                                cstate <= START1;

                                end

                                ADD1:

                                begin

                                        if(`scl_low)

                                                if(num == 4'd8)

                                                begin

                                                        num <= 4'd0;

                                                        sda_r <= 1'b1;

                                                        sda_link <= 1'b0;

                                                        cstate <= ACK1;

                                                end

                                                else

                                                begin

                                                        cstate <= ADD1;

                                                        num <= num + 1'b1;

                                                        case(num)

                                                                4'd0: sda_r <= db_r[7];

                                                                4'd1: sda_r <= db_r[6];

                                                                4'd2: sda_r <= db_r[5];

                                                                4'd3: sda_r <= db_r[4];

                                                                4'd4: sda_r <= db_r[3];

                                                                4'd5: sda_r <= db_r[2];

                                                                4'd6: sda_r <= db_r[1];

                                                                4'd7: sda_r <= db_r[0];

                                                                default: ;

                                                        endcase

                                                end

                                        else

                                                cstate <= ADD1;

                                end

                                ACK1:

                                begin

                                        if(`scl_neg)

                                        begin

                                                cstate <= ADD2;

                                                db_r <= `BYTE_ADDR;

                                        end

                                        else

                                                cstate <= ACK1;

                                end

                                ADD2:

                                begin

                                        if(`scl_low)

                                                if(num == 4'd8)

                                                begin

                                                        num <= 4'd0;

                                                        sda_r <= 1'b1;

                                                        sda_link <= 1'b0;

                                                        cstate <= ACK2;

                                                end

                                                else

                                                begin

                                                        cstate <= ADD2;

                                                        num <= num + 1'b1;

                                                        case(num)

                                                                4'd0: sda_r <= db_r[7];

                                                                4'd1: sda_r <= db_r[6];

                                                                4'd2: sda_r <= db_r[5];

                                                                4'd3: sda_r <= db_r[4];

                                                                4'd4: sda_r <= db_r[3];

                                                                4'd5: sda_r <= db_r[2];

                                                                4'd6: sda_r <= db_r[1];

                                                                4'd7: sda_r <= db_r[0];

                                                                default: ;

                                                        endcase

                                                end

                                        else

                                                cstate <= ADD2;

                                end

                                ACK2:

                                begin

                                        if(`scl_neg)

                                        begin

                                                if(bu1_r)

                                                begin

                                                        cstate <= DATA;

                                                        db_r <= `WRITE_DATA;

                                                end

                                                else if(bu2_r)

                                                begin

                                                        cstate <= START2;

                                                        db_r <= `DEVICE_READ;

                                                end

                                        end

                                        else

                                                cstate <= ACK2;

                                end

                                START2:

                                begin

                                        if(`scl_high)

                                        begin

                                                sda_r <= 1'b0;

                                                cstate <= ADD3;

                                        end

                                        else

                                        begin

                                                sda_link <= 1'b1;

                                                sda_r <= 1'b1;

                                                cstate <= START2;

                                        end

                                end

                                ADD3:

                                begin

                                        if(`scl_low)

                                                if(num == 4'd8)

                                                begin

                                                        num <= 4'd0;

                                                        sda_r <= 1'b1;

                                                        sda_link <= 1'b0;

                                                        cstate <= ACK3;

                                                end

                                                else

                                                begin

                                                        cstate <= ADD2;

                                                        num <= num + 1'b1;

                                                        case(num)

                                                                4'd0: sda_r <= db_r[7];

                                                                4'd1: sda_r <= db_r[6];

                                                                4'd2: sda_r <= db_r[5];

                                                                4'd3: sda_r <= db_r[4];

                                                                4'd4: sda_r <= db_r[3];

                                                                4'd5: sda_r <= db_r[2];

                                                                4'd6: sda_r <= db_r[1];

                                                                4'd7: sda_r <= db_r[0];

                                                                default: ;

                                                        endcase

                                                end

                                        else

                                                cstate <= ADD2;

                                end

                                ACK3:

                                begin

                                        if(`scl_neg)

                                        begin

                                                cstate <= DATA;

                                                sda_link <= 1'b0;

                                        end

                                        else

                                                cstate <= ACK2;

                                end

                                DATA:

                                begin

                                        if(bu2_r)

                                        begin

                                                if(num <=7)

                                                begin

                                                        cstate <= DATA;

                                                        if(`scl_high)

                                                        begin

                                                                num <= num + 1'b1;

                                                                case(num)

                                                                        4'd0: sda_r <= db_r[7];

                                                                        4'd1: sda_r <= db_r[6];

                                                                        4'd2: sda_r <= db_r[5];

                                                                        4'd3: sda_r <= db_r[4];

                                                                        4'd4: sda_r <= db_r[3];

                                                                        4'd5: sda_r <= db_r[2];

                                                                        4'd6: sda_r <= db_r[1];

                                                                        4'd7: sda_r <= db_r[0];

                                                                        default: ;

                                                                endcase

                                                        end

                                                end

                                                else if(`scl_low && num == 4'd8)

                                                begin

                                                        num <= 4'd0;

                                                        cstate <= ACK4;

                                                end

                                        else

                                                cstate <= DATA;

                                        end

                                else if(bu1_r)

                                begin

                                        sda_link <= 1'b1;

                                        if(num <=7)

                                                begin

                                                        cstate <= DATA;

                                                        if(`scl_high)

                                                        begin

                                                        sda_link <= 1'b1;

                                                                num <= num + 1'b1;

                                                                case(num)

                                                                        4'd0: sda_r <= db_r[7];

                                                                        4'd1: sda_r <= db_r[6];

                                                                        4'd2: sda_r <= db_r[5];

                                                                        4'd3: sda_r <= db_r[4];

                                                                        4'd4: sda_r <= db_r[3];

                                                                        4'd5: sda_r <= db_r[2];

                                                                        4'd6: sda_r <= db_r[1];

                                                                        4'd7: sda_r <= db_r[0];

                                                                        default: ;

                                                                endcase

                                                        end

                                                end

                                                else if(`scl_low && num == 4'd8)

                                                begin

                                                        num <= 4'd0;

                                                        cstate <= ACK4;

                                                end

                                        else

                                                cstate <= DATA;

                                        end

                                end

                                //end

                                ACK4:

                                begin

                                        if(`scl_neg)

                                                cstate <= STOP1;

                                        else

                                                cstate <= ACK4;

                                end

                                STOP1:

                                begin

                                        if(`scl_low)

                                        begin

                                                sda_link <= 1'b1;

                                                sda_r <= 1'b0;

                                                cstate <= STOP1;

                                        end

                                        else if(`scl_high)

                                        begin

                                                sda_r <= 1'b1;

                                                cstate <= STOP2;

                                        end

                                end

                                STOP2:

                                        if(`scl_low)

                                                sda_r <= 1'b1;

                                        else if(cnt_20ms == 20'hfffff)

                                                cstate <= IDLE;

                                        else

                                                cstate <= STOP2;

                                default: cstate <= IDLE;

                        endcase

                end

        assign sda = sda_link? sda_r:1'bz;

        assign out_data = read_data;

endmodule

文档

Verilog程序8、I2C通信协议

接口定义状态机:状态机涉及的变量有:        reg[3:0]cstate;        regsda_r;        regsda_link;        reg[3:0]num;        reg[7:0]db_r;        reg[7:0]read_data;没有仿真、没有下载测试。解决方法:可以从杨老师那里自己焊一个板子来试验。`timescale1ns/1ps///////////////////////////////////////////////////
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top