📄 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 [3: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 = 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 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
always @(posedge clock or negedge rst_l)
if (!rst_l)
i2c_state <= #1 idle;
else case(i2c_state)
idle : if (i2c_go)
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 dis_clk1;
dis_clk1 : if (scl_tick && scl)
i2c_state <= #1 wait1;
wait1 : if (scl_tick)
i2c_state <= #1 start2;
start2 : if (scl_tick)
i2c_state <= #1 dev_add2;
dev_add2 : if (cntr_done && scl_tick)
i2c_state <= #1 ack3;
ack3 : if (scl_tick && scl)
i2c_state <= #1 data;
data : if (cntr_done && scl_tick)
i2c_state <= #1 ack4;
ack4 : if (scl_tick && scl)
i2c_state <= #1 stop1;
stop1 : if (scl_tick && scl)
i2c_state <= #1 idle;
default :
i2c_state <= #1 idle;
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 == dev_add2) ||
(i2c_state == data))
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 == start2)
scl_en <= #1 1'b1;
else if (i2c_state == stop1 && 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 == stop1) ||
((i2c_state == dev_add1) && // write address
(bit_cntr != 3'b111) && // device bit 7
(bit_cntr != 3'b101)) || // device bit 5
((i2c_state == dev_add2) && // 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_add[bit_cntr];
else
sda <= #1 1'b1;
always @(posedge clock or negedge rst_l)
if (!rst_l)
i2c_rdata <= #1 8'b0;
else if ((i2c_state == data) && 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_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)) && 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 + -