Skip to content

Add a 24 series I2C EEPROM emulator #741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake . --impure
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@
/*.bit
/*.json
/*.csv

.direnv

# Nix build outputs
/result
/result-*
76 changes: 76 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
flake-compat.url = "github:edolstra/flake-compat";
};
outputs =
{ nixpkgs, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
lib = pkgs.lib;
in
{
packages = rec {
glasgow = pkgs.glasgow.overrideAttrs {
version = "0+unstable-memory-24x-emu";
src = ./.;
doInstallCheck = false;
};
default = glasgow;
};

devShell = pkgs.mkShell {
packages = with pkgs; [
# Must come before yosys in this array, so it has precedence
# over the propagatedBuildInput python3 from yosys.
(python3.withPackages (
pypkgs: with pypkgs; [
typing-extensions
amaranth
packaging
platformdirs
fx2
libusb1
pyvcd
aiohttp

unittestCheckHook
]
))

yosys
icestorm
nextpnr

sdcc

];

YOSYS = "${lib.getBin pkgs.yosys}/bin/yosys";
ICEPACK = "${lib.getBin pkgs.icestorm}/bin/icepack";
NEXTPNR_ICE40 = "${lib.getBin pkgs.nextpnr}/bin/nextpnr-ice40";
};

formatter = pkgs.nixfmt-rfc-style;
}
);
}
10 changes: 10 additions & 0 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).shellNix
55 changes: 55 additions & 0 deletions software/glasgow/applet/memory/_24x_emu/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 24-series I²C EEPROM emulation applet

Emulates the read and write operations of a generic 24-series I²C EEPROM. The memory size, address width, and initial contents can be chosen at build time.

Operations besides read and write operations no further operations are implemented. Reads and writes are not paged and may be performed in arbitrarily sized batches (reads only or writes only). Paging reliant behavior like writes/reads wrapping around to the start of a page when the end of a page is reached in an operation is not supported. All reads and writes will always access the current address, wrapping around only once the end of the memory is reached.

<!--
TODO: packet diagrams are not flexible enough
START/STOP are not really normal bits
can't have a discontinuous section
-->

## Random Address Read
During a random address read the I²C initiator sends a start strobe initiating a write and writes as many bytes as the chosen address width. This is followed by a restart strobe initiating a read. This read will return the byte from the selected address.

Deviating from I²C devices, the initiator may follow up with further reads. Each read will increment the address being read from. See [Sequential Read](#sequential-read)

```mermaid
---
title: Random Address Read
---
packet-beta
0: "STA"
1-7: "I²C device address"
8: "R/W"
9: "ACK"
10-17: "memory address (= n)"
18: "ACK"
19: "STA"
20-26: "I²C device address"
27: "R/w"
28: "ACK"
29-36: "data (n)"
37: "NAK"
38: "STO"
```

## Sequential Read
During a sequential read, the initiator sends a start strobe initiating a read. The read will return the byte in memory stored at the current address. This may be followed by as many further reads as desired. Each read increments the current address, i.e. consecutive reads will read bytes sequentially from memory.

```mermaid
---
title: Sequential Read
---
packet-beta
0: "STA"
1-7: "I²C device address"
8: "R/w"
9: "ACK"
10-17: "data (n)"
18: "ACK"
19-26: "data (n + 1)"
27: "NAK"
28: "STO"
```
Loading
Loading