📄 i2c_st.v
字号:
//----------------------------------------------------------------------------
//
// Name: i2c_st.v
//
// Description: Statemachine module of the I2C serial controller
//
// $Revision: 1.0 $
//
// Copyright 2004 Lattice Semiconductor Corporation. All rights reserved.
//
//----------------------------------------------------------------------------
// Permission:
//
// Lattice Semiconductor grants permission to use this code for use
// in synthesis for any Lattice programmable logic product. Other
// use of this code, including the selling or duplication of any
// portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL or Verilog source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. Lattice Semiconductor provides no warranty
// regarding the use or functionality of this code.
//----------------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97124
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 408-826-6000 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
//----------------------------------------------------------------------------
`timescale 1 ns / 100 ps
/*
This module provides the state machine for the I2C interface.
*/
module i2c_st( rst_l,
clock,
scl_tick,
i2c_go,
wrd_add,
sda_pin,
sda,
scl,
scl_cnt_en,
i2c_rdy,
i2c_act,
i2c_rdata,
ack_err);
//-------------------------------------------------------------------
// port list
input rst_l; // reset
input clock; // mpu clock
input scl_tick; // 5 usec clock tick
input i2c_go; // start i2c cycle
input [7:0] wrd_add; // i2c address
input sda_pin; // i2c data muxed input
output sda; // i2c data
output scl; // i2c clock
output scl_cnt_en; // scl cntr enable
output i2c_rdy; // i2c ready
output i2c_act; // i2c cycle active
output [7:0] i2c_rdata; // i2c read data
output ack_err; // ack error
//-------------------------------------------------------------------
// 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
/*
parameter idle = 4'b0000; // state 0
parameter en_clk = 4'b0001; // state 1
parameter start1 = 4'b1100; // state C
parameter dev_add1 = 4'b1000; // state 8
parameter ack1 = 4'b0100; // state 4
parameter w_add = 4'b1010; // state A
parameter ack2 = 4'b0101; // state 5
parameter w_data1 = 4'b0011; // state 3
parameter ack3 = 4'b1111; // state F
parameter w_data2 = 4'b1101; // state D
parameter ack4 = 4'b1001; // state 9
parameter stop1 = 4'b1110; // state E
*/
/*
parameter wait1 = 4'b0011; // state 3
parameter dis_clk1 = 4'b1111; // state F
parameter start2 = 4'b1101; // state D
parameter dev_add2 = 4'b1001; // state 9
parameter ack3 = 4'b0110; // state 6
parameter data = 4'b1011; // state B
parameter ack4 = 4'b0111; // state 7
parameter stop1 = 4'b1110; // state E
*/
//-------------------------------------------------------------------
// 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;
$display($time,": finish stop1");
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 read wirte addr");
i2c_state <= #1 dev_add2;
end
dev_add2 : if (cntr_done && scl_tick)
i2c_state <= #1 ack5;
ack5 : if (scl_tick && scl)
begin
$display($time,": start read wirte adds");
i2c_state <= #1 w_add2;
end
w_add2 : if (cntr_done && scl_tick)
i2c_state <= #1 ack6;
ack6 : if (scl_tick && scl)
i2c_state <= #1 dis_clk2;
dis_clk2 : if (scl_tick && scl)
i2c_state <= #1 wait2;
wait2 : if (scl_tick)
begin
$display($time,": read statr3");
i2c_state <= #1 start3;
end
start3 : if (scl_tick)
i2c_state <= #1 dev_add3;
dev_add3 : if (cntr_done && scl_tick)
begin
$display($time,": start read read adta");
i2c_state <= #1 ack7;
end
ack7 : if (scl_tick && scl)
i2c_state <= #1 r_data1;
r_data1 : if (cntr_done && scl_tick)
i2c_state <= #1 ack8;
ack8 : if (scl_tick && scl)
begin
$display($time,": start rea222222222");
i2c_state <= #1 stop2;
end
stop2 : if (scl_tick && scl)
i2c_state <= #1 dis_clk1;
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 == r_data1)) // word address
// sda <= #1 wrd_add1[bit_cntr];
//else if((i2c_state == r_data2)) // word address
// sda <= #1 wrd_add2[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'b0;
else if (( (i2c_state == r_data1) ||(i2c_state == r_data2) ) && scl)
i2c_rdata[bit_cntr] <= #1 sda_pin;
else if (i2c_go)
i2c_rdata <= #1 8'b0;
always @(posedge clock or negedge rst_l)
if (!rst_l)
i2c_rdy <= #1 1'b0;
else if ((i2c_state == stop1) && scl)
i2c_rdy <= #1 1'b1;
else if ((i2c_state == stop2) && scl)
i2c_rdy <= #1 1'b1;
else if (i2c_go)
i2c_rdy <= #1 1'b0;
always @(posedge clock or negedge rst_l)
if (!rst_l)
ack_err <= #1 1'b0;
else if (((i2c_state == ack1) ||
(i2c_state == ack2) ||
(i2c_state == ack3) ||
(i2c_state == ack4) ||
(i2c_state == ack5) ||
(i2c_state == ack6) ||
(i2c_state == ack7)
//(i2c_state == ack8)
) && scl && sda_pin)
ack_err <= #1 1'b1;
else if (i2c_go)
ack_err <= #1 1'b0;
assign i2c_act = ~(i2c_state == idle);
endmodule
//------------------------------- E O F --------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -