1、IIC verilogtimescale 1ns / 1psmodule iicmax(clk,rst_n,sw1,sw2,sw3,sw4,scl,sda,leddata,ledcom);input clk; / 50MHzinput rst_n; /复位信号,低有效input sw1,sw2,sw3,sw4; /按键,(1按下执行写入操作,2按下执行读操作,3按下执行连写操作,4按下执行连读操作)output scl; / 24C08的时钟端口inout sda; / 24C08的数据端口output 7:0 ledcom; /数码管片选信号,低有效output 7:0 leddata; /
2、7段数码管(不包括小数点)wire7:0 tansdata; /传送的数据wire2: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
3、) );endmodule IICCOM 模块timescale 1ns / 1psmodule iiccom(clk,rst_n,sw1,sw2,sw3,sw4,scl,sda,ackflag,outdata);input clk; / 50MHzinput rst_n; /复位信号,低有效input sw1,sw2,sw3,sw4; /按键,(1按下执行写入操作,2按下执行读操作,3按下执行连写操作,4按下执行连读操作)output scl; / 24C08的时钟端口output 2:0ackflag;/后面显示接收到数据的标准inout sda; / 24C08的数据端口output 7
4、:0 outdata; /数码管显示的数据/-/按键检测reg sw1_r,sw2_r,sw3_r,sw4_r; /键值锁存寄存器,每20ms检测一次键值 reg19:0 cnt_20ms; /20ms计数寄存器always (posedge clk or negedge rst_n)if(!rst_n) cnt_20ms = 20d0;elseif(cnt_20ms = 20hfffff) cnt_20ms = 20h0;elsecnt_20ms = cnt_20ms+1b1; /不断计数always (posedge clk or negedge rst_n)if(!rst_n) begi
5、nsw1_r = 1b1; /键值寄存器复位,没有键盘按下时键值都为1sw2_r = 1b1;sw3_r = 1b1;sw4_r = 1b1;endelseif(cnt_20ms = 20hffff0) beginsw1_r = sw1; /按键值锁存sw2_r = sw2;sw3_r = sw3;sw4_r = sw4; end/-/分频部分reg2:0 cnt; / cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间reg8:0 cnt_delay; /500循环计数,产生iic所需要的时钟reg scl_r; /时钟脉冲寄存器a
6、lways (posedge clk or negedge rst_n)if(!rst_n) cnt_delay = 9d0;elseif(cnt_delay = 9d499) cnt_delay = 9d0; /计数到10us为scl的周期,即100KHzelsecnt_delay = cnt_delay+1b1; /时钟计数always (posedge clk or negedge rst_n) beginif(!rst_n) cnt = 3d5;elsebegincase(cnt_delay)9d124: cnt = 3d1; /cnt=1:scl高电平中间,用于数据采样9d255:
7、cnt = 3d2; /cnt=2:scl下降沿后面点9d374: cnt = 3d3; /cnt=3:scl低电平中间,用于数据变化9d495: cnt = 3d0; /cnt=0:scl上升沿前面点default: cnt = 3d5;endcaseendenddefine SCL_POS (cnt=3d0) /cnt=0:scl上升沿前面点define SCL_HIG (cnt=3d1) /cnt=1:scl高电平中间,用于数据采样define SCL_NEG (cnt=3d2) /cnt=2:scl下降沿后面点define SCL_LOW (cnt=3d3) /cnt=3:scl低电平
8、中间,用于数据变化always (posedge clk or negedge rst_n)if(!rst_n) scl_r = 1b0;elseif(cnt_delay=9d499) scl_r = 1b1; /scl信号上升沿elseif(cnt_delay=9d249) scl_r = 1b0; /scl信号下降沿assign scl = scl_r; /产生iic所需要的时钟/-/需要写入24C02的地址和数据define DEVICE_READ 8b1010_1001 /被寻址器件地址(读操作)define DEVICE_WRITE 8b1010_1000 /被寻址器件地址(写操作)
9、define WRITE_DATA0 8b1000_1000 define WRITE_DATA1 8b0010_0001 /写入EEPROM的数据define WRITE_DATA2 8b0100_0011define WRITE_DATA3 8b0110_0101define WRITE_DATA4 8b1000_0111define BYTE_ADDR 8b0000_0100 /写入/读出EEPROM的地址寄存器 reg7:0 db_r; /在IIC上传送的数据寄存器reg7:0 read_data; /读出EEPROM的数据寄存器reg7:0 outdata_r; /输出数据贮存器pa
10、rameter PAGEDATA_NUM = 3d4; /页写数据个数/-/读、写时序parameter IDLE = 17b0_0000_0000_0000_0001;/初始态parameter START1 = 17b0_0000_0000_0000_0010;/起始信号parameter ADD1 = 17b0_0000_0000_0000_0100;/写入器件地址parameter ACK1 = 17b0_0000_0000_0000_1000;/应答parameter ADD2 = 17b0_0000_0000_0001_0000;/写入字节地址parameter ACK2 = 17
11、b0_0000_0000_0010_0000;/应答parameter START2 = 17b0_0000_0000_0100_0000;/读操作开始前的起始信号parameter ADD3 = 17b0_0000_0000_1000_0000;/写入器件地址parameter ACK3 = 17b0_0000_0001_0000_0000;/应答parameter ACKR = 17b1_0000_0000_0000_0000;/fpga给应答parameter DATA = 17b0_0000_0010_0000_0000;/字节读写parameter PAGER = 17b0_0000
12、_0100_0000_0000;/页读parameter PAGEW = 17b0_0000_1000_0000_0000;/页写parameter ACK4 = 17b0_0001_0000_0000_0000;/应答parameter HIGH = 17b0_0010_0000_0000_0000;/高电平parameter STOP1 = 17b0_0100_0000_0000_0000;/停止位parameter STOP2 = 17b0_1000_0000_0000_0000;/延时同步reg16:0 cstate; /状态寄存器reg sda_r; /输出数据寄存器reg sda_
13、link; /输出数据sda信号inout方向控制位 reg3:0 num; /读写的字节计数reg2:0 ackflag;/连读时的数据标志reg2:0 pagecnt;/连读连写时的数据计数器reg7:0 pagedata_r;/连读储存器always (posedge clk or negedge rst_n) beginif(!rst_n) beginpagedata_r = 8d0;endelsebegincase(pagecnt)3d0: pagedata_r = WRITE_DATA1;3d1: pagedata_r = WRITE_DATA2;3d2: pagedata_r =
14、 WRITE_DATA3;3d3: pagedata_r = WRITE_DATA4;default:;endcaseendend/-状态机-/always(posedge clk or negedge rst_n) beginif(!rst_n) begincstate = IDLE;sda_r = 1b1;sda_link = 1b0;num = 4d0;ackflag = 3d0;pagecnt = 3d0;read_data = 8b0000_0000;outdata_r = 8b0000_0000;endelsecase(cstate)IDLE: beginsda_link = 1b
15、1; /数据线sda为inputsda_r = 1b1;read_data = 8b0000_0000;/ackflag = 3d0;if(!sw1_r | !sw2_r | !sw3_r | !sw4_r) begin /SW1,SW2,SW3,SW4键有一个被按下 db_r = DEVICE_WRITE; /送器件地址(写操作)cstate = START1; endelsecstate = IDLE; /没有任何键被按下endSTART1: beginif(SCL_HIG) begin /scl为高电平期间sda_link = 1b1; /数据线sda为outputsda_r = 1b0
16、; /拉低数据线sda,产生起始位信号cstate = ADD1;ackflag = 1b0;num = 4d0; /num计数清零endelsecstate = START1; /等待scl高电平中间位置到来endADD1: beginif(SCL_LOW) beginif(num = 4d8) begin num = 4d0; /num计数清零sda_r = 1b1;sda_link = 1b0; /sda置为高阻态(input)cstate = ACK1;endelsebegincstate = ADD1;num = num+1b1;case(num)4d0: sda_r = db_r7
17、;4d1: sda_r = db_r6;4d2: sda_r = db_r5;4d3: sda_r = db_r4;4d4: sda_r = db_r3;4d5: sda_r = db_r2;4d6: sda_r = db_r1;4d7: sda_r = db_r0;default: ;endcaseendendelsecstate = ADD1;endACK1: beginif(SCL_NEG) begin cstate = ADD2; /从机响应信号db_r = BYTE_ADDR; / 1地址 endelsecstate = ACK1; /等待从机响应end ADD2: beginif(SCL_LOW) beginif(num=4d8) begin num = 4d0; /num计数清零sda_r = 1b1;sda_link = 1b0; /sda置为高阻态(input)cstate = ACK2;endelsebeginsda_link = 1b1; /sda作为outputnum = num+1b1;case(num)4d0: sda_r = db_r7;4d1: sda_r = db_r6;4d2: sda_r = db_r5;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1