<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Silician Sketchbook &#187; hardware</title>
	<atom:link href="http://www.silician.com/sketchbook/category/hardware/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.silician.com/sketchbook</link>
	<description>A chronicle of misadventures</description>
	<lastBuildDate>Thu, 20 Nov 2008 04:48:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Karaoke headphones</title>
		<link>http://www.silician.com/sketchbook/2008/09/28/karaoke-headphones/</link>
		<comments>http://www.silician.com/sketchbook/2008/09/28/karaoke-headphones/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 18:47:36 +0000</pubDate>
		<dc:creator>introspect</dc:creator>
				<category><![CDATA[hardware]]></category>
		<category><![CDATA[misadventures]]></category>

		<guid isPermaLink="false">http://www.silician.com/sketchbook/?p=93</guid>
		<description><![CDATA[When one of the channels on a headset drops out, and you have to fiddle with the wires to find the sweet spot such that it&#8217;ll come back, you know that the headset is on its last legs. But I&#8217;m not about to go and buy a new headset just yet. The one I was [...]]]></description>
			<content:encoded><![CDATA[<p>When one of the channels on a headset drops out, and you have to fiddle with the wires to find the sweet spot such that it&#8217;ll come back, you know that the headset is on its last legs.  But I&#8217;m not about to go and buy a new headset just yet.  The one I was using was not really mine at first, and I wound up claiming it because no one else was using it.</p>
<p>I&#8217;ve since gone back to my original headset, but there was a reason why I stopped using it in the first place, which I&#8217;ve just rediscovered.</p>
<p>For one, the foam piece that covered the microphone spontaneously came off, but that&#8217;s not a big deal.  More troublesome was that one day, the headset decided to switch to mono, and at the time I couldn&#8217;t figure out why.</p>
<p>A cool side-effect of having the headphones magically go mono is that the vocal channel of a song is either heavily attenuated or outright eliminated.  And it turns out that if I twist the headphone connector around enough, I can likewise ditch the karaoke channel and get the vocals.</p>
<p>The novelty doesn&#8217;t last very long, but fortunately I can get stereo back by pulling the connector out slightly.  One side is slightly attenuated as a result, but it&#8217;s better than being completely blindsided in a game.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.silician.com/sketchbook/2008/09/28/karaoke-headphones/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bit-parallel finite field multiplier design (Part 2)</title>
		<link>http://www.silician.com/sketchbook/2008/09/22/bit-parallel-finite-field-multiplier-design-part-2/</link>
		<comments>http://www.silician.com/sketchbook/2008/09/22/bit-parallel-finite-field-multiplier-design-part-2/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 05:09:06 +0000</pubDate>
		<dc:creator>introspect</dc:creator>
				<category><![CDATA[education]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.silician.com/sketchbook/?p=80</guid>
		<description><![CDATA[For why and reference material, see Part 1. So first off, the d and e vectors. Recall that multiplication of terms is accomplished by an AND gate since the operands are bits, and addition is accomplished by an XOR gate. I&#8217;ll go over the construction of d, but the same steps apply for e as [...]]]></description>
			<content:encoded><![CDATA[<p>For why and reference material, see <a href="http://www.silician.com/sketchbook/2008/09/21/bit-parallel-finite-field-multiplier-design-part-1/">Part 1</a>.</p>
<p>So first off, the <strong>d</strong> and <strong>e</strong> vectors.  Recall that multiplication of terms is accomplished by an AND gate since the operands are bits, and addition is accomplished by an XOR gate.  I&#8217;ll go over the construction of <strong>d</strong>, but the same steps apply for <strong>e</strong> as well.</p>
<pre>
def gen_d(m):
    a = ['a[%i]' % i for i in xrange(m)]
    a.reverse()
    a = a + [False for i in xrange(m-1)]
    L = []
    for i in xrange(m):
        L.append(a[-m:])
        a.pop()

    b = ['b[%i]' % i for i in xrange(m)]
    d = [' ^ '.join([s for s in map(cond_and, L[i], b) if s != ''])
         for i in xrange(m)]

    return ['d%i = ' % i + d[i] for i in xrange(m)]
</pre>
<p>The only parameter is m, which is the m in GF(2<sup>m</sup>), so for GF(256), m = 8.</p>
<p>First, I need to construct the <strong>L</strong> matrix, which is m by m.  I use something similar to a sliding window to construct the rows of <strong>L</strong>, popping the trailing element out on each iteration to shift the window to the left.</p>
<p>What&#8217;s interesting to note is that instead of padding the row with zeros, like in the paper, I used a boolean.  I could have also used an empty string, but it&#8217;s better to play it safe and use an explicit boolean.  On the other hand, a non-empty string evaluates to &#8220;True.&#8221;</p>
<p>To do the matrix multiplication, I use <code>map</code> on a row of <strong>L</strong> and the vector <strong>b</strong>.  The function that is applied to pairs of elements is below:</p>
<pre>
def cond_and(x, y):
    if x:
        return '(%s and %s)' % (x, y)
    return ''
</pre>
<p>To make the equation strings a bit cleaner, if the row element is False (i.e. 0) then an empty string is returned.  Otherwise, it constructs the product term of the row element and the vector element.  The string builder filters out those empty strings when xor-ing the product terms together.</p>
<p>Lastly, the appropriate d<sub>i</sub> term is placed at the beginning of each equation, and a list is returned.  To print out the entire list, try <code>print '\n'.join(gen_d(8))</code></p>
<p>To generate the terms in <strong>e</strong>, the exact same steps occur, except that the <strong>U</strong> matrix is m-1 by m, and so the number of equations is m-1.</p>
<pre>
def gen_e(m):
    a = ['a[%i]' % i for i in xrange(m)]
    a.reverse()
    a = [False for i in xrange(m-1)] + a[:-1]

    U = []
    for i in xrange(m):
        U.append(a[-m:])
        a.pop()

    b = ['b[%i]' % i for i in xrange(m)]
    e = [' ^ '.join([s for s in map(cond_and, U[i], b) if s != ''])
         for i in xrange(m-1)]

    return ['e%i = ' % i + e[i] for i in xrange(m-1)]
</pre>
<p>When you print out the terms for <strong>d</strong> and <strong>e</strong> one after the other, you see how they could interlock, hence the very regular layout of the multiplier.</p>
<p>Code to generate <strong>Q</strong><sup>T</sup> is below.</p>
<pre>
def Q_transpose(prim):
    mul = gf_256.mul_table(prim)
    m = 8
    alphas = [1]
    for i in xrange(1, 15):
        alphas.append(mul[2][alphas[i-1]])

    combinations = [to_bits(i) for i in xrange(256)]
    x = [0 for i in xrange(256)]
    for i in xrange(256):
        k = reduce(gf_add, map(multiply, combinations[i],
                               alphas[:m]))
        x[k] = combinations[i]

    Q = [0 for i in xrange(7)]
    for i, j in zip(xrange(7), alphas[m:]):
        Q[i] = x[j]

    Q = numpy.array(Q)
    Q_t = Q.transpose()
    return Q_t
</pre>
<p>Right off the bat you see that I generate a finite field multiplication look-up table based on the primitive polynomial (i.e. 0x1D).  In the interests of keeping things concise, I&#8217;m not going to give the code to generate such a table, but you may find <a href="http://en.wikipedia.org/wiki/Finite_field_arithmetic#Program_examples">Wikipedia</a> useful for coding that stuff yourself.</p>
<p>I&#8217;m too lazy to write out equation (5) so look it up yourself.  But the important points is that <strong>Q</strong> can only have binary elements, so multiplication is really just an on/off switching, and since we&#8217;re in the finite field, addition is XOR.</p>
<p>I never figured out why people always use &#8220;primitive element&#8221; and &#8220;&alpha;&#8221; when they could just say &#8220;2&#8243;, because that&#8217;s what it really is in all practical finite fields.  So I construct a vector containing the powers of 2 within the finite field, by repeated multiplication using the look-up table.</p>
<p>Since there are only 256 possible linear combinations of &alpha;<sup>0</sup> &#8230; &alpha;<sup>7</sup>, I use a brute force approach, converting 0 &#8230; 255 into boolean vectors.</p>
<pre>
def to_bits(byte):
    ret = []
    for i in xrange(8):
        ret.append(bool(byte &#038; 1))
        byte = byte >> 1
    return ret
</pre>
<p>Now in Python, you can mix types to a certain extent.  I&#8217;m using the property that a boolean can multiply with an integer, with the result being either the integer itself (if the boolean was True) or 0 (if the boolean was False).  I&#8217;m not going to post the code to the <code>multiply</code> function.</p>
<p>The list of products are reduced, i.e. summed using XOR.  I&#8217;m not going to post the code to the <code>gf_add</code> function.</p>
<p>In this fashion, I compute the result of all possible linear combinations, and pick the ones that equal to &alpha;<sup>8</sup> &#8230; &alpha;<sup>14</sup>.  <code>numpy</code> makes it easy to convert a list of lists into an array and then transpose it.  If you use Python on Linux, chances are good that you already have numpy, or even scipy.</p>
<p>To implement <strong>c</strong> = <strong>d</strong> + <strong>Q</strong><sup>T</sup><strong>e</strong>, see below:</p>
<pre>
def gen_c(Q_t):
    e = ['e%i' % i for i in xrange(7)]
    c = []
    for i in xrange(8):
        t = ' ^ '.join([s for s in map(multiply, Q_t[i], e) if s != ''])
        s = 'c%i = d%i ^ %s' % (i, i, t)
        c.append(s)
    return c
</pre>
<p>I use the exact same multiply function without regard for typing.  Python returns an empty string if the boolean operand is False, and the string itself if the boolean operand is True, so a simple filter gets rid of the terms that are not needed.</p>
<p>To verify, you can copy and paste the code blocks for <strong>d</strong>, <strong>e</strong>, and <strong>c</strong> into a function that takes <code>a, b</code> as arguments, and returns an integer that the resulting <strong>c</strong> elements represent.  Then you can repeatedly call that function with all possible inputs and verify the result against the multiplication look-up table.  I leave all that as an exercise for the reader.</p>
<p>With a bit of tweaking to the above code, or just find/replace, you can use the code blocks as the body of a VHDL entity or Verilog module.  That is also an exercise for those inclined.  Of course, for multiplication by a constant the logic could be simplified beforehand, but I would be perfectly fine with the synthesizer optimizing that stuff out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.silician.com/sketchbook/2008/09/22/bit-parallel-finite-field-multiplier-design-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bit-parallel finite field multiplier design (Part 1)</title>
		<link>http://www.silician.com/sketchbook/2008/09/21/bit-parallel-finite-field-multiplier-design-part-1/</link>
		<comments>http://www.silician.com/sketchbook/2008/09/21/bit-parallel-finite-field-multiplier-design-part-1/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 20:15:06 +0000</pubDate>
		<dc:creator>introspect</dc:creator>
				<category><![CDATA[education]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[dsp]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[vhdl]]></category>

		<guid isPermaLink="false">http://www.silician.com/sketchbook/?p=64</guid>
		<description><![CDATA[So for various reasons, it turns out that I don&#8217;t really need Reed-Solomon codes for what I&#8217;ll be doing, but I still have more than a passing interest in the decoding side of things, if only for hobby reasons. You can make the case that the fundamental building block for a Reed-Solomon decoder is the [...]]]></description>
			<content:encoded><![CDATA[<p>So for various reasons, it turns out that I don&#8217;t really need <a href="http://www.silician.com/sketchbook/2008/07/12/reed-solomon-for-noobs/">Reed-Solomon codes</a> for what I&#8217;ll be doing, but I still have more than a passing interest in the decoding side of things, if only for hobby reasons.</p>
<p>You can make the case that the fundamental building block for a Reed-Solomon decoder is the finite field multiplier.  Addition in GF(2<sup>m</sup>) is easy &mdash; just xor &mdash; but multiplication is another story entirely.  The multiplier itself is dependent upon the field primitive polynomial, so that&#8217;s why you don&#8217;t see embedded FFM blocks on an FPGA, or even a general purpose processor for that matter.</p>
<p>That may change in the future when Intel introduces <a href="http://en.wikipedia.org/wiki/Advanced_Vector_Extensions">AVX</a> with its cryptography accelerating instructions, but even then, from what little I can understand, it doesn&#8217;t sound like a single instruction does FFM on a register; you may still have to do the modulo reduction yourself.</p>
<p>Anyway, I&#8217;m here today to talk about hardware FFM&#8217;s, specifically on 8-bit operands.  Google has a tough time finding information on how to design a FFM, although I suppose it all depends on how you ask it.  You can find some implementations, like on <a href="http://opencores.org/">OpenCores</a>, but I&#8217;m not that enthusiastic about having to register for a once totally open site (you can try your luck with <a href="http://www.bugmenot.com/">BugMeNot</a> though), plus implementations rarely ever convey <em>how</em> they were created.</p>
<p>I finally found a fairly friendly method, in a paper by <a href="http://www.eng.uwo.ca/people/areyhani/">A. Reyhani-Masoleh</a> and <a href="http://www.ece.uwaterloo.ca/People/faculty/hasan.html">M. A. Hasan</a>.  See <a href="http://www.eng.uwo.ca/people/areyhani/download%20Files/PB-TC-Aug04.pdf">Low Complexity Bit Parallel Polynomial Basis Multiplication over GF(2<sup>m</sup>)</a>.</p>
<p>Note that &#8220;FFM&#8221;, &#8220;finite field&#8221;, or &#8220;Galois&#8221; are nowhere to be found in the title.  I suppose I am unfamiliar with the nomenclature, which is what made searching for information more difficult.</p>
<p>I think it should also be noted that IEEE papers are generally not freely available, so if it weren&#8217;t for Dr. Reyhani-Masoleh&#8217;s generosity, you&#8217;d have to access the paper through your own, or university&#8217;s, subscription to IEEE Xplore.</p>
<p>For the ASIC layout folks, the paper details a very regular structure for the multiplier, so bonus.</p>
<p>From a design standpoint, there are three variables.  Two of them, the <strong>d</strong> and <strong>e</strong> vectors, depend only on the bit-width so they are constant regardless of the primitive polynomial.  How they are combined is determined by the transpose of the <strong>Q</strong> matrix, and to get at <strong>Q</strong> you need to solve equation (5).</p>
<p>The elements of <strong>Q</strong> are constrained to be either 1 or 0, so multiplication is really an on/off operation, and addition is xor.  At least for small values of m (the m in GF(2<sup>m</sup>)) you can brute force the solution.  Also, when working out <strong>d</strong> and <strong>e</strong> from the Toeplitz matrices, multiplication is the and operation.</p>
<p>All vectors are indexed starting from 0, i.e. <strong>e</strong> = [<em>e<sub>0</sub></em>, <em>e<sub>1</sub></em>, ... , <em>e<sub>m-2</sub></em>].  Bit-level multiplication is accomplished with an and gate.</p>
<p>The algorithm lends itself well to code generation, so I wrote my own Python functions to generate and verify the basic bit-level equations.  With a bit of find/replace, it&#8217;s easy to just port those over to something like VHDL.  Here&#8217;s <a href="http://www.silician.com/sketchbook/wp-content/uploads/2008/09/gf_mul_1d.txt">a link</a> for a 0x1D multiplier in GF(256), i.e. P(x) = x<sup>8</sup>  + x<sup>4</sup> + x<sup>3</sup> + x<sup>2</sup> + 1.  I <em>think</em> it should synthesize, but without running it through Quartus or ISE, I can&#8217;t say for sure.  Until I get my hands on an FPGA development board, I&#8217;m not really motivated to install either of those packages.</p>
<p>In Part 2, I&#8217;ll post my Python code, which I&#8217;m more confident in.  For now, enjoy the multiplier, whose polynomial is used in ATSC, WiMAX, and DVB Reed-Solomon codes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.silician.com/sketchbook/2008/09/21/bit-parallel-finite-field-multiplier-design-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
