About Social Code
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpgbin0 -> 46335 bytes
-rw-r--r--html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-scaled.jpgbin0 -> 178193 bytes
-rw-r--r--html/assets/2020-04-07-generating-video/IMG_20200407_172119-scaled.jpgbin0 -> 178193 bytes
-rw-r--r--html/assets/2020-04-07-generating-video/sync.pngbin0 -> 11435 bytes
-rw-r--r--html/assets/2020-04-07-generating-video/visible_invisible.pngbin0 -> 26098 bytes
-rw-r--r--html/assets/2021-12-10-n64brew-gamejam-2021/bug_1.pngbin0 -> 23642 bytes
-rw-r--r--html/assets/2021-12-10-n64brew-gamejam-2021/bug_2.pngbin0 -> 49652 bytes
-rw-r--r--html/assets/2021-12-10-n64brew-gamejam-2021/bug_3.pngbin0 -> 69392 bytes
-rw-r--r--html/assets/2021-12-10-n64brew-gamejam-2021/bug_4.pngbin0 -> 58208 bytes
-rw-r--r--html/assets/2021-12-10-n64brew-gamejam-2021/bug_5.pngbin0 -> 50718 bytes
-rw-r--r--html/assets/style.css33
-rw-r--r--html/index.html13
-rw-r--r--html/notes/generating-video.html487
-rw-r--r--html/notes/n64brew-gamejam-2021.html71
-rw-r--r--notes/generating-video.md289
-rw-r--r--notes/n64brew-gamejam-2021.md57
16 files changed, 950 insertions, 0 deletions
diff --git a/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpg b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpg
new file mode 100644
index 0000000..4e1633e
--- /dev/null
+++ b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpg
Binary files differ
diff --git a/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-scaled.jpg b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-scaled.jpg
new file mode 100644
index 0000000..8f0e350
--- /dev/null
+++ b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-1-scaled.jpg
Binary files differ
diff --git a/html/assets/2020-04-07-generating-video/IMG_20200407_172119-scaled.jpg b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-scaled.jpg
new file mode 100644
index 0000000..8f0e350
--- /dev/null
+++ b/html/assets/2020-04-07-generating-video/IMG_20200407_172119-scaled.jpg
Binary files differ
diff --git a/html/assets/2020-04-07-generating-video/sync.png b/html/assets/2020-04-07-generating-video/sync.png
new file mode 100644
index 0000000..719a7e6
--- /dev/null
+++ b/html/assets/2020-04-07-generating-video/sync.png
Binary files differ
diff --git a/html/assets/2020-04-07-generating-video/visible_invisible.png b/html/assets/2020-04-07-generating-video/visible_invisible.png
new file mode 100644
index 0000000..d31711b
--- /dev/null
+++ b/html/assets/2020-04-07-generating-video/visible_invisible.png
Binary files differ
diff --git a/html/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png
new file mode 100644
index 0000000..ca96bd9
--- /dev/null
+++ b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png
Binary files differ
diff --git a/html/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png
new file mode 100644
index 0000000..cf3949e
--- /dev/null
+++ b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png
Binary files differ
diff --git a/html/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png
new file mode 100644
index 0000000..f435e96
--- /dev/null
+++ b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png
Binary files differ
diff --git a/html/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png
new file mode 100644
index 0000000..fc00022
--- /dev/null
+++ b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png
Binary files differ
diff --git a/html/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png
new file mode 100644
index 0000000..7a202b2
--- /dev/null
+++ b/html/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png
Binary files differ
diff --git a/html/assets/style.css b/html/assets/style.css
index faee4ab..06345df 100644
--- a/html/assets/style.css
+++ b/html/assets/style.css
@@ -8,6 +8,39 @@
background-color: #e9e9e7;
}
+div.gallery p {
+ margin: 5px;
+ width: auto;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+
+div.gallery img {
+ width: 300px;
+ height: auto;
+ margin-bottom: 2px;
+ margin-left: 2px;
+ margin-right: 0;
+ margin-top: 0;
+}
+
+table
+{
+ border-collapse: collapse;
+}
+
+td
+{
+ padding: 2px;
+}
+
+table, th, td
+{
+ border: 1px solid;
+}
+
body
{
background-color: #e9e9e7;
diff --git a/html/index.html b/html/index.html
index 67fe83c..3a84a5f 100644
--- a/html/index.html
+++ b/html/index.html
@@ -39,6 +39,13 @@
<h2 class="main-heading">Notes</h2>
<div class="notes-container">
+ <a href="/notes/n64brew-gamejam-2021.html" class="note-link">
+ <div class="note-box">
+ <img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png">
+ <h2>N64Brew GameJam 2021</h2>
+ <p>So this year, myself and two others decided to participate together in the N64Brew homebrew where ...</p>
+ </div>
+ </a>
<a href="/notes/digital_garden.html" class="note-link">
<div class="note-box">
<h2>Digital Garden</h2>
@@ -59,6 +66,12 @@
<p>After re-watching suckerpinch’s Reverse Emulation video I got inspired to try and replicate what ...</p>
</div>
</a>
+ <a href="/notes/generating-video.html" class="note-link">
+ <div class="note-box">
+ <h2>Generating Video</h2>
+ <p>One thing I’m very interested in is computer graphics. This could be complex 3D graphics or 2D ...</p>
+ </div>
+ </a>
</div>
</div> </main>
</body>
diff --git a/html/notes/generating-video.html b/html/notes/generating-video.html
new file mode 100644
index 0000000..0ec6c74
--- /dev/null
+++ b/html/notes/generating-video.html
@@ -0,0 +1,487 @@
+<!doctype html>
+
+<html class="html-note-page" lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>Generating Video</title>
+ <meta name="dcterms.date" content="2020-04-07" />
+
+ <link rel="stylesheet" href="/assets/style.css">
+ <link rel="icon" type="image/x-icon" href="/assets/favicon.svg">
+</head>
+
+<body>
+ <div class="header-bar">
+ <a href="/index.html">
+ <img src="/assets/favicon.svg" alt="frycon logo">
+ </a>
+ <div class="header-links">
+ <a href="/now.html" class="header-link">Now</a>
+ <a href="/about.html" class="header-link">About</a>
+ </div>
+ </div>
+ <main>
+<div class="page-title-header-container">
+ <h1 class="page-title-header">Generating Video</h1>
+ <div class="page-info-container">
+ <div class="plant-status">
+ <img src="/assets/evergreen.svg">
+ <div class="plant-status-text">
+ <p>evergreen</p>
+ </div>
+ </div>
+ <div class="page-info-date-container">
+ <p class="page-info-date">Published: 2020-04-07</p>
+ <p class="page-info-date">Last Edited: 2022-01-20</p>
+ </div>
+ </div>
+ </div>
+<div class="note-divider"></div>
+<div class="main-container">
+ <div class="note-body">
+<p>One thing I’m very interested in is computer graphics. This could be complex 3D graphics or simple 2D graphics. The idea of getting a computer to display visual data fascinates me. One fundamental part of showing visual data is interfacing with a computer monitor. This can be accomplished by generating a video signal that the monitor understands. Below I have written instructions on how an FPGA can be used to generate a video signal. I have specifically worked with the iCEBreaker FPGA but the theory contained within this should work with any FPGA or device that you can generate the appropriate timings for.</p>
+<h3 id="tools">Tools</h3>
+<p>Hardware used (<a href="https://www.crowdsupply.com/1bitsquared/icebreaker-fpga">link for board</a>):</p>
+<ul>
+<li>iCEBreaker FPGA</li>
+<li>iCEBreaker 12-Bit DVI Pmod</li>
+</ul>
+<p>Software Used:</p>
+<ul>
+<li>IceStorm FPGA toolchain (<a href="https://github.com/esden/summon-fpga-tools">follow install instructions here</a>)</li>
+</ul>
+<h3 id="theory">Theory</h3>
+<p>A video signal is composed of several parts, primarily the colour signals and the sync signals. For this DVI Pmod, there is also a data enable signal for the visible screen area. For the example here we are going to be generating a 640x480 60 Hz video signal. Below is a table describing the important data for our video signal.</p>
+<table>
+<tbody>
+<tr>
+<td>
+Pixel Clock
+</td>
+<td>
+25.175 MHz
+</td>
+</tr>
+<tr>
+<td>
+Pixels Per Line
+</td>
+<td>
+800 Pixels
+</td>
+</tr>
+<tr>
+<td>
+Pixels Visible Per Line
+</td>
+<td>
+640 Pixels
+</td>
+</tr>
+<tr>
+<td>
+Horizontal Sync Front Porch Length
+</td>
+<td>
+16 Pixels
+</td>
+</tr>
+<tr>
+<td>
+Horizontal Sync Length
+</td>
+<td>
+96 Pixels
+</td>
+</tr>
+<tr>
+<td>
+Horizontal Sync Back Porch Length
+</td>
+<td>
+48 Pixels
+</td>
+</tr>
+<tr>
+<td>
+Lines Per Frame
+</td>
+<td>
+525 Lines
+</td>
+</tr>
+<tr>
+<td>
+Lines Visible Per Frame
+</td>
+<td>
+480 Lines
+</td>
+</tr>
+<tr>
+<td>
+Vertical Front Porch Length
+</td>
+<td>
+10 Lines
+</td>
+</tr>
+<tr>
+<td>
+Vertical Sync Length
+</td>
+<td>
+2 Lines
+</td>
+</tr>
+<tr>
+<td>
+Vertical Back Porch Length
+</td>
+<td>
+33 Lines
+</td>
+</tr>
+</tbody>
+</table>
+<p>Sourced from http://www.tinyvga.com/vga-timing/640x480@60Hz</p>
+<p>The data from this table raises a few questions:</p>
+<ol type="1">
+<li>What is the Pixel Clock?</li>
+<li>What is the difference between “Pixels/Lines” and “Visible Pixels/Lines”?</li>
+<li>What is “Front Porch”, “Sync”, and “Back Porch”?</li>
+</ol>
+<h4 id="pixel-clock">Pixel Clock</h4>
+<p>The pixel clock is a fairly straightforward idea; this is the rate at which we generate pixels. For video signal generation, the “pixel” is a fundamental building block and we count things in the number of pixels it takes up. Every time the pixel clock “ticks” we have incremented the number of pixels we have processed. So for a 640x480 video signal, a full line is 800 pixels, or 800 clock ticks. For the full 800x525 frame there is 800 ticks x 525 lines, or 420000 clock ticks. If we are running the display at 60 Hz, 420000 pixels per frame are generated 60 times per second. Therefore, 25200000 pixels or clock ticks will pass in one second. From this we can see the pixel clock frequency of 25.175 MHz is roughly equal to 25200000 clock ticks. There is a small deviance from the “true” values here, but monitors are flexible enough to accept this video signal (my monitor reports it as 640x480@60Hz), and all information I can find online says that 25.175 MHz is the value you want to use. Later on we will see that the pixel clock is not required to be exactly 25.175 Mhz.</p>
+<h4 id="visible-area-vs-invisible-area">Visible Area vs Invisible Area</h4>
+<p><img src="/assets/2020-04-07-generating-video/visible_invisible.png" /></p>
+<p>From the above image we can see that a 640x480 video signal actually generates a resolution larger than 640x480. The true resolution we generate is 800x525, but only a 640x480 portion of that signal is visible. The area that is not visible is where we generate the sync signal. In other words, every part of the above image that is black is where a sync signal is being generated.</p>
+<h4 id="front-porch-back-porch-sync">Front Porch, Back Porch &amp; Sync</h4>
+<p>To better understand the front porch, back porch and sync signal, let’s look at what the horizontal sync signal looks like during the duration of a line:</p>
+<p><img src="/assets/2020-04-07-generating-video/sync.png" /></p>
+<p>From this we can see that the “Front Porch” is the invisible pixels between the visible pixels and the sync pixels, and is represented by a logical one or high signal. The “Sync” is the invisible pixels between the front porch and back porch, and is represented by a logical zero or low signal. The “Back Porch” is the invisible pixels after the sync signal, and is represented by a logical one. For the case of 640x480 video, the visible pixel section lasts for 640 pixels. The front porch section lasts for 16 pixels, after which the sync signal will become a logical zero. This logical zero sync will last for 96 pixels, after which the sync signal will become a logical one again. The back porch will then last for 48 pixels. If you do a quick calculation right now of 640 + 16 + 96 + 48, we get 800 pixels which represents the full horizontal resolution of the display. The vertical sync signal works almost exactly the same, except the vertical sync signal acts on lines.</p>
+<h3 id="implementation">Implementation</h3>
+<p>The first thing we can do that is going to simplify a lot of the following logic is to keep track of which pixel, and which line we are on. The below code block creates two registers to keep track of the current pixel on the line (column) and the current line (line):</p>
+<div class="sourceCode" id="cb1"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">9</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> line<span class="op">;</span></span>
+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">9</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> column<span class="op">;</span></span>
+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">always</span> <span class="op">@(</span><span class="kw">posedge</span> clk <span class="dt">or</span> <span class="kw">posedge</span> reset<span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">if</span><span class="op">(</span>reset <span class="op">==</span> <span class="dv">1</span><span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">begin</span></span>
+<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">if</span><span class="op">(</span>column <span class="op">==</span> <span class="dv">799</span> <span class="op">&amp;&amp;</span> line <span class="op">==</span> <span class="dv">524</span><span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">if</span><span class="op">(</span>column <span class="op">==</span> <span class="dv">799</span><span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> line <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">begin</span></span>
+<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> column <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span></code></pre></div>
+<p>This block of Verilog works by first initializing the line and column register to zero on a reset. This is important to make sure that we start from known values, otherwise the line and column register could contain any value and our logic would not work. Next, we check if we are at the bottom of the screen by comparing the current column to 799 (the last pixel in the line) and the current line is 524 (the last line in the frame). If these conditions are both true then we reset the line and column back to zero to signify that we are starting a new frame. The next block checks if the current column equals 799. Because the above if statement failed,we know that we are at the end of the line but not the end of the frame. If this is true we increment the current line count and set the column back to zero to signify that we are starting a new line. The final block simply increments the current pixel count. If we reach this block ,we are neither at the end of the line or the end of the frame so we can simply increment to the next pixel.</p>
+<p>Now that we are keeping track of the current column and current line, we can use this information to generate the horizontal and vertical sync signals. From the theory above we know that the sync signal is only low when we are between the front and back porch, at all other times the signal is high. From this we can generate the sync signal with an OR and two compares.</p>
+<div class="sourceCode" id="cb2"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>logic horizontal_sync<span class="op">;</span></span>
+<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>logic vertical_sync<span class="op">;</span></span>
+<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> horizontal_sync <span class="op">=</span> column <span class="op">&lt;</span> <span class="dv">656</span> <span class="op">||</span> column <span class="op">&gt;=</span> <span class="dv">752</span><span class="op">;</span></span>
+<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> vertical_sync <span class="op">=</span> line <span class="op">&lt;</span> <span class="dv">490</span> <span class="op">||</span> line <span class="op">&gt;=</span> <span class="dv">492</span><span class="op">;</span></span></code></pre></div>
+<p>Let’s examine the horizontal sync signal more closely. This statement will evaluate to true if the current column is less than 656 or the current column is greater than or equal to 752. This means that the horizontal sync signal will be true except for when the current column is between 656 and 751 inclusively. That is starting on column 656 the horizontal sync signal will become false (low) and will remain that way for the next 96 pixels until we reach pixel 752 where it will return to being true (high). The vertical sync signal will work in the same way except it is turned on based on the current line. Therefore, the signal will remain high when the line is less than 490 and greater than or equal to 492, and will remain low between lines 490 and 491 inclusive.</p>
+<h4 id="putting-it-all-together">Putting It All Together</h4>
+<p>Now that we have generated the video signal, we need to route it towards the video output connectors on the iCEBreaker 12-bit DVI Pmod. We also need to configure the iCEBreaker FPGA to have the appropriate pixel clock frequency. First to get the correct pixel clock we are going to use the following block of code:</p>
+<div class="sourceCode" id="cb3"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>SB_PLL40_PAD #<span class="op">(</span></span>
+<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> .DIVR<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> .DIVF<span class="op">(</span><span class="bn">7&#39;b1000010</span><span class="op">),</span></span>
+<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> .DIVQ<span class="op">(</span><span class="bn">3&#39;b101</span><span class="op">),</span></span>
+<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> .FILTER_RANGE<span class="op">(</span><span class="bn">3&#39;b001</span><span class="op">),</span></span>
+<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> .FEEDBACK_PATH<span class="op">(</span><span class="st">&quot;SIMPLE&quot;</span><span class="op">),</span></span>
+<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> .DELAY_ADJUSTMENT_MODE_FEEDBACK<span class="op">(</span><span class="st">&quot;FIXED&quot;</span><span class="op">),</span></span>
+<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> .FDA_FEEDBACK<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> .DELAY_ADJUSTMENT_MODE_RELATIVE<span class="op">(</span><span class="st">&quot;FIXED&quot;</span><span class="op">),</span></span>
+<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a> .FDA_RELATIVE<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a> .SHIFTREG_DIV_MODE<span class="op">(</span><span class="bn">2&#39;b00</span><span class="op">),</span></span>
+<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a> .PLLOUT_SELECT<span class="op">(</span><span class="st">&quot;GENCLK&quot;</span><span class="op">),</span></span>
+<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a> .ENABLE_ICEGATE<span class="op">(</span><span class="bn">1&#39;b0</span><span class="op">)</span></span>
+<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> usb_pll_inst <span class="op">(</span></span>
+<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a> .PACKAGEPIN<span class="op">(</span>CLK<span class="op">),</span></span>
+<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a> .PLLOUTCORE<span class="op">(</span>pixel_clock<span class="op">),</span></span>
+<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a> .EXTFEEDBACK<span class="op">(),</span></span>
+<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a> .DYNAMICDELAY<span class="op">(),</span></span>
+<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a> .RESETB<span class="op">(</span><span class="bn">1&#39;b1</span><span class="op">),</span></span>
+<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a> .BYPASS<span class="op">(</span><span class="bn">1&#39;b0</span><span class="op">),</span></span>
+<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a> .LATCHINPUTVALUE<span class="op">(),</span></span>
+<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
+<p>This block is mainly a copy paste of the PLL setup code from the iCEBreaker examples, but with a few important changes. The DIVR, DIVF, and DIVQ values are changed to create a 25.125 MHz. This is not exactly 25.175 MHz, but it is close enough that the monitor is happy enough and recognizes it as a 640x480@60 Hz signal. These values were found through the “icepll” utility, below is an example of calling this utility from the command line:</p>
+<pre><code>$ icepll -i 12 -o 25.175
+
+F_PLLIN: 12.000 MHz (given)
+F_PLLOUT: 25.175 MHz (requested)
+F_PLLOUT: 25.125 MHz (achieved)
+
+FEEDBACK: SIMPLE
+F_PFD: 12.000 MHz
+F_VCO: 804.000 MHz
+
+DIVR: 0 (4&#39;b0000)
+DIVF: 66 (7&#39;b1000010)
+DIVQ: 5 (3&#39;b101)
+
+FILTER_RANGE: 1 (3&#39;b001)</code></pre>
+<p>From here we can see we had an input clock of 12 MHz (This comes from the FTDI chip on the iCEBreaker board), and we wanted to get a 25.175 MHz output clock. The closest the PLL could generate was a 25.125 MHz clock with the settings provided for the DIVR, DIVF, and DIVQ values.</p>
+<p>Now that we have a pixel clock we can wire up the necessary signals for the DVI video out. The DVI Pmod has the following mapping for all of its connectors:</p>
+<table>
+<tbody>
+<tr>
+<td>
+PMOD 1
+</td>
+<td>
+</td>
+<td>
+PMOD 2
+</td>
+<td>
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A1</strong>
+</td>
+<td>
+Red bit 4
+</td>
+<td>
+<strong>P1B1</strong>
+</td>
+<td>
+Blue bit 4
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A2</strong>
+</td>
+<td>
+Red bit 3
+</td>
+<td>
+<strong>P1B2</strong>
+</td>
+<td>
+Pixel clock
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A3</strong>
+</td>
+<td>
+Green bit 4
+</td>
+<td>
+<strong>P1B3</strong>
+</td>
+<td>
+Blue bit 3
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A4</strong>
+</td>
+<td>
+Green bit 3
+</td>
+<td>
+<strong>P1B4</strong>
+</td>
+<td>
+Horizontal Sync
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A7</strong>
+</td>
+<td>
+Red bit 2
+</td>
+<td>
+<strong>P1B7</strong>
+</td>
+<td>
+Blue bit 2
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A8</strong>
+</td>
+<td>
+Red bit 1
+</td>
+<td>
+<strong>P1B8</strong>
+</td>
+<td>
+Blue bit 1
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A9</strong>
+</td>
+<td>
+Green bit 2
+</td>
+<td>
+<strong>P1B9</strong>
+</td>
+<td>
+Data Enable
+</td>
+</tr>
+<tr>
+<td>
+<strong>P1A10</strong>
+</td>
+<td>
+Green bit 1
+</td>
+<td>
+<strong>P1B10</strong>
+</td>
+<td>
+Vertical Sync
+</td>
+</tr>
+</tbody>
+</table>
+<p>From this we can see that we need 4 bits for each colour channel, a horizontal sync signal, a vertical sync signal, and additionally a data enable signal. The data enable signal is not part of a standard video signal and is just used by the DVI transmitter chip on the Pmod to signify when we are in visible pixel area or invisible pixel area. Therefore we will set the Date enable line when the current column is less than 640 and the current line is less than 480. Based on this we can connect the outputs like so:</p>
+<div class="sourceCode" id="cb5"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> r<span class="op">;</span></span>
+<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> g<span class="op">;</span></span>
+<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> b<span class="op">;</span></span>
+<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>logic data_enable<span class="op">;</span></span>
+<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> data_enable <span class="op">=</span> column <span class="op">&lt;</span> <span class="dv">640</span> <span class="op">&amp;&amp;</span> line <span class="op">&lt;</span> <span class="dv">480</span><span class="op">;</span></span>
+<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> <span class="op">{</span>P1A1<span class="op">,</span> P1A2<span class="op">,</span> P1A3<span class="op">,</span> P1A4<span class="op">,</span> P1A7<span class="op">,</span> P1A8<span class="op">,</span> P1A9<span class="op">,</span> P1A10<span class="op">}</span> <span class="op">=</span> </span>
+<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span>r<span class="op">[</span><span class="dv">3</span><span class="op">],</span> r<span class="op">[</span><span class="dv">2</span><span class="op">],</span> g<span class="op">[</span><span class="dv">3</span><span class="op">],</span> g<span class="op">[</span><span class="dv">2</span><span class="op">],</span> r<span class="op">[</span><span class="dv">1</span><span class="op">],</span> r<span class="op">[</span><span class="dv">0</span><span class="op">],</span> g<span class="op">[</span><span class="dv">1</span><span class="op">],</span> g<span class="op">[</span><span class="dv">0</span><span class="op">]};</span></span>
+<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> <span class="op">{</span>P1B1<span class="op">,</span> P1B2<span class="op">,</span> P1B3<span class="op">,</span> P1B4<span class="op">,</span> P1B7<span class="op">,</span> P1B8<span class="op">,</span> P1B9<span class="op">,</span> P1B10<span class="op">}</span> <span class="op">=</span> </span>
+<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span>b<span class="op">[</span><span class="dv">3</span><span class="op">],</span> pixel_clock<span class="op">,</span> b<span class="op">[</span><span class="dv">2</span><span class="op">],</span> horizontal_sync<span class="op">,</span> b<span class="op">[</span><span class="dv">1</span><span class="op">],</span> b<span class="op">[</span><span class="dv">0</span><span class="op">],</span> data_enable<span class="op">,</span> vertical_sync<span class="op">};</span></span></code></pre></div>
+<p>Now for testing purposes we are going to set the output colour to be fixed to pure red so additional logic to pick a pixel colour is not required for this example. We can do this as shown below:</p>
+<div class="sourceCode" id="cb6"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> r <span class="op">=</span> <span class="bn">4&#39;b1111</span><span class="op">;</span></span>
+<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> g <span class="op">=</span> <span class="bn">4&#39;b0000</span><span class="op">;</span></span>
+<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> b <span class="op">=</span> <span class="bn">4&#39;b0000</span><span class="op">;</span></span></code></pre></div>
+<p>Putting all of the above code together with whatever additional inputs are required for the iCEBreaker FPGA gives us the following block of code:</p>
+<div class="sourceCode" id="cb7"><pre class="sourceCode verilog"><code class="sourceCode verilog"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> top</span>
+<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span></span>
+<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="dt">input</span> CLK<span class="op">,</span></span>
+<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="dt">output</span> LEDR_N<span class="op">,</span></span>
+<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="dt">output</span> LEDG_N<span class="op">,</span></span>
+<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="dt">input</span> BTN_N<span class="op">,</span></span>
+<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="dt">output</span> P1A1<span class="op">,</span> P1A2<span class="op">,</span> P1A3<span class="op">,</span> P1A4<span class="op">,</span> P1A7<span class="op">,</span> P1A8<span class="op">,</span> P1A9<span class="op">,</span> P1A10<span class="op">,</span></span>
+<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="dt">output</span> P1B1<span class="op">,</span> P1B2<span class="op">,</span> P1B3<span class="op">,</span> P1B4<span class="op">,</span> P1B7<span class="op">,</span> P1B8<span class="op">,</span> P1B9<span class="op">,</span> P1B10</span>
+<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
+<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="ot">`define PIXELS_PER_LINE 10&#39;d800</span></span>
+<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="ot">`define PIXELS_VISIBLE_PER_LINE 10&#39;d640</span></span>
+<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="ot">`define LINES_PER_FRAME 10&#39;d525</span></span>
+<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a><span class="ot">`define LINES_VISIBLE_PER_FRAME 10&#39;d480</span></span>
+<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a><span class="ot">`define HORIZONTAL_FRONTPORCH 10&#39;d656</span></span>
+<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="ot">`define HORIZONTAL_BACKPORCH 10&#39;d752</span></span>
+<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a><span class="ot">`define VERTICAL_FRONTPORCH 10&#39;d490</span></span>
+<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a><span class="ot">`define VERTICAL_BACKPORCH 10&#39;d492</span></span>
+<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">9</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> line<span class="op">;</span></span>
+<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">9</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> column<span class="op">;</span></span>
+<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>logic horizontal_sync<span class="op">;</span></span>
+<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>logic vertical_sync<span class="op">;</span></span>
+<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>logic data_enable<span class="op">;</span></span>
+<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>logic pixel_clock<span class="op">;</span></span>
+<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>logic reset<span class="op">;</span></span>
+<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> r<span class="op">;</span></span>
+<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> g<span class="op">;</span></span>
+<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a>logic <span class="op">[</span><span class="dv">3</span><span class="op">:</span><span class="dv">0</span><span class="op">]</span> b<span class="op">;</span></span>
+<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> horizontal_sync <span class="op">=</span> column <span class="op">&lt;</span> <span class="op">(</span><span class="ot">`HORIZONTAL_FRONTPORCH</span><span class="op">)</span> <span class="op">||</span> column <span class="op">&gt;=</span> <span class="op">(</span><span class="ot">`HORIZONTAL_BACKPORCH</span><span class="op">);</span></span>
+<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> vertical_sync <span class="op">=</span> line <span class="op">&lt;</span> <span class="op">(</span><span class="ot">`VERTICAL_FRONTPORCH</span><span class="op">)</span> <span class="op">||</span> line <span class="op">&gt;=</span> <span class="op">(</span><span class="ot">`VERTICAL_BACKPORCH</span><span class="op">);</span></span>
+<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> data_enable <span class="op">=</span> <span class="op">(</span>column <span class="op">&lt;</span> <span class="ot">`PIXELS_VISIBLE_PER_LINE</span><span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span>line <span class="op">&lt;</span> <span class="ot">`LINES_VISIBLE_PER_FRAME</span><span class="op">);</span></span>
+<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> reset <span class="op">=</span> <span class="op">~</span>BTN_N<span class="op">;</span></span>
+<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> LEDR_N <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb7-38"><a href="#cb7-38" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> LEDG_N <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb7-39"><a href="#cb7-39" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-40"><a href="#cb7-40" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> r <span class="op">=</span> <span class="bn">4&#39;b1111</span><span class="op">;</span></span>
+<span id="cb7-41"><a href="#cb7-41" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> g <span class="op">=</span> <span class="bn">4&#39;b0000</span><span class="op">;</span></span>
+<span id="cb7-42"><a href="#cb7-42" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> b <span class="op">=</span> <span class="bn">4&#39;b0000</span><span class="op">;</span></span>
+<span id="cb7-43"><a href="#cb7-43" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-44"><a href="#cb7-44" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> <span class="op">{</span>P1A1<span class="op">,</span> P1A2<span class="op">,</span> P1A3<span class="op">,</span> P1A4<span class="op">,</span> P1A7<span class="op">,</span> P1A8<span class="op">,</span> P1A9<span class="op">,</span> P1A10<span class="op">}</span> <span class="op">=</span> </span>
+<span id="cb7-45"><a href="#cb7-45" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span>r<span class="op">[</span><span class="dv">3</span><span class="op">],</span> r<span class="op">[</span><span class="dv">2</span><span class="op">],</span> g<span class="op">[</span><span class="dv">3</span><span class="op">],</span> g<span class="op">[</span><span class="dv">2</span><span class="op">],</span> r<span class="op">[</span><span class="dv">1</span><span class="op">],</span> r<span class="op">[</span><span class="dv">0</span><span class="op">],</span> g<span class="op">[</span><span class="dv">1</span><span class="op">],</span> g<span class="op">[</span><span class="dv">0</span><span class="op">]};</span></span>
+<span id="cb7-46"><a href="#cb7-46" aria-hidden="true" tabindex="-1"></a><span class="kw">assign</span> <span class="op">{</span>P1B1<span class="op">,</span> P1B2<span class="op">,</span> P1B3<span class="op">,</span> P1B4<span class="op">,</span> P1B7<span class="op">,</span> P1B8<span class="op">,</span> P1B9<span class="op">,</span> P1B10<span class="op">}</span> <span class="op">=</span> </span>
+<span id="cb7-47"><a href="#cb7-47" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span>b<span class="op">[</span><span class="dv">3</span><span class="op">],</span> pixel_clock<span class="op">,</span> b<span class="op">[</span><span class="dv">2</span><span class="op">],</span> horizontal_sync<span class="op">,</span> b<span class="op">[</span><span class="dv">1</span><span class="op">],</span> b<span class="op">[</span><span class="dv">0</span><span class="op">],</span> data_enable<span class="op">,</span> vertical_sync<span class="op">};</span></span>
+<span id="cb7-48"><a href="#cb7-48" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-49"><a href="#cb7-49" aria-hidden="true" tabindex="-1"></a><span class="co">// Pixel and line counter</span></span>
+<span id="cb7-50"><a href="#cb7-50" aria-hidden="true" tabindex="-1"></a><span class="kw">always</span> <span class="op">@(</span><span class="kw">posedge</span> pixel_clock <span class="dt">or</span> <span class="kw">posedge</span> reset<span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb7-51"><a href="#cb7-51" aria-hidden="true" tabindex="-1"></a> <span class="kw">if</span><span class="op">(</span>reset <span class="op">==</span> <span class="dv">1</span><span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb7-52"><a href="#cb7-52" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> <span class="ot">`LINES_PER_FRAME</span> <span class="op">-</span> <span class="dv">2</span><span class="op">;</span></span>
+<span id="cb7-53"><a href="#cb7-53" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="ot">`PIXELS_PER_LINE</span> <span class="op">-</span> <span class="dv">16</span><span class="op">;</span></span>
+<span id="cb7-54"><a href="#cb7-54" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb7-55"><a href="#cb7-55" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">begin</span></span>
+<span id="cb7-56"><a href="#cb7-56" aria-hidden="true" tabindex="-1"></a> <span class="kw">if</span><span class="op">(</span>column <span class="op">==</span> <span class="op">(</span><span class="ot">`PIXELS_PER_LINE</span> <span class="op">-</span> <span class="dv">1</span><span class="op">)</span> <span class="op">&amp;&amp;</span> line <span class="op">==</span> <span class="op">(</span><span class="ot">`LINES_PER_FRAME</span> <span class="op">-</span> <span class="dv">1</span><span class="op">))</span> <span class="kw">begin</span></span>
+<span id="cb7-57"><a href="#cb7-57" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb7-58"><a href="#cb7-58" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb7-59"><a href="#cb7-59" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb7-60"><a href="#cb7-60" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">if</span><span class="op">(</span>column <span class="op">==</span> <span class="ot">`PIXELS_PER_LINE</span> <span class="op">-</span> <span class="dv">1</span><span class="op">)</span> <span class="kw">begin</span></span>
+<span id="cb7-61"><a href="#cb7-61" aria-hidden="true" tabindex="-1"></a> line <span class="op">&lt;=</span> line <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb7-62"><a href="#cb7-62" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">;</span></span>
+<span id="cb7-63"><a href="#cb7-63" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb7-64"><a href="#cb7-64" aria-hidden="true" tabindex="-1"></a> <span class="kw">else</span> <span class="kw">begin</span></span>
+<span id="cb7-65"><a href="#cb7-65" aria-hidden="true" tabindex="-1"></a> column <span class="op">&lt;=</span> column <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
+<span id="cb7-66"><a href="#cb7-66" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb7-67"><a href="#cb7-67" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
+<span id="cb7-68"><a href="#cb7-68" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
+<span id="cb7-69"><a href="#cb7-69" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-70"><a href="#cb7-70" aria-hidden="true" tabindex="-1"></a>SB_PLL40_PAD #<span class="op">(</span></span>
+<span id="cb7-71"><a href="#cb7-71" aria-hidden="true" tabindex="-1"></a> .DIVR<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb7-72"><a href="#cb7-72" aria-hidden="true" tabindex="-1"></a> .DIVF<span class="op">(</span><span class="bn">7&#39;b1000010</span><span class="op">),</span></span>
+<span id="cb7-73"><a href="#cb7-73" aria-hidden="true" tabindex="-1"></a> .DIVQ<span class="op">(</span><span class="bn">3&#39;b101</span><span class="op">),</span></span>
+<span id="cb7-74"><a href="#cb7-74" aria-hidden="true" tabindex="-1"></a> .FILTER_RANGE<span class="op">(</span><span class="bn">3&#39;b001</span><span class="op">),</span></span>
+<span id="cb7-75"><a href="#cb7-75" aria-hidden="true" tabindex="-1"></a> .FEEDBACK_PATH<span class="op">(</span><span class="st">&quot;SIMPLE&quot;</span><span class="op">),</span></span>
+<span id="cb7-76"><a href="#cb7-76" aria-hidden="true" tabindex="-1"></a> .DELAY_ADJUSTMENT_MODE_FEEDBACK<span class="op">(</span><span class="st">&quot;FIXED&quot;</span><span class="op">),</span></span>
+<span id="cb7-77"><a href="#cb7-77" aria-hidden="true" tabindex="-1"></a> .FDA_FEEDBACK<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb7-78"><a href="#cb7-78" aria-hidden="true" tabindex="-1"></a> .DELAY_ADJUSTMENT_MODE_RELATIVE<span class="op">(</span><span class="st">&quot;FIXED&quot;</span><span class="op">),</span></span>
+<span id="cb7-79"><a href="#cb7-79" aria-hidden="true" tabindex="-1"></a> .FDA_RELATIVE<span class="op">(</span><span class="bn">4&#39;b0000</span><span class="op">),</span></span>
+<span id="cb7-80"><a href="#cb7-80" aria-hidden="true" tabindex="-1"></a> .SHIFTREG_DIV_MODE<span class="op">(</span><span class="bn">2&#39;b00</span><span class="op">),</span></span>
+<span id="cb7-81"><a href="#cb7-81" aria-hidden="true" tabindex="-1"></a> .PLLOUT_SELECT<span class="op">(</span><span class="st">&quot;GENCLK&quot;</span><span class="op">),</span></span>
+<span id="cb7-82"><a href="#cb7-82" aria-hidden="true" tabindex="-1"></a> .ENABLE_ICEGATE<span class="op">(</span><span class="bn">1&#39;b0</span><span class="op">)</span></span>
+<span id="cb7-83"><a href="#cb7-83" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> usb_pll_inst <span class="op">(</span></span>
+<span id="cb7-84"><a href="#cb7-84" aria-hidden="true" tabindex="-1"></a> .PACKAGEPIN<span class="op">(</span>CLK<span class="op">),</span></span>
+<span id="cb7-85"><a href="#cb7-85" aria-hidden="true" tabindex="-1"></a> .PLLOUTCORE<span class="op">(</span>pixel_clock<span class="op">),</span></span>
+<span id="cb7-86"><a href="#cb7-86" aria-hidden="true" tabindex="-1"></a> .EXTFEEDBACK<span class="op">(),</span></span>
+<span id="cb7-87"><a href="#cb7-87" aria-hidden="true" tabindex="-1"></a> .DYNAMICDELAY<span class="op">(),</span></span>
+<span id="cb7-88"><a href="#cb7-88" aria-hidden="true" tabindex="-1"></a> .RESETB<span class="op">(</span><span class="bn">1&#39;b1</span><span class="op">),</span></span>
+<span id="cb7-89"><a href="#cb7-89" aria-hidden="true" tabindex="-1"></a> .BYPASS<span class="op">(</span><span class="bn">1&#39;b0</span><span class="op">),</span></span>
+<span id="cb7-90"><a href="#cb7-90" aria-hidden="true" tabindex="-1"></a> .LATCHINPUTVALUE<span class="op">(),</span></span>
+<span id="cb7-91"><a href="#cb7-91" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
+<span id="cb7-92"><a href="#cb7-92" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb7-93"><a href="#cb7-93" aria-hidden="true" tabindex="-1"></a><span class="kw">endmodule</span></span></code></pre></div>
+<p>To build this, you will require a .pcf file describing the pin mapping of the iCEBreaker board. I grabbed mine from the iCEBreaker examples <a href="https://raw.githubusercontent.com/icebreaker-fpga/icebreaker-examples/master/icebreaker.pcf">here</a>. Grab that file and put it in the same folder as the file for the code provided above. We can the run the following commands to generate a binary to program onto the FPGA:</p>
+<pre><code>yosys -ql out.log -p &#39;synth_ice40 -top top -json out.json&#39; top.sv
+nextpnr-ice40 --up5k --json out.json --pcf icebreaker.pcf --asc out.asc
+icetime -d up5k -mtr out.rpt out.asc
+icepack out.asc out.bin</code></pre>
+<p>This will generate an out.bin file that we will need to flash onto the board. Make sure your iCEBreaker FPGA is connected via USB to your computer and you can program it with the following commands.</p>
+<pre><code>iceprog out.bin</code></pre>
+<p>Now connect up a video cable (my DVI Pmod has an HDMI connector, but it only carries the DVI video signal) to the board and monitor and you should get results like this:</p>
+<p><img src="/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpg" /></p>
+<p>You can also see from the monitor settings menu that the video signal was recognized as 640x480@60 Hz. Now the code presented in this post is specific to the iCEBreaker board and the DVI Pmod, but the theory can be applied to any FPGA and any connector that uses a video signal like this. For example you could wire up a DAC with a resistor ladder to generate a VGA signal. The logic for the timings here would be exactly the same if you wanted a 640x480@60 Hz VGA signal.</p>
+ </div>
+</div> </main>
+</body>
+</html>
diff --git a/html/notes/n64brew-gamejam-2021.html b/html/notes/n64brew-gamejam-2021.html
new file mode 100644
index 0000000..48383af
--- /dev/null
+++ b/html/notes/n64brew-gamejam-2021.html
@@ -0,0 +1,71 @@
+<!doctype html>
+
+<html class="html-note-page" lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>N64Brew GameJam 2021</title>
+ <meta name="dcterms.date" content="2021-12-10" />
+
+ <link rel="stylesheet" href="/assets/style.css">
+ <link rel="icon" type="image/x-icon" href="/assets/favicon.svg">
+</head>
+
+<body>
+ <div class="header-bar">
+ <a href="/index.html">
+ <img src="/assets/favicon.svg" alt="frycon logo">
+ </a>
+ <div class="header-links">
+ <a href="/now.html" class="header-link">Now</a>
+ <a href="/about.html" class="header-link">About</a>
+ </div>
+ </div>
+ <main>
+<div class="page-title-header-container">
+ <h1 class="page-title-header">N64Brew GameJam 2021</h1>
+ <div class="page-info-container">
+ <div class="plant-status">
+ <img src="/assets/evergreen.svg">
+ <div class="plant-status-text">
+ <p>evergreen</p>
+ </div>
+ </div>
+ <div class="page-info-date-container">
+ <p class="page-info-date">Published: 2021-12-10</p>
+ <p class="page-info-date">Last Edited: 2023-01-20</p>
+ </div>
+ </div>
+ </div>
+<div class="note-divider"></div>
+<div class="main-container">
+ <div class="note-body">
+<p>So this year, myself and two others decided to participate together in the N64Brew homebrew GameJam, where we were supposed to build a homebrew game that would run on a real Nintendo 64. The game jam took place from October 8th until December 8th and was the second GameJam in N64Brew history. Unfortunately, we never ended up finishing the game, but we did build a really cool tech demo. Our project was called “Bug Game”, and if you want to check it out you can find it <a href="https://hazematman.itch.io/bug-game">here</a>. To play the game you’ll need a flash cart to load it on a real Nintendo 64, or you can use an accurate emulator such as <a href="https://ares.dev/">ares</a> or <a href="https://github.com/n64dev/cen64">cen64</a>. The reason an accurate emulator is required is that we made use of this new open source 3D microcode for N64 called “<a href="https://github.com/snacchus/libdragon/tree/ugfx">ugfx</a>”, created by the user Snacchus. This microcode is part of the Libdragon project, which is trying to build a completely open source library and toolchain to build N64 games, instead of relying on the official SDK that has been leaked to the public through liquidation auctions of game companies that have shut down over the years.</p>
+<div class="gallery">
+<p><img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png" /> <img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png" /> <img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png" /> <img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png" /> <img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png" /></p>
+<p>Screenshots of Bug Game</p>
+</div>
+<h2 id="libdragon-and-ugfx">Libdragon and UGFX</h2>
+<p>Ugfx was a brand new development in the N64 homebrew scene. By complete coincidence, Snacchus happened to release it on September 21st, just weeks before the GameJam was announced. There have been many attempts to create an open source 3D microcode for the N64 (my <a href="https://github.com/Hazematman/libhfx">libhfx</a> project included), but ugfx was the first project to complete with easily usable documentation and examples. This was an exciting development for the open source N64 brew community, as for the first time we could build 3D games that ran on the N64 without using the legally questionable official SDK. I jumped at the opportunity to use this and be one of the first fully 3D games running on Libdragon.</p>
+<p>One of the “drawbacks” of ufgx was that it tried to follow a lot of the design decisions the official 3D microcode for Nintendo used. This made it easier for people familiar with the official SDK to jump ship over to libdragon, but also went against the philosophy of the libdragon project to provide simple easy to use APIs. The Nintendo 64 was notoriously difficult to develop for, and one of the reasons for that was because of the extremely low level interface that the official 3D microcodes provided. Honestly writing 3D graphics code on the N64 reminds me more of writing a 3D OpenGL graphics driver (like I do in my day job), than building a graphics application. Unnecessarily increasing the burden of entry to developing 3D games on the Nintendo 64. Now that ugfx has been released, there is an ongoing effort in the community to revamp it and build a more user friendly API to access the 3D functionality of the N64.</p>
+<h2 id="ease-of-development">Ease of development</h2>
+<p>One of the major selling points of libdragon is that it tries to provide a standard toolchain with access to things like the c standard library as well as the c++ standard library. To save time on the development of bug game, I decided to put that claim to test. When building a 3D game from scratch two things that can be extremely time consuming are implementing linear algebra operations, and implementing physics that work in 3D. Luckily for modern developers, there are many open source libraries you can use instead of building these from scratch, like <a href="https://glm.g-truc.net/0.9.9/">GLM</a> for math operations and <a href="https://github.com/bulletphysics/bullet3">Bullet</a> for physics. I don’t believe anyone has tried to do this before, but knowing that libdragon provides a pretty standard c++ development environment I tried to build GLM and Bullet to run on the Nintendo 64 and I was successful! Both GLM and Bullet were able to run on real N64 hardware. This saved time during development as we were no longer concerned with having to build our own physics or math libraries. There were some tricks I needed to do to get bullet running on the hardware.</p>
+<p>First bullet will allocate more memory for its internal pools than is available on the N64. This is an easy fix as you can adjust the heap sizes when you go to initialize Bullet using the below code:</p>
+<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>btDefaultCollisionConstructionInfo constructionInfo <span class="op">=</span> btDefaultCollisionConstructionInfo<span class="op">();</span></span>
+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>constructionInfo<span class="op">.</span><span class="va">m_defaultMaxCollisionAlgorithmPoolSize</span> <span class="op">=</span> <span class="dv">512</span><span class="op">;</span></span>
+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>constructionInfo<span class="op">.</span><span class="va">m_defaultMaxPersistentManifoldPoolSize</span> <span class="op">=</span> <span class="dv">512</span><span class="op">;</span></span>
+<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>btDefaultCollisionConfiguration<span class="op">*</span> collisionConfiguration <span class="op">=</span> <span class="kw">new</span> btDefaultCollisionConfiguration<span class="op">(</span>constructionInfo<span class="op">);</span></span></code></pre></div>
+<p>This lets you modify the memory pools and specify a size in KB for the pools to use. The above code will limit the internal pools to 1MB, allowing us to easily run within the 4MB of RAM that is available on the N64 without the expansion pak (an accessory to the N64 that increases the available RAM to 8MB).</p>
+<p>The second issue I ran into with bullet was that the N64 floating point unit does not implement de-normalized floating point numbers. Now I’m not an expert in floating point numbers, but from my understanding, de-normalized numbers are a way to represent values between the smallest normal floating point number and zero. This allows floating point calculations to slowly fall towards zero in a more accurate way instead of rounding directly to zero. Since the N64 CPU does not implement de-normalized floats, if any calculations would have generated de-normalized float on the N64 they would instead cause a floating point exception. Because of the way the physics engine works, when two objects got very close together this would cause de-normalized floats to be generated and crash the FPU. This was a problem that had me stumped for a bit, I was concerned I would have to go into bullet’s source code and modify and calculations to round to zero if the result would be small enough. This would have been a monumental effort! Thankfully after digging through the NEC VR4300 programmer’s manual I was able to discover that there is a mode you can set the FPU to, which forces rounding towards zero if a de-normalized float would be generated. I enabled this mode and tested it out, and all my floating point troubles were resolved! I submitted a <a href="https://github.com/DragonMinded/libdragon/pull/195">pull request</a> (that was accepted) to the libdragon project to have this implemented by default, so no one else will run into the same annoying problems I ran into.</p>
+<h2 id="whats-next">What’s next?</h2>
+<p>If you decided to play our game you probably would have noticed that it’s not very much of a game. Even though this is the case I’m very happy with how the project turned out, as it’s one of the first 3D libdragon projects to be released. It also easily makes use of amazing open technologies like bullet physics, showcasing just how easy libdragon is to integrate with modern tools and libraries. As I mentioned before in this post there is an effort to take Snacchus’s work and build an easier to use graphics API that feels more like building graphics applications and less like building a graphics driver. The effort for that has already started and I plan to contribute to it. Some of the cool features this effort is bringing are:</p>
+<ul>
+<li>A standard interface for display lists and microcode overlays. Easily allowing multiple different microcodes to seamless run on the RSP and swap out with display list commands. This will be valuable for using the RSP for audio and graphics at the same time.</li>
+<li>A new 3D microcode that takes some lessons learned from ugfx to build a more powerful and easier to use interface.</li>
+</ul>
+<p>Overall this is an exciting time for Nintendo 64 homebrew development! It’s easier than ever to build homebrew on the N64 without knowing about the arcane innards of the console. I hope that this continued development of libdragon will bring more people to the scene and allow us to see new and novel games running on the N64. One project I would be excited to start working on is using the serial port on modern N64 Flashcarts for networking, allowing the N64 to have online multiplayer through a computer connected over USB. I feel that projects like this could really elevate the kind of content that is available on the N64 and bring it into the modern era.</p>
+ </div>
+</div> </main>
+</body>
+</html>
diff --git a/notes/generating-video.md b/notes/generating-video.md
new file mode 100644
index 0000000..1776d0b
--- /dev/null
+++ b/notes/generating-video.md
@@ -0,0 +1,289 @@
+---
+title: "Generating Video"
+date: "2020-04-07"
+last_edit: "2022-01-20"
+status: 3
+---
+
+One thing I'm very interested in is computer graphics. This could be complex 3D graphics or simple 2D graphics. The idea of getting a computer to display visual data fascinates me. One fundamental part of showing visual data is interfacing with a computer monitor. This can be accomplished by generating a video signal that the monitor understands. Below I have written instructions on how an FPGA can be used to generate a video signal. I have specifically worked with the iCEBreaker FPGA but the theory contained within this should work with any FPGA or device that you can generate the appropriate timings for.
+
+### Tools
+
+Hardware used ([link for board](https://www.crowdsupply.com/1bitsquared/icebreaker-fpga)):
+
+- iCEBreaker FPGA
+- iCEBreaker 12-Bit DVI Pmod
+
+Software Used:
+
+- IceStorm FPGA toolchain ([follow install instructions here](https://github.com/esden/summon-fpga-tools))
+
+### Theory
+
+A video signal is composed of several parts, primarily the colour signals and the sync signals. For this DVI Pmod, there is also a data enable signal for the visible screen area. For the example here we are going to be generating a 640x480 60 Hz video signal. Below is a table describing the important data for our video signal.
+
+<table><tbody><tr><td>Pixel Clock</td><td>25.175 MHz</td></tr><tr><td>Pixels Per Line</td><td>800 Pixels</td></tr><tr><td>Pixels Visible Per Line</td><td>640 Pixels</td></tr><tr><td>Horizontal Sync Front Porch Length</td><td>16 Pixels</td></tr><tr><td>Horizontal Sync Length</td><td>96 Pixels</td></tr><tr><td>Horizontal Sync Back Porch Length</td><td>48 Pixels</td></tr><tr><td>Lines Per Frame</td><td>525 Lines</td></tr><tr><td>Lines Visible Per Frame</td><td>480 Lines</td></tr><tr><td>Vertical Front Porch Length</td><td>10 Lines</td></tr><tr><td>Vertical Sync Length</td><td>2 Lines</td></tr><tr><td>Vertical Back Porch Length</td><td>33 Lines</td></tr></tbody></table>
+
+Sourced from http://www.tinyvga.com/vga-timing/640x480@60Hz
+
+The data from this table raises a few questions:
+
+1. What is the Pixel Clock?
+2. What is the difference between "Pixels/Lines" and "Visible Pixels/Lines"?
+3. What is "Front Porch", "Sync", and "Back Porch"?
+
+#### Pixel Clock
+
+The pixel clock is a fairly straightforward idea; this is the rate at which we generate pixels. For video signal generation, the "pixel" is a fundamental building block and we count things in the number of pixels it takes up. Every time the pixel clock "ticks" we have incremented the number of pixels we have processed. So for a 640x480 video signal, a full line is 800 pixels, or 800 clock ticks. For the full 800x525 frame there is 800 ticks x 525 lines, or 420000 clock ticks. If we are running the display at 60 Hz, 420000 pixels per frame are generated 60 times per second. Therefore, 25200000 pixels or clock ticks will pass in one second. From this we can see the pixel clock frequency of 25.175 MHz is roughly equal to 25200000 clock ticks. There is a small deviance from the "true" values here, but monitors are flexible enough to accept this video signal (my monitor reports it as 640x480@60Hz), and all information I can find online says that 25.175 MHz is the value you want to use. Later on we will see that the pixel clock is not required to be exactly 25.175 Mhz.
+
+#### Visible Area vs Invisible Area
+
+![](/assets/2020-04-07-generating-video/visible_invisible.png)
+
+From the above image we can see that a 640x480 video signal actually generates a resolution larger than 640x480. The true resolution we generate is 800x525, but only a 640x480 portion of that signal is visible. The area that is not visible is where we generate the sync signal. In other words, every part of the above image that is black is where a sync signal is being generated.
+
+#### Front Porch, Back Porch & Sync
+
+To better understand the front porch, back porch and sync signal, let's look at what the horizontal sync signal looks like during the duration of a line:
+
+![](/assets/2020-04-07-generating-video/sync.png)
+
+From this we can see that the "Front Porch" is the invisible pixels between the visible pixels and the sync pixels, and is represented by a logical one or high signal. The "Sync" is the invisible pixels between the front porch and back porch, and is represented by a logical zero or low signal. The "Back Porch" is the invisible pixels after the sync signal, and is represented by a logical one. For the case of 640x480 video, the visible pixel section lasts for 640 pixels. The front porch section lasts for 16 pixels, after which the sync signal will become a logical zero. This logical zero sync will last for 96 pixels, after which the sync signal will become a logical one again. The back porch will then last for 48 pixels. If you do a quick calculation right now of 640 + 16 + 96 + 48, we get 800 pixels which represents the full horizontal resolution of the display. The vertical sync signal works almost exactly the same, except the vertical sync signal acts on lines.
+
+### Implementation
+
+The first thing we can do that is going to simplify a lot of the following logic is to keep track of which pixel, and which line we are on. The below code block creates two registers to keep track of the current pixel on the line (column) and the current line (line):
+
+```verilog
+logic [9:0] line;
+logic [9:0] column;
+
+always @(posedge clk or posedge reset) begin
+ if(reset == 1) begin
+ line <= 0;
+ column <= 0;
+ end
+ else begin
+ if(column == 799 && line == 524) begin
+ line <= 0;
+ column <= 0;
+ end
+ else if(column == 799) begin
+ line <= line + 1;
+ column <= 0;
+ end
+ else begin
+ column <= column + 1;
+ end
+ end
+end
+```
+
+This block of Verilog works by first initializing the line and column register to zero on a reset. This is important to make sure that we start from known values, otherwise the line and column register could contain any value and our logic would not work. Next, we check if we are at the bottom of the screen by comparing the current column to 799 (the last pixel in the line) and the current line is 524 (the last line in the frame). If these conditions are both true then we reset the line and column back to zero to signify that we are starting a new frame. The next block checks if the current column equals 799. Because the above if statement failed,we know that we are at the end of the line but not the end of the frame. If this is true we increment the current line count and set the column back to zero to signify that we are starting a new line. The final block simply increments the current pixel count. If we reach this block ,we are neither at the end of the line or the end of the frame so we can simply increment to the next pixel.
+
+Now that we are keeping track of the current column and current line, we can use this information to generate the horizontal and vertical sync signals. From the theory above we know that the sync signal is only low when we are between the front and back porch, at all other times the signal is high. From this we can generate the sync signal with an OR and two compares.
+
+```verilog
+logic horizontal_sync;
+logic vertical_sync;
+assign horizontal_sync = column < 656 || column >= 752;
+assign vertical_sync = line < 490 || line >= 492;
+```
+
+Let's examine the horizontal sync signal more closely. This statement will evaluate to true if the current column is less than 656 or the current column is greater than or equal to 752. This means that the horizontal sync signal will be true except for when the current column is between 656 and 751 inclusively. That is starting on column 656 the horizontal sync signal will become false (low) and will remain that way for the next 96 pixels until we reach pixel 752 where it will return to being true (high). The vertical sync signal will work in the same way except it is turned on based on the current line. Therefore, the signal will remain high when the line is less than 490 and greater than or equal to 492, and will remain low between lines 490 and 491 inclusive.
+
+#### Putting It All Together
+
+Now that we have generated the video signal, we need to route it towards the video output connectors on the iCEBreaker 12-bit DVI Pmod. We also need to configure the iCEBreaker FPGA to have the appropriate pixel clock frequency. First to get the correct pixel clock we are going to use the following block of code:
+
+```verilog
+SB_PLL40_PAD #(
+ .DIVR(4'b0000),
+ .DIVF(7'b1000010),
+ .DIVQ(3'b101),
+ .FILTER_RANGE(3'b001),
+ .FEEDBACK_PATH("SIMPLE"),
+ .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"),
+ .FDA_FEEDBACK(4'b0000),
+ .DELAY_ADJUSTMENT_MODE_RELATIVE("FIXED"),
+ .FDA_RELATIVE(4'b0000),
+ .SHIFTREG_DIV_MODE(2'b00),
+ .PLLOUT_SELECT("GENCLK"),
+ .ENABLE_ICEGATE(1'b0)
+) usb_pll_inst (
+ .PACKAGEPIN(CLK),
+ .PLLOUTCORE(pixel_clock),
+ .EXTFEEDBACK(),
+ .DYNAMICDELAY(),
+ .RESETB(1'b1),
+ .BYPASS(1'b0),
+ .LATCHINPUTVALUE(),
+);
+```
+
+This block is mainly a copy paste of the PLL setup code from the iCEBreaker examples, but with a few important changes. The DIVR, DIVF, and DIVQ values are changed to create a 25.125 MHz. This is not exactly 25.175 MHz, but it is close enough that the monitor is happy enough and recognizes it as a 640x480@60 Hz signal. These values were found through the "icepll" utility, below is an example of calling this utility from the command line:
+
+```
+$ icepll -i 12 -o 25.175
+
+F_PLLIN: 12.000 MHz (given)
+F_PLLOUT: 25.175 MHz (requested)
+F_PLLOUT: 25.125 MHz (achieved)
+
+FEEDBACK: SIMPLE
+F_PFD: 12.000 MHz
+F_VCO: 804.000 MHz
+
+DIVR: 0 (4'b0000)
+DIVF: 66 (7'b1000010)
+DIVQ: 5 (3'b101)
+
+FILTER_RANGE: 1 (3'b001)
+```
+
+From here we can see we had an input clock of 12 MHz (This comes from the FTDI chip on the iCEBreaker board), and we wanted to get a 25.175 MHz output clock. The closest the PLL could generate was a 25.125 MHz clock with the settings provided for the DIVR, DIVF, and DIVQ values.
+
+Now that we have a pixel clock we can wire up the necessary signals for the DVI video out. The DVI Pmod has the following mapping for all of its connectors:
+
+<table><tbody><tr><td>PMOD 1</td><td></td><td>PMOD 2</td><td></td></tr><tr><td><strong>P1A1</strong></td><td>Red bit 4</td><td><strong>P1B1</strong></td><td>Blue bit 4</td></tr><tr><td><strong>P1A2</strong></td><td>Red bit 3</td><td><strong>P1B2</strong></td><td>Pixel clock</td></tr><tr><td><strong>P1A3</strong></td><td>Green bit 4</td><td><strong>P1B3</strong></td><td>Blue bit 3</td></tr><tr><td><strong>P1A4</strong></td><td>Green bit 3</td><td><strong>P1B4</strong></td><td>Horizontal Sync</td></tr><tr><td><strong>P1A7</strong></td><td>Red bit 2</td><td><strong>P1B7</strong></td><td>Blue bit 2</td></tr><tr><td><strong>P1A8</strong></td><td>Red bit 1</td><td><strong>P1B8</strong></td><td>Blue bit 1</td></tr><tr><td><strong>P1A9</strong></td><td>Green bit 2</td><td><strong>P1B9</strong></td><td>Data Enable</td></tr><tr><td><strong>P1A10</strong></td><td>Green bit 1</td><td><strong>P1B10</strong></td><td>Vertical Sync</td></tr></tbody></table>
+
+From this we can see that we need 4 bits for each colour channel, a horizontal sync signal, a vertical sync signal, and additionally a data enable signal. The data enable signal is not part of a standard video signal and is just used by the DVI transmitter chip on the Pmod to signify when we are in visible pixel area or invisible pixel area. Therefore we will set the Date enable line when the current column is less than 640 and the current line is less than 480. Based on this we can connect the outputs like so:
+
+```verilog
+logic [3:0] r;
+logic [3:0] g;
+logic [3:0] b;
+logic data_enable;
+assign data_enable = column < 640 && line < 480;
+assign {P1A1, P1A2, P1A3, P1A4, P1A7, P1A8, P1A9, P1A10} =
+ {r[3], r[2], g[3], g[2], r[1], r[0], g[1], g[0]};
+assign {P1B1, P1B2, P1B3, P1B4, P1B7, P1B8, P1B9, P1B10} =
+ {b[3], pixel_clock, b[2], horizontal_sync, b[1], b[0], data_enable, vertical_sync};
+```
+
+Now for testing purposes we are going to set the output colour to be fixed to pure red so additional logic to pick a pixel colour is not required for this example. We can do this as shown below:
+
+```verilog
+assign r = 4'b1111;
+assign g = 4'b0000;
+assign b = 4'b0000;
+```
+
+Putting all of the above code together with whatever additional inputs are required for the iCEBreaker FPGA gives us the following block of code:
+
+```verilog
+module top
+(
+input CLK,
+output LEDR_N,
+output LEDG_N,
+input BTN_N,
+output P1A1, P1A2, P1A3, P1A4, P1A7, P1A8, P1A9, P1A10,
+output P1B1, P1B2, P1B3, P1B4, P1B7, P1B8, P1B9, P1B10
+);
+
+`define PIXELS_PER_LINE 10'd800
+`define PIXELS_VISIBLE_PER_LINE 10'd640
+`define LINES_PER_FRAME 10'd525
+`define LINES_VISIBLE_PER_FRAME 10'd480
+`define HORIZONTAL_FRONTPORCH 10'd656
+`define HORIZONTAL_BACKPORCH 10'd752
+`define VERTICAL_FRONTPORCH 10'd490
+`define VERTICAL_BACKPORCH 10'd492
+
+logic [9:0] line;
+logic [9:0] column;
+logic horizontal_sync;
+logic vertical_sync;
+logic data_enable;
+logic pixel_clock;
+logic reset;
+
+logic [3:0] r;
+logic [3:0] g;
+logic [3:0] b;
+
+assign horizontal_sync = column < (`HORIZONTAL_FRONTPORCH) || column >= (`HORIZONTAL_BACKPORCH);
+assign vertical_sync = line < (`VERTICAL_FRONTPORCH) || line >= (`VERTICAL_BACKPORCH);
+assign data_enable = (column < `PIXELS_VISIBLE_PER_LINE) && (line < `LINES_VISIBLE_PER_FRAME);
+
+assign reset = ~BTN_N;
+assign LEDR_N = 1;
+assign LEDG_N = 1;
+
+assign r = 4'b1111;
+assign g = 4'b0000;
+assign b = 4'b0000;
+
+assign {P1A1, P1A2, P1A3, P1A4, P1A7, P1A8, P1A9, P1A10} =
+ {r[3], r[2], g[3], g[2], r[1], r[0], g[1], g[0]};
+assign {P1B1, P1B2, P1B3, P1B4, P1B7, P1B8, P1B9, P1B10} =
+ {b[3], pixel_clock, b[2], horizontal_sync, b[1], b[0], data_enable, vertical_sync};
+
+// Pixel and line counter
+always @(posedge pixel_clock or posedge reset) begin
+ if(reset == 1) begin
+ line <= `LINES_PER_FRAME - 2;
+ column <= `PIXELS_PER_LINE - 16;
+ end
+ else begin
+ if(column == (`PIXELS_PER_LINE - 1) && line == (`LINES_PER_FRAME - 1)) begin
+ line <= 0;
+ column <= 0;
+ end
+ else if(column == `PIXELS_PER_LINE - 1) begin
+ line <= line + 1;
+ column <= 0;
+ end
+ else begin
+ column <= column + 1;
+ end
+ end
+end
+
+SB_PLL40_PAD #(
+ .DIVR(4'b0000),
+ .DIVF(7'b1000010),
+ .DIVQ(3'b101),
+ .FILTER_RANGE(3'b001),
+ .FEEDBACK_PATH("SIMPLE"),
+ .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"),
+ .FDA_FEEDBACK(4'b0000),
+ .DELAY_ADJUSTMENT_MODE_RELATIVE("FIXED"),
+ .FDA_RELATIVE(4'b0000),
+ .SHIFTREG_DIV_MODE(2'b00),
+ .PLLOUT_SELECT("GENCLK"),
+ .ENABLE_ICEGATE(1'b0)
+) usb_pll_inst (
+ .PACKAGEPIN(CLK),
+ .PLLOUTCORE(pixel_clock),
+ .EXTFEEDBACK(),
+ .DYNAMICDELAY(),
+ .RESETB(1'b1),
+ .BYPASS(1'b0),
+ .LATCHINPUTVALUE(),
+);
+
+endmodule
+```
+
+To build this, you will require a .pcf file describing the pin mapping of the iCEBreaker board. I grabbed mine from the iCEBreaker examples [here](https://raw.githubusercontent.com/icebreaker-fpga/icebreaker-examples/master/icebreaker.pcf). Grab that file and put it in the same folder as the file for the code provided above. We can the run the following commands to generate a binary to program onto the FPGA:
+
+```
+yosys -ql out.log -p 'synth_ice40 -top top -json out.json' top.sv
+nextpnr-ice40 --up5k --json out.json --pcf icebreaker.pcf --asc out.asc
+icetime -d up5k -mtr out.rpt out.asc
+icepack out.asc out.bin
+```
+
+This will generate an out.bin file that we will need to flash onto the board. Make sure your iCEBreaker FPGA is connected via USB to your computer and you can program it with the following commands.
+
+```
+iceprog out.bin
+```
+
+Now connect up a video cable (my DVI Pmod has an HDMI connector, but it only carries the DVI video signal) to the board and monitor and you should get results like this:
+
+![](/assets/2020-04-07-generating-video/IMG_20200407_172119-1-1024x768.jpg)
+
+You can also see from the monitor settings menu that the video signal was recognized as 640x480@60 Hz. Now the code presented in this post is specific to the iCEBreaker board and the DVI Pmod, but the theory can be applied to any FPGA and any connector that uses a video signal like this. For example you could wire up a DAC with a resistor ladder to generate a VGA signal. The logic for the timings here would be exactly the same if you wanted a 640x480@60 Hz VGA signal.
diff --git a/notes/n64brew-gamejam-2021.md b/notes/n64brew-gamejam-2021.md
new file mode 100644
index 0000000..2ffd93f
--- /dev/null
+++ b/notes/n64brew-gamejam-2021.md
@@ -0,0 +1,57 @@
+---
+title: "N64Brew GameJam 2021"
+date: "2021-12-10"
+last_edit: "2023-01-20"
+tags:
+ - "3d"
+ - "homebrew"
+ - "n64"
+ - "n64brew"
+ - "nintendo64"
+cover_image: "/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png"
+status: 3
+---
+
+So this year, myself and two others decided to participate together in the N64Brew homebrew GameJam, where we were supposed to build a homebrew game that would run on a real Nintendo 64. The game jam took place from October 8th until December 8th and was the second GameJam in N64Brew history. Unfortunately, we never ended up finishing the game, but we did build a really cool tech demo. Our project was called "Bug Game", and if you want to check it out you can find it [here](https://hazematman.itch.io/bug-game). To play the game you'll need a flash cart to load it on a real Nintendo 64, or you can use an accurate emulator such as [ares](https://ares.dev/) or [cen64](https://github.com/n64dev/cen64). The reason an accurate emulator is required is that we made use of this new open source 3D microcode for N64 called "[ugfx](https://github.com/snacchus/libdragon/tree/ugfx)", created by the user Snacchus. This microcode is part of the Libdragon project, which is trying to build a completely open source library and toolchain to build N64 games, instead of relying on the official SDK that has been leaked to the public through liquidation auctions of game companies that have shut down over the years.
+
+<div class="gallery">
+![](/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png)
+![](/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png)
+![](/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png)
+![](/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png)
+![](/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png)
+
+Screenshots of Bug Game
+</div>
+
+## Libdragon and UGFX
+
+Ugfx was a brand new development in the N64 homebrew scene. By complete coincidence, Snacchus happened to release it on September 21st, just weeks before the GameJam was announced. There have been many attempts to create an open source 3D microcode for the N64 (my [libhfx](https://github.com/Hazematman/libhfx) project included), but ugfx was the first project to complete with easily usable documentation and examples. This was an exciting development for the open source N64 brew community, as for the first time we could build 3D games that ran on the N64 without using the legally questionable official SDK. I jumped at the opportunity to use this and be one of the first fully 3D games running on Libdragon.
+
+One of the "drawbacks" of ufgx was that it tried to follow a lot of the design decisions the official 3D microcode for Nintendo used. This made it easier for people familiar with the official SDK to jump ship over to libdragon, but also went against the philosophy of the libdragon project to provide simple easy to use APIs. The Nintendo 64 was notoriously difficult to develop for, and one of the reasons for that was because of the extremely low level interface that the official 3D microcodes provided. Honestly writing 3D graphics code on the N64 reminds me more of writing a 3D OpenGL graphics driver (like I do in my day job), than building a graphics application. Unnecessarily increasing the burden of entry to developing 3D games on the Nintendo 64. Now that ugfx has been released, there is an ongoing effort in the community to revamp it and build a more user friendly API to access the 3D functionality of the N64.
+
+## Ease of development
+
+One of the major selling points of libdragon is that it tries to provide a standard toolchain with access to things like the c standard library as well as the c++ standard library. To save time on the development of bug game, I decided to put that claim to test. When building a 3D game from scratch two things that can be extremely time consuming are implementing linear algebra operations, and implementing physics that work in 3D. Luckily for modern developers, there are many open source libraries you can use instead of building these from scratch, like [GLM](https://glm.g-truc.net/0.9.9/) for math operations and [Bullet](https://github.com/bulletphysics/bullet3) for physics. I don't believe anyone has tried to do this before, but knowing that libdragon provides a pretty standard c++ development environment I tried to build GLM and Bullet to run on the Nintendo 64 and I was successful! Both GLM and Bullet were able to run on real N64 hardware. This saved time during development as we were no longer concerned with having to build our own physics or math libraries. There were some tricks I needed to do to get bullet running on the hardware.
+
+First bullet will allocate more memory for its internal pools than is available on the N64. This is an easy fix as you can adjust the heap sizes when you go to initialize Bullet using the below code:
+
+```c++
+btDefaultCollisionConstructionInfo constructionInfo = btDefaultCollisionConstructionInfo();
+constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize = 512;
+constructionInfo.m_defaultMaxPersistentManifoldPoolSize = 512;
+btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(constructionInfo);
+```
+
+This lets you modify the memory pools and specify a size in KB for the pools to use. The above code will limit the internal pools to 1MB, allowing us to easily run within the 4MB of RAM that is available on the N64 without the expansion pak (an accessory to the N64 that increases the available RAM to 8MB).
+
+The second issue I ran into with bullet was that the N64 floating point unit does not implement de-normalized floating point numbers. Now I'm not an expert in floating point numbers, but from my understanding, de-normalized numbers are a way to represent values between the smallest normal floating point number and zero. This allows floating point calculations to slowly fall towards zero in a more accurate way instead of rounding directly to zero. Since the N64 CPU does not implement de-normalized floats, if any calculations would have generated de-normalized float on the N64 they would instead cause a floating point exception. Because of the way the physics engine works, when two objects got very close together this would cause de-normalized floats to be generated and crash the FPU. This was a problem that had me stumped for a bit, I was concerned I would have to go into bullet's source code and modify and calculations to round to zero if the result would be small enough. This would have been a monumental effort! Thankfully after digging through the NEC VR4300 programmer's manual I was able to discover that there is a mode you can set the FPU to, which forces rounding towards zero if a de-normalized float would be generated. I enabled this mode and tested it out, and all my floating point troubles were resolved! I submitted a [pull request](https://github.com/DragonMinded/libdragon/pull/195) (that was accepted) to the libdragon project to have this implemented by default, so no one else will run into the same annoying problems I ran into.
+
+## What's next?
+
+If you decided to play our game you probably would have noticed that it's not very much of a game. Even though this is the case I'm very happy with how the project turned out, as it's one of the first 3D libdragon projects to be released. It also easily makes use of amazing open technologies like bullet physics, showcasing just how easy libdragon is to integrate with modern tools and libraries. As I mentioned before in this post there is an effort to take Snacchus's work and build an easier to use graphics API that feels more like building graphics applications and less like building a graphics driver. The effort for that has already started and I plan to contribute to it. Some of the cool features this effort is bringing are:
+
+- A standard interface for display lists and microcode overlays. Easily allowing multiple different microcodes to seamless run on the RSP and swap out with display list commands. This will be valuable for using the RSP for audio and graphics at the same time.
+- A new 3D microcode that takes some lessons learned from ugfx to build a more powerful and easier to use interface.
+
+Overall this is an exciting time for Nintendo 64 homebrew development! It's easier than ever to build homebrew on the N64 without knowing about the arcane innards of the console. I hope that this continued development of libdragon will bring more people to the scene and allow us to see new and novel games running on the N64. One project I would be excited to start working on is using the serial port on modern N64 Flashcarts for networking, allowing the N64 to have online multiplayer through a computer connected over USB. I feel that projects like this could really elevate the kind of content that is available on the N64 and bring it into the modern era.