<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://abapages.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://abapages.com/" rel="alternate" type="text/html" /><updated>2026-04-23T05:41:40+00:00</updated><id>https://abapages.com/feed.xml</id><title type="html">G Abarajithan</title><subtitle>PhD student @ UC San Diego; SoC Integration; Hardware Security &amp; Verification; RTL for Edge AI</subtitle><author><name>G Abarajithan</name></author><entry><title type="html">CGRA4ML: Py+SV+C Framework for DNNs → FPGA/ASIC</title><link href="https://abapages.com/cgra4ml/" rel="alternate" type="text/html" title="CGRA4ML: Py+SV+C Framework for DNNs → FPGA/ASIC" /><published>2026-03-16T20:10:00+00:00</published><updated>2026-03-16T20:10:00+00:00</updated><id>https://abapages.com/cgra4ml-edge-deployment</id><content type="html" xml:base="https://abapages.com/cgra4ml/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/cgra4ml_sys.png" alt="" /></p>

<p>CGRA4ML is an open-source, modular hardware/software co-design framework built to implement deep neural networks (DNNs) for scientific edge computing applications.</p>

<p><strong><a href="https://dl.acm.org/doi/10.1145/3801097">Read our framework paper at ACM TRETS</a></strong></p>

<p>While existing tools like hls4ml and FINN excel at small, low-latency models, they often struggle to scale to deeper networks. This is due to their layer-by-layer dataflow architecture, which consumes increasing hardware resources as model depth grows. CGRA4ML addresses this by employing a lightweight and highly parameterizable Coarse-Grained Reconfigurable Array (CGRA) that reuses processing elements (PEs) across layers. This approach enables the deployment of larger models, such as ResNet-50 and PointNet, on FPGAs and ASICs.</p>

<h2 id="features">Features</h2>

<ul>
  <li>Python frontend built around Google’s <code class="language-plaintext highlighter-rouge">qkeras</code> to build and train models.</li>
  <li>Generates a custom, parameterized AXI-Stream Deep Neural Network (DNN) CGRA engine in vendor-agnostic SystemVerilog RTL.
    <ul>
      <li>Dynamic Column Regrouping: Columns in the 2D PE array can regroup at runtime to process varying convolution kernel widths and output channels.</li>
      <li>Memory Efficiency: Weight cache with ping-pong buffers for full throughput and a pixel shifter that exploits vertical data locality to reduce required input bandwidth.</li>
      <li>Unified Dataflow Architecture maximizing data reuse via weight caches (ping-pong buffers) and pixel-shifters.</li>
    </ul>
  </li>
  <li>“Bundle” computation architecture for hardware/software partitioning. Dense, convolutional operations stay on the CGRA while skip connections or complex pixel operations are CPU-handled.</li>
  <li>Verification via <a href="/firebridge/">FireBridge</a> &amp; <a href="/reusable-axis-vip/">AXI-Stream VIP</a>: Comprehensive system verification using SystemVerilog DPI-C wrappers and a testbench that runs the same C-firmware to uncover real memory congestion bugs with randomized AXI <code class="language-plaintext highlighter-rouge">ready/valid</code> signals.</li>
  <li>Supports full System-on-Chip integration (e.g., ZYNQ, Ibex RISC-V SoC, ARM NanoSoC).</li>
</ul>

<p><img src="https://media.abapages.com/content/images/2026/cgra4ml_soc.png" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026/cgra4ml_infra.png" alt="" /></p>

<h2 id="unified-dataflow">Unified Dataflow</h2>

<p><img src="https://media.abapages.com/content/images/2026/cgra4ml_conv.png" alt="" /></p>

<h2 id="validation-and-results">Validation and Results</h2>

<p>The framework has been experimentally validated on AMD-Xilinx FPGAs and Cadence ASIC flows. Iso-resource microbenchmarking on a Pynq-Z2 at 150 MHz shows that while hls4ml excels at small workloads, fitting larger workloads requires an exponentially increasing reuse factor. In contrast, a 16x16 CGRA4ML array maintains stable latency and higher throughput when extreme resource constraints are required.</p>

<p>Deployment is streamlined via automated TCL scripts for synthesis, floorplanning, and SoC integration—including integration with the popular Ibex RISC-V SoC. By filling the gap between small-model dataflow tools and traditional 8-bit AI accelerators, CGRA4ML enables the scientific community to move sophisticated processing to extreme edge hardware.</p>

<p><strong>Check out the repo here:</strong> <a href="https://github.com/KastnerRG/cgra4ml">GitHub - cgra4ml</a></p>

<p><img src="https://media.abapages.com/content/images/2026/cgra4ml_7nm.png" alt="Synthesis, Place and Route results for TSMC 7nm with Cadence tools" /></p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Lightweight Formal AXI VIP</title><link href="https://abapages.com/formal-axi/" rel="alternate" type="text/html" title="Lightweight Formal AXI VIP" /><published>2026-03-16T20:05:00+00:00</published><updated>2026-03-16T20:05:00+00:00</updated><id>https://abapages.com/formal-axi-verification</id><content type="html" xml:base="https://abapages.com/formal-axi/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/axi.png" alt="" /></p>

<p>A standard AXI interface has 5 channels, each with its own handshake protocol and inter-channel dependencies. It’s incredibly easy to write a memory-mapped component that works 99% of the time, only to fail when a write response channel stalls irregularly or a read transaction is interleaved differently.</p>

<ul>
  <li>Reusable formal checkers for AXI4, focusing on protocol properties and channel interactions.</li>
  <li>A formally proven Synchronous FIFO and Skid Buffer as foundational building blocks.</li>
  <li>Compatibility with open-source tools like SymbiYosys (SBY) as well as commercial tools like Questa Formal.</li>
</ul>

<h2 id="technical-details">Technical Details</h2>

<p>AXI has both intra-channel rules and inter-channel rules. For example,</p>

<ul>
  <li>Intra-channel: <code class="language-plaintext highlighter-rouge">araddr</code> should remain stable during a stall (when <code class="language-plaintext highlighter-rouge">ar_valid &amp;&amp; !ar_ready</code>)</li>
  <li>Inter-channel: For narrow bursts, <code class="language-plaintext highlighter-rouge">wstrb</code> in each beat should match the <code class="language-plaintext highlighter-rouge">awlen</code>, <code class="language-plaintext highlighter-rouge">awsize</code>, <code class="language-plaintext highlighter-rouge">awburst</code> and <code class="language-plaintext highlighter-rouge">awaddr</code> of the corresponding <code class="language-plaintext highlighter-rouge">aw</code> beat.</li>
</ul>

<p>Writing intra-channel SVAs is pretty easy, which I’ve already done. For inter-channel properties, we need to match the corresponding beats &amp; packets between channels. I’m working on a FIFO abstraction to do this with minimal overhead. <a href="https://github.com/abarajithan11/formal_fifo">GitHub - formal_fifo</a></p>

<h4 id="package-with-properties">Package with properties</h4>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="c1">// pkg_axi_fvip.sv</span>
  <span class="k">property</span> <span class="n">stable_next_when</span><span class="p">(</span><span class="n">when_cond</span><span class="p">,</span> <span class="n">signal</span><span class="p">);</span>
    <span class="n">when_cond</span> <span class="o">|=&gt;</span> <span class="p">$</span><span class="nb">stable</span><span class="p">(</span><span class="n">signal</span><span class="p">);</span>
  <span class="k">endproperty</span>

  <span class="k">property</span> <span class="n">burst_no_4kb_cross</span><span class="p">(</span><span class="n">valid</span><span class="p">,</span> <span class="n">burst</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="nb">size</span><span class="p">);</span>
    <span class="n">valid</span> <span class="o">&amp;&amp;</span> <span class="n">burst</span> <span class="o">==</span> <span class="n">BURST_INCR</span> <span class="o">|-&gt;</span>
      <span class="p">(</span><span class="n">addr</span> <span class="o">&gt;&gt;</span> <span class="mi">12</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="n">end_byte</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="nb">size</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">12</span><span class="p">);</span>
  <span class="k">endproperty</span>
</code></pre></div></div>

<h4 id="sub-fvip-for-ar-channel">Sub-FVIP for AR channel</h4>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="c1">// ar_fvip.sv</span>

  <span class="cp">`ifdef</span> <span class="n">AXI_FVIP_SLAVE_AR</span>
    <span class="cp">`define</span> ASSUME assert<span class="cp">
</span>    <span class="cp">`define</span> ASSERT assume<span class="cp">
</span>  <span class="cp">`else</span>
    <span class="cp">`define</span> ASSUME assume<span class="cp">
</span>    <span class="cp">`define</span> ASSERT assert<span class="cp">
</span>  <span class="cp">`endif</span>

  <span class="k">default</span> <span class="k">clocking</span> <span class="n">cb</span> <span class="o">@</span><span class="p">(</span><span class="kt">posedge</span> <span class="n">clk</span><span class="p">);</span> <span class="k">endclocking</span>
  <span class="k">default</span> <span class="kt">disable</span> <span class="k">iff</span> <span class="p">(</span><span class="o">!</span><span class="n">rstn</span><span class="p">);</span>
  <span class="kt">wire</span> <span class="n">stall</span> <span class="o">=</span> <span class="n">ar_valid</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">ar_ready</span><span class="p">;</span>
  <span class="kt">wire</span> <span class="n">hsk</span> <span class="o">=</span> <span class="n">ar_valid</span> <span class="o">&amp;&amp;</span> <span class="n">ar_ready</span><span class="p">;</span>

  <span class="nl">a_addr_stall_stable:</span>
    <span class="cp">`ASSUME</span> <span class="k">property</span> <span class="p">(</span><span class="n">stable_next_when</span><span class="p">(</span><span class="n">stall</span><span class="p">,</span> <span class="n">ar_addr</span><span class="p">));</span>
  <span class="nl">a_burst_no_4kb_cross:</span>
    <span class="cp">`ASSUME</span> <span class="k">property</span> <span class="p">(</span><span class="n">burst_no_4kb_cross</span><span class="p">(</span><span class="n">ar_valid</span><span class="p">,</span> <span class="n">ar_burst</span><span class="p">,</span> <span class="n">ar_addr</span><span class="p">,</span> <span class="n">ar_len</span><span class="p">,</span> <span class="n">ar_size</span><span class="p">));</span>
</code></pre></div></div>

<h4 id="full-axi-fvip-that-can-switch-between-master-and-slave">Full AXI FVIP that can switch between master and slave</h4>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="cp">`ifdef</span> <span class="n">MASTER</span>
    <span class="cp">`define</span> AXI_FVIP_MASTER_AR<span class="cp">
</span>    <span class="cp">`define</span> MODNAME_AXI m_axi_fvip<span class="cp">
</span>    <span class="cp">`define</span> MODNAME_AR  m_ar_fvip<span class="cp">
</span>  <span class="cp">`else</span>
    <span class="cp">`define</span> AXI_FVIP_SLAVE_AR<span class="cp">
</span>    <span class="cp">`define</span> MODNAME_AXI s_axi_fvip<span class="cp">
</span>    <span class="cp">`define</span> MODNAME_AR  s_ar_fvip<span class="cp">
</span>  <span class="cp">`endif</span>
  <span class="cp">`include</span> <span class="s">"ar_fvip.sv"</span>

  <span class="cp">`MODNAME_AR</span> <span class="p">#(</span>
    <span class="p">.</span><span class="n">ADDR_W</span><span class="p">(</span><span class="n">ADDR_W</span><span class="p">),</span> 
    <span class="p">.</span><span class="n">DATA_W</span><span class="p">(</span><span class="n">DATA_W</span><span class="p">),</span> 
    <span class="p">.</span><span class="n">ID_W</span><span class="p">(</span><span class="n">ID_W</span><span class="p">),</span> 
    <span class="p">.</span><span class="n">USER_W</span><span class="p">(</span><span class="n">USER_W</span><span class="p">),</span> 
    <span class="p">.</span><span class="n">AXI_MAX_STALL_ENV</span><span class="p">(</span><span class="n">AXI_MAX_STALL_ENV</span><span class="p">),</span> 
    <span class="p">.</span><span class="n">AXI_MAX_STALL_DUT</span><span class="p">(</span><span class="n">AXI_MAX_STALL_DUT</span><span class="p">)</span>
    <span class="p">)</span> <span class="n">u_ar</span> <span class="p">(.</span><span class="o">*</span><span class="p">);</span>
</code></pre></div></div>

<h4 id="users-testbench">User’s testbench</h4>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="cp">`define</span> <span class="n">MASTER</span>
  <span class="cp">`include</span> <span class="s">"axi_sva/our/axi_fvip.sv"</span>
  <span class="cp">`undef</span> <span class="n">MASTER</span>

  <span class="cp">`define</span> SLAVE<span class="cp">
</span>  <span class="cp">`include</span> <span class="s">"axi_sva/our/axi_fvip.sv"</span>
  <span class="cp">`undef</span> <span class="n">SLAVE</span>
</code></pre></div></div>

<p>Code: <a href="https://github.com/abarajithan11/formal_axi">GitHub - formal_axi</a></p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">SystemVerilog Course at Scale</title><link href="https://abapages.com/systemverilog-course/" rel="alternate" type="text/html" title="SystemVerilog Course at Scale" /><published>2026-03-15T20:45:00+00:00</published><updated>2026-03-15T20:45:00+00:00</updated><id>https://abapages.com/systemverilog-course</id><content type="html" xml:base="https://abapages.com/systemverilog-course/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/sv_first_page.png" alt="" /></p>

<p>In November 2020, I conducted a free, open, and independent hands-on webinar.</p>

<ul>
  <li>It was widely successful, with 170+ attending from 9 institutes in Sri Lanka, India, and Sweden.</li>
  <li>Zoom recording was downloaded over 2300 times.</li>
  <li><a href="https://bit.ly/sv-feedback">Feedback</a> about the <a href="http://bit.ly/sv-slides">content, visuals</a>, and teaching style was overwhelmingly positive.</li>
  <li><a href="https://github.com/SkillSurf/systemverilog">GitHub Repo with example</a></li>
</ul>

<p>I have iteratively delivered this course <strong>3 times: in 2020, 2024, and 2025</strong>.</p>

<p><img src="https://media.abapages.com/content/images/2026/sv_fir.png" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026/sv_p2s.png" alt="" /></p>

<h2 id="the-story">The Story</h2>

<p>When I TA’d for the digital design course in Sri Lanka, I noticed that several students found digital design counterintuitive. They approach HDLs with the software programming mindset, and write RTL code with a lot of nested in-conditions and convoluted state machines. In addition, our program does not teach an HDL explicitly but expects students to pick things up from Verilog basics and learn as they go. As a result, many are unaware of the advanced features of SystemVerilog that make their lives easy by reducing bugs and saving time.</p>

<p>During COVID lockdowns, I started reading SystemVerilog books by Stuart Sutherland and Chris Spear on the language and took notes. When I returned, I rebuilt Kraken using the advanced features I had learned. I wanted to pass this knowledge on to the students. So, I picked this as the first topic of my initiative: Missing Semester, inspired by <a href="https://missing.csail.mit.edu/2020/version-control/">MIT’s course of the same name</a>.</p>

<p>Later, Kithmin and I delivered similar workshops in other areas like Robotics and Embedded Systems. Dr. Subodha joined us to make this into a standalone startup, delivering many more courses. We partnered with Synopsys for two of the iterations. They provided access to their tools and sent many of their engineers to be trained.</p>

<p>My goals for each course are:</p>
<ul>
  <li>Little to no prerequisites (knowledge about logic gates should be enough)</li>
  <li>Content applicable for beginners to intermediate level</li>
  <li>Hands-on, with real-world examples</li>
  <li>Concise, clean code</li>
  <li>Open-source tools (Icarus Verilog, Verilator)</li>
  <li>Interactive - students ask questions throughout the session</li>
</ul>

<h2 id="selected-feedback">Selected Feedback</h2>

<p>From beginners to fresh graduates working at Synopsys, participants consistently said the course helped them build a strong foundation in SystemVerilog, ASIC design, and real industry practices, and many described it as well worth the investment.</p>

<blockquote>
  <p>What I feel is that this session was the cream of the HDL extracted from internet and every references. If you can do this kind of dedications, it would really helpful for the new comers to the field.</p>
</blockquote>

<blockquote>
  <p>The things I learned from this course - the insights, tactics, and guidance - felt more valuable than everything else I gained. Hats-off to the entire team… These kind of initiatives deserves to reach much more audience.</p>
</blockquote>

<blockquote>
  <p>Special thanks to the ABA sir and the skillsurf team. This course is worth more than money, and it will definitely be a turning point in my life. I highly recommend it to all FPGA and ASIC enthusiasts.</p>
</blockquote>

<blockquote>
  <p>As a fresh graduate, I never knew the importance of testbenches. Now I feel I have a very solid foundation in ASIC development.</p>
</blockquote>

<h2 id="my-teaching-method">My Teaching Method</h2>

<p>I structured the course into modular, hands-on labs with increasing complexity. For each circuit, I explained the background, the problem, how it is designed, and then the implementation and verification constraints. <a href="https://github.com/SkillSurf/systemverilog">GitHub Repo with example</a></p>

<h4 id="combinational-circuits">Combinational Circuits</h4>
<ul>
  <li><strong>full_adder</strong>: Introduces assignments, logic operators, assertions, and variables.</li>
  <li><strong>n_bit_adder</strong>: Ripple carry adder showing parameters, <code class="language-plaintext highlighter-rouge">for</code> loops, and simple constraints (<code class="language-plaintext highlighter-rouge">std::randomize</code>).</li>
  <li><strong>alu</strong>: ALUs with <code class="language-plaintext highlighter-rouge">signed</code> types, <code class="language-plaintext highlighter-rouge">if-else</code> vs <code class="language-plaintext highlighter-rouge">unique case</code>, and 4-state vs 2-state variables.</li>
  <li><strong>function_lut</strong>: Demonstrates lookup tables, recursive functions, arrays, and synthesis impact.</li>
  <li><strong>decoder</strong>: Streamlining a 435-line verbose instruction decoder into 95-lines utilizing “last assignment wins” feature of verilog.</li>
</ul>

<h4 id="sequential-circuits">Sequential Circuits</h4>
<ul>
  <li><strong>counter</strong>: N-bit counters, synchronous active-high resets, and non-blocking assignments (<code class="language-plaintext highlighter-rouge">always_ff</code>).</li>
  <li><strong>fir_filter</strong>: FIR filters, shift registers, retiming.</li>
</ul>

<h4 id="advanced-soc--interconnects">Advanced SoC &amp; Interconnects</h4>
<ul>
  <li><strong>p2s</strong>: Parallel-to-Serial converter with a simple state machine.</li>
  <li><strong>uart_rx &amp; uart_tx</strong>: UART modules with AXI-Stream interfaces to connect the outside world to the FPGA.</li>
  <li><strong>skid_buffer</strong>: Breaking combinational paths in the <code class="language-plaintext highlighter-rouge">ready</code> of AXI-Stream interfaces.</li>
  <li><strong>matvec_mul</strong>: Parameterized adder trees and 2D packed arrays representing matrix operations.</li>
  <li><strong>mvm_uart_system</strong>: The final capstone system connecting a UART terminal (PC) to an AXI-Matrix Multiplier instantiated on an FPGA!</li>
</ul>

<p><a href="https://www.youtube.com/watch?v=Lr4yGma89oE">Teaching Method</a></p>

<h2 id="references">References</h2>

<ol>
  <li><strong>RTL Modeling with SystemVerilog for Simulation and Synthesis: Using SystemVerilog for ASIC and FPGA Design</strong> by Stuart Sutherland<br />
Primary reference material I used for the slides. Especially for synthesizable RTL design features of SystemVerilog</li>
  <li><strong>SystemVerilog for Verification: A Guide to Learning the Testbench Language Features</strong> by Chris Spear<br />
I referred to this to understand the simulation features (OOP, assertions) of SystemVerilog</li>
  <li><strong>Zynq Training</strong> by Mohammad S. Sadri [<a href="https://www.youtube.com/playlist?list=PLLAhvA_pexcxXi9BDwja4Bd9t2aVeVPkK">YouTube playlist</a>] <br />
Excellent guide on AXI4 protocol and SoC design with Vivado. Play at 1.25x speed</li>
  <li><strong>Parallel Programming for FPGAs</strong> by Ryan Kastner [<a href="https://github.com/KastnerRG/pp4fpgas/raw/gh-pages/main.pdf">free download</a>]<br />
Notes from UCSD (University of California San Diego) on parallelizing algorithms and implementing them with Vivado HLS (C-based HDL). I’m reading this now</li>
  <li><strong>Computer Organization and Design:</strong> <br />
<strong>The Hardware/Software Interface, RISC-V Edition</strong> by David A Patterson<br />
One of the most popular books. Especially on processor design. I haven’t read it yet.</li>
</ol>]]></content><author><name>G Abarajithan</name></author><category term="Teaching" /><category term="Projects" /><category term="Community Work" /><category term="Teaching" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Hardware Fuzzing Benchmark Framework for AXI</title><link href="https://abapages.com/soc-fuzzing-benchmark/" rel="alternate" type="text/html" title="Hardware Fuzzing Benchmark Framework for AXI" /><published>2026-03-10T20:00:00+00:00</published><updated>2026-03-10T20:00:00+00:00</updated><id>https://abapages.com/soc-fuzzing-benchmark</id><content type="html" xml:base="https://abapages.com/soc-fuzzing-benchmark/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/soc_harness.png" alt="" /></p>

<p>Hardware fuzzing is an emerging technique in SoC verification. Recently, there has been a lot of buzz around fuzzers like Google’s “HW like SW”, Intel PreSiFuzz, HyperFuzzer, RFuzz, and many FIRRTL/Chisel fuzzers. However, measuring how effective different fuzzers are against real-world designs can be extremely challenging. This project aims to create a framework that can evaluate various verification methods by automatically injecting bugs into standard SoC IPs from popular open-source repositories such as PULP, TAXI, ZipCPU and proprietary IPs from ARM and Xilinx, giving researchers a standardized benchmark to measure their fuzzers’ performance.</p>

<h2 id="features">Features</h2>

<ul>
  <li><strong>Unified Harness:</strong> A standardized AXI harness that consumes packed binary commands from standard input, mapping them seamlessly to AXI reads, writes, and parallel transactions.</li>
  <li><strong>Broad Tool Support:</strong> Integrated with both Verilator and Synopsys VCS simulation environments.</li>
  <li><strong>Multiple Supported Fuzzers:</strong> Built-in scripts to run fuzzers seamlessly (<code class="language-plaintext highlighter-rouge">hw_like_sw</code>, <code class="language-plaintext highlighter-rouge">hyperfuzzer</code>, <code class="language-plaintext highlighter-rouge">presifuzz</code>, <code class="language-plaintext highlighter-rouge">hw_fuzzing_afl</code>, <code class="language-plaintext highlighter-rouge">rfuzz</code>, etc.)</li>
  <li><strong>Industrial IPCores:</strong> Evaluates against AXI IPs from sources like PULP, TAXI, ARM, and Xilinx.</li>
  <li><strong>Containerized Environment:</strong> Full Docker support so anyone can run the entire suite of fuzzers with a single <code class="language-plaintext highlighter-rouge">make run_example</code> command.</li>
</ul>

<h2 id="technical-details">Technical Details</h2>

<p>Fuzzers generate randomly mutated bytes to be input into the hardware’s pins. For protocol-based designs, randomly mutating the inputs causes almost all inputs to be invalid. A bus grammar and a harness are needed to bridge this gap.</p>

<p>I created a SystemVerilog module that acts as a drop-in replacement for the randomized AXI driver in CRV testbenches. This module pulls in data bytes straight from the fuzzers (via <code class="language-plaintext highlighter-rouge">/dev/stdin</code>) and translates those bytes into standard AXI signals (<code class="language-plaintext highlighter-rouge">AW</code>, <code class="language-plaintext highlighter-rouge">W</code>, <code class="language-plaintext highlighter-rouge">B</code>, <code class="language-plaintext highlighter-rouge">AR</code>, <code class="language-plaintext highlighter-rouge">R</code>). I packed over 30 separate timing parameters, control attributes, burst sizes, and opcode commands into a command vector.</p>

<p>For timing and performance, wait cycles (<code class="language-plaintext highlighter-rouge">t_aw_m2s</code>, <code class="language-plaintext highlighter-rouge">t_r_s2m</code>, etc.) have their own byte slots in the vector and are natively supported by the harness, allowing the fuzzer to create arbitrarily long or short stalls on the handshake signals. I have SystemVerilog queues inside the design to connect our drop-in AXI Source and Sink, so the delays can be inserted on both ends.</p>

<p>If the command randomly generated by a fuzzer breaks fundamental AXI protocol rules, it’s legalized in the <code class="language-plaintext highlighter-rouge">params.svh</code> before being issued, ensuring the fuzzer doesn’t get stuck chasing invalid protocol states. I also added an extra byte which defines different ways to violate AXI protocol, to catch the bugs from the module behaving unexpectedly. We have AXI protocol checkers from ARM (SVA based) and ZipCPU in each of the Source and Sink to identify the DUT violating protocol, cause a crash and send a signal to the fuzzer.</p>

<p>To run our harness,</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make fuzz_axi <span class="nv">FUZZER</span><span class="o">=</span>hw_like_sw <span class="nv">IP</span><span class="o">=</span>axi_fifo <span class="nv">VENDOR</span><span class="o">=</span>pulp <span class="nv">SIM</span><span class="o">=</span>verilator
</code></pre></div></div>

<p>The system automatically spins up the target IP, binds the harness, and begins bombarding the design with packed fuzzed bytes to uncover edge-case behavioral bugs or security violations. By standardizing this, we can easily inject known bugs and quantify precisely which fuzzers identify the faults earliest and with the least overhead.</p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Adobe cities and Atomic bombs: New Mexico - Texas Trip ‘25</title><link href="https://abapages.com/travel/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/" rel="alternate" type="text/html" title="Adobe cities and Atomic bombs: New Mexico - Texas Trip ‘25" /><published>2026-02-13T18:03:07+00:00</published><updated>2026-02-13T18:03:07+00:00</updated><id>https://abapages.com/travel/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25</id><content type="html" xml:base="https://abapages.com/travel/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/"><![CDATA[<p>Santa Fe and ABQ Old Town have a unique vibe, filled with adobe-like houses. This architectural style originated with the native tribes and was improved upon by the Spanish settlers. Many buildings have mud verandahs (திண்ணை), and are decorated with red chilies woven into various patterns. New Mexico cuisine is also unique, using a lot of red and green chilies.</p>

<p>Santa Fe had several artisan galleries with modern pottery and other artwork inspired by native tribes.
We visited a museum about native history, but it wasn’t particularly interesting.</p>

<p>We rented a car from ABQ airport, paying $850 for 13 days. I had booked a medium economy car, but they gave me an SUV: Subaru Outback. It was a pleasure to drive, especially since we drove it for 4600 km.</p>

<p>Los Alamos is about 30 minutes from Santa Fe. We visited Oppenheimer’s house, saw his Bhagavad Gita, and the intact project gate. The museum there explains the science and history of nuclear bomb development very well. The landscape around Los Alamos was gorgeous, which was one of the reasons Oppenheimer chose this spot.</p>

<p><a href="/travel/texas-trip-16-days-4600-km-drive/">Overview of the road trip</a></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565563429923.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565567070014.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565565869984.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565559869834.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565568150041.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565564389947.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565565189967.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565564309945.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565562429898.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565560349846.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565561789882.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565566429998.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565567350021.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565567630028.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565569110065.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565569390072.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565560789857.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565563789932.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565562229893.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565560229843.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565560069839.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565563509925.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/adobe-cities-and-atomic-bombs-new-mexico-texas-trip-25/10237565565069964.jpg" alt="" /></p>]]></content><author><name>G Abarajithan</name></author><category term="Travel" /><category term="Travels" /><category term="USA" /><category term="History" /><summary type="html"><![CDATA[Santa Fe and ABQ Old Town have a unique vibe, filled with adobe-like houses. This architectural style originated with the native tribes and was improved upon by the Spanish settlers. Many buildings have mud verandahs (திண்ணை), and are decorated with red chilies woven into various patterns. New Mexico cuisine is also unique, using a lot of red and green chilies.]]></summary></entry><entry><title type="html">Texas Trip - 16 days, 4600 km drive</title><link href="https://abapages.com/travel/texas-trip-16-days-4600-km-drive/" rel="alternate" type="text/html" title="Texas Trip - 16 days, 4600 km drive" /><published>2026-02-09T07:24:21+00:00</published><updated>2026-02-09T07:24:21+00:00</updated><id>https://abapages.com/travel/texas-trip-16-days-4600-km-drive</id><content type="html" xml:base="https://abapages.com/travel/texas-trip-16-days-4600-km-drive/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504303938474.jpg" alt="" /></p>

<p>Drove 4660 km (2896 mi) in 13 days in a Subaru Outback as a road trip across New Mexico, Texas, and Louisiana. We visited 3 national parks and camped for 4 days straight, with 0 °C weather on the last day. Highlights:</p>

<ul>
  <li><strong>Los Alamos</strong> — where Oppenheimer’s team developed the bomb</li>
  <li><strong>Santa Fe</strong> — Adobe (mud) houses</li>
  <li><strong>White Sands NP</strong> — a sea of whitest sand dunes in the middle of nowhere</li>
  <li><strong>Carlsbad Caverns NP</strong> — once an underground sea, dripping water has created massive structures</li>
  <li><strong>Ford Davis</strong> — several cities with laws to limit light pollution for stargazing. We observed the Andromeda galaxy, Saturn, Jupiter &amp; moons through telescopes.</li>
  <li><strong>Big Bend NP</strong> — massive swaths of remoteness; a tiny, unprotected creek that serves as the US-Mexico border</li>
  <li><strong>San Antonio, Austin, Dallas</strong> — beautiful river walk; wild trail within the city; unbelievable BBQ; gas station with 250 pumps.</li>
  <li><strong>Fortworth</strong> — cowboys; cattle herding; gun sale</li>
  <li><strong>Houston</strong> — we have a problem (NASA); with a full Saturn V rocket; moon rock we could touch</li>
  <li><strong>Lafayette</strong> — swamp tour, alligators</li>
  <li><strong>New Orleans</strong> — city with the best vibes in the US; amazing street music at every corner; cute, colorful houses.</li>
</ul>

<p>More info in future posts…</p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504304418486.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504308498588.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504307378560.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504306018526.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504304698493.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504305018501.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504304858497.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504309378610.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504305658517.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504306978550.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504311858672.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504309218606.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504313658717.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504309578615.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504307178555.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504309978625.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504312098678.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504313098703.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504308938599.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504307578565.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504311658667.jpg" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/10237504313338709.jpg" alt="" /></p>

<video controls="" src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/1443562780725462.mp4" preload="metadata"></video>

<video controls="" src="https://media.abapages.com/content/images/2026_from_fb/texas-trip-16-days-4600-km-drive/1427307505556370.mp4" preload="metadata"></video>]]></content><author><name>G Abarajithan</name></author><category term="Travel" /><category term="Travels" /><category term="Nature" /><category term="USA" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">AXI-Stream Systolic Array → SoC Testbed</title><link href="https://abapages.com/axis-systolic-array-testbed/" rel="alternate" type="text/html" title="AXI-Stream Systolic Array → SoC Testbed" /><published>2025-12-10T20:15:00+00:00</published><updated>2025-12-10T20:15:00+00:00</updated><id>https://abapages.com/axis-systolic-array-testbed</id><content type="html" xml:base="https://abapages.com/axis-systolic-array-testbed/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/axis-sa.png" alt="" /></p>

<p>I built this during my <a href="/cgra4ml/">CGRA4ML project</a>. I created many SoC integration &amp; verification methods to get CGRA4ML working, and I wanted to reuse that on many of my own projects and my friends’ projects. So I extracted the SoC-specific parts and created this testbed. As a simple, yet usable core IP, I created a systolic array that performs matrix multiplication.</p>

<h2 id="features">Features</h2>

<ul>
  <li>Currently being formally verified.</li>
  <li>Fully parameterized AXI-Stream Systolic Array that performs (<code class="language-plaintext highlighter-rouge">y = k.T @ x + a</code>).</li>
  <li>Configurable AXI memory ports (up to 4 <code class="language-plaintext highlighter-rouge">M_AXI</code> interfaces and 1 <code class="language-plaintext highlighter-rouge">S_AXIL</code>).</li>
  <li>Custom DMA controller with a register bank custom-mapped to firmware.</li>
  <li>Baremetal TCL implementation scripts for Xilinx ZCU104/ZCU102 boards.</li>
  <li>Ibex-SoC integration.</li>
</ul>

<p><strong><a href="https://github.com/abarajithan11/axis-systolic-array">GitHub - axis-systolic-array</a></strong></p>

<h2 id="systolic-array-dataflow">Systolic Array Dataflow</h2>

<p>The most interesting part was designing the propagation of control signals. To avoid heavy routing congestion and timing violations, standard AXI <code class="language-plaintext highlighter-rouge">valid</code> and <code class="language-plaintext highlighter-rouge">last</code> signals cannot be globally broadcast. Instead, they must move <strong>diagonally</strong> through the array during the multiply-accumulate phase. Then, when a compute matrix is complete, the results shift <strong>linearly</strong> to the right to be streamed out of the AXI ports.</p>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="c1">// Delay control signals diagonally across the array's computed length (LM+LA+D)</span>
  <span class="n">n_delay</span> <span class="p">#(.</span><span class="n">N</span><span class="p">(</span><span class="n">LM</span><span class="o">+</span><span class="n">LA</span><span class="o">+</span><span class="n">D</span><span class="p">),</span> <span class="p">.</span><span class="n">W</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="n">VALID</span> <span class="p">(.</span><span class="n">clk</span><span class="p">,</span> <span class="p">.</span><span class="n">e</span><span class="p">(</span><span class="n">en_mac</span><span class="p">),</span> <span class="p">.</span><span class="n">i</span><span class="p">(</span><span class="n">s_valid</span>           <span class="p">),</span> <span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">valid</span><span class="p">));</span>
  <span class="n">n_delay</span> <span class="p">#(.</span><span class="n">N</span><span class="p">(</span><span class="n">LM</span><span class="o">+</span><span class="n">LA</span><span class="o">+</span><span class="n">D</span><span class="p">),</span> <span class="p">.</span><span class="n">W</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="n">VLAST</span> <span class="p">(.</span><span class="n">clk</span><span class="p">,</span> <span class="p">.</span><span class="n">e</span><span class="p">(</span><span class="n">en_mac</span><span class="p">),</span> <span class="p">.</span><span class="n">i</span><span class="p">(</span><span class="n">s_valid</span> <span class="o">&amp;&amp;</span> <span class="n">s_last</span> <span class="p">),</span> <span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">vlast</span><span class="p">));</span>

  <span class="c1">// Output Register Control - Linear shifting of results </span>
  <span class="k">for</span> <span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">d</span><span class="o">&lt;</span><span class="n">D</span><span class="p">;</span> <span class="n">d</span><span class="o">=</span><span class="n">d</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="k">begin</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="o">==</span><span class="mi">0</span><span class="p">)</span>
      <span class="k">assign</span> <span class="n">r_last</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">r_valid</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="k">else</span>
      <span class="k">always_ff</span> <span class="o">@</span><span class="p">(</span><span class="kt">posedge</span> <span class="n">clk</span><span class="p">)</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">rstn</span><span class="p">)</span>
            <span class="n">r_last</span><span class="p">[</span><span class="n">d</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">en_shift</span><span class="p">)</span> 
          <span class="k">if</span> <span class="p">(</span><span class="n">d</span> <span class="o">&gt;=</span> <span class="n">C</span><span class="o">-</span><span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">m_last</span><span class="p">)</span> 
            <span class="n">r_last</span><span class="p">[</span><span class="n">d</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">;</span>            <span class="c1">// At the last AXI beat, clear all diagonal regs beyond C</span>
          <span class="k">else</span>
            <span class="n">r_last</span><span class="p">[</span><span class="n">d</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="n">r_last</span><span class="p">[</span><span class="n">d</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>  <span class="c1">// On non-last beats, shift the validation bits right linearly</span>
  <span class="k">end</span>
</code></pre></div></div>

<h2 id="simulation-via-axi-stream-vip">Simulation via AXI-Stream VIP</h2>

<p>Since the dataflow is quite delicate, I used my custom <a href="/reusable-axis-vip/">SystemVerilog AXI-Stream VIP</a> to verify the AXI-Stream IP with transaction-level randomized verification. This stress-tests the design with highly randomized backpressure, randomly dropping <code class="language-plaintext highlighter-rouge">tready</code> and inserting arbitrary gaps in <code class="language-plaintext highlighter-rouge">tvalid</code>.</p>

<p>I then built my <a href="/firebridge/">FireBridge VIP</a> around this, to do stress testing with real C firmware, emulating congestion in the full AXI ports (not just AXI Stream).</p>

<h2 id="formal-verification-with-ghost-abstractions">Formal Verification with Ghost Abstractions</h2>

<p>Currently, I am actively working on <strong>formally verifying</strong> this systolic array implementation. You can check my <a href="https://github.com/abarajithan11/axis-systolic-array/blob/master/formal/tb_axis_sa.sv">formal testbench here</a>.</p>

<p>I’m using the ghost abstraction method. I leave two input matrices unconstrained, so the tool can verify for all inputs. At an arbitrarily picked time, I wait for the current input packet to complete (<code class="language-plaintext highlighter-rouge">s_last_handshake</code>), then drive the selected input matrices on the slave side, after each handshake (<code class="language-plaintext highlighter-rouge">s_valid</code> is left arbitrary). On the output side, I compare every beat of the data to the expected matrix and set a flag. The SVA basically says “If input was seen, then output must be seen within X clock cycles”. There are a few fairness assumptions to prevent the tool from just holding <code class="language-plaintext highlighter-rouge">m_ready</code> down forever and giving a trivial counterexample.</p>

<h2 id="soc-design-elements">SoC Design Elements</h2>

<p>I used DMAs and the interconnect from Alex Forencich’s <a href="https://github.com/alexforencich/verilog-axi">AXI repository</a> to turn the AXI-Stream module into a full AXI module. I built a DMA controller for the four DMAs with a register bank that is written and read from the firmware. I have TCL scripts for Vivado to implement this on the FPGA, which I have tested on ZYNQ boards.</p>

<p>I then integrated this with Ibex-SoC to create a full SoC. The same C firmware compiles to RISC-V and runs on Ibex in simulation.</p>

<p>I used my <a href="/firebridge/">FireBridge</a> VIP to stress test the full AXI ports with real C firmware, emulating congestion.</p>

<h2 id="fixing-the-soc-deadlock-due-to-circular-dependency">Fixing the SoC Deadlock due to Circular Dependency</h2>

<p>I faced an AXI deadlock problem during Ibex integration. The systolic array does <code class="language-plaintext highlighter-rouge">y = k@x + a</code>, on 3 input matrices. All 4 interfaces are AXI-Stream (3 slaves, one master). I put 4 AXI DMAs on them, which gave 4 AXI masters. Then I used a crossbar across them to unify the 4 masters into one master, and connected that to the memory slave. I set the burst length to 1.</p>

<p>During simulation, the k-DMA kept sending requests, the crossbar kept sending that to the slave. At some point, the k-AXI-Stream got stalled by the SA, because the SA didn’t have the a-stream, because the single AXI port was being used by the k-DMA. So now, the k-DMA cannot push data into the stream. But the slave was responding with rdata for its requests, and it cannot accept them. So the crossbar is stalled, waiting for the k-AXI port to accept the slave’s responses before switching to another master. This is a deadlock because of this circular dependency.</p>

<p>One way to temporarily solve it is by using FIFOs of appropriate length on the AXI port. But that does not work when the matrix sizes and lengths of AXI packets are dynamic.</p>

<p>The real bug was that Alex Forencich’s DMA was pre-fetching requests without having enough buffer to hold the responses of its outstanding requests when the output stream stalls. Fixing this within the IP is non-trivial, so I implemented a patch by gating the DMA’s request port using the <code class="language-plaintext highlighter-rouge">ready</code> from the stream side. When the systolic array pulls <code class="language-plaintext highlighter-rouge">ready</code> down, the DMA thinks the crossbar has also pulled <code class="language-plaintext highlighter-rouge">arready</code> down and the crossbar thinks DMA has pulled <code class="language-plaintext highlighter-rouge">arvalid</code> down. This worked, although it is not strictly AXI compliant in a way where <code class="language-plaintext highlighter-rouge">valid</code> has to be held stable during an <code class="language-plaintext highlighter-rouge">arready</code> stall.</p>

<p><strong><a href="https://github.com/abarajithan11/axis-systolic-array">GitHub - axis-systolic-array</a></strong></p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">TIL a little more about Noether’s theorem</title><link href="https://abapages.com/other/til-a-little-more-about-noether-s-theorem/" rel="alternate" type="text/html" title="TIL a little more about Noether’s theorem" /><published>2025-12-09T00:11:48+00:00</published><updated>2025-12-09T00:11:48+00:00</updated><id>https://abapages.com/other/til-a-little-more-about-noether-s-theorem</id><content type="html" xml:base="https://abapages.com/other/til-a-little-more-about-noether-s-theorem/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026_from_fb/noether.png" alt="" /></p>

<p>Emmy Noether was a mathematician who looked into why energy is not conserved in Einstein’s General Relativity, and came up with a fundamental theorem of reality that generalizes to all conservation laws. For example:</p>

<ul>
  <li>Momentum is conserved iff there’s a translation symmetry (if it doesn’t matter WHERE something happens)</li>
  <li>Energy is conserved iff there’s a time symmetry (if it doesn’t matter WHEN something happens)</li>
</ul>

<p><a href="https://www.youtube.com/watch?app=desktop&amp;v=04ERSb06dOg&amp;t=610s">Basic intro</a></p>

<p><a href="https://www.youtube.com/watch?v=w7Q5mQA_74o">Proof and simple derivations</a></p>]]></content><author><name>G Abarajithan</name></author><category term="Other" /><category term="Thoughts" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">AI Engine Experiments</title><link href="https://abapages.com/amd-aie-explorations/" rel="alternate" type="text/html" title="AI Engine Experiments" /><published>2025-10-25T20:40:00+00:00</published><updated>2025-10-25T20:40:00+00:00</updated><id>https://abapages.com/amd-aie-explorations</id><content type="html" xml:base="https://abapages.com/amd-aie-explorations/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/aie_tiles.png" alt="" /></p>

<p><img src="https://media.abapages.com/content/images/2026/aie_wave.jpg" alt="" /></p>

<p>AMD AI Engine development usually involves three pieces:</p>

<ol>
  <li><strong>Kernel code</strong> (C++)</li>
  <li><strong>Graph code</strong> (C++ or Python)</li>
  <li><strong>Host code</strong> (C++ or Python)</li>
</ol>

<p>For kernels, I have explored the lower-level side of the stack:</p>

<ul>
  <li><strong>Intrinsics</strong>: direct programming of AIE vector/MAC operations</li>
  <li><strong>APIs</strong>: C++ wrappers around intrinsics from AMD</li>
</ul>

<p>For graph design, the options are:</p>

<ul>
  <li><strong>Vitis graph flow</strong> in C++</li>
  <li><strong>MATLAB/Simulink-based flow</strong></li>
  <li><strong>IRON</strong> in Python</li>
</ul>

<h2 id="early-work-intrinsics--matlab">Early work: intrinsics + MATLAB</h2>

<p>My first AIE experiments started with <strong>intrinsics + MATLAB</strong> in this repo: <strong><a href="https://github.com/abarajithan11/amd_aie_matlab">amd_aie_matlab</a></strong>.</p>

<p>This repo includes small matrix/vector experiments such as <code class="language-plaintext highlighter-rouge">gemv</code>, <code class="language-plaintext highlighter-rouge">gemv_opt</code>, and <code class="language-plaintext highlighter-rouge">gemv_opt_i8</code>, along with MATLAB/Simulink files and AIE kernel code. The flow was simple: generate test data, run the model, and compare the simulated output against a golden result.</p>

<p><img src="https://media.abapages.com/content/images/2026/aie_autoenc_matlab.png" alt="" /></p>

<p>That work later evolved into this repository where some undegrad students work on optimizing intrinsics for GEMV and GEMM: <strong><a href="https://github.com/KastnerRG/aie-intrinsics-nn">aie-intrinsics-nn</a></strong>. This effort moved toward a more structured intrinsics-based workflow for small neural-network style building blocks. The focus was on reusable kernels and a clearer path from GemV-style experiments toward denser NN-style compositions.</p>

<h2 id="lightweight-backend-work-for-hls4ml">Lightweight backend work for hls4ml</h2>

<p>The next step was this repo: <strong><a href="https://github.com/KastnerRG/hls4ml-backend">hls4ml-backend</a></strong>, for mapping small neural-network style computations onto AIE as an effort to create a backend for the popular python based tool <code class="language-plaintext highlighter-rouge">hls4ml</code>. It includes quickstart and <code class="language-plaintext highlighter-rouge">run_workload.py</code>, serving as a sandbox for experimenting with how small physics NN layers could be laid out across AIE resources.</p>

<p><img src="https://media.abapages.com/content/images/2026/aie_stream_window.png" alt="" /></p>

<h2 id="teaching-material">Teaching material</h2>

<p>I also worked as a Teaching Assistant (TA) for the AI Engine portion of Ryan’s <strong>CSE237C</strong> course. The public assignment and starter material are here:</p>

<ul>
  <li><strong><a href="https://pp4fpgas.readthedocs.io/en/latest/project_aie.html">Assignment page</a></strong></li>
  <li><strong><a href="https://github.com/KastnerRG/Read_the_docs/tree/master/project_files/aie-project">Starter files</a></strong></li>
</ul>

<p>This material introduces the AIE programming model through:</p>

<ul>
  <li>host / graph / kernel separation</li>
  <li>IRON-based Python graph construction</li>
  <li>tiled matrix multiplication</li>
  <li>single-core and whole-array examples</li>
  <li>small NN-style exercises built from these pieces</li>
</ul>

<p>The assignment code includes files like <code class="language-plaintext highlighter-rouge">basic_mm.py</code>, <code class="language-plaintext highlighter-rouge">matmul.cc</code>, <code class="language-plaintext highlighter-rouge">passthrough.py</code>, and <code class="language-plaintext highlighter-rouge">nn.py</code>.</p>

<p><img src="https://media.abapages.com/content/images/2026/aie_project.png" alt="" /></p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="Other Hardware" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">FireBridge: Verifying SoC Subsystems with Real Firmware Without Simulating a CPU</title><link href="https://abapages.com/firebridge/" rel="alternate" type="text/html" title="FireBridge: Verifying SoC Subsystems with Real Firmware Without Simulating a CPU" /><published>2025-10-16T20:00:00+00:00</published><updated>2025-10-16T20:00:00+00:00</updated><id>https://abapages.com/firebridge-soc-verification</id><content type="html" xml:base="https://abapages.com/firebridge/"><![CDATA[<p><img src="https://media.abapages.com/content/images/2026/firebridge.png" alt="" /></p>

<p>Verifying hardware accelerators at the system level is a classic headache. We first verify the RTL design using transaction level testbenches, then write firmware to control them, then put them together on an FPGA and bang our heads wondering why they hang. Getting the firmware and hardware to work together often takes weeks of iterative debugging. On the other hand, simulating a full CPU + accelerator as an SoC takes forever.</p>

<p>I wanted to quickly co-develop SystemVerilog hardware and C firmware. This led me to build <strong>FireBridge</strong> as part of a <strong>CGRA4ML</strong> project.</p>

<h2 id="features-of-firebridge">Features of FireBridge</h2>

<ul>
  <li>Allows transactional verification of an SoC with real C firmware.</li>
  <li>Completely removes the need to simulate the entire CPU.</li>
  <li>Seamlessly integrates with Ibex and typical RISC-V toolchains.</li>
  <li>Supports randomized ready/valid throttling, which uncovers subtle corner cases.</li>
</ul>

<h2 id="how-to-use">How to use</h2>

<p>C Firmware:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">cfg0</span> <span class="o">=</span> <span class="p">(</span><span class="n">fb_reg_t</span><span class="o">*</span><span class="p">)</span><span class="mh">0xA0000000u</span><span class="p">;</span>  <span class="c1">// slave window 0</span>
<span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">cfg1</span> <span class="o">=</span> <span class="p">(</span><span class="n">fb_reg_t</span><span class="o">*</span><span class="p">)</span><span class="mh">0xA1000000u</span><span class="p">;</span>  <span class="c1">// slave window 1</span>

<span class="n">fb_write_reg</span><span class="p">(</span><span class="n">cfg0</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// write 10 to the 2nd register in slave 0</span>
<span class="n">fb_write_reg</span><span class="p">(</span><span class="n">cfg1</span> <span class="o">+</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">20</span><span class="p">);</span> <span class="c1">// write 20 to the 6th register in slave 1</span>
</code></pre></div></div>

<p>SystemVerilog Testbench:</p>

<div class="language-verilog highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">module</span> <span class="n">tb</span><span class="p">;</span>
  <span class="k">localparam</span> <span class="kt">int</span> <span class="n">S_COUNT</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">M_COUNT</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>

  <span class="c1">// VIP -&gt; DUT slave windows (MMIO)</span>
  <span class="kt">logic</span> <span class="p">[</span><span class="n">S_COUNT</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">][</span><span class="n">ID_W</span>  <span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span> <span class="n">s_axi_awid</span><span class="p">;</span>
  <span class="kt">logic</span> <span class="p">[</span><span class="n">S_COUNT</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">][</span><span class="n">ADDR_W</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span> <span class="n">s_axi_awaddr</span><span class="p">;</span>
  <span class="p">...</span>
  <span class="c1">// DUT masters -&gt; VIP DDR</span>
  <span class="kt">logic</span> <span class="p">[</span><span class="n">M_COUNT</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">][</span><span class="n">ID_W</span>  <span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span> <span class="n">m_axi_arid</span><span class="p">;</span>
  <span class="kt">logic</span> <span class="p">[</span><span class="n">M_COUNT</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">][</span><span class="n">ADDR_W</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span> <span class="n">m_axi_araddr</span><span class="p">;</span>
  <span class="p">...</span>

  <span class="c1">// Two slave base addrs. Concatenation corresponds to indices [1], [0].</span>
  <span class="k">localparam</span> <span class="p">[</span><span class="n">S_COUNT</span><span class="o">-</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">][</span><span class="mi">31</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span> <span class="n">S_BASE</span> <span class="o">=</span> <span class="o">{</span>
    <span class="mh">32'hA100_0000</span><span class="p">,</span>  <span class="c1">// s=1 (window 1)</span>
    <span class="mh">32'hA000_0000</span>   <span class="c1">// s=0 (window 0)</span>
  <span class="o">}</span><span class="p">;</span>

  <span class="n">fb_axi_vip</span> <span class="p">#(</span>
    <span class="p">.</span><span class="n">S_COUNT</span><span class="p">(</span><span class="n">S_COUNT</span><span class="p">),</span>
    <span class="p">.</span><span class="n">M_COUNT</span><span class="p">(</span><span class="n">M_COUNT</span><span class="p">),</span>
    <span class="p">.</span><span class="n">S_AXI_BASE_ADDR</span><span class="p">(</span><span class="n">S_BASE</span><span class="p">),</span>
    <span class="p">...</span>
  <span class="p">)</span> <span class="n">FB</span> <span class="p">(.</span><span class="o">*</span><span class="p">);</span>

  <span class="n">my_ip</span> <span class="n">DUT</span> <span class="p">(</span>
    <span class="p">.</span><span class="n">clk</span><span class="p">(</span><span class="n">clk</span><span class="p">),</span> <span class="p">.</span><span class="n">rstn</span><span class="p">(</span><span class="n">rstn</span><span class="p">),</span> <span class="p">...</span>
    <span class="p">.</span><span class="n">s_axi0_awaddr</span> <span class="p">(</span><span class="n">s_axi_awaddr</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">...</span>
    <span class="p">.</span><span class="n">s_axi1_awaddr</span> <span class="p">(</span><span class="n">s_axi_awaddr</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">...</span>
    <span class="p">.</span><span class="n">m_axi0_araddr</span> <span class="p">(</span><span class="n">m_axi_araddr</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">...</span>
    <span class="p">.</span><span class="n">m_axi1_araddr</span> <span class="p">(</span><span class="n">m_axi_araddr</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">...</span>
  <span class="p">);</span>

  <span class="k">initial</span> <span class="k">begin</span>
    <span class="kt">repeat</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">@</span><span class="p">(</span><span class="kt">posedge</span> <span class="n">clk</span><span class="p">);</span>
    <span class="n">rstn</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="k">wait</span> <span class="p">(</span><span class="n">firebridge_done</span><span class="p">);</span>
    <span class="p">$</span><span class="nb">finish</span><span class="p">;</span>
  <span class="k">end</span>
<span class="k">endmodule</span>
</code></pre></div></div>

<h2 id="technical-details">Technical Details</h2>

<p>I built an SV + C harness that behaves in simulation as an AXI Interconnect + CPU. The C firmware is compiled and executed in the host machine (x86). The register writes &amp; reads are mapped to SV tasks that drive the AXI slave interfaces. The AXI master ports of the subsystem read/write from the host machine’s DDR through C functions.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifdef SIM
</span>  <span class="k">extern</span> <span class="kt">void</span> <span class="nf">fb_task_write_reg</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">data</span><span class="p">);</span>
  <span class="k">extern</span> <span class="kt">void</span> <span class="nf">fb_task_read_reg</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">);</span>
  <span class="k">extern</span> <span class="kt">uint64_t</span> <span class="nf">fb_fn_read_reg</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>

  <span class="k">static</span> <span class="kr">inline</span> <span class="n">fb_reg_t</span> <span class="nf">fb_read_reg</span><span class="p">(</span><span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">fb_task_read_reg</span><span class="p">((</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">addr</span><span class="p">);</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">fb_reg_t</span><span class="p">)</span><span class="n">fb_fn_read_reg</span><span class="p">();</span>
  <span class="p">}</span>
  <span class="k">static</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">fb_write_reg</span><span class="p">(</span><span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="n">fb_reg_t</span> <span class="n">data</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">fb_task_write_reg</span><span class="p">((</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">addr</span><span class="p">,</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">)</span><span class="n">data</span><span class="p">);</span>
  <span class="p">}</span>
<span class="cp">#else
</span>  <span class="k">static</span> <span class="kr">inline</span> <span class="n">fb_reg_t</span> <span class="nf">fb_read_reg</span><span class="p">(</span><span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="o">*</span><span class="n">addr</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">static</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">fb_write_reg</span><span class="p">(</span><span class="n">fb_reg_t</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="n">fb_reg_t</span> <span class="n">data</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">*</span><span class="n">addr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
  <span class="p">}</span>
<span class="cp">#endif
</span></code></pre></div></div>

<p>I built a Makefile flow to make this setup work with XSim and Xcelium. The entire setup is also containerized in Docker for reproducibility.</p>

<h2 id="problems-faced-and-solved">Problems Faced and Solved</h2>

<p>A real CPU stalls and cache misses. While FireBridge doesn’t model these exact CPU stalls, I implemented randomized delays and randomized ready/valid backpressure on the AXI channels. This ended up being far more effective at catching timing bugs in the DMA and Systolic Array than standard CPU execution.</p>

<p>Integrating the full Ibex SoC for final validation proved this approach. The design verified via FireBridge worked as is on the actual Ibex-driven SoC simulation, and on FPGA with ARM-based Zynq SoC.</p>

<p>You can check out the testbed and the code here: <a href="https://github.com/abarajithan11/axis-systolic-array/tree/master/firebridge">GitHub</a></p>]]></content><author><name>G Abarajithan</name></author><category term="Projects" /><category term="SoC" /><category term="AXI" /><summary type="html"><![CDATA[]]></summary></entry></feed>