📄 i2c_core.v
字号:
// ********************************************************************* //
// Filename: i2c_core.v //
// Projects: STiMi-Receiver //
// Author : XQ-Wang //
// Date : 2007-06-25 //
// Version : 1.0 //
// ********************************************************************* //
`timescale 1ns/1ps
module i2c_core(
SYS_CLK ,
RST ,
RD ,
WR ,
Chip_id ,
Addr ,
DATA_in ,
DTyp ,
DNum ,
DATA_out,
SCL ,
SDA_in ,
SDA_out ,
SDA_sel ,
ACK
);
input SYS_CLK ;
input RST ;
input RD ;
input WR ;
input [7:0] Chip_id ;
input [7:0] Addr ;
input [7:0] DATA_in ;
input [2:0] DTyp ;
input [7:0] DNum ;
input SDA_in ;
output [7:0] DATA_out ;
wire [7:0] DATA_out ;
output SCL ;
reg SCL ;
output SDA_out ;
wire SDA_out ;
output SDA_sel ;
wire SDA_sel ;
output ACK ;
wire ACK ;
//------------------------------------------------
reg WF,RF;
reg FF;
reg [7:0] chip_id_slave;
reg [7:0] addr_slave;
reg [7:0] data_to_slave;
reg [1:0] head_buf;
reg [1:0] stop_buf;
reg [8:0] sh8out_state;
reg [9:0] sh8in_state;
reg [2:0] head_state;
reg [2:0] stop_state;
reg [7:0] main_state; // 8 state
reg [7:0] sh8out_buf;
reg [7:0] data_from_slave;
reg link_sda;
reg link_read;
reg link_head;
reg link_write;
reg link_stop;
reg link_ack;
wire sda_out1,sda_out2,sda_out3,sda_out4;
reg [7:0] dnum_cnt;
reg [2:0] dtype;
reg [7:0] clk_cnt;
//--------------- Main state defination ---------
parameter Idea = 8'b00000001;
parameter Ready = 8'b00000010;
parameter Write_start = 8'b00000100;
parameter Write_chip_id = 8'b00001000;
parameter Write_addr = 8'b00010000;
parameter Write_data = 8'b00100000;
parameter Read_data = 8'b01000000;
parameter Stop = 8'b10000000;
//--------------Parallel data to serial----------
parameter sh8out_bit7 = 9'b000000001;
parameter sh8out_bit6 = 9'b000000010;
parameter sh8out_bit5 = 9'b000000100;
parameter sh8out_bit4 = 9'b000001000;
parameter sh8out_bit3 = 9'b000010000;
parameter sh8out_bit2 = 9'b000100000;
parameter sh8out_bit1 = 9'b001000000;
parameter sh8out_bit0 = 9'b010000000;
parameter sh8out_end = 9'b100000000;
//--------------Serial data to parallel----------
parameter sh8in_begin = 10'b0000000001;
parameter sh8in_bit7 = 10'b0000000010;
parameter sh8in_bit6 = 10'b0000000100;
parameter sh8in_bit5 = 10'b0000001000;
parameter sh8in_bit4 = 10'b0000010000;
parameter sh8in_bit3 = 10'b0000100000;
parameter sh8in_bit2 = 10'b0001000000;
parameter sh8in_bit1 = 10'b0010000000;
parameter sh8in_bit0 = 10'b0100000000;
parameter sh8in_end = 10'b1000000000;
//--------------Start state---------------------
parameter head_begin = 3'b001;
parameter head_bit = 3'b010;
parameter head_end = 3'b100;
//--------------Sotp state----------------------
parameter stop_begin = 3'b001;
parameter stop_bit = 3'b010;
parameter stop_end = 3'b100;
//--------------Parameter define----------------
parameter YES = 1'b1;
parameter NO = 1'b0;
//----------- Generate SCL ---------------------
parameter CLK_PERIOD = 8'b10010110; //60M/400K=150
always @(negedge SYS_CLK)
begin
if(RST)
begin
SCL <= 1'b1;
clk_cnt <= 8'b0;
end
else
begin
if(clk_cnt==CLK_PERIOD)
begin
SCL <= ~SCL;
clk_cnt <= 8'b00000001;
end
else if(clk_cnt==(CLK_PERIOD>>1))
begin
SCL <= ~SCL;
clk_cnt <= clk_cnt + 1;
end
else
clk_cnt <= clk_cnt + 1;
end
end
//---------------- Data Output -----------------
assign sda_out1 = (link_head) ? head_buf[1] : 1'b0;
assign sda_out2 = (link_write) ? sh8out_buf[7] : 1'b0;
assign sda_out3 = (link_stop) ? stop_buf[1] : 1'b0;
assign sda_out4 = (sda_out1 | sda_out2 | sda_out3);
assign SDA_out = (link_sda) ? sda_out4 : 1'b0;
assign DATA_out = (link_read) ? data_from_slave : 8'hzz;
assign ACK = (link_ack) ? SDA_in : 1'b1;
assign SDA_sel = link_ack;
//----------- Data Buf --------------------------
always @(posedge SYS_CLK, posedge RST)
begin
if(RST)
dtype <= 3'b000;
else if(WR || RD)
begin
dtype <= DTyp;
chip_id_slave <= Chip_id;
addr_slave <= Addr;
data_to_slave <= DATA_in;
end
end
//----------- Main FSM --------------------------
always @(posedge SYS_CLK, posedge RST)
begin
if(RST)
begin
link_read <= NO;
link_write <= NO;
link_head <= NO;
link_stop <= NO;
link_sda <= NO;
link_ack <= NO;
RF <= 1'b0;
WF <= 1'b0;
FF <= 1'b0;
main_state <= Idea;
dnum_cnt <= 8'b0;
// head_buf <= 2'b00;
// stop_buf <= 2'b00;
// sh8out_state <= 9'b0;
// sh8in_state <= 10'b0;
// head_state <= 3'b0;
// stop_state <= 3'b0;
// sh8out_buf <= 8'b0;
// data_from_slave <= 8'b0;
end
else if(clk_cnt==(CLK_PERIOD>>2) || clk_cnt==(CLK_PERIOD>>2)+(CLK_PERIOD>>1))
begin
case(main_state)
Idea: begin
link_read <= NO;
link_write <= NO;
link_head <= NO;
link_stop <= NO;
link_sda <= NO;
link_ack <= NO;
dnum_cnt <= DNum;
if(WR)
begin
WF <= 1'b1;
main_state <= Ready;
end
else if(RD)
begin
RF <= 1'b1;
main_state <= Ready;
end
else
begin
WF <= 1'b0;
RF <= 1'b0;
main_state <= Idea;
end
end
Ready: begin
link_head <= YES;
link_sda <= YES;
dnum_cnt <= DNum;
head_buf[1:0] <= 2'b10;
stop_buf[1:0] <= 2'b01;
head_state <= head_begin;
FF <= 1'b0;
main_state <= Write_start;
end
Write_start: begin
if(!FF)
shift_head;
else begin
link_sda <= YES;
link_head <= NO;
link_write <= YES;
FF <= 1'b0;
if(dtype[1:0]==2'b01)
begin
if(dnum_cnt==DNum)
begin
sh8out_buf[7:0] <= chip_id_slave;
sh8out_state <= sh8out_bit6;
main_state <= Write_chip_id;
end
else
begin
sh8out_buf[7:0] <= addr_slave;
sh8out_state <= sh8out_bit6;
main_state <= Write_addr;
end
end
else if(dtype[1:0]==2'b10)
begin
sh8out_buf[7:0] <= addr_slave;
sh8out_state <= sh8out_bit6;
main_state <= Write_addr ;
end
end
end
Write_chip_id:begin
if(!FF)
shift8_out;
else begin
if(!WR && !RD)
begin
link_read <= NO;
link_write <= NO;
link_head <= NO;
link_stop <= NO;
link_sda <= NO;
RF <= 1'b0;
WF <= 1'b0;
FF <= 1'b0;
main_state <= Idea;
dnum_cnt <= 8'b0;
end
else if(!SCL)
begin
link_sda <= YES;
link_write <= YES;
link_ack <= NO;
FF <= 1'b0;
main_state <= Write_addr;
sh8out_buf[7:0] <= addr_slave;
sh8out_state <= sh8out_bit6;
end
end
end
Write_addr: begin
if(!FF)
shift8_out;
else begin
if(!WR && !RD)
begin
link_read <= NO;
link_write <= NO;
link_head <= NO;
link_stop <= NO;
link_sda <= NO;
RF <= 1'b0;
WF <= 1'b0;
FF <= 1'b0;
main_state <= Idea;
dnum_cnt <= 8'b0;
end
else if(!SCL)
begin
link_sda <= YES;
link_ack <= NO;
FF <= 1'b0;
if(WF)
begin
link_write <= YES;
sh8out_buf[7:0] <= data_to_slave;
sh8out_state <= sh8out_bit6;
main_state <= Write_data;
end
else if(RF)
begin
link_read <= YES;
sh8in_state <= sh8in_begin;
main_state <= Read_data;
end
end
end
end
Write_data: begin
if(!FF)
shift8_out;
else begin
if(!SCL)
begin
link_sda <= YES;
link_ack <= NO;
FF <= 1'b0;
if(dnum_cnt==8'b0)
begin
link_stop <= YES;
stop_buf[1:0] <= 2'b01;
stop_state <= stop_bit;
main_state <=Stop;
end
else if(!dtype[2])
begin
link_head <= YES;
head_buf[1:0] <= 2'b10;
head_state <= head_begin;
main_state <= Write_start;
end
else if(dtype[2])
begin
link_write <= YES;
sh8out_buf[7:0] <= data_to_slave;
sh8out_state <= sh8out_bit6;
main_state <= Write_data;
end
end
end
end
Read_data: begin
if(!FF)
shift8_in;
else begin
link_sda <= YES;
link_ack <= NO ;
FF <= 1'b0;
if(dnum_cnt==8'b0)
begin
link_stop <= YES;
stop_buf[1:0] <= 2'b01;
stop_state <= stop_bit;
main_state <=Stop;
end
else if(!dtype[2])
begin
link_head <= YES;
head_buf[1:0] <= 2'b10;
head_state <= head_begin;
main_state <= Write_start;
end
else if(dtype[2])
begin
link_read <= YES;
sh8in_state <= sh8in_begin;
main_state <= Read_data;
end
end
end
Stop: begin
if(!FF)
shift_stop;
else
begin
link_stop <= NO;
link_sda <= NO;
WF <= 1'b0;
RF <= 1'b0;
main_state <= Idea;
end
end
default: main_state <= Idea;
endcase
end
end
//-----------------------------------------------
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'b1;
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'b1;
end
else
stop_state <= stop_end;
endcase
end
endtask
//-----------------------------------------------
task shift8_in;
begin
casex(sh8in_state)
sh8in_begin:
sh8in_state <= sh8in_bit7;
sh8in_bit7: begin
if(SCL)
begin
data_from_slave[7] <= SDA_in;
sh8in_state <= sh8in_bit6;
end
else
sh8in_state <= sh8in_bit7;
end
sh8in_bit6: begin
if(SCL)
begin
data_from_slave[6] <= SDA_in;
sh8in_state <= sh8in_bit5;
end
else
sh8in_state <=sh8in_bit6;
end
sh8in_bit5: begin
if(SCL)
begin
data_from_slave[5] <= SDA_in;
sh8in_state <= sh8in_bit4;
end
else
sh8in_state <= sh8in_bit5;
end
sh8in_bit4: begin
if(SCL)
begin
data_from_slave[4] <= SDA_in;
sh8in_state <= sh8in_bit3;
end
else
sh8in_state <= sh8in_bit4;
end
sh8in_bit3: begin
if(SCL)
begin
data_from_slave[3] <= SDA_in;
sh8in_state <= sh8in_bit2;
end
else
sh8in_state <= sh8in_bit3;
end
sh8in_bit2: begin
if(SCL)
begin
data_from_slave[2] <= SDA_in;
sh8in_state <= sh8in_bit1;
end
else
sh8in_state <= sh8in_bit2;
end
sh8in_bit1: begin
if(SCL)
begin
data_from_slave[1] <= SDA_in;
sh8in_state <= sh8in_bit0;
end
else
sh8in_state <= sh8in_bit1;
end
sh8in_bit0: begin
if(SCL)
begin
data_from_slave[0] <= SDA_in;
sh8in_state <= sh8in_end;
end
else
sh8in_state <= sh8in_bit0;
end
sh8in_end: begin
if(SCL)
begin
link_read <= YES;
link_ack <= YES;
FF <= 1'b1;
sh8in_state <= sh8in_bit7;
if(main_state==Read_data)
dnum_cnt <= dnum_cnt - 1;
end
else
sh8in_state <= sh8in_end;
end
default: begin
link_read <= NO;
sh8in_state <= sh8in_bit7;
end
endcase
end
endtask
//-----------------------------------------------
task shift8_out;
begin
casex(sh8out_state)
sh8out_bit7:
begin
if(!SCL)
begin
link_sda <= YES;
link_write <= YES;
sh8out_state <= sh8out_bit6;
end
else
sh8out_state <= sh8out_bit7;
end
sh8out_bit6:
begin
if(!SCL)
begin
link_sda <= YES;
link_write <= YES;
sh8out_state <= sh8out_bit5;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit6;
end
sh8out_bit5:
begin
if(!SCL)
begin
sh8out_state <= sh8out_bit4;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit5;
end
sh8out_bit4:
begin
if(!SCL)
begin
sh8out_state <= sh8out_bit3;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit4;
end
sh8out_bit3:
begin
if(!SCL)
begin
sh8out_state <= sh8out_bit2;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit3;
end
sh8out_bit2:
begin
if(!SCL)
begin
sh8out_state <= sh8out_bit1;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit2;
end
sh8out_bit1:
begin
if(!SCL)
begin
sh8out_state <= sh8out_bit0;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit1;
end
sh8out_bit0:
begin
if(!SCL)
begin
sh8out_state <= sh8out_end;
sh8out_buf <= sh8out_buf<<1;
end
else
sh8out_state <= sh8out_bit0;
end
sh8out_end:
if(!SCL)
begin
link_sda <= NO;
link_write <= NO;
link_ack <= YES;
FF <= 1'b1;
if(main_state==Write_data)
dnum_cnt <= dnum_cnt - 1;
end
else
sh8out_state <= sh8out_end;
endcase
end
endtask
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -