manta/v0.1.0/block_memory_core/index.html

992 lines
35 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Manta Documentation">
<meta name="author" content="Fischer Moseley">
<link rel="canonical" href="https://fischermoseley.github.io/manta/v0.1.0/block_memory_core/">
<link rel="prev" href="../logic_analyzer_core/">
<link rel="next" href="../uart_interface/">
<link rel="icon" href="../assets/logo_ray_only_with_shadow.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.39">
<title>Block Memory Core - Manta Documentation</title>
<link rel="stylesheet" href="../assets/stylesheets/main.8c3ca2c6.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../stylesheets/extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="custom" data-md-color-accent="light-blue">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#overview" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden>
<aside class="md-banner md-banner--warning">
<div class="md-banner__inner md-grid md-typeset">
You're not viewing the latest version.
<a href="../..">
<strong>Click here to go to latest.</strong>
</a>
</div>
<script>var el=document.querySelector("[data-md-component=outdated]"),outdated=__md_get("__outdated",sessionStorage);!0===outdated&&el&&(el.hidden=!1)</script>
</aside>
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Manta Documentation" class="md-header__button md-logo" aria-label="Manta Documentation" data-md-component="logo">
<img src="../assets/logo_minimal_border.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Manta Documentation
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Block Memory Core
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="custom" data-md-color-accent="light-blue" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="custom" data-md-color-accent="light-blue" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/fischermoseley/manta/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Manta Documentation" class="md-nav__button md-logo" aria-label="Manta Documentation" data-md-component="logo">
<img src="../assets/logo_minimal_border.png" alt="logo">
</a>
Manta Documentation
</label>
<div class="md-nav__source">
<a href="https://github.com/fischermoseley/manta/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-ellipsis">
Reference
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Reference
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../getting_started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../io_core/" class="md-nav__link">
<span class="md-ellipsis">
IO Core
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic_analyzer_core/" class="md-nav__link">
<span class="md-ellipsis">
Logic Analyzer Core
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Block Memory Core
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Block Memory Core
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configuration" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
<nav class="md-nav" aria-label="Configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#dimensions" class="md-nav__link">
<span class="md-ellipsis">
Dimensions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#python-api" class="md-nav__link">
<span class="md-ellipsis">
Python API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#under-the-hood" class="md-nav__link">
<span class="md-ellipsis">
Under the Hood
</span>
</a>
<nav class="md-nav" aria-label="Under the Hood">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#address-assignment" class="md-nav__link">
<span class="md-ellipsis">
Address Assignment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#synchronicity" class="md-nav__link">
<span class="md-ellipsis">
Synchronicity
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../uart_interface/" class="md-nav__link">
<span class="md-ellipsis">
UART Interace
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ethernet_interface/" class="md-nav__link">
<span class="md-ellipsis">
Ethernet Interface
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="">
<span class="md-ellipsis">
For Developers
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
For Developers
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../repository_structure/" class="md-nav__link">
<span class="md-ellipsis">
Repository Structure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../how_it_works/" class="md-nav__link">
<span class="md-ellipsis">
How It Works
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://github.com/fischermoseley/manta/milestones" class="md-nav__link">
<span class="md-ellipsis">
Roadmap
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configuration" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
<nav class="md-nav" aria-label="Configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#dimensions" class="md-nav__link">
<span class="md-ellipsis">
Dimensions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#python-api" class="md-nav__link">
<span class="md-ellipsis">
Python API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#under-the-hood" class="md-nav__link">
<span class="md-ellipsis">
Under the Hood
</span>
</a>
<nav class="md-nav" aria-label="Under the Hood">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#address-assignment" class="md-nav__link">
<span class="md-ellipsis">
Address Assignment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#synchronicity" class="md-nav__link">
<span class="md-ellipsis">
Synchronicity
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1>Block Memory Core</h1>
<h2 id="overview">Overview</h2>
<p>Block Memory (also called Block RAM, or BRAM) is the de facto means of storing data on FPGAs when the space needed exceeds a few registers. As a result, Manta provides a Block Memory core, which instantiates a dual-port BRAM on the FPGA. One port is provided to the host, and the other is connected to your logic with the standard BRAM interface (<code>addr</code>, <code>din</code>, <code>dout</code>, <code>wea</code>). This allows the host to provide reasonably large amounts of data to user logic - or the other way around, or a mix of both!</p>
<p>This is a very, very simple task - and while configuration is straightforward, there are a few caveats. More on both topics below:</p>
<h2 id="configuration">Configuration</h2>
<p>Just like the rest of the cores, the Block Memory core is configured via an entry in a project's configuration file. This is easiest to show by example:</p>
<div class="language-yaml highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nn">---</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="nt">cores</span><span class="p">:</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="nt">my_block_memory</span><span class="p">:</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">block_memory</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="w"> </span><span class="nt">width</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">12</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="w"> </span><span class="nt">depth</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">16384</span>
</span></code></pre></div>
<p>There's a few parameters that get configured here, including:</p>
<ul>
<li><code>name</code>: The name of the Block Memory core. This name is used to reference the core when working with the API, and can be whatever you'd like.</li>
<li><code>type</code>: This denotes that this is a Block Memory core. All cores contain a <code>type</code> field, which must be set to <code>block_memory</code> to be recognized as an Block Memory core.</li>
</ul>
<h3 id="dimensions">Dimensions</h3>
<p>The dimensions of the block memory are specified in the config file with the <code>width</code> and <code>depth</code> entries.</p>
<p>Manta won't impose any limit on the width or depth of the block memory you instantiate, but since Manta instantiates BRAM primitives on the FPGA, you will be limited by what your FPGA can support. It helps to know your particular FPGA's architecture here.</p>
<p>If your BRAM is more than 16 bits wide, check out the section on <a href="#synchronicity">Synchronicity</a> and make sure your project will tolerate how Manta writes to the block memory.</p>
<h3 id="python-api">Python API</h3>
<p>The Block Memory core functionality is stored in the <code>Manta.IOCore</code> and <code>Manta.IOCoreProbe</code> classes in <a href="https://github.com/fischermoseley/manta/blob/main/src/manta/io_core/__init__.py">src/manta/io_core/__init__.py</a>, and it may be controlled with the two functions:</p>
<p>Just like with the other cores, interfacing with the BRAM with the Python API is simple:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="kn">from</span> <span class="nn">manta</span> <span class="kn">import</span> <span class="n">Manta</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="n">m</span> <span class="o">=</span> <span class="n">manta</span><span class="p">(</span><span class="s1">&#39;manta.yaml&#39;</span><span class="p">)</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">addr</span><span class="o">=</span><span class="mi">38</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="mi">600</span><span class="p">)</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">addr</span><span class="o">=</span><span class="mh">0x1234</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="mb">0b100011101011</span><span class="p">)</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="mh">0x0612</span><span class="p">,</span> <span class="mh">0x2001</span><span class="p">)</span>
</span><span id="__span-1-7"><a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a>
</span><span id="__span-1-8"><a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a><span class="n">foo</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">addr</span><span class="o">=</span><span class="mi">38</span><span class="p">)</span>
</span><span id="__span-1-9"><a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="n">foo</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">addr</span><span class="o">=</span><span class="mi">1234</span><span class="p">)</span>
</span><span id="__span-1-10"><a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a><span class="n">foo</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="mh">0x0612</span><span class="p">)</span>
</span></code></pre></div>
<p>Reading/writing in batches is also supported. This is recommended where possible, as reads are massively sped up by performing them in bulk:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="n">addrs</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1234</span><span class="p">))</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="n">datas</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1234</span><span class="p">,</span> <span class="mi">2468</span><span class="p">))</span>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">addrs</span><span class="p">,</span> <span class="n">datas</span><span class="p">)</span>
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="n">foo</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">my_block_memory</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">addrs</span><span class="p">)</span>
</span></code></pre></div>
<h3 id="examples">Examples</h3>
<p>A Block Memory core is used in the <a href="https://github.com/fischermoseley/manta/blob/main/examples/nexys_a7/video_sprite">video_sprite</a> example. This uses the core to store a 128x128 image sprite in 12-bit color, and outputs it to a VGA display at 1024x768. The sprite contents can be filled with an arbitrary image using the <a href="https://github.com/fischermoseley/manta/blob/main/examples/nexys_a7/video_sprite/send_image.py">send_image.py</a> python script.</p>
<h2 id="under-the-hood">Under the Hood</h2>
<p>Each Block Memory core is actually a set of 16-bit wide BRAMs with their ports concatenated together, with any spare bits masked off. Here's a diagram:</p>
<p><img alt="" src="../assets/block_memory_architecture.png" /></p>
<p>This has one major consequence: if the core doesn't have a width that's an exact multiple of 16, synthesis engines (Vivado in particular) will throw some warnings as they optimize out the unused bits. This is expected behavior, and while the warnings are a little annoying, not having to manually deal with the unused bits simplifies the implementation immensely. No Python is needed to generate the core, and it'll configure itself just based on Verilog parameters. This turns the block memory core from a complicated conditionally-instantiated beast to a simple ~<em>100 line</em> <a href="https://github.com/fischermoseley/manta/blob/main/src/manta/block_memory.v">Verilog file</a>.</p>
<h3 id="address-assignment">Address Assignment</h3>
<p>Since each <span class="arithmatex">\(n\)</span>-bit wide block memory is actually <span class="arithmatex">\(ceil(n/16)\)</span> BRAMs under the hood, addressing the BRAMs correctly from Manta's internal bus is important. BRAMs are organized such that each 16-bit slice of a <span class="arithmatex">\(N\)</span>-bit word in the Block Memory core are placed next to each other in bus address space. For instance, a 34-bit wide block memory would exist on Manta's internal bus as:</p>
<table>
<thead>
<tr>
<th>Bus Address Space</th>
<th>BRAM Address Space</th>
</tr>
</thead>
<tbody>
<tr>
<td>BASE_ADDR + 0</td>
<td>address 0, bits 0-15</td>
</tr>
<tr>
<td>BASE_ADDR + 1</td>
<td>address 0, bits 16-31</td>
</tr>
<tr>
<td>BASE_ADDR + 2</td>
<td>address 0, bits 32-33</td>
</tr>
<tr>
<td>BASE_ADDR + 3</td>
<td>address 1, bits 0-15</td>
</tr>
<tr>
<td>BASE_ADDR + 4</td>
<td>address 1, bits 16-31</td>
</tr>
<tr>
<td>BASE_ADDR + 5</td>
<td>address 1, bits 32-33</td>
</tr>
</tbody>
</table>
<p>...and so on.</p>
<h3 id="synchronicity">Synchronicity</h3>
<p>Since Manta's <a href="../system_architecture">data bus</a> is only 16-bits wide, it's only possible to manipulate the BRAM core in 16-bit increments. This means that if you have a BRAM that's ≤16 bits wide, you'll only need to issue a single bus transaction to read/write one entry in the BRAM. However, if you have a BRAM that's ≥16 bits wide, you'll need to issue a bus transaction to update each 16-bit slice of it. For instance, updating a single entry in a 33-bit wide BRAM would require sending 3 messages to the FPGA: one for bits 1-16, another for bits 17-32, and one for bit 33. If your application expects each BRAM entry to update instantaneously, this could be problematic.</p>
<p>There's a few different ways to solve this - you could use an IO core to signal when a BRAM's contents or valid - or you could ping-pong between two BRAMs while one is being modified. The choice is yours, and Manta makes no attempt to presribe any particular approach.</p>
<p>Lastly, the interface you use (and to a lesser extent, your operating system) will determine the space between bus transactions. For instance, 100Mbit Ethernet is a thousand times faster than 115200bps UART, so the time where the BRAM is invalid is a thousand times smaller.</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.copy", "content.code.annotate", "navigation.sections", "navigation.expand"], "search": "../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.525ec568.min.js"></script>
<script src="../javascripts/mathjax.js"></script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
</body>
</html>