aicherry 发表于 2012-4-24 11:11:07

求助关于读取adxl 345加速度模块值的FPGA的程序

求助关于读取adxl 345加速度模块值的FPGA的程序
最近在网上找了一个实例程序 但是感觉不正确。

wye11083 发表于 2012-4-24 11:20:19

你这程序是什么东西呀,看不懂。你需要一个I2C_Host来读取数据。我给你一个测试过的代码,目前挂在我的3个设备的I2C总线上,正常工作。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    22:01:45 04/18/2012
// Design Name:
// Module Name:    I2CHost
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//                Formal I2C host module. Note that Start signal will only be send
//                if there's a data write operation after Start bit is set.
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module I2CHost(
    input int_in_GCLK,
    input int_in_GRST,
       
        // Bus definition
    input int_in_Control,
        input int_in_Validate_Ctrl,
    output int_out_Status,
    input int_in_Data,
        input int_in_Validate_Data,
    output int_out_Data,
        // If to input one byte, assert this wire to initiate a read cycle.
        input int_in_Read_Probe,
       
        // Port definition
        output port_out_SCL,
        inout port_io_SDA
    );
       
        // 100KHz -- 100MHz
        reg rc_I2C_SCK_Counter_Threshold = 12'd999;
        // The following two signals are used to tell Clock generator whether to generate clock.
        reg r_I2C_Transmit_Enable = 1'b0;
        wire w_I2C_Transmit_Clock;
        wire w_I2C_Start_Stop_Clock;
       
        // SDA output control register.
        reg r_SDA_Assert_Zero = 1'b0;
        reg r_SCL_Assert_Zero = 1'b0;
       
        // Configure register. b7-Start b6-Stop b5-LastRD b1-ACK b0-Done.
        // External write should not affect except b7 to b5.
        // Because LastRD has no actual effect, we just skip it and set to zero every ACK period.
        reg r_I2C_Control = 8'h00;
        wire w_Start = r_I2C_Control;
        wire w_Stop = r_I2C_Control;
        wire w_LastRD = r_I2C_Control;
        // Status routed directly to Control register.
        assign int_out_Status = r_I2C_Control;
       
        // Data will be latched only when controller is IDLE and int_in_Validate_Data is asserted HIGH.
        reg r_I2C_Data_In;
        reg r_I2C_Data_Out;
        // Output data is routed to r_I2C_To_Parallel_Data_Out, which will be affected after one transaction.
        reg r_I2C_To_Parallel_Data_Out;
        assign int_out_Data = r_I2C_To_Parallel_Data_Out;
       
        reg rs_I2C_Transceive;
        reg rc_I2C_Transceive;
       
        wire ws_I2C_Transceive_IDLE                                         = 0;
        wire ws_I2C_Transceive_Start_Begin                        = 1;
        wire ws_I2C_Transceive_Start_SCL_Transition        = 2;
        wire ws_I2C_Transceive_Send_Begin                                = 3;
        wire ws_I2C_Transceive_Send_Transition                = 4;
        wire ws_I2C_Transceive_Read_Begin                                = 5;
        wire ws_I2C_Transceive_Read_Latch                                = 6;
        wire ws_I2C_Transceive_Read_ACK                                = 7;
        wire ws_I2C_Transceive_ACK                                        = 8;
        wire ws_I2C_Transceive_Stop_Begin                                = 9;
        wire ws_I2C_Transceive_Stop_SCL_Transition        = 10;
        wire ws_I2C_Transceive_SCL_Low_Last_Cycle                = 11;
       
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        r_I2C_Control <= 0;
                                        r_I2C_Data_In <= 0;
                                        r_I2C_Data_Out <= 0;
                                        rs_I2C_Transceive <= ws_I2C_Transceive_IDLE;
                                        rc_I2C_Transceive <= 0;
                                        r_I2C_Transmit_Enable <= 0;
                                        r_SDA_Assert_Zero <= 0;
                                        r_SCL_Assert_Zero <= 1;
                                        rc_I2C_SCK_Counter_Threshold <= 12'd999;
                                end
                        else
                                begin
                                        // Control register is updated whenever a write operation occurs.
                                        // We assume this command's only executed serially (not parallelly).
                                        if(int_in_Validate_Ctrl)
                                                r_I2C_Control <= int_in_Control;
                                        else
                                                begin
                                        case (rs_I2C_Transceive)
                                                ws_I2C_Transceive_IDLE:
                                                        begin
                                                                // Idle state. Wait for any changes in Control Register.
                                                                // When Stop is asserted, then generate a stop condition.
                                                                // Else wait for Data Validate command.
                                                                if(w_Stop)
                                                                        begin
                                                                        // State 14 is used for Stop condition.
                                                                                r_I2C_Transmit_Enable <= 1;
                                                                                r_SDA_Assert_Zero <= 1;
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Stop_Begin;
                                                                                r_I2C_Control <= 0;
                                                                                // Clear Stop bit.
                                                                                r_I2C_Control <= 0;
                                                                        end
                                                                else if(int_in_Validate_Data)
                                                                        begin
                                                                                // Load data;
                                                                                r_I2C_Data_In <= int_in_Data;
                                                                                r_I2C_Control <= 0;
                                                                                rc_I2C_Transceive <= 0;
                                                                                r_I2C_Transmit_Enable <= 1;
                                                                                if(w_Start)
                                                                                        begin
                                                                                                // State 1 is the state for initial transmission.
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Start_Begin;
                                                                                                // SDA is set to 1 ahead of other operation.
                                                                                                r_SDA_Assert_Zero <= 0;
                                                                                                // Clear Start bit.
                                                                                                r_I2C_Control <= 0;
                                                                                        end
                                                                                else
                                                                                        begin
                                                                                                // Just goto State 3 to send data.
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Send_Begin;
                                                                                        end
                                                                        end
                                                                else if(int_in_Read_Probe)
                                                                        begin
                                                                                // Read data. First load internal register to output register.
                                                                                r_I2C_To_Parallel_Data_Out <= r_I2C_Data_Out;
                                                                                r_I2C_Control <= 0;
                                                                                // Goto State 5 for read operation. ACK to device.
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Read_Begin;
                                                                                r_SDA_Assert_Zero <= 0;
                                                                                rc_I2C_Transceive <= 0;
                                                                                r_I2C_Transmit_Enable <= 1;
                                                                        end
                                                                else
                                                                        begin
                                                                                r_SDA_Assert_Zero <= 0;
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                r_I2C_Transmit_Enable <= 0;
                                                                                r_I2C_Control <= 1;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Start_Begin:
                                                        begin
                                                                // Start condition. Assume SDA is previously set to 1.
                                                                r_SCL_Assert_Zero <= 0;
                                                                // Wait for w_I2C_Transmit_Clock becomes high to change pole.
                                                                if(w_I2C_Start_Stop_Clock)
                                                                        begin
                                                                                r_SDA_Assert_Zero <= 1;
                                                                                // Goto state 15 so that after this send cycle return to IDLE.
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Start_SCL_Transition;
                                                                        end
                                                                else
                                                                        rs_I2C_Transceive <= rs_I2C_Transceive;
                                                        end
                                                ws_I2C_Transceive_Start_SCL_Transition:
                                                        begin
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Send_Begin;
                                                                        end
                                                                else
                                                                        rs_I2C_Transceive <= rs_I2C_Transceive;
                                                        end
                                                ws_I2C_Transceive_Send_Begin:
                                                        begin
                                                                // After start condition. Begin transmit data (MSB first).
                                                                // First set data, then goto State 3.
                                                                if(~w_I2C_Transmit_Clock)
                                                                        begin
                                                                                // Set data first if rc_I2C_Transceive is not 7.
                                                                                // If rc_I2C_Transceive is 7, then it means 8 bits are sent, and next to receive ACK.
                                                                                rc_I2C_Transceive <= rc_I2C_Transceive + 1;
                                                                                r_I2C_Data_In <= {r_I2C_Data_In,1'b0};
                                                                                if(rc_I2C_Transceive == 8)
                                                                                        begin
                                                                                                // Receive ACK bit.
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_ACK;
                                                                                                r_SDA_Assert_Zero <= 0;
                                                                                        end
                                                                                else
                                                                                        begin
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Send_Transition;
                                                                                                r_SDA_Assert_Zero <= (r_I2C_Data_In?1'b0:1'b1);
                                                                                        end
                                                                        end
                                                                else
                                                                        rs_I2C_Transceive <= rs_I2C_Transceive;
                                                        end
                                                ws_I2C_Transceive_Send_Transition:
                                                        begin
                                                                // Write data wait w_I2C_Transmit_Clock High.
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Send_Begin;
                                                                        end
                                                                else
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 0;
                                                                                rs_I2C_Transceive <= rs_I2C_Transceive;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Read_Begin:
                                                        begin
                                                                // Read data.
                                                                r_SDA_Assert_Zero <= 0;
                                                                if(~w_I2C_Transmit_Clock)
                                                                        begin
                                                                                // Begin receive data.
                                                                                rc_I2C_Transceive <= rc_I2C_Transceive + 1;
                                                                                if(rc_I2C_Transceive == 8)
                                                                                        begin
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Read_ACK;
                                                                                        end
                                                                                else
                                                                                        begin
                                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Read_Latch;
                                                                                        end
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_I2C_Transceive <= rs_I2C_Transceive;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Read_Latch:
                                                        begin
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                r_I2C_Data_Out <= {r_I2C_Data_Out,port_io_SDA};
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Read_Begin;
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_I2C_Transceive <= rs_I2C_Transceive;
                                                                                r_SCL_Assert_Zero <= 0;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Read_ACK:
                                                        begin
                                                                if(w_LastRD)
                                                                        begin
                                                                                // High-Z SDA
                                                                                r_SDA_Assert_Zero <= 0;
                                                                        end
                                                                else
                                                                        begin
                                                                                r_SDA_Assert_Zero <= 1;
                                                                        end
                                                                // Wait for w_I2C_Transmit_Clock High.
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_I2C_Control <= port_io_SDA;
                                                                                // Goto state 15 so that after this send cycle return to IDLE.
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_SCL_Low_Last_Cycle;
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                r_I2C_Control <= 0;
                                                                        end
                                                                else
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 0;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_ACK:
                                                        begin
                                                                // ACK period. First set SCL high, then read at w_I2C_Transmit_Clock.
                                                                // Assert SCL high. Assume SDA is previously set to float.
                                                                r_SDA_Assert_Zero <= 0;
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_I2C_Control <= port_io_SDA;
                                                                                // Goto state 15 so that after this send cycle return to IDLE.
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_SCL_Low_Last_Cycle;
                                                                                r_SCL_Assert_Zero <= 1;
                                                                        end
                                                                else
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 0;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Stop_Begin:
                                                        begin
                                                                // Stop condition.
                                                                // Assert SCL high. Assume SDA is previously set to zero.
                                                                r_SCL_Assert_Zero <= 0;
                                                                // Wait for w_I2C_Transmit_Clock becomes high to change pole.
                                                                if(w_I2C_Start_Stop_Clock)
                                                                        begin
                                                                                r_SDA_Assert_Zero <= 0;
                                                                                // Goto state 15 so that after this send cycle return to IDLE.
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_Stop_SCL_Transition;
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_I2C_Transceive <= rs_I2C_Transceive;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_Stop_SCL_Transition:
                                                        begin
                                                                if(w_I2C_Transmit_Clock)
                                                                        begin
                                                                                r_SCL_Assert_Zero <= 1;
                                                                                rs_I2C_Transceive <= ws_I2C_Transceive_SCL_Low_Last_Cycle;
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_I2C_Transceive <= rs_I2C_Transceive;
                                                                        end
                                                        end
                                                ws_I2C_Transceive_SCL_Low_Last_Cycle:
                                                        begin
                                                                // Last active cycle. After w_I2C_Transmit_Clock low, goto IDLE.
                                                                if(~w_I2C_Transmit_Clock)
                                                                        rs_I2C_Transceive <= ws_I2C_Transceive_IDLE;
                                                                else
                                                                        rs_I2C_Transceive <= rs_I2C_Transceive;
                                                        end
                                                default:
                                                        begin
                                                                rs_I2C_Transceive <= ws_I2C_Transceive_IDLE;
                                                        end
                                        endcase
                                                end
                                end
                end       
       
       
        BaudGenerator clk_I2C_Transmit(
                .int_in_GCLK(int_in_GCLK),
                .port_in_RXD(1'b1),
                .int_out_RcvCLK(w_I2C_Transmit_Clock),
                .int_in_CountEnable(r_I2C_Transmit_Enable),                // Enable when 1
                .int_in_CountValue({4'h0,rc_I2C_SCK_Counter_Threshold})
    );
       
        BaudGenerator clk_I2C_StartStopBitClk(
                .int_in_GCLK(int_in_GCLK),
                .port_in_RXD(1'b1),
                .int_out_RcvCLK(w_I2C_Start_Stop_Clock),
                .int_in_CountEnable(r_I2C_Transmit_Enable),                // Enable when 1
                .int_in_CountValue({5'h0,rc_I2C_SCK_Counter_Threshold})
    );
       
        assign port_io_SDA = r_SDA_Assert_Zero?1'b0:1'bz;
        assign port_out_SCL = r_SCL_Assert_Zero?1'b0:1'bz;

endmodule


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    08:07:48 04/08/2012
// Design Name:
// Module Name:    BaudGenerator
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module BaudGenerator(
    input int_in_GCLK,
    input port_in_RXD,
    output int_out_RcvCLK,
    input int_in_CountEnable,                // Enable when 1
    input int_in_CountValue
    );

        reg r_port_in_RXD_delay;
       
        always @(posedge int_in_GCLK)
                r_port_in_RXD_delay <= {r_port_in_RXD_delay,port_in_RXD};
       
        wire w_int_RXD_edge = ^r_port_in_RXD_delay;                // Edge detect.
        wire w_int_CountReset = ~w_int_RXD_edge & int_in_CountEnable;        // Reset counter on edge or count enable.
       
        reg r_Counter;
        reg r_int_out_RcvCLK;
       
        assign int_out_RcvCLK = r_int_out_RcvCLK;
       
        always @(posedge int_in_GCLK or negedge w_int_CountReset)
                begin
                        if(~w_int_CountReset)
                                begin
                                        r_Counter <= 0;
                                        r_int_out_RcvCLK <= 0;
                                end
                        else
                                begin
                                        if(r_Counter == int_in_CountValue)
                                                begin
                                                        r_Counter <= 0;
                                                        r_int_out_RcvCLK <= 0;
                                                end
                                        else
                                                begin
                                                        r_Counter <= r_Counter + 1;
                                                        if(r_Counter == {1'b0,int_in_CountValue})
                                                                begin
                                                                        r_int_out_RcvCLK <= 1;
                                                                end
                                                        else
                                                                begin
                                                                        r_int_out_RcvCLK <= r_int_out_RcvCLK;
                                                                end
                                                end
                                end
                end

endmodule

注意这个是I2CHost,操作方式同EZ-USB FX2的I2C总线寄存器操作,写寄存器bmSTART,bmSTOP,读bmACK,bmDONE,写I2DAT,读I2DAT。100KHz。注意你读超过8位数据时,需要每读一个字节后要回应设备nACK,要不然设备就认为传输结束,而停止继续输出数据。

aicherry 发表于 2012-4-27 08:48:39

wye11083 发表于 2012-4-24 11:20 static/image/common/back.gif
你这程序是什么东西呀,看不懂。你需要一个I2C_Host来读取数据。我给你一个测试过的代码,目前挂在我的3个 ...

谢谢啦~~~{:biggrin:}
我对FPGA不熟...所以在 编写IIC时有点吃力
页: [1]
查看完整版本: 求助关于读取adxl 345加速度模块值的FPGA的程序