IIC verilog.docx

上传人:b****7 文档编号:23485991 上传时间:2023-05-17 格式:DOCX 页数:27 大小:19.70KB
下载 相关 举报
IIC verilog.docx_第1页
第1页 / 共27页
IIC verilog.docx_第2页
第2页 / 共27页
IIC verilog.docx_第3页
第3页 / 共27页
IIC verilog.docx_第4页
第4页 / 共27页
IIC verilog.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

IIC verilog.docx

《IIC verilog.docx》由会员分享,可在线阅读,更多相关《IIC verilog.docx(27页珍藏版)》请在冰豆网上搜索。

IIC verilog.docx

IICverilog

`timescale1ns/1ps

moduleiicmax(

            clk,rst_n,

            sw1,sw2,sw3,sw4,

            scl,sda,

            leddata,ledcom

        );

         

inputclk;     //50MHz

inputrst_n;   //复位信号,低有效

inputsw1,sw2,sw3,sw4; //按键,(1按下执行写入操作,2按下执行读操作,3按下执行连写操作,4按下执行连读操作)

outputscl;    //24C08的时钟端口

inoutsda;     //24C08的数据端口

 

output[7:

0]ledcom;   //数码管片选信号,低有效

output[7:

0]leddata;  //7段数码管(不包括小数点)

 

 

wire[7:

0]tansdata;    //传送的数据

wire[2:

0]ackflag;     //标志

 

iiccom     iiccom(

                    .clk(clk),

                    .rst_n(rst_n),

                    .sw1(sw1),

                    .sw2(sw2),

                    .sw3(sw3),

                    .sw4(sw4),

                    .sda(sda),

                    .scl(scl),

                    .ackflag(ackflag),

                    .outdata(tansdata)

                  );

ledshow    ledshow(

                .clk(clk),

                .rst_n(rst_n),

                .ackflag(ackflag),

                .ledcom(ledcom),

                .leddata(leddata),

                .indata(tansdata)  

                );

     

         

 

endmodule      

IICCOM模块

`timescale1ns/1ps

moduleiiccom(

            clk,rst_n,

            sw1,sw2,sw3,sw4,

            scl,sda,

            ackflag,

            outdata

        );

 

inputclk;     //50MHz

inputrst_n;   //复位信号,低有效

inputsw1,sw2,sw3,sw4; //按键,(1按下执行写入操作,2按下执行读操作,3按下执行连写操作,4按下执行连读操作)

outputscl;    //24C08的时钟端口

output[2:

0]ackflag;//后面显示接收到数据的标准

inoutsda;     //24C08的数据端口

output[7:

0]outdata;  //数码管显示的数据

 

//--------------------------------------------

        //按键检测

regsw1_r,sw2_r,sw3_r,sw4_r;   //键值锁存寄存器,每20ms检测一次键值

reg[19:

0]cnt_20ms;//20ms计数寄存器

 

always@(posedgeclkornegedgerst_n)

    if(!

rst_n)cnt_20ms<=20'd0;

    else if(cnt_20ms==20'hfffff)cnt_20ms<=20'h0;

    else cnt_20ms<=cnt_20ms+1'b1; //不断计数

 

always@(posedgeclkornegedgerst_n)

    if(!

rst_n)begin

            sw1_r<=1'b1;  //键值寄存器复位,没有键盘按下时键值都为1

            sw2_r<=1'b1;

            sw3_r<=1'b1;

            sw4_r<=1'b1;

        end

    else if(cnt_20ms==20'hffff0)begin

            sw1_r<=sw1;   //按键值锁存

            sw2_r<=sw2;

            sw3_r<=sw3;

            sw4_r<=sw4;   

        end

 

//---------------------------------------------

        //分频部分

reg[2:

0]cnt;  //cnt=0:

scl上升沿,cnt=1:

scl高电平中间,cnt=2:

scl下降沿,cnt=3:

scl低电平中间

reg[8:

0]cnt_delay;//500循环计数,产生iic所需要的时钟

regscl_r;     //时钟脉冲寄存器

 

always@(posedgeclkornegedgerst_n)

    if(!

rst_n)cnt_delay<=9'd0;

    else if(cnt_delay==9'd499)cnt_delay<=9'd0; //计数到10us为scl的周期,即100KHz

    else cnt_delay<=cnt_delay+1'b1;   //时钟计数

 

always@(posedgeclkornegedgerst_n)begin

    if(!

rst_n)cnt<=3'd5;

    else begin

        case (cnt_delay)

            9'd124:

cnt<=3'd1;//cnt=1:

scl高电平中间,用于数据采样

            9'd255:

cnt<=3'd2;//cnt=2:

scl下降沿后面点

            9'd374:

cnt<=3'd3;//cnt=3:

scl低电平中间,用于数据变化

            9'd495:

cnt<=3'd0;//cnt=0:

scl上升沿前面点

            default:

cnt<=3'd5;

            endcase

        end

end

 

 

`defineSCL_POS    (cnt==3'd0)    //cnt=0:

scl上升沿前面点

`defineSCL_HIG    (cnt==3'd1)    //cnt=1:

scl高电平中间,用于数据采样

`defineSCL_NEG    (cnt==3'd2)    //cnt=2:

scl下降沿后面点

`defineSCL_LOW    (cnt==3'd3)    //cnt=3:

scl低电平中间,用于数据变化

 

 

always@(posedgeclkornegedgerst_n)

    if(!

rst_n)scl_r<=1'b0;

    else if(cnt_delay==9'd499)scl_r<=1'b1;   //scl信号上升沿

    else if(cnt_delay==9'd249)scl_r<=1'b0;   //scl信号下降沿

 

assignscl=scl_r;//产生iic所需要的时钟

//---------------------------------------------

        //需要写入24C02的地址和数据

                 

`defineDEVICE_READ    8'b1010_1001   //被寻址器件地址(读操作)

`defineDEVICE_WRITE   8'b1010_1000   //被寻址器件地址(写操作)

`defineWRITE_DATA0    8'b1000_1000   

`defineWRITE_DATA1    8'b0010_0001   //写入EEPROM的数据

`defineWRITE_DATA2    8'b0100_0011

`defineWRITE_DATA3    8'b0110_0101

`defineWRITE_DATA4    8'b1000_0111

`defineBYTE_ADDR      8'b0000_0100   //写入/读出EEPROM的地址寄存器

reg[7:

0]db_r;     //在IIC上传送的数据寄存器

reg[7:

0]read_data;//读出EEPROM的数据寄存器

reg[7:

0]outdata_r;//输出数据贮存器

parameter  PAGEDATA_NUM=3'd4;       //页写数据个数

//---------------------------------------------

        //读、写时序

parameter  IDLE   =17'b0_0000_0000_0000_0001;//初始态

parameter  START1 =17'b0_0000_0000_0000_0010;//起始信号

parameter  ADD1   =17'b0_0000_0000_0000_0100;//写入器件地址

parameter  ACK1   =17'b0_0000_0000_0000_1000;//应答

parameter  ADD2   =17'b0_0000_0000_0001_0000;//写入字节地址

parameter  ACK2   =17'b0_0000_0000_0010_0000;//应答

parameter  START2 =17'b0_0000_0000_0100_0000;//读操作开始前的起始信号

parameter  ADD3   =17'b0_0000_0000_1000_0000;//写入器件地址

parameter  ACK3   =17'b0_0000_0001_0000_0000;//应答

parameter  ACKR   =17'b1_0000_0000_0000_0000;//fpga给应答

parameter  DATA   =17'b0_0000_0010_0000_0000;//字节读写

parameter  PAGER  =17'b0_0000_0100_0000_0000;//页读

parameter  PAGEW  =17'b0_0000_1000_0000_0000;//页写

parameter  ACK4   =17'b0_0001_0000_0000_0000;//应答

parameter  HIGH   =17'b0_0010_0000_0000_0000;//高电平

parameter  STOP1  =17'b0_0100_0000_0000_0000;//停止位

parameter  STOP2  =17'b0_1000_0000_0000_0000;//延时同步

 

reg[16:

0]cstate;  //状态寄存器

regsda_r;     //输出数据寄存器

regsda_link;  //输出数据sda信号inout方向控制位      

reg[3:

0]num;  //读写的字节计数

reg[2:

0]ackflag;//连读时的数据标志

reg[2:

0]pagecnt;//连读连写时的数据计数器

reg[7:

0]pagedata_r;//连读储存器

 

always@(posedgeclkornegedgerst_n)begin

    if(!

rst_n)begin

            pagedata_r<=8'd0;

                end

    else begin

            case(pagecnt)

                3'd0:

  pagedata_r<=`WRITE_DATA1;

                3'd1:

  pagedata_r<=`WRITE_DATA2;

                3'd2:

  pagedata_r<=`WRITE_DATA3;

                3'd3:

  pagedata_r<=`WRITE_DATA4;

                default:

;

            endcase

         end

end

//---------------------------------------状态机---------------------------------------------//

always@(posedgeclkornegedgerst_n)begin

    if(!

rst_n)begin

            cstate<=IDLE;

            sda_r<=1'b1;

            sda_link<=1'b0;

            num<=4'd0;

            ackflag<=3'd0;

            pagecnt<=3'd0;

            read_data<=8'b0000_0000;

            outdata_r<=8'b0000_0000;

        end

    else     

        case (cstate)

            IDLE:

  begin

                    sda_link<=1'b1;           //数据线sda为input

                    sda_r<=1'b1;

                    read_data<=8'b0000_0000;

                    //ackflag<=3'd0;

                    if(!

sw1_r||!

sw2_r||!

sw3_r||!

sw4_r)begin   //SW1,SW2,SW3,SW4键有一个被按下         

                        db_r<=`DEVICE_WRITE;                      //送器件地址(写操作)

                        cstate<=START1;       

                        end

                    else cstate<=IDLE;//没有任何键被按下

                end

            START1:

begin

                    if(`SCL_HIG)begin     //scl为高电平期间

                        sda_link<=1'b1;   //数据线sda为output

                        sda_r<=1'b0;      //拉低数据线sda,产生起始位信号

                        cstate<=ADD1;

                        ackflag<=1'b0;

                        num<=4'd0;    //num计数清零

                        end

                    else cstate<=START1;//等待scl高电平中间位置到来

                end

            ADD1:

  begin

                    if(`SCL_LOW)begin

                            if(num==4'd8)begin  

                                    num<=4'd0;        //num计数清零

                                    sda_r<=1'b1;

                                    sda_link<=1'b0;       //sda置为高阻态(input)

                                    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

                        end

                    else cstate<=ADD1;

                end

            ACK1:

  begin

                    if(`SCL_NEG)begin 

                            cstate<=ADD2; //从机响应信号

                            db_r<=`BYTE_ADDR; //1地址     

                        end

                    else cstate<=ACK1;    //等待从机响应

                end

            ADD2:

  begin

                    if(`SCL_LOW)begin

                            if(num==4'd8)begin

                                    num<=4'd0;        //num计数清零

                                    sda_r<=1'b1;

                                    sda_link<=1'b0;       //sda置为高阻态(input)

                                    cstate<=ACK2;

                                end

                            else begin

                                    sda_link<=1'b1;       //sda作为output

                                    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];

                         

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1