FPGA sample - Lattice I2C IP (EFB) #2
Lattice Diamond Setting
- Click "IPexpress button" and select "EFB" IPX
- Select "Project Path" (source code files), "File Name" and "Module Output" is Verilog
- Click "Customize"
- Select Primary I2C
- EFB have 2 I2C controller, suggestion use primary I2C
- "EFB Enable" tab → "EFB Function Enable" Field → Click "Primary User"
- Configuration Primary I2C
- Speed is 400KHz
- Slave Address is "0001001"
- "I2C" tab → "Primary I2C " Field → "I2C Bus Preformance" is 400KHz → "Slave Address" is 7'b0001001
- Click "Generate" to generate hardware I2C code
- Founad hardware I2C IPX in your project files
範例程式碼
- 宣告 EFB-IP
/***********************************************************************
* *
* EFB Module Instanitiation *
* *
***********************************************************************/
wire rst_p = ~RST_N ;
efbi2c UUT ( .wb_clk_i (CLK ),
.wb_rst_i (rst_p ),
.wb_cyc_i (wb_cyc_i ),
.wb_stb_i (wb_stb_i ),
.wb_we_i (wb_we_i ),
.wb_adr_i (wb_adr_i ),
.wb_dat_i (wb_dat_i ),
.wb_dat_o (wb_dat_o ),
.wb_ack_o (wb_ack_o ),
.i2c1_scl (SCL ),
.i2c1_sda (SDA ),
.i2c1_irqo(i2c1_irq_o) );
- EFB-IP 的 address / data / control pin 訊號順序
/////////////////////////////////////////////
// //
// State Machines Sequential Block //
// //
//////////////////////////////////////////////
always @ (posedge CLK or negedge RST_N)
begin
if(!RST_N)
begin
wb_dat_i <= 8'h00;
wb_stb_i <= 1'b0 ;
wb_adr_i <= 8'h00;
wb_we_i <= 1'b0;
end
else
begin
wb_dat_i <= n_wb_dat_i;
wb_stb_i <= n_wb_stb_i;
wb_adr_i <= n_wb_adr_i;
wb_we_i <= n_wb_we_i ;
end
end
always @ (posedge CLK or negedge RST_N)
begin
if(!RST_N)
begin
c_state <= 10'h000;
efb_flag <= 1'b0 ;
dat_count <= 8'd0;
end
else
begin
c_state <= n_state ;
efb_flag <= n_efb_flag;
dat_count <= n_dat_count ;
end
end
- EFB-IP state machine 加入 oem 程序碼
//////////////////////////////////////////////
// //
// State Machines Combinational Block //
// //
//////////////////////////////////////////////
always @ ( * )
begin
n_efb_flag = 1'b0 ;
n_state = c_state ;
n_dat_count = dat_count ;
n_wb_dat_i = 8'h00;
n_wb_stb_i = 1'b0 ;
n_wb_adr_i = 8'h00;
n_wb_we_i = 1'b0;
n_temp0 = temp0;
i2c_cmd_d = i2c_cmd_q;
i2c_check_d = i2c_check_q;
i2c_data_d = i2c_data_q;
cmdVRMEn_d = cmdVRMEn_q;
case(c_state)
`state0 : // I2C in idle
begin
n_wb_dat_i = 8'h00;
n_wb_stb_i = 1'b0;
n_wb_adr_i = 8'h00;
n_wb_we_i = 1'b0;
n_wb_stb_i = 1'b0;
n_state = `state1 ;
end
`state1 : // Enable I2C Interface
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_state = `state2;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_adr_i = `MICO_EFB_I2C_CR;
n_wb_dat_i = 8'h88;
n_wb_we_i = `WRITE;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state2 : // Clock Disable
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_state = `state3;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_adr_i = `MICO_EFB_I2C_CMDR;
n_wb_dat_i = 8'h04;
n_wb_we_i = `WRITE;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state3 : // Wait for not BUSY
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(wb_dat_o & ( `MICO_EFB_I2C_SR_BUSY) )
n_state = c_state;
else
n_state = `state4;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state4 : // Discard data 1
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_temp0 = wb_dat_o;
n_state = `state5;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_DATA;
n_wb_adr_i = `MICO_EFB_I2C_RXDR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state5 : // Discard data 2
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_temp0 = wb_dat_o;
n_state = `state7; // keep clock stretching disabled per PCN#10A-13
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_DATA;
n_wb_adr_i = `MICO_EFB_I2C_RXDR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state7: // wait for data to come
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(wb_dat_o & (`MICO_EFB_I2C_SR_TRRDY))
n_state = `state8;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state8: // Store i2C Command Information
begin
if (wb_ack_o && efb_flag) begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
i2c_cmd_d = wb_dat_o;
n_state = `state9;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_DATA;
n_wb_adr_i = `MICO_EFB_I2C_RXDR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state9 : // Send ACK or NACK Based upon Command Receive & Wait for Stop `state 17
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
// oem command
end
else
begin if(!wb_ack_o)
n_efb_flag = `HIGH ;
n_wb_adr_i = `MICO_EFB_I2C_CMDR;
n_wb_dat_i = {4'h0,~cmd_data,3'b100};
n_wb_we_i = `WRITE;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state10 : // Command Valid
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY) )
n_state = `state11;
else if (~wb_dat_o[6]) // if stop bit
n_state = `state2;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state11: // Store checksum byte Information
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
i2c_check_d = wb_dat_o;
if(command_data == ~i2c_check_d)
begin
// oem command
end
else
n_state = `state17;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_DATA;
n_wb_adr_i = `MICO_EFB_I2C_RXDR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state12: // Wait for TRRDY Bit
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY))
begin
// Read command
end
else if (~wb_dat_o[6])
n_state = `state2;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state13: // Check for read or write operation Go to State15
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(wb_dat_o & ( `MICO_EFB_I2C_SR_SRW))
n_state = `state15;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state14:
begin // Read Data
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_dat_count = dat_count - 1;
i2c_wr_data[n_dat_count] <= wb_dat_o;
n_state = `state19;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_DATA;
n_wb_adr_i = `MICO_EFB_I2C_RXDR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state15: // Send Data to Master
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
n_state = `state18;
n_dat_count = dat_count - 1 ;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_adr_i = `MICO_EFB_I2C_TXDR;
if(n_dat_count != 1)
n_wb_dat_i = i2c_cmd_q;
else
n_wb_dat_i = i2c_data_q;
n_wb_we_i = `WRITE;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state16: // Send NACK Based upon Command Receive
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
// n_count_en = `LOW ;
n_state = `state17;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_adr_i = `MICO_EFB_I2C_CMDR;
n_wb_dat_i = 8'h0C;
n_wb_we_i = `WRITE;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state17: // Wait till Stop is Send
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if(~wb_dat_o[6])
n_state = `state2;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state18: // Wait for TxRDY flag and send data again if required
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if ( dat_count == 8'h00)
n_state = `state16; // Send Nack for Any More Read Request
else if(wb_dat_o & (`MICO_EFB_I2C_SR_TRRDY ))
n_state = `state15; // Send Data
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
`state19: // Wait for TRRDY bit
begin
if (wb_ack_o && efb_flag)
begin
n_wb_dat_i = `ALL_ZERO ;
n_wb_adr_i = `ALL_ZERO ;
n_wb_we_i = `LOW ;
n_wb_stb_i = `LOW ;
n_efb_flag = `LOW ;
if ( dat_count == 8'h00)
n_state = `state16;
else if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY) )
n_state = `state14;
else if (~wb_dat_o[6])
n_state = `state2;
else
n_state = c_state;
end
else if(!wb_ack_o)
begin
n_efb_flag = `HIGH ;
n_wb_we_i = `READ_STATUS;
n_wb_adr_i = `MICO_EFB_I2C_SR;
n_wb_dat_i = 0 ;
n_wb_stb_i = `HIGH ;
n_state = c_state;
end
end
endcase
end
參考資料
- LatticeMicroEFB16.pdf
- I2cSlavePeripherialUsingEmbeddedFunctionBlock.pdf
- I2cSlavePeripherialUsingEmbeddedFunctionBlock Sample Code
您好,工程文件可以发出来参考一下嘛?
回覆刪除