element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
FPGA
  • Technologies
  • More
FPGA
Blog VHDL design for ROHM Heart Rate sensor BH1790 - try i2c
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join FPGA to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 22 Jan 2022 11:31 AM Date Created
  • Views 6393 views
  • Likes 5 likes
  • Comments 14 comments
  • i2c
  • fpga
  • vhdl
  • summer_of_fpga
Related
Recommended

VHDL design for ROHM Heart Rate sensor BH1790 - try i2c

Jan Cumps
Jan Cumps
22 Jan 2022
VHDL design for ROHM Heart Rate sensor BH1790 - try i2c

I'm going to try and run an i2c design in VHDL fabric. For self-training.
The target device is the Rohm BH1790 optical heart rate sensor.
It's a device where the i2c protocol is straightforward but strict. A good candidate for training - a RTL state machine should be able to control the flow.

What I'd like to achieve is: controlling the complete sampling part of heart rate sensor in plain VHDL/RTL, portable/independent of FPGA make. Make the raw data available.
Then, there is a second part of interpreting/filtering the raw data.
I'm going to start doing that in software, then try translating that into FPGA designs. These may be pure VHDL, or Xilinx proprietary.
If all of that is successful, I'd like to use DMA and streaming to provide that data to a program. That's definitely going to be device dependent.
The exercise is broken up in a few posts. I write as I go. This one checks out the i2c IP I'd like to use for the design.

First, I tested this sensor with Rohm's original code on an Arduino. An exercise to know how it works, and view the communication.
It's easier to design for something that you know how to operate. Because only the FPGA/VHDL part is the unknown. I understand the IC and its protocol.

i2c IP

Vivado / Zynq come with smart i2c IP. In two flavours*: to be used within the fabric, and a version that can be used in a MicroBlaze.
I'm after one that's implemented in fabric. I'm not using Xilinx' proprietary implementation, because I try to improve my VHDL skills in this design. Not my knowledge of Xilinx IP 
*I believe there's also i2c support in the Linux/PS part of the Zynq, comparable to i2c on a Pi. That's not what I'm trying to learn here.

On the other hand, I'd like to reuse an existing VHDL i2c design.
I'd first like to implement a design that uses a working i2c IP. I'm not up to writing my own implementation of that yet.
I landed with a design posted on Digi-Key's Tech Forum. Like Avnet's element14, Digi-Key also has a community. I found this design over there.
It's written - and improved over time - by Scott Larson. Written for Quartus II (Intel/Altera).
Ideally, the end result should be cross-community, cross-distributor, cross-manufacturer.
The source code and related blog don't mention a license. I expect that writing about it, and change some parts of the code (see table below), is in line with community behaviour.
I will restrict my blogs to changes I made to the original code, and why. The ZIP attachments will contain the adapted code with link to the original in the source files.

VHDL buffer in a top design

The i2c design of Scott Larson uses an output of type BUFFER for the ack_error flag.
ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave

A VHDL BUFFER is an output port, that can be read to and written from inside the architecture.
A normal OUT port can't be read from inside an implementation. You can assign it a value.

The consequence of BUFFER type is that it needs to be implemented all the way up in the design. Upstream ports that connect to it, need to be BUFFER too.
But that's not always what you desire. In the end, for external design that uses the IP, the flag is just an output. Type BUFFER is used because that's how the internal implementation of the IP uses it.

There are alternatives to BUFFER though. One of them is to define the flag as OUT. Then create a SIGNAL internally in the IP that can be written to and read from.
In the IP implementation, assign that SIGNAL to the out pin.
It's explained here: How to stop using "buffer" ports in VHDL?
How does this change Scott Larson's VHDL?

Original:

ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave
-- ...
  IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
    ack_error <= '1'; --set error output if no-acknowledge
-- ...

Revised:

ack_error : OUT STD_LOGIC; --flag if improper acknowledge from slave
-- ...
SIGNAL s_ack_error : STD_LOGIC;
-- ...
  IF(sda /= '0' OR s_ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
    s_ack_error <= '1'; --set error output if no-acknowledge
-- ...
ack_error <= s_ack_error;

The i2c IP interface

The i2c IP has, like all IPs, a set of input and output connections.
They are very similar to the APIs you have access to in a microcontroller's i2c driver.

image

There are 2 variables that are set as GENERIC. clock frequency and i2c frequency.
They are set to 500 MHz and 400 kHz. You can overwrite those in a Vivado block design without wrapping or coding:

image

I kept the 400 kHz i2c speed. The heart rate sensor supports it.
I adapted the input clock frequency. I've set it equal to the Fabric ClocK 1 speed. That's the clock I'm attaching the IP to.

Open Drain SDA and SCL

i2c protocol uses open drain active devices, in combination with pull-up resistors.
In a constraint file, there's no way to define it. The way to do it in RTL, is by setting the output to High-impedance instead of '1' when driving an output high.
The SDA is bi-directional, input and output. But that doesn't add complexity. Implementing it is simpler than I thought.
You can just ignore any state (in or out), except output high. For output high, you assign high impedance:

sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z';

Design Decision for the next post

I'm going to write a IP that reflects the BH11790 sensor.
I could have instantiated the i2c IP in its code. But I'd like to write a sensor class that's isolated from that.
The plan is that it exposes pins that can be connected to the i2c IP, and that I link them together in the block design.
It's the first time that I do this, so it may or may not be the right decision. The future will tell ...

  • Sign in to reply
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    ... and it's solved. The developer of VSG has created a branch with a fix. I tested it and now all upper case STD_LOGIC occurences are consistently changed to lower case. There will be a new VSG release that includes the fix.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    I created a separate post to investigate TRI-STATE ...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    edit: I raised an issue on the project github: https://github.com/jeremiah-c-leary/vhdl-style-guide/issues/729

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to jc2048

    The style checker profile of VSG that I am using is set to flag (and if desired - fix) types to lower case.
    It has done that for all upper case ones except this one:

    init : in STD_LOGIC)

    Maybe it's fooled by the bracket? It caught all the ones that had STD_LOGIC with blank or ; behind it.
    I should be able to check because the VSG source code is on github ...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    Here's my constraint:

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube