Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Dimitris Lampridis
VFC-HD
Commits
3a8c6a9d
Commit
3a8c6a9d
authored
Feb 05, 2016
by
unknown
Browse files
new module for the control of the I2C mux and expanders
parent
5fcddb19
Changes
2
Hide whitespace changes
Inline
Side-by-side
Hdl/FpgaModules/SystemSpecific/I2cMuxAndExpMaster.v
0 → 100644
View file @
3a8c6a9d
//============================================================================================\\
//################################## Module Information ##################################\\
//============================================================================================\\
//
// Company: CERN (BE-BI)
//
// File Name: I2cExpAndMuxMaster.v
//
// File versions history:
//
// DATE VERSION AUTHOR DESCRIPTION
// - <date> <version> Andrea Boccardi <description>
//
// Language: Verilog 2005
//
// Description:
//
// The requests are level sensitive and accepted when the module is not busy.
//
//============================================================================================\\
//############################################################################################\\
//============================================================================================\\
`timescale
1
ns
/
100
ps
module
I2cExpAndMuxMaster
//==================================== Global Parameters ===================================\\
#(
parameter
g_SclHalfPeriod
=
10'd256
)
//======================================== I/O ports =======================================\\
(
//==== Clocks & Resets ====\\
input
Clk_ik
,
input
Rst_irq
,
//==== Status and Requests====\\
output
reg
Busy_o
,
input
IoExpWrReq_i
,
input
IoExpRdReq_i
,
input
I2cMuxEnChReq_i
,
input
I2cMuxIntRdReq_i
,
input
FifoAccessReq_i
,
output
reg
IoExpWrOn_oq
,
output
reg
IoExpRdOn_oq
,
output
reg
I2cEnChOn_oq
,
output
reg
I2cMuxRdIntOn_oq
,
output
reg
FifoAccessOn_oq
,
output
reg
NewByteRead_op
,
output
reg
[
7
:
0
]
ByteOut_ob8
,
output
reg
AckError_op
,
// IO Expanders parameters:
input
[
2
:
0
]
IoExpAddr_i
,
input
[
1
:
0
]
IoExpRegAddr_ib2
,
input
[
7
:
0
]
IoExpData_ib8
,
// I2C Mux parameters:
input
I2cMuxAddress_i
,
input
[
1
:
0
]
I2cMuxChannel_ib2
,
// FIFO access programming interface:
output
FifoFull_o
,
output
FifoEmpty_o
,
input
[
10
:
0
]
FifoCommand_ib11
,
input
FifoCommandWr_i
,
output
reg
FifoWriteDone_op
,
output
reg
FifoWriteAck_o
,
output
reg
FifoReadDone_op
,
output
reg
[
7
:
0
]
FifoByteRead_ob8
,
//==== I2C Bus ====\\
inout
Scl_ioz
,
inout
Sda_ioz
);
//======================================= Declarations =====================================\\
//==== Local parameters ====\\
// FSM:
localparam
s_Idle
=
4'h0
,
s_FetchCommand
=
4'h1
,
s_StartExecution
=
4'h2
,
s_StartSda1
=
4'h3
,
s_StartScl1
=
4'h4
,
s_StartSda0
=
4'h5
,
s_StartScl0
=
4'h6
,
s_SendScl0
=
4'h7
,
s_SendScl1
=
4'h8
,
s_GetScl0
=
4'h9
,
s_GetScl1
=
4'ha
,
s_StopSda0
=
4'hb
,
s_StopScl1
=
4'ha
,
s_StopSda1
=
4'hb
;
// Command sequence ROM:
localparam
c_IoExpWriteSeq
=
3'd0
,
c_IoExpReadSeq
=
3'd1
,
c_I2cMuxIntReadSeq
=
3'd2
,
c_I2cMuxEnChSeq
=
3'd3
,
c_FifoSeq
=
3'd4
;
// Commands:
localparam
c_SendStartBit
=
3'd1
,
c_SendStopBit
=
3'd2
,
c_SendByte
=
3'd3
,
c_GetByte
=
3'd4
,
c_GoToIdle
=
3'b0
;
//Comment: required also in FIFO mode to close stop the transaction
//==== Wires & Regs ====\\
// FSM
reg
[
3
:
0
]
State_qb4
,
NextState_ab4
;
wire
AnyRequest_a
=
IoExpWrReq_i
||
IoExpRdReq_i
||
I2cMuxIntRdReq_i
||
I2cMuxEnChReq_i
||
FifoAccessReq_i
;
// Support Logic
reg
[
2
:
0
]
Command_b3
;
reg
[
9
:
0
]
SclCounter_c10
;
reg
[
3
:
0
]
BitCounter_c4
;
reg
SclOe_e
,
SdaOe_e
;
reg
I2CAck
;
reg
[
7
:
0
]
ShReg_b8
;
reg
[
2
:
0
]
ActiveSequence_b3
;
// FIFO connections
wire
[
10
:
0
]
FifoDout_b11
;
reg
FifoRead
;
// Command Sequences
reg
[
2
:
0
]
IoExpAddr_qb3
;
reg
[
1
:
0
]
IoExpRegAddr_qb2
;
reg
[
7
:
0
]
IoExpData_qb8
;
reg
[
10
:
0
]
IoExpWriteSeq_b11
,
IoExpReadSeq_b11
;
reg
I2cMuxAddress_q
;
reg
[
1
:
0
]
I2cMuxChannel_qb2
;
reg
[
10
:
0
]
I2cMuxReadSeq_b11
,
I2cMuxEnChSeq_b11
;
//======================================= User Logic =======================================\\
//==== I2C command's sequences ====\\
always
@
(
posedge
Clk_ik
)
if
(
~
Busy_o
&&
(
IoExpWrReq_i
||
IoExpRdReq_i
))
begin
IoExpAddr_qb3
<=
#
1
IoExpAddr_ib3
;
IoExpRegAddr_qb2
<=
#
1
IoExpRegAddr_ib2
;
IoExpData_qb8
<=
#
1
IoExpData_ib8
;
end
always
@
(
posedge
Clk_ik
)
if
(
~
Busy_o
&&
(
I2cMuxIntRdReq_i
||
I2cMuxEnChReq_i
))
begin
I2cMuxAddress_q
<=
#
1
I2cMuxAddress_i
;
I2cMuxChannel_qb2
<=
#
1
I2cMuxChannel_ib2
;
end
// Writing a value in a register of one IO expander
always
@
(
posedge
Clk_ik
)
case
(
CommandPointer_b4
)
4'd0
:
IoExpWriteSeq_b11
<=
#
1
{
c_SendStartBit
,
8'h0
}
;
4'd1
:
IoExpWriteSeq_b11
<=
#
1
{
c_SendByte
,
4'b0100
,
IoExpAddr_qb3
,
1'b0
}
;
//Comment: Selection of the Slave in write mode
4'd2
:
IoExpWriteSeq_b11
<=
#
1
{
c_SendByte
,
6'b0
,
IoExpRegAddr_qb2
}
;
//Comment: Writing the Register address
4'd3
:
IoExpWriteSeq_b11
<=
#
1
{
c_SendByte
,
IoExpData_qb8
}
;
//Comment: Writing the Register Value
4'd4
:
IoExpWriteSeq_b11
<=
#
1
{
c_SendStopBit
,
8'h0
}
;
default:
IoExpWriteSeq_b11
<=
#
1
{
c_GoToIdle
,
8'h0
}
;
// Reading a value from a register of one IO expander
always
@
(
posedge
Clk_ik
)
case
(
CommandPointer_b4
)
4'd0
:
IoExpReadSeq_b11
<=
#
1
{
c_SendStartBit
,
8'h0
}
;
4'd1
:
IoExpReadSeq_b11
<=
#
1
{
c_SendByte
,
4'b0100
,
IoExpAddr_qb3
,
1'b0
}
;
//Comment: Selection of the Slave in write mode
4'd2
:
IoExpReadSeq_b11
<=
#
1
{
c_SendByte
,
6'b0
,
IoExpRegAddr_qb2
}
;
//Comment: Writing the Register address
4'd3
:
IoExpReadSeq_b11
<=
#
1
{
c_SendStartBit
,
8'h0
}
;
//Comment: Repeated start (new cycle)
4'd4
:
IoExpReadSeq_b11
<=
#
1
{
c_SendByte
,
4'b0100
,
IoExpAddr_qb3
,
1'b1
}
;
//Comment: Selection of the Slave in read mode
4'd5
:
IoExpReadSeq_b11
<=
#
1
{
c_GetByte
,
8
h1
}
;
//Comment: Read of the last Byte (single read)
4'd6
:
IoExpReadSeq_b11
<=
#
1
{
c_SendStopBit
,
8'h0
}
;
default:
IoExpReadSeq_b11
<=
#
1
{
c_GoToIdle
,
8'h0
}
;
// Reading the value of the interrupt and configuration status of one I2C mux
always
@
(
posedge
Clk_ik
)
case
(
CommandPointer_b4
)
4'd0
:
I2cMuxReadSeq_b11
=
{
c_SendStartBit
,
8'h0
}
;
4'd1
:
I2cMuxReadSeq_b11
=
{
c_SendByte
,
6'h38
,
I2cMuxAddress_q
,
1'b1
}
;
//Comment: Selection of the Slave in read mode
4'd2
:
I2cMuxReadSeq_b11
=
{
c_GetByte
,
8
h1
}
;
//Comment: Read of the last Byte (single read)
4'd3
:
I2cMuxReadSeq_b11
=
{
c_SendStopBit
,
8'h0
}
;
default:
I2cMuxReadSeq_b11
=
{
c_GoToIdle
,
8'h0
}
;
// Enabling one channel of a I2C mux (and disabling all the others)
always
@
(
posedge
Clk_ik
)
case
(
CommandPointer_b4
)
4'd0
:
I2cMuxEnChSeq_b11
=
{
c_SendStartBit
,
8'h0
}
;
4'd1
:
I2cMuxEnChSeq_b11
=
{
c_SendByte
,
6'h38
,
~
I2cMuxAddress_q
,
1'b0
}
;
//Comment: Selection of the other Slave in Write mode
4'd2
:
I2cMuxEnChSeq_b11
=
{
c_SendByte
,
5'b0
,
3'b0
}
;
//Comment: Disabling all channels
4'd3
:
I2cMuxEnChSeq_b11
=
{
c_SendStopBit
,
8'h0
}
;
4'd4
:
I2cMuxEnChSeq_b11
=
{
c_SendStartBit
,
8'h0
}
;
4'd5
:
I2cMuxEnChSeq_b11
=
{
c_SendByte
,
6'h38
,
I2cMuxAddress_q
,
1'b0
}
;
//Comment: Selection of the other Slave in Write mode
4'd6
:
I2cMuxEnChSeq_b11
=
{
c_SendByte
,
5'b0
,
1'b1
,
I2cMuxChannel_qb2
}
;
//Comment: Enabling the desired channel
4'd7
:
I2cMuxEnChSeq_b11
=
{
c_SendStopBit
,
8'h0
}
;
default:
I2cMuxEnChSeq_b11
=
{
c_GoToIdle
,
8'h0
}
;
// User custom sequence (always to be closed by a back to idle command!)
generic_fifo_dc_gray
#(.
dw
(
11
),
.
aw
(
4
))
i_CommandFifo
(
.
rd_clk
(
Clk_ik
),
.
wr_clk
(
Clk_ik
),
.
rst
(
1'b1
),
.
clr
(
Rst_irq
),
.
din
(
FifoCommand_ib11
),
.
we
(
FifoCommandWr_i
),
.
dout
(
FifoDout_b11
),
.
re
(
FifoRead
),
.
full
(
FifoFull_o
),
.
empty
(
FifoEmpty_o
));
//==== State Machine ====\\
always
@
(
posedge
Clk_ik
)
State_qb4
<=
#
1
Rst_irq
?
s_Idle
:
NextState_ab4
;
always
@*
begin
NextState_ab4
=
State_qb4
;
case
(
State_qb4
)
// Waiting for a request
s_Idle:
if
(
AnyRequest_a
)
NextState_ab4
=
s_FetchCommand
;
// Fetching and decoding the command
s_FetchCommand:
if
(
~
FifoEmpty_o
||
ActiveSequence_b3
!=
c_FifoSeq
)
NextState_ab4
=
s_StartExecution
;
s_StartExecution:
if
(
Command_b3
==
c_SendStartBit
)
NextState_ab4
=
s_StartSda1
;
else
if
(
Command_b3
==
c_SendByte
)
NextState_ab4
=
s_SendScl0
;
else
if
(
Command_b3
==
c_GetByte
)
NextState_ab4
=
s_GetScl0
;
else
if
(
Command_b3
==
c_SendStopBit
)
NextState_ab4
=
s_StopSda0
,
else
if
(
Command_b3
==
c_GoToIdle
)
NextState_ab4
=
s_Idle
;
// Start bit sequence
s_StartSda1:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_StartScl1
;
s_StartScl1:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_StartSda0
;
s_StartSda0:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_StartScl0
;
s_StartScl0:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_FetchCommand
;
// Byte sending sequence
s_SendScl0:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
(
BitCounter_c4
==
4'd9
)
?
s_FetchCommand
:
s_SendScl1
;
s_SendScl1:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_SendScl0
;
// Byte getting sequence
s_GetScl0
:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
(
BitCounter_c4
==
4'd9
)
?
s_FetchCommand
:
s_GetScl1
;
s_GetScl1
:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_GetScl0
;
// Stop bit sequence
s_StopSda0:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_StopScl1
;
s_StopScl1:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_StopSda1
;
s_StopSda1:
if
(
SclCounter_c10
==
g_SclHalfPeriod
)
NextState_ab4
=
s_FetchCommand
;
// Protection from bad state condition
default:
NextState_ab4
=
s_Idle
;
endcase
end
always
@
(
posedge
Clk_ik
)
begin
// Default assignments
Busy_o
<=
#
1
NextState_ab4
!=
s_Idle
;
IoExpWrOn_oq
<=
#
1
Busy_o
&&
ActiveSequence_b3
==
c_IoExpWriteSeq
;
IoExpRdOn_oq
<=
#
1
Busy_o
&&
ActiveSequence_b3
==
c_IoExpReadSeq
;
I2cEnChOn_oq
<=
#
1
Busy_o
&&
ActiveSequence_b3
==
c_I2cMuxIntReadSeq
;
I2cMuxRdIntOn_oq
<=
#
1
Busy_o
&&
ActiveSequence_b3
==
c_I2cMuxEnChSeq
;
FifoAccessOn_oq
<=
#
1
Busy_o
&&
ActiveSequence_b3
==
c_FifoSeq
;
SclOe_e
<=
#
1
1'b0
;
SdaOe_e
<=
#
1
1'b0
;
I2cMuxWriteDone_op
<=
#
1
1'b0
;
I2cMuxReadDone_op
<=
#
1
1'b0
;
IoExpWriteDone_op
<=
#
1
1'b0
;
IoExpReadDone_op
<=
#
1
1'b0
;
FifoWriteDone_op
<=
#
1
1'b0
;
FifoReadDone_op
<=
#
1
1'b0
;
FifoRead
<=
#
1
1'b0
;
NewByteRead_op
<=
#
1
1'b0
;
AckError_op
<=
#
1
1'b0
;
// Reset conditions (if different from default)
if
(
Rst_irq
)
begin
BitCounter_c4
<=
#
1
4'b0
;
SclCounter_c10
<=
#
1
10'b0
;
I2CAck
<=
#
1
1'b0
;
ShReg_b8
<=
#
1
8'b0
;
Command_b3
<=
#
1
3'b0
;
I2cMuxWriteAck_o
<=
#
1
1'b0
;
I2cMuxByteRead_ob8
<=
#
1
8'b0
;
IoExpWriteAck_o
<=
#
1
1'b0
;
IoExpByteRead_ob8
<=
#
1
8'b0
;
FifoWriteAck_o
<=
#
1
1'b0
;
FifoByteRead_ob8
<=
#
1
8'b0
;
Busy_o
<=
#
1
1'b1
;
CommandPointer_b4
<=
#
1
4'h0
;
ActiveSequence_b3
<=
#
1
3'b0
;
IoExpWrOn_oq
<=
#
1
1'b0
;
IoExpRdOn_oq
<=
#
1
1'b0
;
I2cEnChOn_oq
<=
#
1
1'b0
;
I2cMuxRdIntOn_oq
<=
#
1
1'b0
;
FifoAccessOn_oq
<=
#
1
1'b0
;
ByteOut_ob8
<=
#
1
8'b0
;
end
else
case
(
State_qb4
)
// Waiting for a request
s_Idle
:
begin
CommandPointer_b4
<=
#
1
4'h0
;
if
(
IoExpWrReq_i
)
ActiveSequence_b3
<=
#
1
c_IoExpWriteSeq
;
else
if
(
IoExpRdReq_i
)
ActiveSequence_b3
<=
#
1
c_IoExpReadSeq
;
else
if
(
I2cMuxIntRdReq_i
)
ActiveSequence_b3
<=
#
1
c_I2cMuxIntReadSeq
;
else
if
(
I2cMuxEnChReq_i
)
ActiveSequence_b3
<=
#
1
c_I2cMuxEnChSeq
;
else
if
(
FifoAccessReq_i
)
ActiveSequence_b3
<=
#
1
c_FifoSeq
;
end
// Fetching and decoding the command
s_FetchCommand:
begin
NewByteRead_op
<=
#
1
Command_b3
==
c_GetByte
;
ByteOut_ob8
<=
#
1
ShReg_b8
;
AckError_op
<=
#
1
Command_b3
==
c_SendByte
&&
I2CAck
;
CommandPointer_b4
<=
#
1
CommandPointer_b4
+
1'b1
;
FifoRead
<=
#
1
~
FifoEmpty_o
&&
ActiveSequence_b3
==
c_FifoSeq
;
case
(
ActiveSequence_b3
)
c_IoExpWriteSeq:
{
Command_b3
,
ShReg_b8
}
<=
#
1
IoExpWriteSeq_b11
;
c_IoExpReadSeq:
{
Command_b3
,
ShReg_b8
}
<=
#
1
IoExpReadSeq_b11
;
c_I2cMuxIntReadSeq:
{
Command_b3
,
ShReg_b8
}
<=
#
1
I2cMuxReadSeq_b11
;
c_I2cMuxEnChSeq:
{
Command_b3
,
ShReg_b8
}
<=
#
1
I2cMuxEnChSeq_b11
;
c_FifoSeq:
{
Command_b3
,
ShReg_b8
}
<=
#
1
FifoDout_b11
;
default:
{
Command_b3
,
ShReg_b8
}
<=
#
1
{
c_GoToIdle
,
8'h0
}
;
endcase
end
s_StartExecution
:
begin
BitCounter_c4
<=
#
1
4'h0
;
SclCounter_c10
<=
#
1
10'h0
;
if
(
NextState_ab4
==
s_GetScl0
)
I2CAck
<=
#
1
ShReg_b8
[
0
];
end
// Start bit sequence
s_StartSda1
:
begin
SdaOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
Sda_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_StartScl1
:
begin
SclOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_StartSda0
:
begin
SdaOe_e
<=
#
1
1'b1
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
!
Sda_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_StartScl0
:
begin
SclOe_e
<=
#
1
1'b1
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
!
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
// Byte sending sequence
s_SendScl0
:
begin
SclOe_e
<=
#
1
1'b1
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
!
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
if
(
SclCounter_c10
[
8
:
0
]
==
g_SclHalfPeriod
[
9
:
1
])
SdaOe_e
<=
#
1
BitCounter_c4
[
3
]
?
1'b0
:
!
ShReg_b8
[
7
];
end
s_SendScl1
:
begin
SclOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
begin
BitCounter_c4
<=
#
1
BitCounter_c4
+
1'b1
;
SclCounter_c10
<=
#
1
'h0
;
ShReg_b8
[
7
:
1
]
<=
#
1
ShReg_b8
[
6
:
0
];
I2CAck
<=
#
1
Sda_ioz
;
end
else
if
(
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
// Byte getting sequence
s_GetScl0
:
begin
SclOe_e
<=
#
1
1'b1
;
SdaOe_e
<=
#
1
(
BitCounter_c4
==
4'd8
)
?
!
I2CAck
:
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
!
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_GetScl1
:
begin
SclOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
begin
BitCounter_c4
<=
#
1
BitCounter_c4
+
1'b1
;
SclCounter_c10
<=
#
1
'h0
;
ShReg_b8
<=
#
1
(
BitCounter_c4
==
4'd8
)
?
ShReg_b8
:
{
ShReg_b8
[
6
:
0
],
Sda_ioz
}
;
end
else
if
(
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
// Stop bit sequence
s_StopSda0
:
begin
SdaOe_e
<=
#
1
1'b1
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
!
Sda_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_StopScl1
:
begin
SclOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
Scl_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
s_StopSda1
:
begin
SdaOe_e
<=
#
1
1'b0
;
if
(
NextState_ab4
!=
State_qb4
)
SclCounter_c10
<=
#
1
'h0
;
else
if
(
Sda_ioz
)
SclCounter_c10
<=
#
1
SclCounter_c10
+
1'b1
;
else
SclCounter_c10
<=
#
1
'h0
;
end
// Protection from bad state condition
default:
begin
SclOe_e
<=
#
1
1'b0
;
SdaOe_e
<=
#
1
1'b0
;
BitCounter_c4
<=
#
1
'h0
;
SclCounter_c10
<=
#
1
'h0
;
I2CAck
<=
#
1
CommandReg_qb32
[
0
];
ShReg_b8
<=
#
1
CommandReg_qb32
[
7
:
0
];
end
endcase
end
assign
Scl_ioz
=
SclOe_e
?
1'b0
:
1'bz
;
assign
Sda_ioz
=
SdaOe_e
?
1'b0
:
1'bz
;
endmodule
\ No newline at end of file
Hdl/Simulation/Models/pca9534.v
0 → 100644
View file @
3a8c6a9d
`timescale
1
ns
/
1
ns
module
pca9534
(
input
[
3
:
0
]
A_ib3
,
inout
[
7
:
0
]
IO_iob8
,
output
Int_on
,
inout
Scl_io
,
inout
Sda_io
);
localparam
c_MinPerDown
=
2500
;
wire
SlaveAddress_b7
=
{
4'b0100
,
a_ib3
}
;
reg
[
7
:
0
]
OutputPortRegister_b8
=
8'hFF
;
reg
[
7
:
0
]
PolarityInversionRegister_b8
=
8'h00
;
reg
[
7
:
0
]
ConfigurationRegister_b8
=
8'hFF
;
integer
ShCount
=
0
;
reg
[
3
:
0
]
State
=
1
;
reg
[
7
:
0
]
Mem_m
[
255
:
0
];
reg
[
7
:
0
]
ByteAddr_b8
;
reg
RdWrBit
;
reg
Scl_q
=
1'bz
,
Sda_q
=
1'bz
;
integer
i
;
reg
[
7
:
0
]
ShReg
;
assign
Scl_io
=
Scl_q
;
assign
Sda_io
=
Sda_q
;
localparam
s_Idle
=
1
,
s_Addressing
=
2
,
s_WrRdSel
=
3
,
s_AckAddress
=
4
,
s_ByteAddr
=
5
,
s_AckByteAddr
=
6
,
s_GetByte
=
7
,
s_SendAckData
=
8
,
s_SendByte
=
9
,
s_GetAckByte
=
10
;
always
@
(
negedge
Sda_io
)
if
(
Scl_io
)
begin
State
=
s_Addressing
;
//Start Bit
ShCount
=
'h0
;
end
always
@
(
posedge
Sda_io
)
if
(
Scl_io
)
begin
State
=
s_Idle
;
//Stop Bit
end
always
@
(
posedge
Scl_io
)
case
(
State
)
s_Addressing:
begin
ShReg
=
{
ShReg
[
6
:
0
],
Sda_io
}
;
ShCount
=
ShCount
+
1
;
if
(
ShCount
==
7
)
begin
State
=
(
ShReg
[
6
:
0
]
==
SlaveAddress_b7
)
?
s_WrRdSel
:
s_Idle
;
end
end
s_WrRdSel:
begin
RdWrBit
=
Sda_io
;
State
=
s_AckAddress
;
end
s_AckAddress:
begin
ShCount
=
0
;
if
(
RdWrBit
)
begin
State
=
s_SendByte
;
if
(
ByteAddr_b8
==
8'h00
)
ShReg
=
IO_iob8
^
PolarityInversionRegister_b8
;
if
(
ByteAddr_b8
==
8'h01
)
ShReg
=
OutputPortRegister_b8
;
if
(
ByteAddr_b8
==
8'h02
)
ShReg
=
PolarityInversionRegister_b8
;
if
(
ByteAddr_b8
==
8'h03
)
ShReg
=
ConfigurationRegister_b8
;
end
else
begin
State
=
s_ByteAddr
;
end
end
s_ByteAddr:
begin
ByteAddr_b8
=
{
ByteAddr_b8
[
6
:
0
],
Sda_io
}
;
ShCount
=
ShCount
+
1
;
if
(
ShCount
==
8
)
State
=
s_AckByteAddr
;
end
s_AckByteAddr:
begin
State
=
s_GetByte
;
ShCount
=
0
;
end
s_GetByte:
begin
ShReg
=
{
ShReg
[
6
:
0
],
Sda_io
}
;
ShCount
=
ShCount
+
1
;
if
(
ShCount
==
8
)
begin
State
=
s_SendAckData
;
if
(
ByteAddr_b8
==
8'h01
)
OutputPortRegister_b8
=
ShReg
;
if
(
ByteAddr_b8
==
8'h02
)
PolarityInversionRegister_b8
=
ShReg
;
if
(
ByteAddr_b8
==
8'h03
)
ConfigurationRegister_b8
=
ShReg
;
end
end
s_SendAckData:
begin
ShCount
=
0
;
State
=
s_GetByte
;
end
s_SendByte:
begin
ShReg
=
{
ShReg
[
6
:
0
],
1'b0
}
;
ShCount
=
ShCount
+
1
;
if
(
ShCount
==
8
)
begin
State
=
s_GetAckByte
;
if
(
ByteAddr_b8
!=
8'h00
)
ByteAddr_b8
=
ByteAddr_b8
+
1
;
//The increment isn't quite clear from the datasheet
else
ShReg
=
IO_iob8
^
PolarityInversionRegister_b8
;
//New sampling
if
(
ByteAddr_b8
==
8'h01
)
ShReg
=
OutputPortRegister_b8
;
if
(
ByteAddr_b8
==
8'h02
)
ShReg
=
PolarityInversionRegister_b8
;
if
(
ByteAddr_b8
==
8'h03
)
ShReg
=
ConfigurationRegister_b8
;
end
end
s_GetAckByte:
begin
ShCount
=
0
;
State
=
Sda_io
?
s_Idle
:
s_SendByte
;
end
endcase
always
@
(
negedge
Scl_io
)
begin
Scl_q
=
1'b0
;
#
c_MinPerDown
;
case
(
State
)
s_Addressing:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
s_WrRdSel:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
s_AckAddress:
begin
Sda_q
=
1'b0
;
#
100
;
Scl_q
=
1'bz
;
end
s_ByteAddr:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
s_AckByteAddr:
begin
Sda_q
=
1'b0
;
#
100
;
Scl_q
=
1'bz
;
end
s_GetByte:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
s_SendAckData:
begin
Sda_q
=
1'b0
;
#
100
;
Scl_q
=
1'bz
;
end
s_SendByte:
begin
Sda_q
=
ShReg
[
7
]
?
1'bz
:
1'b0
;
#
100
;
Scl_q
=
1'bz
;
end
s_GetAckByte:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
default:
begin
Sda_q
=
1'bz
;
#
100
;
Scl_q
=
1'bz
;
end
endcase
end
assign
IO_iob8
[
0
]
=
ConfigurationRegister_b8
[
0
]
?
1'bz
:
OutputPortRegister_b8
[
0
];
assign
IO_iob8
[
1
]
=
ConfigurationRegister_b8
[
1
]
?
1'bz
:
OutputPortRegister_b8
[
1
];
assign
IO_iob8
[
2
]
=
ConfigurationRegister_b8
[
2
]
?
1'bz
:
OutputPortRegister_b8
[
2
];
assign
IO_iob8
[
3
]
=
ConfigurationRegister_b8
[
3
]
?
1'bz
:
OutputPortRegister_b8
[
3
];
assign
IO_iob8
[
4
]
=
ConfigurationRegister_b8
[
4
]
?
1'bz
:
OutputPortRegister_b8
[
4
];
assign
IO_iob8
[
5
]
=
ConfigurationRegister_b8
[
5
]
?
1'bz
:
OutputPortRegister_b8
[
5
];
assign
IO_iob8
[
6
]
=
ConfigurationRegister_b8
[
6
]
?
1'bz
:
OutputPortRegister_b8
[
6
];
assign
IO_iob8
[
7
]
=
ConfigurationRegister_b8
[
7
]
?
1'bz
:
OutputPortRegister_b8
[
7
];
endmodule
Write
Preview