Commit ed9a3538 authored by Andrea Boccardi's avatar Andrea Boccardi
Browse files

Adding the latest version of the I2cMuxAndExpMaster from my offline repo

parent 0d1a14f3
......@@ -32,33 +32,29 @@ module I2cExpAndMuxMaster
//==== Clocks & Resets ====\\
input Clk_ik,
input Rst_irq,
//==== Status and Requests====\\
output reg Busy_o,
// IO Expanders parameters:
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 IoExpRdReq_i,
output reg IoExpRdOn_oq,
input [2:0] IoExpAddr_ib3,
input [1:0] IoExpRegAddr_ib2,
input [7:0] IoExpData_ib8,
// I2C Mux parameters:
input I2cSlaveWrReq_i,
output reg I2cSlaveWrOn_o,
input I2cSlaveRdReq_i,
output reg I2cSlaveRdOn_o,
input I2cMuxAddress_i,
input [1:0] I2cMuxChannel_ib2,
// FIFO access programming interface:
output FifoFull_o,
output FifoEmpty_o,
input FifoCommandWr_i,
input [10:0] FifoCommand_ib11,
input [6:0] I2cSlaveAddr_ib7,
input [7:0] I2cSlaveRegAddr_ib8,
input [7:0] I2cSlaveByte_ib8,
//==== Status and Results====\\
output reg Busy_o,
output reg NewByteRead_op,
output reg [7:0] ByteOut_ob8,
output reg AckError_op,
//==== I2C Bus ====\\
inout Scl_ioz,
inout Sda_ioz
......@@ -79,25 +75,23 @@ localparam s_Idle = 4'h0,
s_GetScl0 = 4'h9,
s_GetScl1 = 4'ha,
s_StopSda0 = 4'hb,
s_StopScl1 = 4'ha,
s_StopSda1 = 4'hb;
s_StopScl1 = 4'hc,
s_StopSda1 = 4'hd;
// Command sequence ROM:
localparam c_IoExpWriteSeq = 3'd0,
c_IoExpReadSeq = 3'd1,
c_I2cMuxIntReadSeq = 3'd2,
c_I2cMuxEnChSeq = 3'd3,
c_FifoSeq = 3'd4;
c_I2cSlaveRead = 3'd2,
c_I2cSlaveWrite = 3'd3;
// 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
c_GoToIdle = 3'b0;
//==== 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;
......@@ -105,36 +99,23 @@ 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;
reg [2:0] ActiveSequence_b3;
// Command Sequences
reg [3:0] CommandPointer_c4;
reg [10:0] IoExpWriteSeq_b11, IoExpReadSeq_b11;
reg [2:0] IoExpAddr_qb3;
reg [1:0] IoExpRegAddr_qb2;
reg [7:0] IoExpData_qb8;
reg [10:0] IoExpWriteSeq_b11, IoExpReadSeq_b11;
reg [10:0] I2cMuxRdSlaveRegSeq_b11, I2cMuxWrSlaveRegSeq_b11;
reg I2cMuxAddress_q;
reg [1:0] I2cMuxChannel_qb2;
reg [10:0] I2cMuxReadSeq_b11, I2cMuxEnChSeq_b11;
reg [3:0] CommandPointer_c4;
reg [6:0] I2cSlaveAddr_qb7;
reg [7:0] I2cSlaveRegAddr_qb8;
reg [7:0] I2cSlaveByte_qb8;
//======================================= 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_c4)
4'd0: IoExpWriteSeq_b11 <= #1 {c_SendStartBit, 8'h0};
......@@ -157,44 +138,44 @@ always @(posedge Clk_ik) case(CommandPointer_c4)
default: IoExpReadSeq_b11 <= #1 {c_GoToIdle, 8'h0};
endcase
// Reading the value of the interrupt and configuration status of one I2C mux
// Reading a register from a device attached to a I2C mux
always @(posedge Clk_ik) case(CommandPointer_c4)
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};
4'h0: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'h1: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, 6'h38, I2cMuxAddress_q, 1'b0}; //Comment: Selection of the I2C Mux in Write mode
4'h2: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, 5'b0, 1'b1, I2cMuxChannel_qb2}; //Comment: Enabling the desired channel
4'h3: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
4'h4: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'h5: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveAddr_qb7, 1'b0}; //Comment: Selection of the Slave in write mode
4'h6: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveRegAddr_qb8}; //Comment: Writing the Register address
4'h7: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0}; //Comment: Repeated start (new cycle)
4'h8: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveAddr_qb7, 1'b1}; //Comment: Selection of the Slave in read mode
4'h9: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_GetByte, 8'h1}; //Comment: Read of the last Byte (single read)
4'ha: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
4'hb: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'hc: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, 6'h38, I2cMuxAddress_q, 1'b0}; //Comment: Selection of the I2C Mux in Write mode
4'hd: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendByte, 5'b0, 3'b0}; //Comment: Disabling all channels
4'he: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
default: I2cMuxRdSlaveRegSeq_b11 <= #1 {c_GoToIdle, 8'h0};
endcase
// Enabling one channel of a I2C mux (and disabling all the others)
// Writing a register from a device attached to a I2C mux
always @(posedge Clk_ik) case(CommandPointer_c4)
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};
4'h0: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'h1: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, 6'h38, I2cMuxAddress_q, 1'b0}; //Comment: Selection of the I2C Mux in Write mode
4'h2: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, 5'b0, 1'b1, I2cMuxChannel_qb2}; //Comment: Enabling the desired channel
4'h3: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
4'h4: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'h5: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveAddr_qb7, 1'b0}; //Comment: Selection of the Slave in write mode
4'h6: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveRegAddr_qb8}; //Comment: Writing the Register address
4'h7: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, I2cSlaveByte_qb8}; //Comment: Sending the byte
4'h8: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
4'h9: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStartBit, 8'h0};
4'ha: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, 6'h38, I2cMuxAddress_q, 1'b0}; //Comment: Selection of the I2C Mux in Write mode
4'hb: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendByte, 5'b0, 3'b0}; //Comment: Disabling all channels
4'hc: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_SendStopBit, 8'h0};
default: I2cMuxWrSlaveRegSeq_b11 <= #1 {c_GoToIdle, 8'h0};
endcase
// 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),
.wr_level(/*Not connected*/),
.rd_level(/*Not connected*/));
//==== State Machine ====\\
always @(posedge Clk_ik) State_qb4 <= #1 Rst_irq ? s_Idle : NextState_ab4;
......@@ -202,9 +183,9 @@ always @* begin
NextState_ab4 = State_qb4;
case(State_qb4)
// Waiting for a request
s_Idle: if (AnyRequest_a) NextState_ab4 = s_FetchCommand;
s_Idle: if (~Busy_o&&(IoExpWrReq_i || IoExpRdReq_i || I2cSlaveWrReq_i || I2cSlaveRdReq_i)) NextState_ab4 = s_FetchCommand;
// Fetching and decoding the command
s_FetchCommand: if (~FifoEmpty_o || ActiveSequence_b3!=c_FifoSeq) NextState_ab4 = s_StartExecution;
s_FetchCommand: 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;
......@@ -229,68 +210,67 @@ always @* begin
default: NextState_ab4 = s_Idle;
endcase
end
always @(posedge Clk_ik) begin
// Default assignments
FifoRead <= #1 1'b0;
NewByteRead_op <= #1 1'b0;
AckError_op <= #1 1'b0;
if (NextState_ab4 == s_Idle) begin
Busy_o <= #1 1'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;
end
// 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;
Busy_o <= #1 1'b1;
CommandPointer_c4 <= #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;
SclOe_e <= #1 1'b0;
SdaOe_e <= #1 1'b0;
Busy_o <= #1 1'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;
SclOe_e <= #1 1'b0;
SdaOe_e <= #1 1'b0;
I2cSlaveWrOn_o <= #1 1'b0;
I2cSlaveRdOn_o <= #1 1'b0;
NewByteRead_op <= #1 1'b0;
end else case(State_qb4)
// Waiting for a request
s_Idle : begin
SclOe_e <= #1 1'b0;
SdaOe_e <= #1 1'b0;
CommandPointer_c4 <= #1 4'h0;
CommandPointer_c4 <= #1 4'h0;
IoExpWrOn_oq <= #1 1'b0;
IoExpRdOn_oq <= #1 1'b0;
I2cSlaveWrOn_o <= #1 1'b0;
I2cSlaveRdOn_o <= #1 1'b0;
Busy_o <= #1 1'b0;
NewByteRead_op <= #1 1'b0;
if (NextState_ab4 != s_Idle) begin
Busy_o <= #1 1'b1;
AckError_op <= #1 1'b0;
Busy_o <= #1 1'b1;
if (IoExpWrReq_i) begin
ActiveSequence_b3 <= #1 c_IoExpWriteSeq;
IoExpWrOn_oq <= #1 1'b1;
IoExpAddr_qb3 <= #1 IoExpAddr_ib3;
IoExpRegAddr_qb2 <= #1 IoExpRegAddr_ib2;
IoExpData_qb8 <= #1 IoExpData_ib8;
end else if (IoExpRdReq_i) begin
ActiveSequence_b3 <= #1 c_IoExpReadSeq;
IoExpRdOn_oq <= #1 1'b1;
end else if (I2cMuxIntRdReq_i) begin
ActiveSequence_b3 <= #1 c_I2cMuxIntReadSeq;
I2cEnChOn_oq <= #1 1'b1;
end else if (I2cMuxEnChReq_i) begin
ActiveSequence_b3 <= #1 c_I2cMuxEnChSeq;
I2cMuxRdIntOn_oq <= #1 1'b1;
end else if (FifoAccessReq_i) begin
ActiveSequence_b3 <= #1 c_FifoSeq;
FifoAccessOn_oq <= #1 1'b0;
end
IoExpAddr_qb3 <= #1 IoExpAddr_ib3;
IoExpRegAddr_qb2 <= #1 IoExpRegAddr_ib2;
end else if (I2cSlaveWrReq_i) begin
ActiveSequence_b3 <= #1 I2cMuxWrSlaveRegSeq_b11;
I2cSlaveWrOn_o <= #1 1'b1;
I2cMuxAddress_q <= #1 I2cMuxAddress_i;
I2cMuxChannel_qb2 <= #1 I2cMuxChannel_ib2;
I2cSlaveAddr_qb7 <= #1 I2cSlaveAddr_ib7;
I2cSlaveRegAddr_qb8 <= #1 I2cSlaveRegAddr_ib8;
I2cSlaveByte_qb8 <= #1 I2cSlaveByte_ib8;
end else if (I2cSlaveRdReq_i) begin
ActiveSequence_b3 <= #1 I2cMuxRdSlaveRegSeq_b11;
I2cSlaveRdOn_o <= #1 1'b1;
I2cMuxAddress_q <= #1 I2cMuxAddress_i;
I2cMuxChannel_qb2 <= #1 I2cMuxChannel_ib2;
I2cSlaveAddr_qb7 <= #1 I2cSlaveAddr_ib7;
I2cSlaveRegAddr_qb8 <= #1 I2cSlaveRegAddr_ib8;
end
end
end
// Fetching and decoding the command
......@@ -299,20 +279,19 @@ always @(posedge Clk_ik) begin
ByteOut_ob8 <= #1 ShReg_b8;
AckError_op <= #1 Command_b3 == c_SendByte && I2CAck;
CommandPointer_c4 <= #1 CommandPointer_c4 + 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;
c_IoExpReadSeq: {Command_b3, ShReg_b8} <= #1 IoExpReadSeq_b11;
c_I2cSlaveRead: {Command_b3, ShReg_b8} <= #1 I2cMuxRdSlaveRegSeq_b11;
c_I2cSlaveWrite: {Command_b3, ShReg_b8} <= #1 I2cMuxWrSlaveRegSeq_b11;
default: {Command_b3, ShReg_b8} <= #1 {c_GoToIdle, 8'h0};
endcase
end
s_StartExecution : begin
NewByteRead_op <= #1 1'b0;
BitCounter_c4 <= #1 4'h0;
SclCounter_c10 <= #1 10'h0;
if (NextState_ab4==s_GetScl0) I2CAck <= #1 ShReg_b8[0];
if (NextState_ab4==s_GetScl0) I2CAck <= #1 ShReg_b8[0];
end
// Start bit sequence
s_StartSda1 : begin
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment