/////////////////////////////////////////////////////////////////////// // // Simple I2C Barometric Pressure Sensor module // // this model returns a 24-bit pressure value in Pascals // (100 Pascals = 1 millibar) // // a more advanced version would check for the expected // I2C command // // this module might also be the location of assert statements // to help with debugging // // Ports: // SDA (Inout) // I2C Bidirectional Data pin // // SCL (Input) // I2C Clock pin // // I2C Device Address: // 0001000 // /////////////////////////////////////////////////////////////////////// module simple_pressure_sensor ( inout SDA, input SCL ); timeunit 1ns; timeprecision 100ps; // the real variables "pressure" and "temperature" represent values // for environmental parameters // // in this sensor the real "pressure" value is "sampled" and returned // to the user as a 24-bit integer in Pascals (100 Pascals = 1 millibar) // // the simplified altimeter sensor does not support consideration // of temperature data but the temperature variable exists below // to maintain compatibility with the more complex sensors real pressure = 983.58; // pressure in millibars real temperature = 25.0; // temperature in Celcius int pressure_Pa; // pressure in Pascals int i; logic SDA_Out; // // the values specified here should be both conservative // and easy to achieve in practice // // these values have been selected to support a transfer rate // of 100kbits/s // specify // Serial clock timings $period(posedge SCL, 9us); $width(posedge SCL, 4us); $width(negedge SCL, 4us); // Serial Data timings relative to the clock $setup(SDA, posedge SCL, 2us); $setup(SDA, negedge SCL, 2us); endspecify assign SDA = (!SDA_Out) ? '0 : 'z; initial begin SDA_Out = 1; // this is idle condition forever begin @(negedge SDA); if ( SCL == 1 ) // this is detecting the start condition begin pressure_Pa = int'(100*pressure); // sample the pressure variable @(negedge SCL); @(negedge SCL); @(negedge SCL); @(negedge SCL); @(negedge SCL); if ( SDA == 1 ) // check just one bit of device address begin @(negedge SCL); @(negedge SCL); @(negedge SCL); @(negedge SCL); if ( SDA == 1 ) // check for read begin SDA_Out = 0; // acknowledge read @(negedge SCL); // ouput first byte of pressure_Pa for ( i = 7; i >= 0; i--) begin SDA_Out = pressure_Pa[i]; @(negedge SCL); end SDA_Out = 1; // release bus for master acknowledge @(negedge SCL); // ouput second byte of pressure_Pa for ( i = 15; i >= 8; i--) begin SDA_Out = pressure_Pa[i]; @(negedge SCL); end SDA_Out = 1; // release bus for master acknowledge @(negedge SCL); // ouput third byte of pressure_Pa for ( i = 23; i >= 16; i--) begin SDA_Out = pressure_Pa[i]; @(negedge SCL); end SDA_Out = 1; // release bus @(negedge SCL); end end end end end endmodule