📄 i2c_st.v
字号:
module i2c_st( rst_l,
clock,
scl_tick,
sda_pin,
sda,
scl,
scl_cnt_en,
i2c_rdata
);
//-------------------------------------------------------------------
// port list
input rst_l; // reset
input clock; // mpu clock
input scl_tick; // 5 usec clock tick
input sda_pin; // i2c data muxed input
output sda; // i2c data
output scl; // i2c clock
output scl_cnt_en; // scl cntr enable
output [7:0] i2c_rdata; // i2c read data
//-------------------------------------------------------------------
// registers
reg sda;
reg scl;
reg scl_cnt_en;
reg i2c_rdy;
reg [7:0] i2c_rdata;
reg [4:0] i2c_state;
reg [2:0] bit_cntr;
reg scl_en;
reg en_cntr;
reg cntr_done;
reg ack_err;
wire i2c_act;
//-------------------------------------------------------------------
// parameters
parameter idle = 5'b00000; // state 0
parameter en_clk = 5'b00001; // state 1
parameter start1 = 5'b00010; // state 2
parameter dev_add1 = 5'b00011; // state 3
parameter ack1 = 5'b00100; // state 4
parameter w_add = 5'b00101; // state 5
parameter ack2 = 5'b00110; // state 6
parameter w_data1 = 5'b00111; // state 7
parameter ack3 = 5'b01000; // state 8
parameter w_data2 = 5'b01001; // state 9
parameter ack4 = 5'b01010; // state 10
parameter dis_clk1 = 5'b01011; // state 11
parameter wait1 = 5'b01100; // state 12
parameter start2 = 5'b01101; // state 13
parameter dev_add2 = 5'b01110; // state 14
parameter ack5 = 5'b01111; // state 15
parameter w_add2 = 5'b10000; // state 16
parameter ack6 = 5'b10001; // state 17
parameter dis_clk2 = 5'b10010; // state 18
parameter wait2 = 5'b10011; // state 19
parameter start3 = 5'b10100; // state 20
parameter dev_add3 = 5'b10101; // state 21
parameter ack7 = 5'b10110; // state 22
parameter r_data1 = 5'b10111; // state 23
parameter ack8 = 5'b11000; // state 24
parameter r_data2 = 5'b11001; // state 25
parameter ack9 = 5'b11010; // state 26
parameter stop1 = 5'b11011; // state 27
parameter stop2 = 5'b11100; // state 27
//-------------------------------------------------------------------
// state machine
wire [7:0] wrd_add3 = 8'b10010001;
//wire [7:0] wrd_add3 = 8'b0000001;
wire [7:0] wrd_add1 = 8'h62;
wire [7:0] wrd_add2 = 8'h62;
reg [2000:0] i;
always @(posedge clock or negedge rst_l)
if (!rst_l)
begin
i2c_state <= #1 idle;
i <= 0;
end
else case(i2c_state)
idle :
i2c_state <= #1 en_clk;
en_clk : if (scl_tick)
i2c_state <= #1 start1;
start1 : if (scl_tick)
i2c_state <= #1 dev_add1;
dev_add1 : if (cntr_done && scl_tick)
i2c_state <= #1 ack1;
ack1 : if (scl_tick && scl)
i2c_state <= #1 w_add;
w_add : if (cntr_done && scl_tick)
i2c_state <= #1 ack2;
ack2 : if (scl_tick && scl)
i2c_state <= #1 w_data1;
w_data1 : if (cntr_done && scl_tick)
i2c_state <= #1 ack3;
ack3 : if (scl_tick && scl)
i2c_state <= #1 w_data2;
w_data2 : if (cntr_done && scl_tick)
i2c_state <= #1 ack4;
ack4 : if (scl_tick && scl)
begin
i2c_state <= #1 stop1;
$display($time,": finish write");
end
stop1 : if (scl_tick && scl)
begin
i2c_state <= #1 dis_clk1;
end
dis_clk1 : if (scl_tick && scl)
i2c_state <= #1 wait1;
wait1 : if (scl_tick)
i2c_state <= #1 start2;
start2 : if (scl_tick)
begin
$display($time,": start wirte dev addr");
i2c_state <= #1 dev_add2;
end
dev_add2 : if (cntr_done && scl_tick)
i2c_state <= #1 ack5;
ack5 : if (scl_tick && scl)
i2c_state <= #1 w_add2;
w_add2 : if (cntr_done && scl_tick)
begin
i2c_state <= #1 ack6;
$display($time,": start wirte eeprom data addr");
end
ack6 : if (scl_tick && scl)
i2c_state <= #1 dis_clk2;
dis_clk2 : if (scl_tick && scl)
i2c_state <= #1 wait2;
wait2 : if (scl_tick)
i2c_state <= #1 start3;
start3 : if (scl_tick)
i2c_state <= #1 dev_add3;
dev_add3 : if (cntr_done && scl_tick)
begin
$display($time,": start wirte dev addr");
i2c_state <= #1 ack7;
end
ack7 : if (scl_tick && scl)
i2c_state <= #1 r_data1;
r_data1 : if (cntr_done && scl_tick)
begin
$display($time,": start read comm");
i2c_state <= #1 ack8;
end
ack8 : if (scl_tick && scl)
i2c_state <= #1 stop2;
stop2 : if (scl_tick && scl)
i2c_state <= #1 stop2;
default :
i2c_state <= #1 stop2;
endcase
//-------------------------------------------------------------------
// bit counter
always @(posedge clock or negedge rst_l)
if (!rst_l)
bit_cntr <= #1 3'b111;
else if (en_cntr && scl && scl_tick)
bit_cntr <= #1 bit_cntr - 1;
always @(posedge clock or negedge rst_l)
if (!rst_l)
cntr_done <= #1 1'b0;
else if (bit_cntr == 3'b0 && scl)
cntr_done <= #1 1'b1;
else
cntr_done <= #1 1'b0;
always @(posedge clock or negedge rst_l)
if (!rst_l)
en_cntr <= #1 1'b0;
else if ((i2c_state == dev_add1) ||
(i2c_state == w_add) ||
(i2c_state == w_add2) ||
(i2c_state == dev_add2) ||
(i2c_state == dev_add3) ||
(i2c_state == w_data1) ||
(i2c_state == w_data2) ||
(i2c_state == r_data1) ||
(i2c_state == r_data2)
)
en_cntr <= #1 1'b1;
else if (cntr_done)
en_cntr <= #1 1'b0;
//-------------------------------------------------------------------
// scl generation
// enable clock divider
always @(posedge clock or negedge rst_l)
if (!rst_l)
scl_cnt_en <= #1 1'b0;
else if (i2c_state == en_clk)
scl_cnt_en <= #1 1'b1;
else if (i2c_state == idle)
scl_cnt_en <= #1 1'b0;
// enables tick divider
always @(posedge clock or negedge rst_l)
if (!rst_l)
scl_en <= #1 1'b0;
else if (i2c_state == start1)
scl_en <= #1 1'b1;
else if (i2c_state == dis_clk1 && scl_tick)
scl_en <= #1 1'b0;
else if (i2c_state == dis_clk2 && scl_tick)
scl_en <= #1 1'b0;
else if (i2c_state == start2)
scl_en <= #1 1'b1;
else if (i2c_state == start3)
scl_en <= #1 1'b1;
else if (i2c_state == stop1 && scl)
scl_en <= #1 1'b0;
else if (i2c_state == stop2 && scl)
scl_en <= #1 1'b0;
// tick divider
always @(posedge clock or negedge rst_l)
if (!rst_l)
scl <= #1 1'b1;
else if (scl_en && scl_tick)
scl <= #1 ~scl;
//-------------------------------------------------------------------
// sda generation
always @(posedge clock or negedge rst_l)
if (!rst_l)
sda <= #1 1'b1;
else if (
(i2c_state == start1) || // starts
(i2c_state == start2) ||
(i2c_state == start3) ||
(i2c_state == stop1) ||
(i2c_state == stop2) ||
((i2c_state == dev_add1) && // write address
(bit_cntr != 3'b111) && // device bit 7
(bit_cntr != 3'b101)) || // device bit 5
((i2c_state == dev_add2) && // write address
(bit_cntr != 3'b111) && // device bit 7
(bit_cntr != 3'b101)) || // device bit 5
((i2c_state == dev_add3) && // read address
(bit_cntr != 3'b111) && // device bit 7
(bit_cntr != 3'b101) && // device bit 5
(bit_cntr != 3'b000))) // read bit
sda <= #1 1'b0;
else if((i2c_state == w_add)) // word address
sda <= #1 wrd_add3[bit_cntr];
else if((i2c_state == w_data1)) // word address
sda <= #1 wrd_add1[bit_cntr];
else if((i2c_state == w_data2)) // word address
sda <= #1 wrd_add2[bit_cntr];
else if((i2c_state == w_add2)) // word address
sda <= #1 wrd_add3[bit_cntr];
else if((i2c_state == ack8)) // word address
sda <= #1 1'b1;
else
sda <= #1 1'b1;
always @(posedge clock or negedge rst_l)
if (!rst_l)
i2c_rdata <= #1 8'b00001111;
else if (( (i2c_state == r_data1) ||(i2c_state == r_data2) ) && scl)
i2c_rdata[bit_cntr] <= #1 sda_pin;
assign i2c_act = ~(i2c_state == idle);
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -