Created
June 26, 2012 03:40
-
-
Save rswofxd/2993126 to your computer and use it in GitHub Desktop.
Verilog:串行数据总线协议IIC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //////////////////////////////////////////////////////////////////////////////// | |
| //串行数据总线协议IIC | |
| //////////////////////////////////////////////////////////////////////////////// | |
| `timescale 1ns/1ns | |
| module i2c_wr (clk,rst_n,wr,rd,addr,data_w,data_r,ack,scl,sda); | |
| input clk; //clock | |
| input rst_n; //reset | |
| input wr,rd; //write,read command | |
| input [10:0] addr; //write,read eeprom address | |
| input [7:0] data_w; //write data to eeprom | |
| output [7:0] data_r; //read data from eeprom | |
| // output rd_ack; | |
| output ack; //write,read complete | |
| output scl; //i2c scl signal | |
| inout sda; //i2c sda signal | |
| reg ack; | |
| reg scl; | |
| reg wf,rf; | |
| reg ff; | |
| reg [1:0] head_buf; | |
| reg [1:0] stop_buf; | |
| reg [7:0] sh8out_buf; | |
| reg [8:0] sh8out_state; | |
| reg [9:0] sh8in_state; | |
| reg [2:0] head_state; | |
| reg [2:0] stop_state; | |
| reg [10:0] main_state; | |
| reg [7:0] data_r; | |
| reg link_sda; | |
| // reg rd_ack; | |
| reg link_head; | |
| reg link_write; | |
| reg link_stop; | |
| wire sda1,sda2,sda3,sda4; | |
| //---------------串行数据在开关控制下有次序的输出------------------------- | |
| assign sda1 = (link_head) ? head_buf[1]:1'b0; | |
| assign sda2 = (link_write)? sh8out_buf[7]:1'b0; | |
| assign sda3 = (link_stop) ? stop_buf[1]:1'b0; | |
| assign sda4 = (sda1|sda2|sda3); | |
| assign sda = (link_sda) ? sda4:1'bz; | |
| //assign data = (rd_ack) ? data_from_rm:8'hzz; | |
| //---------------主状态机状态定义----------------------------------------- | |
| parameter | |
| Idle =11'b00000000001, | |
| Ready =11'b00000000010, | |
| Write_start =11'b00000000100, | |
| Ctrl_write =11'b00000001000, | |
| Addr_write =11'b00000010000, | |
| Data_write =11'b00000100000, | |
| Read_start =11'b00001000000, | |
| Ctrl_read =11'b00010000000, | |
| Data_read =11'b00100000000, | |
| Stop =11'b01000000000, | |
| Ackn =11'b10000000000, | |
| //--------------并行数据串行输出状态-------------------------------------- | |
| sh8out_bit7 =9'b000000001, | |
| sh8out_bit6 =9'b000000010, | |
| sh8out_bit5 =9'b000000100, | |
| sh8out_bit4 =9'b000001000, | |
| sh8out_bit3 =9'b000010000, | |
| sh8out_bit2 =9'b000100000, | |
| sh8out_bit1 =9'b001000000, | |
| sh8out_bit0 =9'b010000000, | |
| sh8out_end =9'b100000000; | |
| //---------------串行数据并行输出状态------------------------------------ | |
| parameter | |
| sh8in_begin =10'b0000000001, | |
| sh8in_bit7 =10'b0000000010, | |
| sh8in_bit6 =10'b0000000100, | |
| sh8in_bit5 =10'b0000001000, | |
| sh8in_bit4 =10'b0000010000, | |
| sh8in_bit3 =10'b0000100000, | |
| sh8in_bit2 =10'b0001000000, | |
| sh8in_bit1 =10'b0010000000, | |
| sh8in_bit0 =10'b0100000000, | |
| sh8in_end =10'b1000000000, | |
| //--------------启动状态------------------------------------------------- | |
| head_begin =3'b001, | |
| head_bit =3'b010, | |
| head_end =3'b100, | |
| //-------------停止状态------------------------------------------------- | |
| stop_begin =3'b001, | |
| stop_bit =3'b010, | |
| stop_end =3'b100; | |
| parameter | |
| YES =1, | |
| NO =0; | |
| //-------------产生串行时钟SCL,为输入时钟的二分频------------------------ | |
| always @(negedge clk or negedge rst_n) | |
| if(!rst_n) | |
| scl<=0; | |
| else | |
| scl<=~scl; | |
| //-----------主状态机程序------------------------------------------------- | |
| always @(posedge clk or negedge rst_n) | |
| if(!rst_n) | |
| begin | |
| // rd_ack <=NO; | |
| link_write <=NO; | |
| link_head <=NO; | |
| link_stop <=NO; | |
| link_sda <=NO; | |
| ack <=0; | |
| rf <=0; | |
| wf <=0; | |
| ff <=0; | |
| head_buf[1:0] <=2'b00; | |
| main_state <=Idle; | |
| end | |
| else | |
| begin | |
| casex(main_state) | |
| Idle: | |
| begin | |
| // rd_ack <=NO; | |
| link_write <=NO; | |
| link_head <=NO; | |
| link_stop <=NO; | |
| link_sda <=NO; | |
| if(wr) | |
| begin | |
| wf <=1; | |
| main_state<=Ready; | |
| end | |
| else if(rd) | |
| begin | |
| rf<=1; | |
| main_state<=Ready; | |
| end | |
| else | |
| begin | |
| wf<=0; | |
| rf<=0; | |
| main_state<=Idle; | |
| end | |
| end | |
| Ready: | |
| begin | |
| // rd_ack <=NO; | |
| link_write <=NO; | |
| link_stop <=NO; | |
| link_head <=YES; | |
| link_sda <=YES; | |
| head_buf[1:0] <=2'b10; | |
| stop_buf[1:0] <=2'b01; | |
| head_state <=head_begin; | |
| ff <=0; | |
| ack <=0; | |
| main_state <=Write_start; | |
| end | |
| Write_start: | |
| if(ff==0) | |
| shift_head; | |
| else | |
| begin | |
| sh8out_buf[7:0] <={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b0}; | |
| link_head <=NO; | |
| link_write <=YES; | |
| ff <=0; | |
| sh8out_state <=sh8out_bit6; | |
| main_state <=Ctrl_write; | |
| end | |
| Ctrl_write: | |
| if(ff==0) | |
| shift8_out; | |
| else | |
| begin | |
| sh8out_state <=sh8out_bit7; | |
| sh8out_buf[7:0] <=addr[7:0]; | |
| ff <=0; | |
| main_state <=Addr_write; | |
| end | |
| Addr_write: | |
| if(ff==0) | |
| shift8_out; | |
| else | |
| begin | |
| ff <=0; | |
| if(wf) | |
| begin | |
| sh8out_state <=sh8out_bit7; | |
| sh8out_buf[7:0] <=data_w; | |
| main_state <=Data_write; | |
| end | |
| if(rf) | |
| begin | |
| head_buf <=2'b10; | |
| head_state <=head_begin; | |
| main_state <=Read_start; | |
| end | |
| end | |
| Data_write: | |
| if(ff==0) | |
| shift8_out; | |
| else | |
| begin | |
| stop_state <=stop_begin; | |
| main_state <=Stop; | |
| link_write <=NO; | |
| ff <=0; | |
| // ack <=1; | |
| end | |
| Read_start: | |
| if(ff==0) | |
| shift_head; | |
| else | |
| begin | |
| sh8out_buf <={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b1}; | |
| link_head <=NO; | |
| link_sda <=YES; | |
| link_write <=YES; | |
| ff <=0; | |
| sh8out_state <=sh8out_bit6; | |
| main_state <=Ctrl_read; | |
| end | |
| Ctrl_read: | |
| if(ff==0) | |
| shift8_out; | |
| else | |
| begin | |
| link_sda <=NO; | |
| link_write <=NO; | |
| ff <=0; | |
| sh8in_state <=sh8in_begin; | |
| main_state <=Data_read; | |
| end | |
| Data_read: | |
| if(ff==0) | |
| shift8in; | |
| else | |
| begin | |
| // rd_ack <=NO; | |
| link_stop <=YES; | |
| link_sda <=YES; | |
| stop_state <=stop_bit; | |
| ff <=0; | |
| main_state <=Stop; | |
| end | |
| Stop: | |
| if(ff==0) | |
| shift_stop; | |
| else | |
| begin | |
| ack <=1; | |
| ff <=0; | |
| main_state <=Ackn; | |
| end | |
| Ackn: | |
| begin | |
| ack <=0; | |
| wf <=0; | |
| rf <=0; | |
| main_state <=Idle; | |
| end | |
| default: main_state <=Idle; | |
| endcase | |
| end | |
| //------------串行数据转换为并行数据任务----------------------------------- | |
| task shift8in; | |
| begin | |
| casex(sh8in_state) | |
| sh8in_begin: | |
| sh8in_state <=sh8in_bit7; | |
| sh8in_bit7: if(scl) | |
| begin | |
| data_r[7] <=sda; | |
| sh8in_state <=sh8in_bit6; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit7; | |
| sh8in_bit6: if(scl) | |
| begin | |
| data_r[6] <=sda; | |
| sh8in_state <=sh8in_bit5; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit6; | |
| sh8in_bit5: if(scl) | |
| begin | |
| data_r[5] <=sda; | |
| sh8in_state <=sh8in_bit4; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit5; | |
| sh8in_bit4: if(scl) | |
| begin | |
| data_r[4] <=sda; | |
| sh8in_state <=sh8in_bit3; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit4; | |
| sh8in_bit3: if(scl) | |
| begin | |
| data_r[3] <=sda; | |
| sh8in_state <=sh8in_bit2; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit3; | |
| sh8in_bit2: if(scl) | |
| begin | |
| data_r[2] <=sda; | |
| sh8in_state <=sh8in_bit1; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit2; | |
| sh8in_bit1: if(scl) | |
| begin | |
| data_r[1] <=sda; | |
| sh8in_state <=sh8in_bit0; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit1; | |
| sh8in_bit0: if(scl) | |
| begin | |
| data_r[0] <=sda; | |
| sh8in_state <=sh8in_end; | |
| end | |
| else | |
| sh8in_state <=sh8in_bit0; | |
| sh8in_end: if(scl) | |
| begin | |
| // rd_ack <=YES; | |
| ff <=1; | |
| sh8in_state <=sh8in_bit7; | |
| end | |
| else | |
| sh8in_state <=sh8in_end; | |
| default: | |
| begin | |
| // rd_ack <=NO; | |
| sh8in_state <=sh8in_bit7; | |
| end | |
| endcase | |
| end | |
| endtask | |
| //-------------------并行数据转换为串行数据任务--------------------------- | |
| task shift8_out; | |
| begin | |
| casex(sh8out_state) | |
| sh8out_bit7: | |
| if(!scl) | |
| begin | |
| link_sda <=YES; | |
| link_write <=YES; | |
| sh8out_state <=sh8out_bit6; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit7; | |
| sh8out_bit6: | |
| if(!scl) | |
| begin | |
| link_sda <=YES; | |
| link_write <=YES; | |
| sh8out_state <=sh8out_bit5; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit6; | |
| sh8out_bit5: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_bit4; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit5; | |
| sh8out_bit4: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_bit3; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit4; | |
| sh8out_bit3: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_bit2; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit3; | |
| sh8out_bit2: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_bit1; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit2; | |
| sh8out_bit1: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_bit0; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit1; | |
| sh8out_bit0: | |
| if(!scl) | |
| begin | |
| sh8out_state <=sh8out_end; | |
| sh8out_buf <=sh8out_buf<<1; | |
| end | |
| else | |
| sh8out_state <=sh8out_bit0; | |
| sh8out_end: | |
| if(!scl) | |
| begin | |
| link_sda <=NO; | |
| link_write <=NO; | |
| ff <=1; | |
| end | |
| else | |
| sh8out_state <=sh8out_end; | |
| endcase | |
| end | |
| endtask | |
| //-------------输出启动信号任务------------------------------------------------- | |
| task shift_head; | |
| begin | |
| casex(head_state) | |
| head_begin: | |
| if(!scl) | |
| begin | |
| link_write <=NO; | |
| link_sda <=YES; | |
| link_head <=YES; | |
| head_state <=head_bit; | |
| end | |
| else | |
| head_state <=head_begin; | |
| head_bit: | |
| if(scl) | |
| begin | |
| ff <=1; | |
| head_buf <=head_buf<<1; | |
| head_state <=head_end; | |
| end | |
| else | |
| head_state <=head_bit; | |
| head_end: | |
| if(!scl) | |
| begin | |
| link_head <=NO; | |
| link_write <=YES; | |
| end | |
| else | |
| head_state <=head_end; | |
| endcase | |
| end | |
| endtask | |
| //--------------输出---------------------------------------------------- | |
| task shift_stop; | |
| begin | |
| casex(stop_state) | |
| stop_begin: if(!scl) | |
| begin | |
| link_sda <=YES; | |
| link_write <=NO; | |
| link_stop <=YES; | |
| stop_state <=stop_bit; | |
| end | |
| else | |
| stop_state <=stop_begin; | |
| stop_bit: if(scl) | |
| begin | |
| stop_buf <=stop_buf<<1; | |
| stop_state <=stop_end; | |
| end | |
| else | |
| stop_state <=stop_bit; | |
| stop_end: if(!scl) | |
| begin | |
| link_head <=NO; | |
| link_stop <=NO; | |
| link_sda <=NO; | |
| ff <=1; | |
| end | |
| else | |
| stop_state <=stop_end; | |
| endcase | |
| end | |
| endtask | |
| endmodule | |
| //------------------i2c_wr.v文件结束-------------------------------------------- | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment