i2cverilog代码

合集下载

基于FPGA的I2C实验Verilog源代码

基于FPGA的I2C实验Verilog源代码

`timescale 1ns / 1psmodule i2c_drive(clk,rst_n,sw1,sw2,scl,sda,dis_data);input clk;// 50MHzinput rst_n;//复位信号,低有效input sw1,sw2;//按键1、2,(1按下执行写入操作,2按下执行读操作)output scl;// 24C02的时钟端口inout sda;// 24C02的数据端口output [7:0] dis_data;//输出指定单元的数据//--------------------------------------------//按键检测reg sw1_r,sw2_r;//键值锁存寄存器,每20ms检测一次键值reg[19:0] cnt_20ms;//20ms计数寄存器always @ (posedge clk or negedge rst_n)if(!rst_n)cnt_20ms <= 20'd0;elsecnt_20ms <= cnt_20ms+1'b1;//不断计数always @ (posedge clk or negedge rst_n)if(!rst_n)beginsw1_r <= 1'b1;//键值寄存器复位,没有键盘按下时键值都为1sw2_r <= 1'b1;endelse if(cnt_20ms == 20'hfffff)beginsw1_r <= sw1;//按键1值锁存sw2_r <= sw2;//按键2值锁存end//---------------------------------------------//分频部分reg[2:0] cnt;// cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间reg[8:0] cnt_delay;//500循环计数,产生iic所需要的时钟reg scl_r;//时钟脉冲寄存器always @ (posedge clk or negedge rst_n)if(!rst_n)cnt_delay <= 9'd0;else if(cnt_delay == 9'd499)cnt_delay <= 9'd0;//计数到10us为scl的周期,即100KHz elsecnt_delay <= cnt_delay+1'b1;//时钟计数always @ (posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 3'd5;elsebegincase (cnt_delay)9'd124:cnt <= 3'd1;//cnt=1:scl高电平中间,用于数据采样9'd249:cnt <= 3'd2;//cnt=2:scl下降沿9'd374:cnt <= 3'd3;//cnt=3:scl低电平中间,用于数据变化9'd499:cnt <= 3'd0;//cnt=0:scl上升沿default: cnt <= 3'd5;endcaseendend`define SCL_POS(cnt==3'd0)//cnt=0:scl上升沿`define SCL_HIG(cnt==3'd1)//cnt=1:scl高电平中间,用于数据采样`define SCL_NEG(cnt==3'd2)//cnt=2:scl下降沿`define SCL_LOW(cnt==3'd3)//cnt=3:scl低电平中间,用于数据变化always @ (posedge clk or negedge rst_n)if(!rst_n)scl_r <= 1'b0;else if(cnt==3'd0)scl_r <= 1'b1;//scl信号上升沿else if(cnt==3'd2)scl_r <= 1'b0;//scl信号下降沿assign scl = scl_r;//产生iic所需要的时钟//---------------------------------------------//需要写入24C02的地址和数据`define DEVICE_READ8'b1010_0001//被寻址器件地址(读操作)`define DEVICE_WRITE8'b1010_0000//被寻址器件地址(写操作)`define WRITE_DATA 8'b0000_0111//写入EEPROM的数据`define BYTE_ADDR 8'b0000_0100//写入/读出EEPROM的地址寄存器reg[7:0] db_r;//在IIC上传送的数据寄存器reg[7:0] read_data;//读出EEPROM的数据寄存器//---------------------------------------------//读、写时序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;//输出数据sda信号inout方向控制位reg[3:0] num;//always @ (posedge clk or negedge rst_n) beginif(!rst_n)begincstate <= IDLE;sda_r <= 1'b1;sda_link <= 1'b0;num <= 4'd0;read_data <= 8'b0000_0000;endelsecase (cstate)IDLE:beginsda_link <= 1'b1;//数据线sda为inputsda_r <= 1'b1;if(!sw1_r || !sw2_r)begin//SW1,SW2键有一个被按下db_r <= `DEVICE_WRITE;//送器件地址(写操作)cstate <= START1;endelsecstate <= IDLE;//没有任何键被按下endSTART1:beginif(`SCL_HIG)begin//scl为高电平期间sda_link <= 1'b1;//数据线sda为outputsda_r <= 1'b0;//拉低数据线sda,产生起始位信号cstate <= ADD1;num <= 4'd0;//num计数清零endelsecstate <= START1; //等待scl高电平中间位置到来endADD1:beginif(`SCL_LOW)beginif(num == 4'd8)beginnum <= 4'd0;//num计数清零sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态(input)cstate <= ACK1;endelsebegincstate <= 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'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase//sda_r <= db_r[4'd7-num];//送器件地址,从高位开始endend//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0};//器件地址左移1bitelsecstate <= ADD1;endACK1:beginif(/*!sda*/`SCL_NEG)begin//注:24C01/02/04/08/16器件可以不考虑应答位cstate <= ADD2;//从机响应信号db_r <= `BYTE_ADDR;// 1地址endelsecstate <= ACK1;//等待从机响应endADD2:beginif(`SCL_LOW)beginif(num==4'd8)beginnum <= 4'd0;//num计数清零sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态(input)cstate <= ACK2;endelsebeginsda_link <= 1'b1;//sda作为outputnum <= 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'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase//sda_r <= db_r[4'd7-num];//送EEPROM地址(高bit开始)cstate <= ADD2;endend//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0};//器件地址左移1bitelsecstate <= ADD2;endACK2:beginif(/*!sda*/`SCL_NEG) begin//从机响应信号if(!sw1_r) begincstate <= DATA; //写操作db_r <= `WRITE_DATA;//写入的数据endelse if(!sw2_r) begindb_r <= `DEVICE_READ;//送器件地址(读操作),特定地址读需要执行该步骤以下操作cstate <= START2;//读操作endendelse cstate <= ACK2;//等待从机响应endSTART2: begin//读操作起始位if(`SCL_LOW) beginsda_link <= 1'b1;//sda作为outputsda_r <= 1'b1;//拉高数据线sdacstate <= START2;endelse if(`SCL_HIG) begin//scl为高电平中间sda_r <= 1'b0;//拉低数据线sda,产生起始位信号cstate <= ADD3;endelse cstate <= START2;endADD3:begin//送读操作地址if(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0;//num计数清零sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态(input)cstate <= ACK3;endelse beginnum <= 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//sda_r <= db_r[4'd7-num];//送EEPROM地址(高bit开始)cstate <= ADD3;endend//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0};//器件地址左移1bitelse cstate <= ADD3;endACK3:beginif(/*!sda*/`SCL_NEG) begincstate <= DATA;//从机响应信号sda_link <= 1'b0;endelse cstate <= ACK3; //等待从机响应endDATA:beginif(!sw2_r) begin//读操作if(num<=4'd7) begincstate <= DATA;if(`SCL_HIG) beginnum <= num+1'b1;case (num)4'd0: read_data[7] <= sda;4'd1: read_data[6] <= sda;4'd2: read_data[5] <= sda;4'd3: read_data[4] <= sda;4'd4: read_data[3] <= sda;4'd5: read_data[2] <= sda;4'd6: read_data[1] <= sda;4'd7: read_data[0] <= sda;default: ;endcase//read_data[4'd7-num] <= sda;//读数据(高bit开始)end//else if(`SCL_NEG) read_data <= {read_data[6:0],read_data[7]};//数据循环右移endelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;//num计数清零cstate <= ACK4;endelse cstate <= DATA;endelse if(!sw1_r) begin//写操作sda_link <= 1'b1;if(num<=4'd7) begincstate <= DATA;if(`SCL_LOW) beginsda_link <= 1'b1;//数据线sda作为outputnum <= 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//sda_r <= db_r[4'd7-num];//写入数据(高bit开始)end//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0};//写入数据左移1bitendelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态cstate <= ACK4;endelse cstate <= DATA;endendACK4: beginif(/*!sda*/`SCL_NEG) begin//sda_r <= 1'b1;cstate <= STOP1;endelse cstate <= ACK4;endSTOP1:beginif(`SCL_LOW) beginsda_link <= 1'b1;sda_r <= 1'b0;cstate <= STOP1;endelse if(`SCL_HIG) beginsda_r <= 1'b1;//scl为高时,sda产生上升沿(结束信号)cstate <= STOP2;endelse cstate <= STOP1;endSTOP2:beginif(`SCL_LOW) sda_r <= 1'b1;else if(cnt_20ms==20'hffff0) cstate <= IDLE;else cstate <= STOP2;enddefault: cstate <= IDLE;endcaseendassign sda = sda_link ? sda_r:1'bz;assign dis_data = read_data;//---------------------------------------------endmodule。

verilog实现IIC时序逻辑控制

verilog实现IIC时序逻辑控制

Verilog实现IIC时序逻辑控制代码(注释详细,验证可用)Email:xxxxx0901@Address: Haidian.Beijing.China2015-04-09Verilog实现IIC时序逻辑控制代码(注释详细,验证可用)2015-04-09一顶层模块:module iic_top(clk,rst_n,sw1,sw2,scl,sda,sm_cs1_n,sm_cs2_n,sm_db);input clk; // 50MHzinput rst_n; //复位信号,低有效input sw1,sw2; //按键1、2,(1按下执行写入操作,2按下执行读操作) output scl; // 24C02的时钟端口inout sda; // 24C02的数据端口output sm_cs1_n,sm_cs2_n; //数码管片选信号,低有效output[6:0] sm_db; //7段数码管(不包括小数点)wire[7:0] dis_data; //在数码管上显示的16进制数iic_com iic_com(.clk(clk),.rst_n(rst_n),.sw1(sw1),.sw2(sw2),.scl(scl),.sda(sda),.dis_data(dis_data));led_seg7 led_seg7(.clk(clk),.rst_n(rst_n),.dis_data(dis_data),.sm_cs1_n(sm_cs1_n),.sm_cs2_n(sm_cs2_n),.sm_db(sm_db));endmodule二IIC时序模块:module iic_com(clk,rst_n,sw1,sw2,scl,sda,dis_data);input clk; // 50MHzinput rst_n; //复位信号,低有效input sw1,sw2; //按键1、2,(1按下执行写入操作,2按下执行读操作)output scl; // 24C02的时钟端口inout sda; // 24C02的数据端口output[7:0] dis_data; //数码管显示的数据//--------------------------------------------//按键检测//--------------------------------------------reg sw1_r,sw2_r; //键值锁存寄存器,每20ms检测一次键值reg[19:0] cnt_20ms; //20ms计数寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_20ms <= 20'd0;else cnt_20ms <= cnt_20ms+1'b1; //不断计数always @ (posedge clk or negedge rst_n)if(!rst_n) beginsw1_r <= 1'b1; //键值寄存器复位,没有键盘按下时键值都为1sw2_r <= 1'b1;endelse if(cnt_20ms == 20'hfffff) beginsw1_r <= sw1; //按键1值锁存sw2_r <= sw2; //按键2值锁存end//---------------------------------------------//分频部分//--------------------------------------------reg[2:0] cnt; // cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl 低电平中间reg[8:0] cnt_delay; //500循环计数,产生iic所需要的时钟reg scl_r; //时钟脉冲寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_delay <= 9'd0;else if(cnt_delay == 9'd499) cnt_delay <= 9'd0; //计数到10us为scl的周期,即100KHzelse cnt_delay <= cnt_delay+1'b1; //时钟计数always @ (posedge clk or negedge rst_n) beginif(!rst_n) cnt <= 3'd5;else begincase (cnt_delay)9'd124: cnt <= 3'd1; //cnt=1:scl高电平中间,用于数据采样9'd249: cnt <= 3'd2; //cnt=2:scl下降沿9'd374: cnt <= 3'd3; //cnt=3:scl低电平中间,用于数据变化9'd499: cnt <= 3'd0; //cnt=0:scl上升沿default: cnt <= 3'd5;endcaseendend`define SCL_POS (cnt==3'd0) //cnt=0:scl上升沿`define SCL_HIG (cnt==3'd1) //cnt=1:scl高电平中间,用于数据采样`define SCL_NEG (cnt==3'd2) //cnt=2:scl下降沿`define SCL_LOW (cnt==3'd3) //cnt=3:scl低电平中间,用于数据变化always @ (posedge clk or negedge rst_n)if(!rst_n) scl_r <= 1'b0;else if(cnt==3'd0) scl_r <= 1'b1; //scl信号上升沿else if(cnt==3'd2) scl_r <= 1'b0; //scl信号下降沿assign scl = scl_r; //产生iic所需要的时钟//---------------------------------------------//需要写入24C02的地址和数据`define DEVICE_READ 8'b1010_0001 //被寻址器件地址(读操作)`define DEVICE_WRITE 8'b1010_0000 //被寻址器件地址(写操作)`define WRITE_DATA 8'b1101_0001 //写入EEPROM的数据`define BYTE_ADDR 8'b0000_0011 //写入/读出EEPROM的地址寄存器reg[7:0] db_r; //在IIC上传送的数据寄存器reg[7:0] read_data; //读出EEPROM的数据寄存器//---------------------------------------------//读、写时序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; //输出数据sda信号inout方向控制位reg[3:0] num; //always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincstate <= IDLE;sda_r <= 1'b1;sda_link <= 1'b0;num <= 4'd0;read_data <= 8'b0000_0000;endelsecase (cstate)IDLE: beginsda_link <= 1'b1; //数据线sda为outputsda_r <= 1'b1;if(!sw1_r || !sw2_r) begin //SW1,SW2键有一个被按下db_r <= `DEVICE_WRITE; //送器件地址(写操作)cstate <= START1;endelse cstate <= IDLE; //没有任何键被按下endSTART1: beginif(`SCL_HIG) begin //scl为高电平期间sda_link <= 1'b1; //数据线sda为outputsda_r <= 1'b0; //拉低数据线sda,产生起始位信号cstate <= ADD1;num <= 4'd0; //num计数清零endelse cstate <= START1; //等待scl高电平中间位置到来endADD1: beginif(`SCL_LOW) beginif(num == 4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK1;endelse begincstate <= 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// sda_r <= db_r[4'd7-num]; //送器件地址,从高位开始endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD1;endACK1: beginif(/*!sda*/`SCL_NEG) begin //注:24C01/02/04/08/16器件可以不考虑应答位cstate <= ADD2; //从机响应信号db_r <= `BYTE_ADDR; // 1地址endelse cstate <= ACK1; //等待从机响应endADD2: beginif(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK2;endelse beginsda_link <= 1'b1; //sda作为outputnum <= 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// sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD2;endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD2;endACK2: beginif(/*!sda*/`SCL_NEG) begin //从机响应信号if(!sw1_r) begincstate <= DATA; //写操作db_r <= `WRITE_DATA; //写入的数据endelse if(!sw2_r) begindb_r <= `DEVICE_READ; //送器件地址(读操作),特定地址读需要执行该步骤以下操作cstate <= START2; //读操作endendelse cstate <= ACK2; //等待从机响应endSTART2: begin //读操作起始位if(`SCL_LOW) beginsda_link <= 1'b1; //sda作为outputsda_r <= 1'b1; //拉高数据线sdacstate <= START2;endelse if(`SCL_HIG) begin //scl为高电平中间sda_r <= 1'b0; //拉低数据线sda,产生起始位信号cstate <= ADD3;endelse cstate <= START2;endADD3: begin //送读操作地址if(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK3;endelse beginnum <= 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// sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD3;endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD3;endACK3: beginif(/*!sda*/`SCL_NEG) begincstate <= DATA; //从机响应信号sda_link <= 1'b0;endelse cstate <= ACK3; //等待从机响应endDATA: beginif(!sw2_r) begin //读操作if(num<=4'd7) begincstate <= DATA;if(`SCL_HIG) beginnum <= num+1'b1;case (num)4'd0: read_data[7] <= sda;4'd1: read_data[6] <= sda;4'd2: read_data[5] <= sda;4'd3: read_data[4] <= sda;4'd4: read_data[3] <= sda;4'd5: read_data[2] <= sda;4'd6: read_data[1] <= sda;4'd7: read_data[0] <= sda;default: ;endcase// read_data[4'd7-num] <= sda; //读数据(高bit 开始)end// else if(`SCL_NEG) read_data <= {read_data[6:0],read_data[7]}; //数据循环右移endelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0; //num计数清零cstate <= ACK4;endelse cstate <= DATA;endelse if(!sw1_r) begin //写操作sda_link <= 1'b1;if(num<=4'd7) begincstate <= DATA;if(`SCL_LOW) beginsda_link <= 1'b1; //数据线sda作为outputnum <= 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// sda_r <= db_r[4'd7-num]; //写入数据(高bit 开始)end// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //写入数据左移1bitendelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态cstate <= ACK4;endelse cstate <= DATA;endendACK4: beginif(/*!sda*/`SCL_NEG) begin// sda_r <= 1'b1;cstate <= STOP1;endelse cstate <= ACK4;endSTOP1: beginif(`SCL_LOW) beginsda_link <= 1'b1;sda_r <= 1'b0;cstate <= STOP1;endelse if(`SCL_HIG) beginsda_r <= 1'b1; //scl为高时,sda产生上升沿(结束信号)cstate <= STOP2;endelse cstate <= STOP1;endSTOP2: beginif(`SCL_LOW) sda_r <= 1'b1;else if(cnt_20ms==20'hffff0) cstate <= IDLE;else cstate <= STOP2;enddefault: cstate <= IDLE;endcaseendassign sda = sda_link ? sda_r:1'bz;assign dis_data = read_data;//---------------------------------------------endmodule三数码管显示模块:module led_seg7(clk,rst_n,dis_data,sm_cs1_n,sm_cs2_n,sm_db);input clk; // 50MHzinput rst_n; // 复位信号,低有效input[7:0] dis_data; //显示数据output sm_cs1_n,sm_cs2_n; //数码管片选信号,低有效output[6:0] sm_db; //7段数码管(不包括小数点)reg[7:0] cnt;always @ (posedge clk or negedge rst_n)if(!rst_n) cnt <= 8'd0;else cnt <= cnt+1'b1;//------------------------------------------------------------------------------- /* 共阴极:不带小数点;0, 1, 2, 3, 4, 5, 6, 7,db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h;8, 9, a, b, c, d, e, f , 灭db 7fh,6fh,77h,7ch,39h,5eh,79h,71h,00h*/ parameter seg0 = 7'h3f,seg1 = 7'h06,seg2 = 7'h5b,seg3 = 7'h4f,seg4 = 7'h66,seg5 = 7'h6d,seg6 = 7'h7d,seg7 = 7'h07,seg8 = 7'h7f,seg9 = 7'h6f,sega = 7'h77,segb = 7'h7c,segc = 7'h39,segd = 7'h5e,sege = 7'h79,segf = 7'h71;reg[6:0] sm_dbr; //7段数码管(不包括小数点)wire[3:0] num; //显示数据assign num = cnt[7] ? dis_data[7:4] : dis_data[3:0]; assign sm_cs1_n = cnt[7]; //数码管1常开assign sm_cs2_n = ~cnt[7]; //数码管2常开always @ (posedge clk)case (num) //NUM值显示在两个数码管上4'h0: sm_dbr <= seg0;4'h1: sm_dbr <= seg1;4'h2: sm_dbr <= seg2;4'h3: sm_dbr <= seg3;4'h4: sm_dbr <= seg4;4'h5: sm_dbr <= seg5;4'h6: sm_dbr <= seg6;4'h7: sm_dbr <= seg7;4'h8: sm_dbr <= seg8;4'h9: sm_dbr <= seg9;4'ha: sm_dbr <= sega;4'hb: sm_dbr <= segb;4'hc: sm_dbr <= segc;4'hd: sm_dbr <= segd;4'he: sm_dbr <= sege;4'hf: sm_dbr <= segf;default: ;endcase assign sm_db = sm_dbr; endmodule。

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用 I2C在芯片的配置中应用还是很多的,比如摄像头、VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用。

 EEPROM 我使用的这个芯片是AT24C32,它手册上还有一种AT24C64,其实操作都是一样的,只是内存大小不同,AT24C32是32k(4096x8)AT24C64是64k(8192x8), SCL设置为频率200Khz SCL clk posedge data输入EEPROM SCL clk negedge data输出EEPROM SDA 双向Pin A2,A1,A0 Device Addr default all 0,只操作一片可悬空引脚。

 WP 接地正常读写,WP接Vcc写操作被禁止 字节寻址地址,是由12(AT24C32)或13bit(AT24C64)的地址组成,需要操作16位字地址高3或4位忽略即可。

 Device Address 8’hA0写器件地址,8’hA1读器件地址 写字节操作 随机读字节操作 我这个芯片是双字节数据地址,所以在写数据地址时要写两次,先是高字节后是低字节。

 开始结束标志 这个I2C总线的时序是一致的。

 EEPROM应答 输出应答sclk的第九个周期给出,低电平应答。

如果主机没有收到应答,需要重新配置。

 数据传输时序 sda数据线在scl时钟的下降沿中间变化,可以避免产生误触开始结束标志。

 I2C Design i2c_start为高电平有效,传输完成后会产生一个i2c_done结束标志,表示操作完成。

 I2C状态转移图 I2C写操作 (1)产生start位 (2)传送器件地址ID_Address,器件地址的最后一位为数据的传输方向位,R/W,低电平0表示主机往从机写数据(W),1表示主机从从机读数据(R)。

I2C_Verilog

I2C_Verilog

69// synopsys translate_off70`include "timescale.v"71// synopsys translate_on7273`include "i2c_master_defines.v" 7475module i2c_master_byte_ctrl (76clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,77cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );7879//80// inputs & outputs81//82input clk; // master clock83input rst; // synchronous active high reset 84input nReset; // asynchronous active low reset 85input ena; // core enable signal8687input [15:0] clk_cnt; // 4x SCL8889// control inputs90input start;91input stop;92input read;93input write;94input ack_in;95input [7:0] din;9697// status outputs98output cmd_ack;99reg cmd_ack;100output ack_out;101reg ack_out;102output i2c_busy;103output i2c_al;104output [7:0] dout;105106// I2C signals107input scl_i;108output scl_o;109output scl_oen;110input sda_i;111output sda_o;112output sda_oen;115//116// Variable declarations117//118119// statemachine120parameter [4:0] ST_IDLE = 5'b0_0000; 121parameter [4:0] ST_START = 5'b0_0001; 122parameter [4:0] ST_READ = 5'b0_0010; 123parameter [4:0] ST_WRITE = 5'b0_0100; 124parameter [4:0] ST_ACK = 5'b0_1000; 125parameter [4:0] ST_STOP = 5'b1_0000; 126127// signals for bit_controller128reg [3:0] core_cmd;129reg core_txd;130wire core_ack, core_rxd;131132// signals for shift register133reg [7:0] sr; //8bit shift register 134reg shift, ld;135136// signals for state machine137wire go;138reg [2:0] dcnt;139wire cnt_done;140141//142// Module body143//144145// hookup bit_controller146i2c_master_bit_ctrl bit_controller (147.clk ( clk ),148.rst ( rst ),149.nReset ( nReset ),150.ena ( ena ),151.clk_cnt ( clk_cnt ),152.cmd ( core_cmd ),153.cmd_ack ( core_ack ),154.busy ( i2c_busy ),155.al ( i2c_al ),156.din ( core_txd ),157.dout ( core_rxd ),158.scl_i ( scl_i ),159.scl_o ( scl_o ),160.scl_oen ( scl_oen ),161.sda_i ( sda_i ),162.sda_o ( sda_o ),163.sda_oen ( sda_oen )164);165166// generate go-signal167assign go = (read | write | stop) & ~cmd_ack; 168169// assign dout output to shift-register170assign dout = sr;171172// generate shift register173always @(posedge clk or negedge nReset) 174 if (!nReset)175 sr <= #1 8'h0;176 else if (rst)177 sr <= #1 8'h0;178 else if (ld)179 sr <= #1 din;180 else if (shift)181 sr <= #1 {sr[6:0], core_rxd};182183// generate counter184always @(posedge clk or negedge nReset) 185 if (!nReset)186 dcnt <= #1 3'h0;187 else if (rst)188 dcnt <= #1 3'h0;189 else if (ld)190 dcnt <= #1 3'h7;191 else if (shift)192 dcnt <= #1 dcnt - 3'h1;193194assign cnt_done = ~(|dcnt);195196//197// state machine198//199reg [4:0] c_state; // synopsis enum_state 200201always @(posedge clk or negedge nReset) 202 if (!nReset)203 begin204 core_cmd <= #1 `I2C_CMD_NOP;205 core_txd <= #1 1'b0;206 shift <= #1 1'b0;207 ld <= #1 1'b0;208 cmd_ack <= #1 1'b0;209 c_state <= #1 ST_IDLE;210 ack_out <= #1 1'b0;211 end212 else if (rst | i2c_al)213 begin214 core_cmd <= #1 `I2C_CMD_NOP;215 core_txd <= #1 1'b0;216 shift <= #1 1'b0;217 ld <= #1 1'b0;218 cmd_ack <= #1 1'b0;219 c_state <= #1 ST_IDLE;220 ack_out <= #1 1'b0;221 end222else223 begin224 // initially reset all signals225 core_txd <= #1 sr[7];226 shift <= #1 1'b0;227 ld <= #1 1'b0;228 cmd_ack <= #1 1'b0;229230 case (c_state) // synopsys full_case parallel_case 231 ST_IDLE:232 if (go)233 begin234 if (start)235 begin236 c_state <= #1 ST_START;237 core_cmd <= #1 `I2C_CMD_START; 238 end239 else if (read)240 begin241 c_state <= #1 ST_READ;242 core_cmd <= #1 `I2C_CMD_READ; 243 end244 else if (write)245 begin246 c_state <= #1 ST_WRITE;247 core_cmd <= #1 `I2C_CMD_WRITE; 248 end249 else // stop250 begin251 c_state <= #1 ST_STOP;252 core_cmd <= #1 `I2C_CMD_STOP; 253 end254255 ld <= #1 1'b1;256 end257258 ST_START:259 if (core_ack)260 begin261 if (read)262 begin263 c_state <= #1 ST_READ;264 core_cmd <= #1 `I2C_CMD_READ; 265 end266 else267 begin268 c_state <= #1 ST_WRITE;269 core_cmd <= #1 `I2C_CMD_WRITE; 270 end271272 ld <= #1 1'b1;273 end274275 ST_WRITE:276 if (core_ack)277 if (cnt_done)278 begin279 c_state <= #1 ST_ACK;280 core_cmd <= #1 `I2C_CMD_READ; 281 end282 else283 begin284c_state <= #1 ST_WRITE; // stay in same state285core_cmd <= #1 `I2C_CMD_WRITE; // write next bit286 shift <= #1 1'b1;287 end288289 ST_READ:290 if (core_ack)291 begin292 if (cnt_done)293 begin294 c_state <= #1 ST_ACK;295 core_cmd <= #1 `I2C_CMD_WRITE; 296 end297 else298 begin299c_state <= #1 ST_READ; // stay in same state300core_cmd <= #1 `I2C_CMD_READ; // read next bit301 end302303 shift <= #1 1'b1; 304 core_txd <= #1 ack_in;305 end306307 ST_ACK:308 if (core_ack)309 begin310 if (stop)311 begin312 c_state <= #1 ST_STOP;313 core_cmd <= #1 `I2C_CMD_STOP;314 end315 else316 begin317 c_state <= #1 ST_IDLE;318 core_cmd <= #1 `I2C_CMD_NOP;319320 // generate command acknowledge signal 321 cmd_ack <= #1 1'b1;322 end323324// assign ack_out output to bit_controller_rxd (contains last received bit)325 ack_out <= #1 core_rxd;326327 core_txd <= #1 1'b1;328 end329 else330 core_txd <= #1 ack_in;331332 ST_STOP:333 if (core_ack)334 begin335 c_state <= #1 ST_IDLE;336 core_cmd <= #1 `I2C_CMD_NOP; 337338 // generate command acknowledge signal 339 cmd_ack <= #1 1'b1;340 end341342 endcase343 end344endmodule。

I2C verilog (非常详细的i2c学习心得)

I2C verilog (非常详细的i2c学习心得)

图 5. AT24C02/4/8/16 读指定地址存储单元的数据帧格式
首先是一堆输入输出、寄存器的定义,我们读程序的时候大可先不看这些,等到后面有 需要的时候再回过头来看这些定义, 这里需要注意的是 SDA 与 DATA 的类型, 都是 inout 型, SDA 我们很容易理解,因为主机和从机都会给 SDA 线上发信号,比如字节写入格式时,主机 先给 SDA 发了 1 个 8 位数据,然后作为应答位,从机要把 SDA 拉低,表示我已经接受到你 的信号了,在应答位时主机是不能操作 SDA 线的。然而 DATA 设定为 inout 型,我们可以看 到图 2,其实在字节写入格式时,DATA 是 signal 模块传输给 EEPROM_WR 模块,作为要写入 的数据。 而在字节读取格式时, EEPROM_WR 通过 SDA 从 EEPROM 中读取数据, 其实跟 DATA 是没有关系的,这里可以只将 DATA 设定为 input 型,设定为 inout 型是因为后续的程序会将 EEPROM_WR 读取到的数据发给 signal,与 signal 当初发送的数据进行比较,检验通信是否 正确。如果将比较数据这程序操作放在 EEPROM_WR 模块中,就可以将 DATA 设为 input。 提到 inout 类型,还得再多补充两句,inout,顾名思义,双向口既能作为输入又能作为 输出,可以节省管脚,在具体实现上一般是用三态门来实现,图 6 就是用三态门实现的 sda 总线的示意图。
单,使用发送数据线 TXD 和接收数据线 RXD 来传送数据,接收和发送可以单独进行也可以 同时进行。它传送数据的格式有严格的规定,每个数据以相同的位串形式传送,每个串行数 据由起始位,数据位,奇偶校验位和停止位组成。从起始位到停止位为一个字符的完整通信 格式。SPI 情况就相对多一些,根据时钟极性(CPOL)和时钟相位(CPHA)两个参数的不同有四 种基本情况,传送数据的格式与 UART 差不多。而 I2C 总线的协议要比 UART 和 SPI 复杂,能 掌握 I2C,也就能掌握 UART 和 SPI。言归正传,回到我们的 I2C 设计实例。 第一步首先了解,这个 I2C 实例的功能。 这个实例实现了通过 I2C 总线对 EEPROM 写入数据, 再将写入 EEPROM 中的数据读取出 来的一个过程。实例的重点在于对 I2C 总线协议时序的掌握,即用 I2C 总线要求的格式将数 据写入到 EEPROM 中,再读取出来。 什么是 EEPROM?EEPROM (Electrically Erasable Programmable Read‐Only Memory),电可 擦可编程只读存储器, 一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设 备上擦除已有信息,重新编程。所以,EEPROM 是可以写入数据也可以读取数据的,并且 EEPROM 掉电数据并不会丢失,在后面将程序烧写到开发板的过程中可以验证这一点。 第二步,简单地了解一下这个实例的各个模块。

i2s的verilog代码

i2s的verilog代码

i2s的verilog代码i2s的Verilog代码是指用Verilog语言编写的用于实现i2s (Inter-IC Sound)接口功能的代码。

i2s接口是一种常用的音频数据传输接口,广泛应用于音频芯片、音频设备和数字信号处理器等领域。

i2s接口由三根线组成,分别是时钟线(SCLK)、数据线(SD)和帧同步线(WS)。

时钟线用于同步数据的传输,数据线用于传输音频数据,帧同步线用于标志数据的起始和结束。

在Verilog代码中,首先需要定义i2s接口的输入输出端口,并根据接口规范进行信号的定义和赋值。

接下来可以根据具体的应用需求,编写相应的模块和逻辑来实现i2s接口的功能。

一个简单的i2s接口的Verilog代码示例如下:```verilogmodule i2s_interface (input wire SCLK, // 时钟线input wire SD, // 数据线input wire WS, // 帧同步线output wire audio // 音频数据输出);reg [15:0] audio_data; // 音频数据寄存器always @(posedge SCLK) beginif (WS) beginaudio_data <= SD; // 读取音频数据endendassign audio = audio_data; // 输出音频数据endmodule```上述代码中,定义了一个名为i2s_interface的模块,该模块包含了一个i2s接口,输入端口为SCLK、SD和WS,输出端口为audio。

在always块中,通过检测时钟线的上升沿,判断帧同步线的状态,如果帧同步线为高电平,则将数据线的数据存入音频数据寄存器中。

最后,通过assign语句将音频数据输出到audio端口。

需要注意的是,上述代码仅为示例,实际的i2s接口实现可能需要根据具体的应用需求进行修改和优化。

此外,在实际应用中,还需要考虑时序约束、数据格式、时钟频率等因素,以确保i2s接口的正常工作。

eeprom_interface Verilog实现的简单程序(I2C总线接口)

eeprom_interface Verilog实现的简单程序(I2C总线接口)

eeprom_interface Verilog实现的简单程序(I2C总线接口)// i2c.vhd////这是是能从一个外部NUM(AT24C02A)读数据到一个256x8的外部SRAM块的I2C主接口程序,//当用于写NUM的外部逻辑寄存器存取时,SRAM就从外部源读数据并且把数据写到特定的I2C地址。

//----------------------------------------------------------------------////Copyright 2004 Actel corporation////----------------------------------------------------------------------//// Version 1.2 06/04/04 J.Vorgert - working file////---------------------------------------------------------------------- `timescale 1ns / 1psmodule i2c (Reset_n, CLK, INIT, IENB, IADDR, IDATA, ICLK, UPDT, UENB, UADDR, UDATA, SDI, SDO, SCK);input Reset_n; /* active low reset */input CLK ; /* processor clock */output INIT ; /* high during init */output IENB ; /* low to enable write */output [7:0] IADDR ; /* init address */output [7:0] IDATA ; /* init data */output ICLK ; /* init clock */input UPDT ; /* high to trigger mirror image update */output UENB ; /* low to enable fifo */input [7:0] UADDR; /* write address */input [7:0] UDATA; /* write data */input SDI ; /* serial input */output SDO ; /* active low open-drain drive enable - data */output SCK ; /* active low open-drain drive enable - clock */reg IENB;reg INIT;reg UENB;reg BTCK;wire STEN; reg [3:0] CSTATE; reg [3:0] BCNT ; reg [7:0] CCNT ; reg DLY ;reg D2 ;wire D2I;wire NKI ;reg NACK ;wire WRI ;wire RDI ;reg [8:0] BYTE ; reg [8:0] SDATA ; wire LD_BYTE ;reg STSP ;wire CTL_VAL ;always @ (posedge CLK or negedge Reset_n)begin if(Reset_n == 1'b0) BTCK else BTCK // reaches state 0101.always @ (negedge Reset_n or posedge CLK)begin if(Reset_n == 1'b0) INIT else if(CSTATE == 4'b0101) INIT end// This state machine is set-up to read/write data to an AT24C02A // serial Flash memory//这个状态机是建立AT24C02A串行闪存串行闪存的数据读写// At power-up, the INIT bit is set, and the state machine executes// a 'sequencial read' operation starting at address 0x000 and // procedding until all 256 bytes have been read and forwarded into // the internal memory block. The state machine then sends a// stop bit to the Flash and clears the INIT control bit.////在上电上电时,INIT被设置为高,状态机从地址0x000开始执行“连续读”操作,//一直进行下去直到所有的256字节都被读,然后向前到内部存储区,//状态机然后给FLASH发送一个停止位并且清除INIT控制位。

iic协议--Verilog及仿真

iic协议--Verilog及仿真

iic协议--Verilog及仿真1、协议原理:IIC(Inter-Integrated Circuit),i2c总线由数据线sda和时钟线scl这两条构成的串⾏总线,主机和从机可以在i2c总线上发送和接收数据。

scl时钟线作为控制,sda则包含有ack、nack、设备地址、字节地址、8bits数据。

起始信号(scl为⾼电平时,sda变成低电平)与结束信号(scl为⾼电平时,sda变成⾼电平)的状态:IIC单字节写时序有两种:1字节地址段器件单字节写时序、2字节地址段器件单字节写时序。

IIC单字节读时序有两种:1字节地址段器件单节读时序、2字节地址段器件单节读时序字节地址⾼三位xxx:这⾥使⽤的EEPROM的存储容量只有8192bits(1024bits*8)=210*23=213,所以16位的字节地址就多余了三位。

2、协议代码:1、这⾥实现的是2字节单次读写。

2、开始和结束时,虽然scl为⾼电平,sda仍要变化;接下来传输字节,scl为低电平,sda才能变化。

这⾥采取在scl⾼电平和低电平中线产⽣标志。

3、通过状态机来实现读写。

综合代码:module IIC_AT24C64(input sys_clk,input sys_rst_n,input iic_en,input [2:0]cs_bit,//可编程地址input [12:0]byte_address,//字节地址input write,input read,input [7:0]write_data,output reg[7:0]read_data,output reg scl,inout sda,output reg done);parameterSYS_CLK=50_000_000,//系统时钟50MHzSCL_CLK=200_000;//scl时钟200KHzreg [7:0]scl_cnt;//时钟计数parameter div_cnt=SYS_CLK/SCL_CLK;always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)scl_cnt<=8'd0;else if(scl_cnt == div_cnt-1'b1)scl_cnt<=8'd0;elsescl_cnt<=scl_cnt+1'b1;end//⽣成scl时钟线always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)scl<=1'b1;else if(scl_cnt == (div_cnt>>1)-1'b1)scl<=1'b0;else if(scl_cnt == div_cnt-1'b1)scl<=1'b1;elsescl<=scl;end//scl电平中线reg scl_high_middle;//scl⾼电平中线reg scl_low_middle;//scl低电平中线always @(posedge sys_clk or negedge sys_rst_n)beginscl_high_middle<=1'b0;scl_low_middle<=1'b0;endelse if(scl_cnt == (div_cnt>>2))scl_high_middle<=1'b1;else if(scl_cnt == (div_cnt>>1)+(div_cnt>>2))scl_low_middle<=1'b1;else beginscl_high_middle<=1'b0;scl_low_middle<=1'b0;endendreg [15:0]state;parameteridle=16'd1,//空闲状态w_or_r_start=16'd2,//设备地址device_ADDR=16'd3,//发送ACK1=16'd4,byte_ADDR_high=16'd5,//字节地址⾼8位ACK2=16'd6,byte_ADDR_low=16'd7,//字节地址低8位ACK3=16'd8,w_data=16'd9,//写数据ACK4=16'd10,r_start=16'd11,//读开始device_ADDR_r=16'd12,//设备地址读ACK5=16'd13,r_data=16'd14,//读数据NACK=16'd15,//⾮应答位stop=16'd16;reg sda_en;//sda数据线使能reg sda_reg;//sda数据暂存位reg [7:0]sda_data_out;//sda数据发给从机暂存reg [7:0]sda_data_in;//sda数据取之从机暂存reg [3:0]bit_cnt;//每⼀bitassign sda=sda_en?sda_reg:1'bz;//读写标志位reg w_flag;reg r_flag;always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)beginstate<=idle;w_flag<=1'b0;r_flag<=1'b0;sda_reg<=1'b1;done<=1'b0;sda_en<=1'b0;endelse begincase(state)idle:beginsda_reg<=1'b1;w_flag<=1'b0;r_flag<=1'b0;sda_en<=1'b0;sda_reg<=1'b1;done<=1'b0;if(iic_en && write)beginw_flag<=1'b1;sda_en<=1'b1;sda_reg<=1'b1;state<=w_or_r_start;endelse if(iic_en && read)beginr_flag<=1'b1;sda_en<=1'b1;sda_reg<=1'b1;state<=w_or_r_start;endelsestate<=idle;endw_or_r_start:beginif(scl_high_middle)beginsda_reg<=1'b0;sda_data_out<={4'b1010,cs_bit,1'b0};//在这⾥装好设备地址bit_cnt<=4'd8;state<=device_ADDR;endelse beginsda_reg<=1'b1;state<=w_or_r_start;endenddevice_ADDR:beginif(scl_low_middle)beginsda_reg<=sda_data_out[7];sda_data_out<={sda_data_out[6:0],1'b0};//在这⾥发出设备地址。

I_2C总线串行数据接口的Verilog实现

I_2C总线串行数据接口的Verilog实现

邮局订阅号:82-946360元/年技术创新嵌入式网络技术应用《PLC技术应用200例》您的论文得到两院院士关注I2C总线串行数据接口的Verilog实现TheVerilogachievementofI2CSerialBusadapter(华南理工大学)林健磊殷瑞祥LINJIANLEIYINRUIXIANG摘要:本文介绍了I2C总线规范,并根据该规范对I2C进行模块化设计,用VerilogHDL语言对每个模块进行具体描述,并通过模块之间的调用,基本实现了I2C的主机从机的发送和接收功能。

关键词:I2C总线;VerilogHDL;模块化设计中图分类号:TN87文献标识码:BAbstract:ThispaperintroducesthestandardofI2CBus,carrysouttheI2Cmodulardesignaccordingtothisstandard,givesthespe-cificdescriptionofeverymoduleinVerilogHDL,bycallingbetweenmodules,achievesthesendingandreceivingfunctionsofI2CMaster/SlaveMachinebasically.Keyword:I2Cbus,VerilogHDL,Modulardesign文章编号:1008-0570(2007)08-2-0043-021引言I2C(Inter-IntegratedCircuit)是由Philip开发的一种简单的双向两线总线。

I2C只要求两条总线路:串行数据线SDA和串行时钟线SCL,来实现有效的IC之间的控制,而且使硬件效益最大而电路最简单。

同时,通过一个CPU的接口来和片上的总线进行数据交换,可以实现对控制寄存器和数据寄存器的读写。

2I2C总线的工作原理2.1.基本结构总线的串行数据(SDA)和串行时钟(SCL)线,在连接到总线的器件间传递信息。

学习笔记一:I2C协议学习和Verilog实现

学习笔记一:I2C协议学习和Verilog实现

学习笔记⼀:I2C协议学习和Verilog实现1//////////////////////////////////////////////////2//clk = 20 MHz ,⼀个周期50ns3//sck = 100 kHz (scl) ,⼀个周期 1000ns4//I2C在sck下降沿更新数据,上升沿读取(采样)数据5///////////////////////////////////////////////////6module demo_I2C #(parameter F100K = 9'd200)(clk,rstn,start_sig,word_addr,wr_data,rd_data,done_sig,scl,sda,sq_i);78input clk ;9input rstn ;1011input [1:0] start_sig ; //12input [7:0] word_addr ; //word address13input [7:0] wr_data ; //Data14output [7:0] rd_data ; //Data from EEPROM15output done_sig ;1617output scl ; //sda和scl其实是⽤来作为仿真信号添加在这⾥的,寄存器信号都⽤rscl和rsda表⽰了,最后⽤assign将rscl和rsda赋值给sda和scl,连到模块外部仿真⽤ 18inout sda ; //sda表⽰当前sda的in或out的值1920output [4:0] sq_i ;21/************************************22在这⾥,iic_func_module.v 的步骤i已经被引出来了。

读者要知道步骤i在⽆论是在设计上还是仿真上都有许多的好处。

23步骤i在仿真中可以充当“调试跟踪”的作⽤,因为只要模块的那个部分出问题,步骤i就会指向它。

i2c_verilog范例

i2c_verilog范例

// $Locker: $
// $State: Exp $
//
// Change History:
//
$Log: i2c_master_top.v,v $
//
Revision 1.10 2003/09/01 10:34:38 rherveille
//
Fix a blocking vs. non-blocking error in the wb_dat output mux.
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
////
//// POSSIBILITY OF SUCH DAMAGE.
////
////
////
/////////////////////////////////////////////////////////////////////
// status register signals
wire irxack;
reg rxack;
// received aknowledge from slave
reg tip;
// transfer in progress
reg irq_flag; // interrupt pending flag
File: Edit1 9/19/2004, 7:54:04PM
/////////////////////////////////////////////////////////////////////
////
////
//// WISHBONE revB.2 compliant I2C Master controller Top-level ////

I2C串行EEPROMVerilog模型24AA01H

I2C串行EEPROMVerilog模型24AA01H

I2C串行EEPROMVerilog模型24AA01H//******************************************************************* ************************************// ** **// ** 24AA01H.v - Microchip 24AA01H 1K-BIT I2C SERIAL EEPROM WITH HALF-ARRAY WRITE-PROTECT **// ** (VCC = +1.7V TO +5.5V) **// ** **//******************************************************************* ************************************// ** **// ** This information is distributed under license from Young Engineering. **// ** COPYRIGHT (c) 2008 YOUNG ENGINEERING **// ** ALL RIGHTS RESERVED **// ** **// ** **// ** Young Engineering provides design expertise for the digital world **// ** Started in 1990, Young Engineering offers products and services for your electronic design **// ** project. We have the expertise in PCB, FPGA, ASIC, firmware, and software design. **// ** From concept to prototype to production, we can help you. **// ** **// ** /doc/3c16244062.html,/ **// ** **//******************************************************************* ************************************// ** This information is provided to you for your convenience and use with Microchip products only. ** // ** Microchip disclaims all liability arising from this information and its use. **// ** **// ** THIS INFORMATION IS PROVIDED "AS IS." MICROCHIP MAKES NO REPRESENTATION OR WARRANTIES OF ** // ** ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO ** // ** THE INFORMATION PROVIDED TO YOU, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, **// ** PERFORMANCE, MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR PURPOSE. **// ** MICROCHIP IS NOT LIABLE, UNDER ANY CIRCUMSTANCES, FOR SPECIAL, INCIDENTAL ORCONSEQUENTIAL **// ** DAMAGES, FOR ANY REASON WHATSOEVER. **// ** **// ** It is your responsibility to ensure that your application meets with your specifications. **// ** **//******************************************************************* ************************************// ** Revision : 1.0 **// ** Modified Date : 10/20/2008 **// ** Revision History: **// ** **// ** 10/20/2008: Initial design **// ** **//******************************************************************* ************************************// ** TABLE OF CONTENTS **//******************************************************************* ************************************// **---------------------------------------------------------------------------------------------------**// ** DECLARATIONS **// **---------------------------------------------------------------------------------------------------**// **---------------------------------------------------------------------------------------------------**// ** INITIALIZATION **// **---------------------------------------------------------------------------------------------------**// **---------------------------------------------------------------------------------------------------**// ** CORE LOGIC **// **---------------------------------------------------------------------------------------------------**// ** 1.01: START Bit Detection **// ** 1.02: STOP Bit Detection **// ** 1.03: Input Shift Register **// ** 1.04: Input Bit Counter **// ** 1.05: Control Byte Register**// ** 1.06: Byte Address Register **// ** 1.07: Write Data Buffer **// ** 1.08: Acknowledge Generator **// ** 1.09: Acknowledge Detect **// ** 1.10: Write Cycle Timer **// ** 1.11: Write Cycle Processor **// ** 1.12: Read Data Multiplexor **// ** 1.13: Read Data Processor **// ** 1.14: SDA Data I/O Buffer **// ** **// **---------------------------------------------------------------------------------------------------**// ** DEBUG LOGIC **// **---------------------------------------------------------------------------------------------------**// ** 2.01: Memory Data Bytes **// ** 2.02: Write Data Buffer **// ** **// **---------------------------------------------------------------------------------------------------**// ** TIMING CHECKS **// **---------------------------------------------------------------------------------------------------**// ** **//******************************************************************* ************************************`timescale 1ns/10psmodule M24AA01H (A0, A1, A2, WP, SDA, SCL, RESET);input A0; // unconnected pininput A1; // unconnected pininput A2; // unconnected pininput WP; // write protect pininout SDA; // serial data I/Oinput SCL; // serial data clockinput RESET; // system reset//******************************************************************* ************************************// ** DECLARATIONS**//******************************************************************* ************************************reg SDA_DO; // serial data - outputreg SDA_OE; // serial data - output enablewire SDA_DriveEnable; // serial data output enablereg SDA_DriveEnableDlyd;// serial data output enable - delayedreg [03:00] BitCounter; // serial bit counterreg START_Rcvd; // START bit received flagreg STOP_Rcvd; // STOP bit received flagreg CTRL_Rcvd; // control byte received flagreg ADDR_Rcvd; // byte address received flagreg MACK_Rcvd; // master acknowledge received flagreg WrCycle; // memory write cyclereg RdCycle; // memory read cyclereg [07:00] ShiftRegister; // input data shift registerreg [07:00] ControlByte; // control byte registerwire RdWrBit; // read/write control bitreg [06:00] StartAddress; // memory access starting address reg [02:00] PageAddress; // memory page addressreg [07:00] WrDataByte [0:7]; // memory write data bufferwire [07:00] RdDataByte; // memory read datareg [15:00] WrCounter; // write buffer counterreg [02:00] WrPointer; // write buffer pointerreg [06:00] RdPointer; // read address pointerreg WriteActive; // memory write cycle activereg [07:00] MemoryBlock [0:127];// EEPROM data memory arrayinteger LoopIndex; // iterative loop indexinteger tAA; // timing parameterinteger tWC; // timing parameter//******************************************************************* ************************************// ** INITIALIZATION **//******************************************************************* ************************************initial begin`ifdef VCC_1_7V_TO_2_5VtAA = 3500; // SCL to SDA output delaytWC = 5000000; // memory write cycle time`else`ifdef VCC_2_5V_TO_5_5VtAA = 900; // SCL to SDA output delaytWC = 5000000; // memory write cycle time`elsetAA = 900; // SCL to SDA output delaytWC = 5000000; // memory write cycle time`endif`endifendinitial begin SDA_DO = 0; SDA_OE = 0; endinitial begin START_Rcvd = 0; STOP_Rcvd = 0; CTRL_Rcvd = 0; ADDR_Rcvd = 0; MACK_Rcvd = 0; endinitial begin BitCounter = 0; ControlByte = 0; endinitial begin WrCycle = 0; RdCycle = 0;WriteActive = 0; end//******************************************************************* ************************************// ** CORE LOGIC **//******************************************************************* ************************************// -------------------------------------------------------------------------------------------------------// 1.01: START Bit Detection// -------------------------------------------------------------------------------------------------------always @(negedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 1;STOP_Rcvd <= 0;CTRL_Rcvd <= 0;ADDR_Rcvd <= 0;MACK_Rcvd <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 0;endend// -------------------------------------------------------------------------------------------------------// 1.02: STOP Bit Detection// -------------------------------------------------------------------------------------------------------always @(posedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 0;STOP_Rcvd <= 1;CTRL_Rcvd <= 0;ADDR_Rcvd <= 0;MACK_Rcvd <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 10;endend// -------------------------------------------------------------------------------------------------------// 1.03: Input Shift Register// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginShiftRegister[00] <= SDA;ShiftRegister[01] <= ShiftRegister[00];ShiftRegister[02] <= ShiftRegister[01];ShiftRegister[03] <= ShiftRegister[02];ShiftRegister[04] <= ShiftRegister[03];ShiftRegister[05] <= ShiftRegister[04];ShiftRegister[06] <= ShiftRegister[05];ShiftRegister[07] <= ShiftRegister[06];end// -------------------------------------------------------------------------------------------------------// 1.04: Input Bit Counter// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (BitCounter < 10) BitCounter <= BitCounter + 1;end// -------------------------------------------------------------------------------------------------------// 1.05: Control Byte Register// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (START_Rcvd & (BitCounter == 8)) beginif (!WriteActive & (ShiftRegister[07:04] == 4'b1010)) begin if (ShiftRegister[00] == 0) WrCycle <= 1;if (ShiftRegister[00] == 1) RdCycle <= 1;ControlByte <= ShiftRegister[07:00];CTRL_Rcvd <= 1;endSTART_Rcvd <= 0;endendassign RdWrBit = ControlByte[00];// -------------------------------------------------------------------------------------------------------// 1.06: Byte Address Register// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (CTRL_Rcvd & (BitCounter == 8)) beginif (RdWrBit == 0) beginStartAddress <= ShiftRegister[06:00];RdPointer <= ShiftRegister[06:00];ADDR_Rcvd <= 1;endWrCounter <= 0;WrPointer <= 0;CTRL_Rcvd <= 0;endend// -------------------------------------------------------------------------------------------------------// 1.07: Write Data Buffer// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (ADDR_Rcvd & (BitCounter == 8)) beginif ((WP == 0 || StartAddress[06] == 1'b0) & (RdWrBit == 0)) beginWrDataByte[WrPointer] <= ShiftRegister[07:00];WrCounter <= WrCounter + 1;WrPointer <= WrPointer + 1;endendend// -------------------------------------------------------------------------------------------------------// 1.08: Acknowledge Generator// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (!WriteActive) beginif (BitCounter == 8) beginif (WrCycle | (START_Rcvd & (ShiftRegister[07:04] ==4'b1010))) beginSDA_DO <= 0;SDA_OE <= 1;endendif (BitCounter == 9) beginBitCounter <= 0;if (!RdCycle) beginSDA_DO <= 0;SDA_OE <= 0;endendendend// -------------------------------------------------------------------------------------------------------// 1.09: Acknowledge Detect// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (RdCycle & (BitCounter == 8)) beginif ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;endendalways @(negedge SCL) MACK_Rcvd <= 0;// -------------------------------------------------------------------------------------------------------// 1.10: Write Cycle Timer// -------------------------------------------------------------------------------------------------------always @(posedge STOP_Rcvd) beginif (WrCycle & (WP == 0 || StartAddress[06]== 1'b0) & (WrCounter > 0)) beginWriteActive = 1;#(tWC);WriteActive = 0;endendalways @(posedge STOP_Rcvd) begin#(1.0);STOP_Rcvd = 0;end// -------------------------------------------------------------------------------------------------------// 1.11: Write Cycle Processor// -------------------------------------------------------------------------------------------------------always @(negedge WriteActive) beginfor (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) beginPageAddress = StartAddress[02:00] + LoopIndex;MemoryBlock[{StartAddress[06:03],PageAddress[02:00]}] = WrDataByte[LoopIndex[02:00]];endend// -------------------------------------------------------------------------------------------------------// 1.12: Read Data Multiplexor// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (BitCounter == 8) beginif (WrCycle & ADDR_Rcvd) beginRdPointer <= StartAddress + WrPointer + 1;endif (RdCycle) beginRdPointer <= RdPointer + 1;endendendassign RdDataByte = MemoryBlock[RdPointer[06:00]];// -------------------------------------------------------------------------------------------------------// 1.13: Read Data Processor// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (RdCycle) beginif (BitCounter == 8) beginSDA_DO <= 0;SDA_OE <= 0;endelse if (BitCounter == 9) beginSDA_DO <= RdDataByte[07];if (MACK_Rcvd) SDA_OE <= 1;endelse beginSDA_DO <= RdDataByte[7-BitCounter];endendend// -------------------------------------------------------------------------------------------------------// 1.14: SDA Data I/O Buffer// -------------------------------------------------------------------------------------------------------bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);assign SDA_DriveEnable = !SDA_DO & SDA_OE;always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;//******************************************************************* ************************************// ** DEBUG LOGIC **//******************************************************************* ************************************// -------------------------------------------------------------------------------------------------------// 2.01: Memory Data Bytes// -------------------------------------------------------------------------------------------------------wire [07:00] MemoryByte00 = MemoryBlock[00];wire [07:00] MemoryByte01 = MemoryBlock[01];wire [07:00] MemoryByte02 = MemoryBlock[02];wire [07:00] MemoryByte03 = MemoryBlock[03];wire [07:00] MemoryByte04 = MemoryBlock[04];wire [07:00] MemoryByte05 = MemoryBlock[05];wire [07:00] MemoryByte06 = MemoryBlock[06];wire [07:00] MemoryByte07 = MemoryBlock[07];wire [07:00] MemoryByte08 = MemoryBlock[08];wire [07:00] MemoryByte09 = MemoryBlock[09];wire [07:00] MemoryByte0A = MemoryBlock[10];wire [07:00] MemoryByte0B = MemoryBlock[11];wire [07:00] MemoryByte0C = MemoryBlock[12];wire [07:00] MemoryByte0D = MemoryBlock[13];wire [07:00] MemoryByte0E = MemoryBlock[14];wire [07:00] MemoryByte0F = MemoryBlock[15];// -------------------------------------------------------------------------------------------------------// 2.02: Write Data Buffer// -------------------------------------------------------------------------------------------------------wire [07:00] WriteData_0 = WrDataByte[00];wire [07:00] WriteData_1 = WrDataByte[01];wire [07:00] WriteData_2 = WrDataByte[02];wire [07:00] WriteData_3 = WrDataByte[03];wire [07:00] WriteData_4 = WrDataByte[04];wire [07:00] WriteData_5 = WrDataByte[05];wire [07:00] WriteData_6 = WrDataByte[06];wire [07:00] WriteData_7 = WrDataByte[07];//******************************************************************* ************************************// ** TIMING CHECKS **//******************************************************************* ************************************wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);wire StopTimingCheckEnable = TimingCheckEnable && SCL;specify`ifdef VCC_1_7V_TO_2_5VspecparamtHI = 4000, // SCL pulse width - hightLO = 4700, // SCL pulse width - lowtSU_STA = 4700, // SCL to SDA setup time tHD_STA = 4000, // SCL to SDA hold time tSU_DAT = 250, // SDA to SCL setup time tSU_STO = 4000, // SCL to SDA setup time tSU_WP = 4000, // WP to SDA setup time tHD_WP = 4700, // WP to SDA hold time tBUF = 4700; // Bus free time`else`ifdef VCC_2_5V_TO_5_5VspecparamtHI = 600, // SCL pulse width - hightLO = 1300, // SCL pulse width - lowtSU_STA = 600, // SCL to SDA setup time tHD_STA = 600, //SCL to SDA hold timetSU_DAT = 100, // SDA to SCL setup time tSU_STO = 600, // SCL to SDA setup time tSU_WP = 600, // WP to SDA setup time tHD_WP = 600, // WP to SDA hold time tBUF = 1300; // Bus free time`elsespecparamtHI = 600, // SCL pulse width - hightLO = 1300, // SCL pulse width - lowtSU_STA = 600, // SCL to SDA setup timetHD_STA = 600, // SCL to SDA hold timetSU_DAT = 100, // SDA to SCL setup timetSU_STO = 600, // SCL to SDA setup timetSU_WP = 600, // WP to SDA setup timetHD_WP = 600, // WP to SDA hold timetBUF = 1300; // Bus free time`endif`endif$width (posedge SCL, tHI);$width (negedge SCL, tLO);$width (posedge SDA &&& SCL, tBUF);$setup (posedge SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);$setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);$setup (posedge SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);$setup (WP, posedge SDA &&& StopTimingCheckEnable, tSU_WP);$hold (negedge SDA &&& TimingCheckEnable, negedge SCL, tHD_STA);$hold (posedge SDA &&& StopTimingCheckEnable, WP, tHD_WP);endspecifyendmodule。

I2C协议说明及verilog实现读写I2C器件

I2C协议说明及verilog实现读写I2C器件

1.2 I2C 总线的数据传送
1.2.1 起始和终止信号
如图 1-3 所示,SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号; SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。
产品用户手册
三英卓越科技发展有限公司 1
三英卓越科技发展有限公司
K2FPGA
实验教程
2.2 特性
z 低工作电流:典型值为 0.25μA(VDD=3.0V,Tamb=25℃时)。 z 世纪标志。
1.2.3 数据传送格式...................................................................................................2
1.2.4 I2C 总线寻址 ....................................................................................................4

图 1-6 方式 1
哈 注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A 表示应答,
A 非表示非应答(高电平)。S 表示起始信号,P 表示终止信号。
b) 主机在第一个字节后,立即从从机读数据,如图 1-7 所示。
图 1-7 方式 2
c) 在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次, 但两次读/写方向位正好反相,如图 1-8 所示。
卓 3. 代码示例...................................................................................................................7

i2c顶层inout 的处理verilog代码

i2c顶层inout 的处理verilog代码

i2c顶层inout 的处理verilog代码什么是I2C 协议?I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在微控制器、传感器、显示屏、存储器和其他外设之间进行数字数据传输。

它于1982年由Philips(现在的NXP半导体)开发,并在全球范围内广泛应用。

I2C 协议中的顶层inout 接口在设计I2C 通信系统时,顶层inout 接口起着核心作用。

I2C 协议中有两条主要的线路,即数据线(SDA)和时钟线(SCL)。

顶层inout 接口是将这两条线路连接到外部设备的关键。

常见的I2C 顶层inout 接口处理方法有几种,下面将逐步介绍这些方法。

第一种方法:Tri-State Buffer(三态缓冲器)Tri-State Buffer 是一种常用的I2C 顶层inout 接口处理方法。

它通过控制一个使能信号来决定输入输出的状态。

当使能信号有效时,内部数据将根据输入信号确定输出;当使能信号无效时,输出则处于高阻态(Hi-Z)。

使用Tri-State Buffer 的I2C 顶层inout 接口处理方法如下:verilogmodule i2c_top (inout wire sda,inout wire scl,input wire enable);TriStateBuffer #(.WIDTH(1)) tri_sda (.i(sda), .o(sda_s), .oe(enable)); TriStateBuffer #(.WIDTH(1)) tri_scl (.i(scl), .o(scl_s), .oe(enable));endmodule在上述代码中,`sda` 和`scl` 是输入输出的I2C 数据线和时钟线,`enable` 是使能输入信号。

通过Tri-State Buffer 控制使能信号,即可实现对I2C 顶层inout 接口的处理。

第二种方法:Assign 语句除了使用Tri-State Buffer,还可以使用Assign 语句来处理I2C 顶层inout 接口。

verilog iic 读写

verilog iic 读写

在Verilog中,实现I2C(Inter-Integrated Circuit)读写操作需要定义I2C的接口信号,包括SCL(Serial Clock Line)和SDA(Serial Data Line),以及根据具体需求定义其他控制信号。

以下是一个简单的Verilog代码示例,实现I2C写操作:verilog复制代码module i2c_write (input wire scl,input wire sda,input wire start,input wire write_bit,input wire [7:0] data,output reg ack);reg [7:0] ack_data;reg ack_flag;always @(posedge scl) beginif (start) beginack_flag <= 1'b0;ack_data <= 8'h00;end else if (write_bit) beginack_data <= data;ack_flag <= 1'b1;endendassign ack = ack_flag & ~sda;endmodule在上述代码中,scl和sda是I2C总线的时钟线和数据线,start信号表示开始信号,write_bit信号表示当前是写操作,data是写入的数据,ack是应答信号。

在时钟上升沿时,根据当前是开始信号还是写操作信号,将相应的数据写入到ack_data寄存器中,并将ack_flag标志位设为1。

最后,将应答信号赋值为ack_flag 和sda的逻辑与。

以下是一个简单的Verilog代码示例,实现I2C读操作:verilog复制代码module i2c_read (input wire scl,input wire sda,input wire start,input wire read_bit,output reg [7:0] data,output reg ack);reg [7:0] ack_data;reg ack_flag;reg read_data;always @(posedge scl) beginif (start) beginack_flag <= 1'b0;ack_data <= 8'h00;end else if (read_bit) beginack_data <= sda;ack_flag <= 1'b1;end else if (!sda) begin// 读取数据时,sda为低电平read_data <= ack_data; // 读取数据到read_data寄存器中endendassign ack = ack_flag & ~sda; // 应答信号为ack_flag和sda的逻辑与取反值assign data = read_data; // 将读取的数据输出到data信号上endmodule在上述代码中,读操作的过程与写操作类似,只是在读取数据时,需要将sda信号拉低,并在时钟上升沿时将读取的数据存储到read_data寄存器中。

最新-用Verilog HDL实现I2C总线功能 精品

最新-用Verilog HDL实现I2C总线功能 精品

用Verilog HDL实现I2C总线功能摘要简述了2总线的特点;介绍了开发时2总线模块的设计思想;给出并解释了用实现部分2总线功能的程序,以及2总线主从模式下的仿真时序图。

关键词2总线时序开发时,利用工具设计芯片实现系统功能已经成为支撑电子设计的通用平台,并逐步向支持系统级的设计方向发展。

在软件设计过程中,越来越强调模块化设计。

2总线是公司推出的双向两线串行通讯标准,具有接口线少、通讯效率高等特点。

把2总线设计成相应的模块,有利于相关的开发。

目前有一些介绍相关开发的资料,但都是利用语言或语言实现的。

本文给出利用语言设计的2总线模块。

12总线概述2总线系统由两根总线即串行时钟线和串行数据线构成。

这种总线可以设计成很多种通讯配置,但本文只讨论主从系统的应用。

主器件控制总线通讯,开始/结束传送、发送信息并产生2系统时钟。

在写操作过程中,从器件一旦被主控器件寻址,就执行特定的相应功能。

在读操作过程中,主控器件从从器件那里获得数据。

在整个主从传送过程中,所有的事件都通过主控器件的时钟线达到同步。

连到总线上的器件的接口形式必须是漏极开路或集电极开路输出状态。

通过上拉电阻,使得两根总线在空闲的状态下都为高电平状态。

因此2总线上具有线与功能,即总线上的所有器件都达到高电子状态时,2总线才能达到高电平状态,从而使总线上的高速器件和慢速器件工作同步。

在2协议中,从器件地址是一个唯一的7位地址。

接下来是一个读写方向标志位,读状态是高电平、写状态是低电子。

范文先生网收集整理22模块的设计与实现根据2协议中传输过程的特点,2模块可以划分为字节发送模块、字节接收模块、开始条件模块、停止条件模块。

其中,字节发送模块、字节接收模块和停止条件模块为基本模块。

在开始条件模块中,因为需要发送从器件地址,所以要调用字节发送模块。

下面给出用语言实现字节发送模块的关键程序。

相关变量的声明在此略去。

用Verilog实现IIC通讯

用Verilog实现IIC通讯

⽤Verilog实现IIC通讯注意,此代码是错误代码,并不能实现想要的结果。

之所以留着,因为⾥⾯的enable 是独⽴开来的思想值得借鉴。

就是控制单元和运算单元分开(我也是借鉴别⼈的实现思想)。

具体⽤verilogHDL实现IIC通讯在⾥会做到。

1//date :2013/7/72//designer :pengxiaoen3//synthesizer:QuartusII 12.14//function : IIC实现HMC5883的通讯 50M /(400k × 4)= 32567 `define WriteAddress 8'h3c8 `define ReadAddress 8'h3d910 `define RegAAddress 8'h00 //配置寄存器A11 `define RegBAddress 8'h01 //配置寄存器B12 `define ModelAddress 8'h02 //模式寄存器13 `define X_MSBAddress 8'h03 //X MSB寄存器14 `define X_LSBAddress 8'h0415 `define Z_MSBAddress 8'h0516 `define Z_LSBAddress 8'h0617 `define Y_MSBAddress 8'h0718 `define Y_LSBAddress 8'h0819 `define STATEAddress 8'h09 //状态寄存器20 `define IdentifyAAddress 8'h10 //识别寄存器A21 `define IdentifyBAddress 8'h1022 `define IdentifyCAddress 8'h102324 `define INITIAL 025 `define MEASURE 12627 `define START 228 `define Re 329 `define Se 430 `define STOP 53132//`default_nettype none3334module HMC5883_IIC (35 clock,reset,36 sda,scl,37 out_seg,3839 sel_seg40 );4142input clock,reset;43inout sda,scl;44output reg [7:0]out_seg;4546output reg [5:0]sel_seg;4748reg [7:0] SEND_buffer;49reg [7:0] Re_buffer ;50reg sda_reg;51reg scl_reg;52reg sda_enable;53reg scl_enable;5455reg IC_state;56reg [2:0]state; //当前状态寄存器57reg state_finish_flag ; //5859reg [5:0] clk_counter;60reg [3:0] step_counter;61reg [5:0] clk_temp ;626364//-------------------------时钟控制模块-------------------------------start------------------65always @ (posedge clock or negedge reset)66if (!reset)67begin68 clk_temp <= 6'd0;69 clk_counter <= 6'd0;70end71else if (clk_temp[5])72begin73 clk_temp <= 6'd0;74if (state_finish_flag) clk_counter <= 6'd0;75else if (clk_counter == 6'b111_111) //这⾥是⼀个保护机制,可以设置⼀个flag76begin77 clk_counter <= 6'b111_111;78end79else clk_counter <= clk_counter + 1;80end81else clk_temp <= clk_temp + 1;82//-------------------------时钟控制模块-----------------------------------end------------------83848586//-----------------状态机控制模块------------------------------------------start-------------------87always @ (posedge clock or negedge reset)88if(!reset)89 IC_state <= `INITIAL;90else IC_state <= `MEASURE;9192always @ (posedge clock or negedge reset)93if (!reset)94begin95 step_counter <= 4'd0;96 SEND_buffer <= 8'd0;97end98else if(IC_state == `INITIAL)99case (step_counter)1000: begin state <= `START; step_counter <= step_counter + 1;end1011: begin SEND_buffer <= 8'h3c;state <= `Se; step_counter <= step_counter + 1; end 1022: begin SEND_buffer <= 8'h02;state <= `Se; step_counter <= step_counter + 1; end 1033: begin SEND_buffer <= 8'h00;state <= `Se; step_counter <= step_counter + 1; end 1044: begin SEND_buffer <= 8'h00;state <= `Se; step_counter <= step_counter + 1; end 105default step_counter <= 4'd0;106endcase107else if (IC_state == `MEASURE)108case (step_counter)1090: begin state <= `START; step_counter <= step_counter + 1;end1101: begin SEND_buffer <= 8'h3c;state <= `Se; step_counter <= step_counter + 1; end 1112: begin SEND_buffer <= 8'h03;state <= `Se; step_counter <= step_counter + 1; end 1123: begin state <= `START; step_counter <= step_counter + 1;end1134: begin SEND_buffer <= 8'h3d;state <= `Se; step_counter <= step_counter + 1; end 1141155: begin state <= `Re; step_counter <= step_counter + 1; end1166: begin state <= `Re; step_counter <= step_counter + 1; end1177: begin state <= `Re; step_counter <= step_counter + 1; end1188: begin state <= `Re; step_counter <= step_counter + 1; end1199: begin state <= `Re; step_counter <= step_counter + 1; end12010: begin state <= `Re; step_counter <= step_counter + 1; end12111: begin state <= `Re; step_counter <= step_counter + 1; end12212: begin state <= `Re; step_counter <= step_counter + 1; end12312413: begin state <= `STOP; step_counter <= 4'd0; end125default step_counter <= 4'd0;126endcase127128//-----------------状态机控制模块-------------------------------------------end---------------------129130131132//------------------------------------------使能控制模块--------------------------start---------------133always @ (posedge clk_counter or negedge reset)134if (!reset)135begin136 sda_enable <= 1'd0;137 scl_enable <= 1'd0;138end139else case (state)140 `START : begin141if(clk_counter >= 6'd4)142begin143 sda_enable <= 1'd0;144 scl_enable <= 1'd0;145end146else147begin148 sda_enable <= 1'd1;149 scl_enable <= 1'd1;150end151end152153 `STOP : begin154if(clk_counter >= 6'd4)155begin156 sda_enable <= 1'd0;157 scl_enable <= 1'd0;158end159else160begin161 sda_enable <= 1'd1;162 scl_enable <= 1'd1;163end164end165166 `Se : begin167if(clk_counter >= 6'd36) //send 完成之后释放掉使能168begin169 sda_enable <= 1'd0;170 scl_enable <= 1'd0;171end172else173begin174 sda_enable <= 1'd1;175 scl_enable <= 1'd1;176end177end178179 `Re : begin180if(clk_counter >= 6'd32) //receive 完成之后释放掉使能181begin182 sda_enable <= 1'd0;183 scl_enable <= 1'd0;184end185else186begin187 sda_enable <= 1'd1;188 scl_enable <= 1'd1;189end190end191endcase192//------------------------------------------使能控制模块--------------------------end---------------193194195196//------------------------------------------------外部数据线控制模块-----------------start---------------197always @ (posedge clk_counter or negedge reset)198if(!reset)199begin200 sda_reg <= 1'd0;201 scl_reg <= 1'd0;202 state_finish_flag <= 1'd0;203 Re_buffer <= 8'd0;204end205else case (state)206 `START : begin207case (clk_counter)2080: begin sda_reg <= 1'd1; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2091: begin sda_reg <= 1'd1; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2102: begin sda_reg <= 1'd1; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2113: begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end212default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end213endcase214end215216 `STOP : begin217case (clk_counter)2180: begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2191: begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2202: begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2213: begin sda_reg <= 1'd1; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end222default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end223endcase224end225226 `Se : begin227case (clk_counter)2280: begin sda_reg <= 1'd0; scl_reg <= 1'd0; end2291: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 2302: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 2313: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 2324: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2335: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 2346: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 2357: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 2368: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2379: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 23810: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 23911: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 24012: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 24113: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 24214: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end24315: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 24416: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end24517: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 24618: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 24719: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 24820: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end24921: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 25022: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 25123: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 25224: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end25325: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 25426: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 25527: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 25628: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end25729: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end 25830: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 25931: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end 26026132: begin/*state_finish_flag <= sda;*/ scl_reg <= 1'd0; /*state_finish_flag <= 1'd0; */ end 26233: begin/*state_finish_flag <= sda;*/ scl_reg <= 1'd0; /*state_finish_flag <= 1'd0; */ end 26334: begin/*state_finish_flag <= sda;*/ scl_reg <= 1'd1; /*state_finish_flag <= 1'd0; */ end 26435: begin state_finish_flag <= sda; scl_reg <= 1'd1; /*state_finish_flag <= 1'd0; */ end 265266default begin scl_reg <= 1'dz; state_finish_flag <= sda; end //等待响应267endcase268end269270 `Re : begin271case (clk_counter)2720: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2731: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2742: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2753: begin Re_buffer[7] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2764: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2775: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2786: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2797: begin Re_buffer[6] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end2808: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end2819: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end28210: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end28311: begin Re_buffer[5] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end28412: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end28513: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end28614: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end28715: begin Re_buffer[4] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end28816: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end28917: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end29018: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end29119: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end29220: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end29321: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end29422: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end29523: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end29624: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end29725: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end29826: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end29927: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end30028: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end30129: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end30230: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end30331: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end304305// 32:begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end //NA 306// 33:begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end307// 34:begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end308// 35:begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end309310default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end311endcase312end313endcase314//------------------------------------------------外部数据线控制模块-----------------end---------------315316317318assign sda = sda_enable ? sda_reg : 1'dz ;319assign scl = scl_enable ? scl_reg : 1'dz ;320321322323324325326always @ (posedge clk_counter or negedge reset) 327if (!reset)328begin329 sel_seg <= 6'b111110;330end331else if(state_finish_flag)332begin333 sel_seg <= {sel_seg[4:0],sel_seg[5]};334end335336always @(posedge clock or negedge reset)337if (!reset) out_seg <= 8'd0;338else339begin340case (Re_buffer)3414'b0000 : out_seg<=8'b1100_0000;//0000_0011 3424'b0001 : out_seg<=8'b1111_1001;//1001_1111 3434'b0010 : out_seg<=8'b1010_0100;//0010_0101 3444'b0011 : out_seg<=8'b1011_0000;//0000_1101 3454'b0100 : out_seg<=8'b1001_1001;//1001_1001 3464'b0101 : out_seg<=8'b1001_0010;//0100_1001 3474'b0110 : out_seg<=8'b1000_0010;//0100_0001 3484'b0111 : out_seg<=8'b1111_1000;//0001_1111 3494'b1000 : out_seg<=8'b1000_0000;//0000_0001 3504'b1001 : out_seg<=8'b1001_1000;//0001_1001 3514'b1010 : out_seg<=8'b1000_1000;//0001_0001 3524'b1011 : out_seg<=8'b1000_0011;//1100_0001 3534'b1100 : out_seg<=8'b1100_0110;//0110_0011 3544'b1101 : out_seg<=8'b1010_0001;//1000_0101 3554'b1110 : out_seg<=8'b1000_0110;//0110_0001 3564'b1111 : out_seg<=8'b1000_1110;//0111_0001 357endcase358end359360361362endmodule。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

4'd5: sda_r <= db_r[2]; 4'd6: sda_r <= db_r[1]; 4'd7: sda_r <= db_r[0]; default:endcase//sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD2;endend//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelsecstate <= ADD2;endACK2:beginif(/*!sda*/`SCL_NEG) begin//从机响应信号if(!sw1_r) begincstate <= DATA;//写操作db_r <= `WRITE_DATA; //写入的数据endelse if(!sw2_r) begindb_r <= `DEVICE_READ; //送器件地址(读操作)地址读需要执行该步骤以下操作cstate <= START2;//读操作endendelse cstate <= ACK2;//等待从机响应START2: begin //读操作起始位if(`SCL_LOW) beginsda_link <= 1'b1; //sda作为outputsda_r <= 1'b1;//拉高数据线sdacstate <= START2;endelse if(`SCL_HIG) begin //scl为高电平中间sda_r <= 1'b0;//拉低数据线sda,产生起始位信号cstate <= ADD3;endelse cstate <= START2; endADD3:begin//送读操作地址if(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0;//num计数清零sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态(input)cstate <= ACK3; endelse beginnum <= 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//sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD3;endend//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD3;endACK3:beginif(/*!sda*/`SCL_NEG) begincstate <= DATA;//从机响应信号sda_link <= 1'b0;endelse cstate <= ACK3;//等待从机响应endDATA:beginif(!sw2_r) begin//读操作if(num<=4'd7) begin cstate <= DATA;if(`SCL_HIG) beginnum <= num+1'b1; case (num)4'd0: read_data[7] <= sda;4'd1: read_data[6] <= sda; 4'd2: read_data[5] <= sda; 4'd3: read_data[4] <= sda; 4'd4: read_data[3] <= sda;4'd5: read_data[2] <= sda; 4'd6: read_data[1] <= sda; 4'd7: read_data[0] <= sda;default:endcase//read_data[4'd7-num] <= sda; // 读数据(高开始)end//elseif(`SCL_NEG)read_data<={read_data[6:0],read_data[7]}; //数据循环右移endelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;//num计数清零cstate <= ACK4;endelse cstate <= DATA;endelse if(!sw1_r) begin //写操作sda_link <= 1'b1;if(num<=4'd7) begin cstate <= DATA;if(`SCL_LOW) beginsda_link <= 1'b1;//数据线sda作为outputnum <= 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//sda_r <= db_r[4'd7-num]; //写入数据(高bit开始)end//else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //写入数据左移1bitendelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;sda_r <= 1'b1;sda_link <= 1'b0;//sda置为高阻态cstate <= ACK4;endelse cstate <= DATA;endendACK4: beginif(/*!sda*/`SCL_NEG) begin //sda_r <= 1'b1; cstate <= STOP1; endelse cstate <= ACK4; endSTOP1:beginif(`SCL_LOW) beginsda_link <= 1'b1;sda_r <= 1'b0;cstate <= STOP1;endelse if(`SCL_HIG) begin sda_r <= 1'b1; //scl为高时,sda产生上升沿(结束信号)cstate <= STOP2;endelse cstate <= STOP1;endSTOP2:beginif(`SCL_LOW) sda_r <= 1'b1;else if(cnt_20ms==20'hffff0) cstate <= IDLE;else cstate <= STOP2;enddefault: cstate <= IDLE;endcaseendassign sda = sda_link ? sda_r:1'bz;assign dis_data = read_data;//---------------------------------------------endmodule写寄存器的标准流程为:1. Master发起START2. Master发送I2C addr(7bit)和w操作0(1bit),等待ACK3. Slave发送ACK4. Master发送reg addr(8bit),等待ACK5. Slave发送ACK6. Master发送data(8bit),即要写入寄存器中的数据,等待ACK7. Slave发送ACK8. 第6步和第7步可以重复多次,即顺序写多个寄存器9. Master发起STOP读寄存器的标准流程为:1. Master发送I2C addr(7bit)和w操作1(1bit),等待ACK2. Slave发送ACK3. Master发送reg addr(8bit),等待ACK4. Slave发送ACK5. Master发起START6. Master发送I2C addr(7bit)和r操作1(1bit),等待ACK7. Slave发送ACK8. Slave发送data(8bit),即寄存器里的值9. Master发送ACK10. 第8步和第9步可以重复多次,即顺序读多个寄存器原理整理清楚编程思路就有了,首先要有开始工作的信号,分读和写来驱动I2C,本设计用M2408这款芯片进行工作,主要是了解到datasheet中时序的要求来进行编写。

编写过程中遇到的问题是scl没有满足时序要求,还有工作状态容易漏掉,比如说地址的发送以及等待ACK 最后通过仿真及下载进行验证得到最终的结果,下图是modelsim的仿真图:。

相关文档
最新文档