Guy Hutchison | 5 Nov 20:14 2014
Picon

[M-Labs devel] [PATCH] Reformatted patch for hamming code generation

Reformatted code per comments, except for new-format string generation which I need to read up on.

- Guy
From b7f0dee52c80cf17563e4aed6428680adaa78811 Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Thu, 21 Aug 2014 15:31:02 -0700
Subject: [PATCH] Added hamming-code gen/check lib

---
 migen/genlib/mhamgen.py | 272 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 272 insertions(+)
 create mode 100755 migen/genlib/mhamgen.py

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
new file mode 100755
index 0000000..88a9fcd
--- /dev/null
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -0,0 +1,272  <at>  <at> 
+#!/usr/bin/env python3
+
+# Copyright (c) 2014 Guy Hutchison
+
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import migen
+import operator
+import argparse
+from migen.fhdl.std import *
+from migen.fhdl.verilog import convert
+
+
+# Base class for Hamming code generator/checker.
+
+# build_seq() is used to create the selection of bits which need
+# to be checked for a particular data parity bit.
+
+# build_bits() is used for the generator portion, it combines the
+# bit sequences for all input and parity bits which are used and
+# removes redundant terms.
+
+# xor_tree() takes a signal and a list of bits to be applied from
+# the signal and generates a balanced xor tree as output.
+class mhamming(Module):
+    def __init__(self):
+
+        pass
+
+    def calc_code_bits(self, dataBits):
+        m = 1
+        c = 0
+
+        while (c < dataBits):
+            m += 1
+            c = 2**m - m - 1
+        return m
+
+    def build_seq(self, bnum, out_width):
+        tmp = []
+
+        ptr = 0
+        cur = 0
+        skip = 2**(bnum)-1
+        if (skip == 0):
+            check = 2**(bnum)
+        else:
+            check = 0
+        while (cur < out_width):
+            if (check > 0):
+                if (cur != 2**(bnum)-1):
+                    tmp.append(cur)
+                    ptr += 1
+                check -= 1
+                if (check == 0):
+                    skip = 2**(bnum)
+            else:
+                skip -= 1
+                if (skip == 0):
+                    check = 2**(bnum)
+            cur += 1
+
+        return tmp
+
+    # Join two lists a and b, such that redundant terms are removed
+    def join_lists(self, a, b):
+        z = []
+        for x in a+b:
+            if x not in z:
+                z.append(x)
+            else:
+                z.remove(x)
+        return z
+
+    def join_operator(self, list, op):
+        if len(list) == 0:
+            return []
+        elif len(list) == 1:
+            return list[0]
+        elif len(list) == 2:
+            return op(list[0], list[1])
+        else:
+            return op(list[0], join_operator(list[1:], op))
+
+    def xor_tree(self, in_signal, in_bits):
+        if len(in_bits) == 0:
+            print ("ERROR: in_bits must be > 0")
+        elif (len(in_bits) == 1):
+            return in_signal[in_bits[0]]
+        elif (len(in_bits) == 2):
+            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
+        elif (len(in_bits) == 3):
+            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+        else:
+            split = int(len(in_bits)/2)
+            return self.xor_tree(in_signal, in_bits[0:split]) ^ self.xor_tree(in_signal, in_bits[split:])
+
+    def build_bits(self, in_width):
+        pnum = 1
+        innum = 0
+        blist = []
+        num_code_bits = self.calc_code_bits(in_width)
+        out_width = in_width + num_code_bits
+        v = [list()] * out_width
+        code_bit_list = []
+
+        for b in range(out_width):
+            if ((b+1) == pnum):
+                pnum = 2*pnum
+            else:
+                v[b] = [innum]
+                innum += 1
+
+        for b in range(num_code_bits):
+            vindex = 2**b-1
+            blist = self.build_seq(b, out_width)
+            for bli in blist:
+                v[vindex] = self.join_lists(v[vindex], v[bli])
+            code_bit_list.append(v[vindex])
+
+        # Calculate parity bit
+        pbit = []
+        for b in v:
+            pbit = self.join_lists(pbit, b)
+        code_bit_list.append(pbit)
+        return code_bit_list
+
+
+# Hamming code generator class
+
+# The class constructor takes a single required input, which is the number of
+# bits of the input data.  The module creates a single output, which is a set
+# of code check bits and a parity bit.
+
+# This generator and its corresponding checker will only generate a single-
+# error correct, double-error detect code.  If double-error detection is
+# not desired, the most-significant code_out bit can be left unconnected.
+
+# If generated as a top-level module, contains its suggested module name
+# in self.name and list of ports in self.ports
+class mhamgen(mhamming):
+    def __init__(self, input_size):
+        self.input_size = input_size
+        self.name = "mhamgen%03d" % input_size
+        self.data_in = Signal(input_size, name='data_in')
+        self.code_out = Signal(self.calc_code_bits(input_size)+1)
+        self.ports = {self.data_in, self.code_out}
+
+    def do_finalize(self):
+        xor_bits = self.build_bits(self.input_size)
+        for b in range(len(xor_bits)):
+            self.comb += self.code_out[b].eq(self.xor_tree(self.data_in, xor_bits[b]))
+
+
+# Hamming code checker class
+
+# Constructor takes two parameters:
+#  input_size (bits of data bus, not counting check bits)
+#  correct (boolean, True if output data should be corrected)
+
+# If used as a check/correct module, the module creates an
+# enable input which can dynamically turn off error correction
+# for debug.
+
+# If double-bit detection is not desired, the most-significant
+# code_in bit can be tied to 0, and the dberr output port left
+# unconnected.
+
+# If generated as a top-level module, contains its suggested module name
+# in self.name and list of ports in self.ports
+class mhamchk(mhamming):
+    def __init__(self, input_size, correct=True):
+        self.input_size = input_size
+        self.correct = correct
+        self.name = "mhamchk%03d" % input_size
+        self.data_in = Signal(input_size, name='data_in')
+        self.code_bits = self.calc_code_bits(input_size)
+        self.code_in = Signal(self.code_bits+1)
+        self.code_out = Signal(self.code_bits)
+        self.sberr = Signal()
+        self.dberr = Signal()
+        self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}
+
+        # vector of which interleaved bit position represents a particular
+        # data bit, used for error correction
+        dbits = []
+
+        # Create interleaved vector of code bits and data bits with code bits
+        # in power-of-two positions
+        pnum = 0
+        dnum = 0
+        self.par_vec = Signal(input_size+self.code_bits)
+        for b in range(input_size+self.calc_code_bits(input_size)):
+            if b+1 == 2**pnum:
+                self.comb += self.par_vec[b].eq(self.code_in[pnum])
+                pnum += 1
+            else:
+                self.comb += self.par_vec[b].eq(self.data_in[dnum])
+                dbits.append(b)
+                dnum += 1
+
+        if correct:
+            self.enable = Signal()
+            self.correct_out = Signal(input_size)
+            self.data_out = Signal(input_size, name='data_out')
+            self.ports.add(self.data_out)
+            self.ports.add(self.enable)
+            for b in range(input_size):
+                self.comb += self.correct_out[b].eq((self.code_out == (dbits[b]+1)) ^ self.data_in[b])
+            self.comb += If(self.enable, self.data_out.eq(self.correct_out)).Else(self.data_out.eq(self.data_in))
+        else:
+            self.ports.add(self.code_out)
+
+        self.comb += self.sberr.eq(self.code_out != 0)
+        parity = Signal()
+        self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
+        self.comb += self.dberr.eq(~parity)
+
+    def do_finalize(self):
+        for b in range(self.calc_code_bits(self.input_size)):
+            bits = [2**b-1]
+            bits += self.build_seq(b, self.input_size+self.calc_code_bits(self.input_size))
+            self.comb += self.code_out[b].eq(self.xor_tree(self.par_vec, bits))
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-g', help="Create generator", default=False, action='store_true')
+    parser.add_argument('-c', help="Create checker", default=False, action='store_true')
+    parser.add_argument('--correct', help="Create correcting checker", default=False, action='store_true')
+    parser.add_argument('-m', "--module", help="Override module name",
+                        type=str)
+    parser.add_argument('-w', '--width', type=int, help="Generator/checker data width")
+    args = parser.parse_args()
+
+    if args.g:
+        mhg = mhamgen(args.width)
+        if args.module is not None:
+            mhg.name = args.module
+        filename = mhg.name + '.v'
+        fh = open(filename, 'w')
+        fh.write(convert(mhg, mhg.ports, name=mhg.name))
+        fh.close()
+    if args.c:
+        mhc = mhamchk(args.width, correct=args.correct)
+        if args.module is not None:
+            mhc.name = args.module
+        filename = mhc.name + '.v'
+        fh = open(filename, 'w')
+        fh.write(convert(mhc, mhc.ports, name=mhc.name))
+        fh.close()
+
+if __name__ == "__main__":
+    main()
-- 
1.8.4.2

From 72e2c04b09059a7ce2baa127dbbb188b8257a35e Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Wed, 1 Oct 2014 13:01:13 +0200
Subject: [PATCH] Code cleanup to match migen coding conventions

---
 migen/genlib/mhamgen.py | 235 ++++++++++++++++++++++++------------------------
 1 file changed, 117 insertions(+), 118 deletions(-)

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
index 88a9fcd..2039fa8 100755
--- a/migen/genlib/mhamgen.py
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -29,119 +29,119  <at>  <at>  from migen.fhdl.std import *
 from migen.fhdl.verilog import convert

 
-# Base class for Hamming code generator/checker.
+# Join two lists a and b, such that redundant terms are removed
+def join_lists(a, b):
+    z = []
+    for x in a+b:
+        if x not in z:
+            z.append(x)
+        else:
+            z.remove(x)
+    return z

-# build_seq() is used to create the selection of bits which need
-# to be checked for a particular data parity bit.

-# build_bits() is used for the generator portion, it combines the
-# bit sequences for all input and parity bits which are used and
-# removes redundant terms.
+def join_operator(list, op):
+    if len(list) == 0:
+        return []
+    elif len(list) == 1:
+        return list[0]
+    elif len(list) == 2:
+        return op(list[0], list[1])
+    else:
+        return op(list[0], join_operator(list[1:], op))

-# xor_tree() takes a signal and a list of bits to be applied from
-# the signal and generates a balanced xor tree as output.
-class mhamming(Module):
-    def __init__(self):
-
-        pass

-    def calc_code_bits(self, dataBits):
-        m = 1
-        c = 0
+def calc_code_bits(dataBits):
+    m = 1
+    c = 0

-        while (c < dataBits):
-            m += 1
-            c = 2**m - m - 1
-        return m
+    while (c < dataBits):
+        m += 1
+        c = 2**m - m - 1
+    return m

-    def build_seq(self, bnum, out_width):
-        tmp = []

-        ptr = 0
-        cur = 0
-        skip = 2**(bnum)-1
-        if (skip == 0):
-            check = 2**(bnum)
-        else:
-            check = 0
-        while (cur < out_width):
-            if (check > 0):
-                if (cur != 2**(bnum)-1):
-                    tmp.append(cur)
-                    ptr += 1
-                check -= 1
-                if (check == 0):
-                    skip = 2**(bnum)
-            else:
-                skip -= 1
-                if (skip == 0):
-                    check = 2**(bnum)
-            cur += 1
-
-        return tmp
-
-    # Join two lists a and b, such that redundant terms are removed
-    def join_lists(self, a, b):
-        z = []
-        for x in a+b:
-            if x not in z:
-                z.append(x)
-            else:
-                z.remove(x)
-        return z
-
-    def join_operator(self, list, op):
-        if len(list) == 0:
-            return []
-        elif len(list) == 1:
-            return list[0]
-        elif len(list) == 2:
-            return op(list[0], list[1])
-        else:
-            return op(list[0], join_operator(list[1:], op))
-
-    def xor_tree(self, in_signal, in_bits):
-        if len(in_bits) == 0:
-            print ("ERROR: in_bits must be > 0")
-        elif (len(in_bits) == 1):
-            return in_signal[in_bits[0]]
-        elif (len(in_bits) == 2):
-            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
-        elif (len(in_bits) == 3):
-            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+# build_seq() is used to create the selection of bits which need
+# to be checked for a particular data parity bit.
+def build_seq(bnum, out_width):
+    tmp = []
+
+    ptr = 0
+    cur = 0
+    skip = 2**(bnum)-1
+    if (skip == 0):
+        check = 2**(bnum)
+    else:
+        check = 0
+    while (cur < out_width):
+        if (check > 0):
+            if (cur != 2**(bnum)-1):
+                tmp.append(cur)
+                ptr += 1
+            check -= 1
+            if (check == 0):
+                skip = 2**(bnum)
         else:
-            split = int(len(in_bits)/2)
-            return self.xor_tree(in_signal, in_bits[0:split]) ^ self.xor_tree(in_signal, in_bits[split:])
-
-    def build_bits(self, in_width):
-        pnum = 1
-        innum = 0
-        blist = []
-        num_code_bits = self.calc_code_bits(in_width)
-        out_width = in_width + num_code_bits
-        v = [list()] * out_width
-        code_bit_list = []
-
-        for b in range(out_width):
-            if ((b+1) == pnum):
-                pnum = 2*pnum
-            else:
-                v[b] = [innum]
-                innum += 1
+            skip -= 1
+            if (skip == 0):
+                check = 2**(bnum)
+        cur += 1

-        for b in range(num_code_bits):
-            vindex = 2**b-1
-            blist = self.build_seq(b, out_width)
-            for bli in blist:
-                v[vindex] = self.join_lists(v[vindex], v[bli])
-            code_bit_list.append(v[vindex])
+    return tmp

-        # Calculate parity bit
+
+# build_bits() is used for the generator portion, it combines the
+# bit sequences for all input and parity bits which are used and
+# removes redundant terms.
+def build_bits(in_width, gen_parity=True):
+    pnum = 1
+    innum = 0
+    blist = []
+    num_code_bits = calc_code_bits(in_width)
+    out_width = in_width + num_code_bits
+    v = [list()] * out_width
+    code_bit_list = []
+
+    for b in range(out_width):
+        if ((b+1) == pnum):
+            pnum = 2*pnum
+        else:
+            v[b] = [innum]
+            innum += 1
+
+    for b in range(num_code_bits):
+        vindex = 2**b-1
+        blist = build_seq(b, out_width)
+        for bli in blist:
+            v[vindex] = join_lists(v[vindex], v[bli])
+        code_bit_list.append(v[vindex])
+
+    # Calculate parity bit
+    if gen_parity:
         pbit = []
         for b in v:
-            pbit = self.join_lists(pbit, b)
+            pbit = join_lists(pbit, b)
         code_bit_list.append(pbit)
-        return code_bit_list
+    return code_bit_list
+
+
+# xor_tree() takes a signal and a list of bits to be applied from
+# the signal and generates a balanced xor tree as output.
+def xor_tree(in_signal, in_bits):
+    if len(in_bits) == 0:
+        print ("ERROR: in_bits must be > 0")
+    elif (len(in_bits) == 1):
+        return in_signal[in_bits[0]]
+    elif (len(in_bits) == 2):
+        return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
+    elif (len(in_bits) == 3):
+        return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+    else:
+        split = int(len(in_bits)/2)
+        return xor_tree(in_signal, in_bits[0:split]) ^ xor_tree(in_signal, in_bits[split:])
+
+
+# Base class for Hamming code generator/checker.

 
 # Hamming code generator class
 <at>  <at>  -156,18 +156,17  <at>  <at>  class mhamming(Module):

 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
-class mhamgen(mhamming):
+class HammingGenerator(Module):
     def __init__(self, input_size):
         self.input_size = input_size
         self.name = "mhamgen%03d" % input_size
-        self.data_in = Signal(input_size, name='data_in')
-        self.code_out = Signal(self.calc_code_bits(input_size)+1)
+        self.data_in = Signal(input_size, name_override='data_in')
+        self.code_out = Signal(calc_code_bits(input_size)+1)
         self.ports = {self.data_in, self.code_out}

-    def do_finalize(self):
-        xor_bits = self.build_bits(self.input_size)
+        xor_bits = build_bits(self.input_size)
         for b in range(len(xor_bits)):
-            self.comb += self.code_out[b].eq(self.xor_tree(self.data_in, xor_bits[b]))
+            self.comb += self.code_out[b].eq(xor_tree(self.data_in, xor_bits[b]))

 
 # Hamming code checker class
 <at>  <at>  -186,17 +185,18  <at>  <at>  class mhamgen(mhamming):

 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
-class mhamchk(mhamming):
-    def __init__(self, input_size, correct=True):
+class HammingChecker(Module):
+    def __init__(self, input_size, correct=True, parity=True):
         self.input_size = input_size
         self.correct = correct
         self.name = "mhamchk%03d" % input_size
-        self.data_in = Signal(input_size, name='data_in')
-        self.code_bits = self.calc_code_bits(input_size)
+        self.data_in = Signal(input_size, name_override='data_in')
+        self.code_bits = calc_code_bits(input_size)
         self.code_in = Signal(self.code_bits+1)
         self.code_out = Signal(self.code_bits)
         self.sberr = Signal()
-        self.dberr = Signal()
+        if parity:
+            self.dberr = Signal()
         self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}

         # vector of which interleaved bit position represents a particular
 <at>  <at>  -208,7 +208,7  <at>  <at>  class mhamchk(mhamming):
         pnum = 0
         dnum = 0
         self.par_vec = Signal(input_size+self.code_bits)
-        for b in range(input_size+self.calc_code_bits(input_size)):
+        for b in range(input_size+calc_code_bits(input_size)):
             if b+1 == 2**pnum:
                 self.comb += self.par_vec[b].eq(self.code_in[pnum])
                 pnum += 1
 <at>  <at>  -234,11 +234,10  <at>  <at>  class mhamchk(mhamming):
         self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
         self.comb += self.dberr.eq(~parity)

-    def do_finalize(self):
-        for b in range(self.calc_code_bits(self.input_size)):
+        for b in range(calc_code_bits(self.input_size)):
             bits = [2**b-1]
-            bits += self.build_seq(b, self.input_size+self.calc_code_bits(self.input_size))
-            self.comb += self.code_out[b].eq(self.xor_tree(self.par_vec, bits))
+            bits += build_seq(b, self.input_size+calc_code_bits(self.input_size))
+            self.comb += self.code_out[b].eq(xor_tree(self.par_vec, bits))

 
 def main():
 <at>  <at>  -252,7 +251,7  <at>  <at>  def main():
     args = parser.parse_args()

     if args.g:
-        mhg = mhamgen(args.width)
+        mhg = HammingGenerator(args.width)
         if args.module is not None:
             mhg.name = args.module
         filename = mhg.name + '.v'
 <at>  <at>  -260,7 +259,7  <at>  <at>  def main():
         fh.write(convert(mhg, mhg.ports, name=mhg.name))
         fh.close()
     if args.c:
-        mhc = mhamchk(args.width, correct=args.correct)
+        mhc = HammingChecker(args.width, correct=args.correct)
         if args.module is not None:
             mhc.name = args.module
         filename = mhc.name + '.v'
-- 
1.8.4.2

From 8dc0ee74f56f995826bcd8385b3e45727d607ba3 Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Wed, 5 Nov 2014 09:18:00 -0800
Subject: [PATCH] Modified code for project commit

---
 migen/genlib/mhamgen.py | 49 +++++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
index 2039fa8..56de6e0 100755
--- a/migen/genlib/mhamgen.py
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -159,10 +159,8  <at>  <at>  def xor_tree(in_signal, in_bits):
 class HammingGenerator(Module):
     def __init__(self, input_size):
         self.input_size = input_size
-        self.name = "mhamgen%03d" % input_size
-        self.data_in = Signal(input_size, name_override='data_in')
+        self.data_in = Signal(input_size)
         self.code_out = Signal(calc_code_bits(input_size)+1)
-        self.ports = {self.data_in, self.code_out}

         xor_bits = build_bits(self.input_size)
         for b in range(len(xor_bits)):
 <at>  <at>  -186,18 +184,16  <at>  <at>  class HammingGenerator(Module):
 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
 class HammingChecker(Module):
-    def __init__(self, input_size, correct=True, parity=True):
+    def __init__(self, input_size, correct=True, gen_parity=True):
         self.input_size = input_size
         self.correct = correct
-        self.name = "mhamchk%03d" % input_size
-        self.data_in = Signal(input_size, name_override='data_in')
+        self.data_in = Signal(input_size)
         self.code_bits = calc_code_bits(input_size)
         self.code_in = Signal(self.code_bits+1)
         self.code_out = Signal(self.code_bits)
         self.sberr = Signal()
-        if parity:
+        if gen_parity:
             self.dberr = Signal()
-        self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}

         # vector of which interleaved bit position represents a particular
         # data bit, used for error correction
 <at>  <at>  -221,18 +217,15  <at>  <at>  class HammingChecker(Module):
             self.enable = Signal()
             self.correct_out = Signal(input_size)
             self.data_out = Signal(input_size, name='data_out')
-            self.ports.add(self.data_out)
-            self.ports.add(self.enable)
             for b in range(input_size):
                 self.comb += self.correct_out[b].eq((self.code_out == (dbits[b]+1)) ^ self.data_in[b])
             self.comb += If(self.enable, self.data_out.eq(self.correct_out)).Else(self.data_out.eq(self.data_in))
-        else:
-            self.ports.add(self.code_out)

         self.comb += self.sberr.eq(self.code_out != 0)
-        parity = Signal()
-        self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
-        self.comb += self.dberr.eq(~parity)
+        if gen_parity:
+            parity = Signal()
+            self.comb += parity.eq(xor_tree(self.data_in, range(input_size)) ^ xor_tree(self.code_in, range(self.code_bits+1)))
+            self.comb += self.dberr.eq(~parity)

         for b in range(calc_code_bits(self.input_size)):
             bits = [2**b-1]
 <at>  <at>  -244,27 +237,43  <at>  <at>  def main():
     parser = argparse.ArgumentParser()
     parser.add_argument('-g', help="Create generator", default=False, action='store_true')
     parser.add_argument('-c', help="Create checker", default=False, action='store_true')
+    parser.add_argument('--noparity', help="Create without parity check", default=False, action='store_true')
     parser.add_argument('--correct', help="Create correcting checker", default=False, action='store_true')
     parser.add_argument('-m', "--module", help="Override module name",
                         type=str)
     parser.add_argument('-w', '--width', type=int, help="Generator/checker data width")
     args = parser.parse_args()
+    parity = not args.noparity

     if args.g:
         mhg = HammingGenerator(args.width)
+        ports = {mhg.data_in, mhg.code_out}
+        mhg.data_in.name_override = "data_in"
         if args.module is not None:
-            mhg.name = args.module
-        filename = mhg.name + '.v'
+            name = args.module
+        else:
+            name = "mhamgen%03d" % args.width
+        filename = name + '.v'
         fh = open(filename, 'w')
-        fh.write(convert(mhg, mhg.ports, name=mhg.name))
+        fh.write(convert(mhg, ports, name=name))
         fh.close()
     if args.c:
         mhc = HammingChecker(args.width, correct=args.correct)
+        ports = {mhc.data_in, mhc.code_in, mhc.sberr, mhc.dberr}
+        if args.correct:
+            ports.add(mhc.data_out)
+            ports.add(mhc.enable)
+        else:
+            ports.add(mhc.code_out)
+        if parity:
+            ports.add(mhc.dberr)
         if args.module is not None:
             mhc.name = args.module
-        filename = mhc.name + '.v'
+        else:
+            name = "mhamchk%03d" % args.width
+        filename = name + '.v'
         fh = open(filename, 'w')
-        fh.write(convert(mhc, mhc.ports, name=mhc.name))
+        fh.write(convert(mhc, ports, name=name))
         fh.close()

 if __name__ == "__main__":
-- 
1.8.4.2

From b7f0dee52c80cf17563e4aed6428680adaa78811 Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Thu, 21 Aug 2014 15:31:02 -0700
Subject: [PATCH] Added hamming-code gen/check lib

---
 migen/genlib/mhamgen.py | 272 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 272 insertions(+)
 create mode 100755 migen/genlib/mhamgen.py

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
new file mode 100755
index 0000000..88a9fcd
--- /dev/null
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -0,0 +1,272  <at>  <at> 
+#!/usr/bin/env python3
+
+# Copyright (c) 2014 Guy Hutchison
+
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import migen
+import operator
+import argparse
+from migen.fhdl.std import *
+from migen.fhdl.verilog import convert
+
+
+# Base class for Hamming code generator/checker.
+
+# build_seq() is used to create the selection of bits which need
+# to be checked for a particular data parity bit.
+
+# build_bits() is used for the generator portion, it combines the
+# bit sequences for all input and parity bits which are used and
+# removes redundant terms.
+
+# xor_tree() takes a signal and a list of bits to be applied from
+# the signal and generates a balanced xor tree as output.
+class mhamming(Module):
+    def __init__(self):
+
+        pass
+
+    def calc_code_bits(self, dataBits):
+        m = 1
+        c = 0
+
+        while (c < dataBits):
+            m += 1
+            c = 2**m - m - 1
+        return m
+
+    def build_seq(self, bnum, out_width):
+        tmp = []
+
+        ptr = 0
+        cur = 0
+        skip = 2**(bnum)-1
+        if (skip == 0):
+            check = 2**(bnum)
+        else:
+            check = 0
+        while (cur < out_width):
+            if (check > 0):
+                if (cur != 2**(bnum)-1):
+                    tmp.append(cur)
+                    ptr += 1
+                check -= 1
+                if (check == 0):
+                    skip = 2**(bnum)
+            else:
+                skip -= 1
+                if (skip == 0):
+                    check = 2**(bnum)
+            cur += 1
+
+        return tmp
+
+    # Join two lists a and b, such that redundant terms are removed
+    def join_lists(self, a, b):
+        z = []
+        for x in a+b:
+            if x not in z:
+                z.append(x)
+            else:
+                z.remove(x)
+        return z
+
+    def join_operator(self, list, op):
+        if len(list) == 0:
+            return []
+        elif len(list) == 1:
+            return list[0]
+        elif len(list) == 2:
+            return op(list[0], list[1])
+        else:
+            return op(list[0], join_operator(list[1:], op))
+
+    def xor_tree(self, in_signal, in_bits):
+        if len(in_bits) == 0:
+            print ("ERROR: in_bits must be > 0")
+        elif (len(in_bits) == 1):
+            return in_signal[in_bits[0]]
+        elif (len(in_bits) == 2):
+            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
+        elif (len(in_bits) == 3):
+            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+        else:
+            split = int(len(in_bits)/2)
+            return self.xor_tree(in_signal, in_bits[0:split]) ^ self.xor_tree(in_signal, in_bits[split:])
+
+    def build_bits(self, in_width):
+        pnum = 1
+        innum = 0
+        blist = []
+        num_code_bits = self.calc_code_bits(in_width)
+        out_width = in_width + num_code_bits
+        v = [list()] * out_width
+        code_bit_list = []
+
+        for b in range(out_width):
+            if ((b+1) == pnum):
+                pnum = 2*pnum
+            else:
+                v[b] = [innum]
+                innum += 1
+
+        for b in range(num_code_bits):
+            vindex = 2**b-1
+            blist = self.build_seq(b, out_width)
+            for bli in blist:
+                v[vindex] = self.join_lists(v[vindex], v[bli])
+            code_bit_list.append(v[vindex])
+
+        # Calculate parity bit
+        pbit = []
+        for b in v:
+            pbit = self.join_lists(pbit, b)
+        code_bit_list.append(pbit)
+        return code_bit_list
+
+
+# Hamming code generator class
+
+# The class constructor takes a single required input, which is the number of
+# bits of the input data.  The module creates a single output, which is a set
+# of code check bits and a parity bit.
+
+# This generator and its corresponding checker will only generate a single-
+# error correct, double-error detect code.  If double-error detection is
+# not desired, the most-significant code_out bit can be left unconnected.
+
+# If generated as a top-level module, contains its suggested module name
+# in self.name and list of ports in self.ports
+class mhamgen(mhamming):
+    def __init__(self, input_size):
+        self.input_size = input_size
+        self.name = "mhamgen%03d" % input_size
+        self.data_in = Signal(input_size, name='data_in')
+        self.code_out = Signal(self.calc_code_bits(input_size)+1)
+        self.ports = {self.data_in, self.code_out}
+
+    def do_finalize(self):
+        xor_bits = self.build_bits(self.input_size)
+        for b in range(len(xor_bits)):
+            self.comb += self.code_out[b].eq(self.xor_tree(self.data_in, xor_bits[b]))
+
+
+# Hamming code checker class
+
+# Constructor takes two parameters:
+#  input_size (bits of data bus, not counting check bits)
+#  correct (boolean, True if output data should be corrected)
+
+# If used as a check/correct module, the module creates an
+# enable input which can dynamically turn off error correction
+# for debug.
+
+# If double-bit detection is not desired, the most-significant
+# code_in bit can be tied to 0, and the dberr output port left
+# unconnected.
+
+# If generated as a top-level module, contains its suggested module name
+# in self.name and list of ports in self.ports
+class mhamchk(mhamming):
+    def __init__(self, input_size, correct=True):
+        self.input_size = input_size
+        self.correct = correct
+        self.name = "mhamchk%03d" % input_size
+        self.data_in = Signal(input_size, name='data_in')
+        self.code_bits = self.calc_code_bits(input_size)
+        self.code_in = Signal(self.code_bits+1)
+        self.code_out = Signal(self.code_bits)
+        self.sberr = Signal()
+        self.dberr = Signal()
+        self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}
+
+        # vector of which interleaved bit position represents a particular
+        # data bit, used for error correction
+        dbits = []
+
+        # Create interleaved vector of code bits and data bits with code bits
+        # in power-of-two positions
+        pnum = 0
+        dnum = 0
+        self.par_vec = Signal(input_size+self.code_bits)
+        for b in range(input_size+self.calc_code_bits(input_size)):
+            if b+1 == 2**pnum:
+                self.comb += self.par_vec[b].eq(self.code_in[pnum])
+                pnum += 1
+            else:
+                self.comb += self.par_vec[b].eq(self.data_in[dnum])
+                dbits.append(b)
+                dnum += 1
+
+        if correct:
+            self.enable = Signal()
+            self.correct_out = Signal(input_size)
+            self.data_out = Signal(input_size, name='data_out')
+            self.ports.add(self.data_out)
+            self.ports.add(self.enable)
+            for b in range(input_size):
+                self.comb += self.correct_out[b].eq((self.code_out == (dbits[b]+1)) ^ self.data_in[b])
+            self.comb += If(self.enable, self.data_out.eq(self.correct_out)).Else(self.data_out.eq(self.data_in))
+        else:
+            self.ports.add(self.code_out)
+
+        self.comb += self.sberr.eq(self.code_out != 0)
+        parity = Signal()
+        self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
+        self.comb += self.dberr.eq(~parity)
+
+    def do_finalize(self):
+        for b in range(self.calc_code_bits(self.input_size)):
+            bits = [2**b-1]
+            bits += self.build_seq(b, self.input_size+self.calc_code_bits(self.input_size))
+            self.comb += self.code_out[b].eq(self.xor_tree(self.par_vec, bits))
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-g', help="Create generator", default=False, action='store_true')
+    parser.add_argument('-c', help="Create checker", default=False, action='store_true')
+    parser.add_argument('--correct', help="Create correcting checker", default=False, action='store_true')
+    parser.add_argument('-m', "--module", help="Override module name",
+                        type=str)
+    parser.add_argument('-w', '--width', type=int, help="Generator/checker data width")
+    args = parser.parse_args()
+
+    if args.g:
+        mhg = mhamgen(args.width)
+        if args.module is not None:
+            mhg.name = args.module
+        filename = mhg.name + '.v'
+        fh = open(filename, 'w')
+        fh.write(convert(mhg, mhg.ports, name=mhg.name))
+        fh.close()
+    if args.c:
+        mhc = mhamchk(args.width, correct=args.correct)
+        if args.module is not None:
+            mhc.name = args.module
+        filename = mhc.name + '.v'
+        fh = open(filename, 'w')
+        fh.write(convert(mhc, mhc.ports, name=mhc.name))
+        fh.close()
+
+if __name__ == "__main__":
+    main()
-- 
1.8.4.2

From 72e2c04b09059a7ce2baa127dbbb188b8257a35e Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Wed, 1 Oct 2014 13:01:13 +0200
Subject: [PATCH] Code cleanup to match migen coding conventions

---
 migen/genlib/mhamgen.py | 235 ++++++++++++++++++++++++------------------------
 1 file changed, 117 insertions(+), 118 deletions(-)

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
index 88a9fcd..2039fa8 100755
--- a/migen/genlib/mhamgen.py
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -29,119 +29,119  <at>  <at>  from migen.fhdl.std import *
 from migen.fhdl.verilog import convert

 
-# Base class for Hamming code generator/checker.
+# Join two lists a and b, such that redundant terms are removed
+def join_lists(a, b):
+    z = []
+    for x in a+b:
+        if x not in z:
+            z.append(x)
+        else:
+            z.remove(x)
+    return z

-# build_seq() is used to create the selection of bits which need
-# to be checked for a particular data parity bit.

-# build_bits() is used for the generator portion, it combines the
-# bit sequences for all input and parity bits which are used and
-# removes redundant terms.
+def join_operator(list, op):
+    if len(list) == 0:
+        return []
+    elif len(list) == 1:
+        return list[0]
+    elif len(list) == 2:
+        return op(list[0], list[1])
+    else:
+        return op(list[0], join_operator(list[1:], op))

-# xor_tree() takes a signal and a list of bits to be applied from
-# the signal and generates a balanced xor tree as output.
-class mhamming(Module):
-    def __init__(self):
-
-        pass

-    def calc_code_bits(self, dataBits):
-        m = 1
-        c = 0
+def calc_code_bits(dataBits):
+    m = 1
+    c = 0

-        while (c < dataBits):
-            m += 1
-            c = 2**m - m - 1
-        return m
+    while (c < dataBits):
+        m += 1
+        c = 2**m - m - 1
+    return m

-    def build_seq(self, bnum, out_width):
-        tmp = []

-        ptr = 0
-        cur = 0
-        skip = 2**(bnum)-1
-        if (skip == 0):
-            check = 2**(bnum)
-        else:
-            check = 0
-        while (cur < out_width):
-            if (check > 0):
-                if (cur != 2**(bnum)-1):
-                    tmp.append(cur)
-                    ptr += 1
-                check -= 1
-                if (check == 0):
-                    skip = 2**(bnum)
-            else:
-                skip -= 1
-                if (skip == 0):
-                    check = 2**(bnum)
-            cur += 1
-
-        return tmp
-
-    # Join two lists a and b, such that redundant terms are removed
-    def join_lists(self, a, b):
-        z = []
-        for x in a+b:
-            if x not in z:
-                z.append(x)
-            else:
-                z.remove(x)
-        return z
-
-    def join_operator(self, list, op):
-        if len(list) == 0:
-            return []
-        elif len(list) == 1:
-            return list[0]
-        elif len(list) == 2:
-            return op(list[0], list[1])
-        else:
-            return op(list[0], join_operator(list[1:], op))
-
-    def xor_tree(self, in_signal, in_bits):
-        if len(in_bits) == 0:
-            print ("ERROR: in_bits must be > 0")
-        elif (len(in_bits) == 1):
-            return in_signal[in_bits[0]]
-        elif (len(in_bits) == 2):
-            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
-        elif (len(in_bits) == 3):
-            return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+# build_seq() is used to create the selection of bits which need
+# to be checked for a particular data parity bit.
+def build_seq(bnum, out_width):
+    tmp = []
+
+    ptr = 0
+    cur = 0
+    skip = 2**(bnum)-1
+    if (skip == 0):
+        check = 2**(bnum)
+    else:
+        check = 0
+    while (cur < out_width):
+        if (check > 0):
+            if (cur != 2**(bnum)-1):
+                tmp.append(cur)
+                ptr += 1
+            check -= 1
+            if (check == 0):
+                skip = 2**(bnum)
         else:
-            split = int(len(in_bits)/2)
-            return self.xor_tree(in_signal, in_bits[0:split]) ^ self.xor_tree(in_signal, in_bits[split:])
-
-    def build_bits(self, in_width):
-        pnum = 1
-        innum = 0
-        blist = []
-        num_code_bits = self.calc_code_bits(in_width)
-        out_width = in_width + num_code_bits
-        v = [list()] * out_width
-        code_bit_list = []
-
-        for b in range(out_width):
-            if ((b+1) == pnum):
-                pnum = 2*pnum
-            else:
-                v[b] = [innum]
-                innum += 1
+            skip -= 1
+            if (skip == 0):
+                check = 2**(bnum)
+        cur += 1

-        for b in range(num_code_bits):
-            vindex = 2**b-1
-            blist = self.build_seq(b, out_width)
-            for bli in blist:
-                v[vindex] = self.join_lists(v[vindex], v[bli])
-            code_bit_list.append(v[vindex])
+    return tmp

-        # Calculate parity bit
+
+# build_bits() is used for the generator portion, it combines the
+# bit sequences for all input and parity bits which are used and
+# removes redundant terms.
+def build_bits(in_width, gen_parity=True):
+    pnum = 1
+    innum = 0
+    blist = []
+    num_code_bits = calc_code_bits(in_width)
+    out_width = in_width + num_code_bits
+    v = [list()] * out_width
+    code_bit_list = []
+
+    for b in range(out_width):
+        if ((b+1) == pnum):
+            pnum = 2*pnum
+        else:
+            v[b] = [innum]
+            innum += 1
+
+    for b in range(num_code_bits):
+        vindex = 2**b-1
+        blist = build_seq(b, out_width)
+        for bli in blist:
+            v[vindex] = join_lists(v[vindex], v[bli])
+        code_bit_list.append(v[vindex])
+
+    # Calculate parity bit
+    if gen_parity:
         pbit = []
         for b in v:
-            pbit = self.join_lists(pbit, b)
+            pbit = join_lists(pbit, b)
         code_bit_list.append(pbit)
-        return code_bit_list
+    return code_bit_list
+
+
+# xor_tree() takes a signal and a list of bits to be applied from
+# the signal and generates a balanced xor tree as output.
+def xor_tree(in_signal, in_bits):
+    if len(in_bits) == 0:
+        print ("ERROR: in_bits must be > 0")
+    elif (len(in_bits) == 1):
+        return in_signal[in_bits[0]]
+    elif (len(in_bits) == 2):
+        return in_signal[in_bits[0]] ^ in_signal[in_bits[1]]
+    elif (len(in_bits) == 3):
+        return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]]
+    else:
+        split = int(len(in_bits)/2)
+        return xor_tree(in_signal, in_bits[0:split]) ^ xor_tree(in_signal, in_bits[split:])
+
+
+# Base class for Hamming code generator/checker.

 
 # Hamming code generator class
 <at>  <at>  -156,18 +156,17  <at>  <at>  class mhamming(Module):

 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
-class mhamgen(mhamming):
+class HammingGenerator(Module):
     def __init__(self, input_size):
         self.input_size = input_size
         self.name = "mhamgen%03d" % input_size
-        self.data_in = Signal(input_size, name='data_in')
-        self.code_out = Signal(self.calc_code_bits(input_size)+1)
+        self.data_in = Signal(input_size, name_override='data_in')
+        self.code_out = Signal(calc_code_bits(input_size)+1)
         self.ports = {self.data_in, self.code_out}

-    def do_finalize(self):
-        xor_bits = self.build_bits(self.input_size)
+        xor_bits = build_bits(self.input_size)
         for b in range(len(xor_bits)):
-            self.comb += self.code_out[b].eq(self.xor_tree(self.data_in, xor_bits[b]))
+            self.comb += self.code_out[b].eq(xor_tree(self.data_in, xor_bits[b]))

 
 # Hamming code checker class
 <at>  <at>  -186,17 +185,18  <at>  <at>  class mhamgen(mhamming):

 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
-class mhamchk(mhamming):
-    def __init__(self, input_size, correct=True):
+class HammingChecker(Module):
+    def __init__(self, input_size, correct=True, parity=True):
         self.input_size = input_size
         self.correct = correct
         self.name = "mhamchk%03d" % input_size
-        self.data_in = Signal(input_size, name='data_in')
-        self.code_bits = self.calc_code_bits(input_size)
+        self.data_in = Signal(input_size, name_override='data_in')
+        self.code_bits = calc_code_bits(input_size)
         self.code_in = Signal(self.code_bits+1)
         self.code_out = Signal(self.code_bits)
         self.sberr = Signal()
-        self.dberr = Signal()
+        if parity:
+            self.dberr = Signal()
         self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}

         # vector of which interleaved bit position represents a particular
 <at>  <at>  -208,7 +208,7  <at>  <at>  class mhamchk(mhamming):
         pnum = 0
         dnum = 0
         self.par_vec = Signal(input_size+self.code_bits)
-        for b in range(input_size+self.calc_code_bits(input_size)):
+        for b in range(input_size+calc_code_bits(input_size)):
             if b+1 == 2**pnum:
                 self.comb += self.par_vec[b].eq(self.code_in[pnum])
                 pnum += 1
 <at>  <at>  -234,11 +234,10  <at>  <at>  class mhamchk(mhamming):
         self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
         self.comb += self.dberr.eq(~parity)

-    def do_finalize(self):
-        for b in range(self.calc_code_bits(self.input_size)):
+        for b in range(calc_code_bits(self.input_size)):
             bits = [2**b-1]
-            bits += self.build_seq(b, self.input_size+self.calc_code_bits(self.input_size))
-            self.comb += self.code_out[b].eq(self.xor_tree(self.par_vec, bits))
+            bits += build_seq(b, self.input_size+calc_code_bits(self.input_size))
+            self.comb += self.code_out[b].eq(xor_tree(self.par_vec, bits))

 
 def main():
 <at>  <at>  -252,7 +251,7  <at>  <at>  def main():
     args = parser.parse_args()

     if args.g:
-        mhg = mhamgen(args.width)
+        mhg = HammingGenerator(args.width)
         if args.module is not None:
             mhg.name = args.module
         filename = mhg.name + '.v'
 <at>  <at>  -260,7 +259,7  <at>  <at>  def main():
         fh.write(convert(mhg, mhg.ports, name=mhg.name))
         fh.close()
     if args.c:
-        mhc = mhamchk(args.width, correct=args.correct)
+        mhc = HammingChecker(args.width, correct=args.correct)
         if args.module is not None:
             mhc.name = args.module
         filename = mhc.name + '.v'
-- 
1.8.4.2

From 8dc0ee74f56f995826bcd8385b3e45727d607ba3 Mon Sep 17 00:00:00 2001
From: Guy Hutchison <guy <at> xpliant.com>
Date: Wed, 5 Nov 2014 09:18:00 -0800
Subject: [PATCH] Modified code for project commit

---
 migen/genlib/mhamgen.py | 49 +++++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py
index 2039fa8..56de6e0 100755
--- a/migen/genlib/mhamgen.py
+++ b/migen/genlib/mhamgen.py
 <at>  <at>  -159,10 +159,8  <at>  <at>  def xor_tree(in_signal, in_bits):
 class HammingGenerator(Module):
     def __init__(self, input_size):
         self.input_size = input_size
-        self.name = "mhamgen%03d" % input_size
-        self.data_in = Signal(input_size, name_override='data_in')
+        self.data_in = Signal(input_size)
         self.code_out = Signal(calc_code_bits(input_size)+1)
-        self.ports = {self.data_in, self.code_out}

         xor_bits = build_bits(self.input_size)
         for b in range(len(xor_bits)):
 <at>  <at>  -186,18 +184,16  <at>  <at>  class HammingGenerator(Module):
 # If generated as a top-level module, contains its suggested module name
 # in self.name and list of ports in self.ports
 class HammingChecker(Module):
-    def __init__(self, input_size, correct=True, parity=True):
+    def __init__(self, input_size, correct=True, gen_parity=True):
         self.input_size = input_size
         self.correct = correct
-        self.name = "mhamchk%03d" % input_size
-        self.data_in = Signal(input_size, name_override='data_in')
+        self.data_in = Signal(input_size)
         self.code_bits = calc_code_bits(input_size)
         self.code_in = Signal(self.code_bits+1)
         self.code_out = Signal(self.code_bits)
         self.sberr = Signal()
-        if parity:
+        if gen_parity:
             self.dberr = Signal()
-        self.ports = {self.data_in, self.code_in, self.sberr, self.dberr}

         # vector of which interleaved bit position represents a particular
         # data bit, used for error correction
 <at>  <at>  -221,18 +217,15  <at>  <at>  class HammingChecker(Module):
             self.enable = Signal()
             self.correct_out = Signal(input_size)
             self.data_out = Signal(input_size, name='data_out')
-            self.ports.add(self.data_out)
-            self.ports.add(self.enable)
             for b in range(input_size):
                 self.comb += self.correct_out[b].eq((self.code_out == (dbits[b]+1)) ^ self.data_in[b])
             self.comb += If(self.enable, self.data_out.eq(self.correct_out)).Else(self.data_out.eq(self.data_in))
-        else:
-            self.ports.add(self.code_out)

         self.comb += self.sberr.eq(self.code_out != 0)
-        parity = Signal()
-        self.comb += parity.eq(self.xor_tree(self.data_in, range(input_size)) ^
self.xor_tree(self.code_in, range(self.code_bits+1)))
-        self.comb += self.dberr.eq(~parity)
+        if gen_parity:
+            parity = Signal()
+            self.comb += parity.eq(xor_tree(self.data_in, range(input_size)) ^ xor_tree(self.code_in, range(self.code_bits+1)))
+            self.comb += self.dberr.eq(~parity)

         for b in range(calc_code_bits(self.input_size)):
             bits = [2**b-1]
 <at>  <at>  -244,27 +237,43  <at>  <at>  def main():
     parser = argparse.ArgumentParser()
     parser.add_argument('-g', help="Create generator", default=False, action='store_true')
     parser.add_argument('-c', help="Create checker", default=False, action='store_true')
+    parser.add_argument('--noparity', help="Create without parity check", default=False, action='store_true')
     parser.add_argument('--correct', help="Create correcting checker", default=False, action='store_true')
     parser.add_argument('-m', "--module", help="Override module name",
                         type=str)
     parser.add_argument('-w', '--width', type=int, help="Generator/checker data width")
     args = parser.parse_args()
+    parity = not args.noparity

     if args.g:
         mhg = HammingGenerator(args.width)
+        ports = {mhg.data_in, mhg.code_out}
+        mhg.data_in.name_override = "data_in"
         if args.module is not None:
-            mhg.name = args.module
-        filename = mhg.name + '.v'
+            name = args.module
+        else:
+            name = "mhamgen%03d" % args.width
+        filename = name + '.v'
         fh = open(filename, 'w')
-        fh.write(convert(mhg, mhg.ports, name=mhg.name))
+        fh.write(convert(mhg, ports, name=name))
         fh.close()
     if args.c:
         mhc = HammingChecker(args.width, correct=args.correct)
+        ports = {mhc.data_in, mhc.code_in, mhc.sberr, mhc.dberr}
+        if args.correct:
+            ports.add(mhc.data_out)
+            ports.add(mhc.enable)
+        else:
+            ports.add(mhc.code_out)
+        if parity:
+            ports.add(mhc.dberr)
         if args.module is not None:
             mhc.name = args.module
-        filename = mhc.name + '.v'
+        else:
+            name = "mhamchk%03d" % args.width
+        filename = name + '.v'
         fh = open(filename, 'w')
-        fh.write(convert(mhc, mhc.ports, name=mhc.name))
+        fh.write(convert(mhc, ports, name=name))
         fh.close()

 if __name__ == "__main__":
--

-- 
1.8.4.2

Tobias Strauch | 4 Nov 14:26 2014

[M-Labs devel] board pdf

Hi folks,
 
your projects look outstanding and I would love to dig into it a little bit more.
 
Unfort. I cannot open the Eagle files of your board-m1 files. May I ask you if you can send me  or release the pdf version as well. I'm interested how you connected the DVI to the FPGA.
 
Thanks a lot in adcanve,
 
Cheers, Tobias
<div>

  <div>
   Hi folks,
  </div> 
  <div>
   &nbsp;
  </div> 
  <div>
   your projects look outstanding and I would love to dig into it a little bit more.
  </div> 
  <div>
   &nbsp;
  </div> 
  <div>
   Unfort. I cannot open the Eagle files of your board-m1 files. May I ask you if you can send me&nbsp; or release the pdf version as well. I'm interested how you connected the DVI to the FPGA.
  </div> 
  <div>
   &nbsp;
  </div> 
  <div>
   Thanks a lot in adcanve,
  </div> 
  <div>
   &nbsp;
  </div> 
  <div>
   Cheers, Tobias
  </div>

</div>
Florent Kermarrec | 31 Oct 15:23 2014
Picon

[M-Labs devel] New Ethernet MAC for MiSoC

Hi,

I've been working on a new Ethernet MAC for MiSoC to replace Minimac3 and
to be more generic (support for various PHYs and user interfaces).

For this new Ethernet MAC, I have added packet support for dataflow in Migen
and added a couples of modules to ease use of dataflow:
- Converter allows easy conversion of data_width for dataflow.
(ex here: Wishbone SRAM reader (32-bits) --> PHY (8-bits))
- Pipeline is a simple module to connect together modules of the dataflow.
DataFlowGraph already allows this, but is more difficult to use and does not
allow use of modules with AutoCSR.

PHYS:
For now, this EthMAC includes MII(10/100Mbps) and GMII(1Gbps) PHYs.
A Loopback PHY is also provided for testing purpose (simulation or
debugging software/gateware)

User Interface:
For now this EthMAC provides Wishbone interface and is also able to
expose dataflow to the user. (In case we want to have a HW UDP/IP for
example). It will be easy in the future to add LASMI interface to it.

Tests:
This EthMac has been validated on the KC705 with GMII with MiniSoC.
(LM32 <at> 125MHz / DDR3 / GbEthernet)
Since I don't have my Mixxeo board with me, I've not been able to test
it on it, but I already tested the PHY on it, so it should work. (In
case someone want to do the test on Milkymist or Mixxeo? :))
Simulation are also available in misoclib/ethmac/test/

Logic:
Logic usage should be very similar to Minimac3 when disabling HW CRC
and Preamble. (Note that Minimac3 has 2 RX slots, 1 TX slot, here
we can configure it and by default it's: 2 RX slots / 2 TX slots).
Adding a second TX slot greatly increases performance (>40%).

Implementation on KC705 still takes lots of time, so I mainly used
ISE. (LM32 LSU is not correctly implemented with Vivado, I'm in contact
with a Xilinx FAE to try to understand that...)

SRAM_READER use FullMemoryWE for it's memory. (Xilinx does not support
byte enable on Dual port RAM). This is maybe something we will have to clean
up.

Patches:
Since the patches are larges, you can find them here:

I've tried to split Migen patches, but the MiSoC patch for the EthMAC
is really large, sorry for the review...

In case you would have done things in a different way, I'm of course OK
to discuss of that.

Regards,

Florent.
<div><div dir="ltr">
<div>Hi,</div>
<div><br></div>
<div>I've been working on a new Ethernet MAC for MiSoC to replace Minimac3 and</div>
<div>to be more generic (support for various PHYs and user interfaces).</div>
<div><br></div>
<div>For this new Ethernet MAC, I have added packet support for dataflow in Migen</div>
<div>and added a couples of modules to ease use of dataflow:</div>
<div>- Converter allows easy conversion of data_width for dataflow.</div>
<div>(ex here: Wishbone SRAM reader (32-bits) --&gt; PHY (8-bits))</div>
<div>- Pipeline is a simple module to connect together modules of the dataflow.</div>
<div>DataFlowGraph already allows this, but is more difficult to use and does not</div>
<div>allow use of modules with AutoCSR.</div>
<div><br></div>
<div>PHYS:</div>
<div>For now, this EthMAC includes MII(10/100Mbps) and GMII(1Gbps) PHYs.</div>
<div>A Loopback PHY is also provided for testing purpose (simulation or</div>
<div>debugging software/gateware)</div>
<div><br></div>
<div>User Interface:</div>
<div>For now this EthMAC provides Wishbone interface and is also able to</div>
<div>expose dataflow to the user. (In case we want to have a HW UDP/IP for</div>
<div>example). It will be easy in the future to add LASMI interface to it.</div>
<div><br></div>
<div>Tests:</div>
<div>This EthMac has been validated on the KC705 with GMII with MiniSoC.</div>
<div>(LM32  <at>  125MHz / DDR3 / GbEthernet)</div>
<div>Since I don't have my Mixxeo board with me, I've not been able to test</div>
<div>it on it, but I already tested the PHY on it, so it should work. (In</div>
<div>case someone want to do the test on Milkymist or Mixxeo? :))</div>
<div>Simulation are also available in misoclib/ethmac/test/≤/div>
<div><br></div>
<div>Logic:</div>
<div>Logic usage should be very similar to Minimac3 when disabling HW CRC</div>
<div>and Preamble. (Note that Minimac3 has 2 RX slots, 1 TX slot, here</div>
<div>we can configure it and by default it's: 2 RX slots / 2 TX slots).</div>
<div>Adding a second TX slot greatly increases performance (&gt;40%).</div>
<div><br></div>
<div>Implementation on KC705 still takes lots of time, so I mainly used</div>
<div>ISE. (LM32 LSU is not correctly implemented with Vivado, I'm in contact</div>
<div>with a Xilinx FAE to try to understand that...)</div>
<div><br></div>
<div>SRAM_READER use&nbsp;FullMemoryWE for it's memory. (Xilinx does not support</div>
<div>byte enable on Dual port RAM). This is maybe something we will have to clean</div>
<div>up.</div>
<div><br></div>
<div>Patches:</div>
<div>Since the patches are larges, you can find them here:</div>
<div><a href="http://enjoy-digital.fr/open-hardware/3/migen_ethmac_patches.7z">enjoy-digital.fr/open-hardware/3/migen_ethmac_patches.7z</a></div>
<div><a href="http://enjoy-digital.fr/open-hardware/3/misoc_ethmac_patches.7z">enjoy-digital.fr/open-hardware/3/misoc_ethmac_patches.7z</a></div>
<div><br></div>
<div>I've tried to split Migen patches, but the MiSoC patch for the EthMAC</div>
<div>is really large, sorry for the review...</div>
<div><br></div>
<div>In case you would have done things in a different way, I'm of course OK</div>
<div>to discuss of that.</div>
<div><br></div>
<div>Regards,</div>
<div><br></div>
<div>Florent.</div>
</div></div>
Sébastien Bourdeauducq | 30 Oct 15:47 2014
Picon

[M-Labs devel] ARTIQ

Hi,

this is probably old news if you are on #m-labs IRC, but I've been
working (with help from Florent and Yann) on developing a new quantum
physics experiment control system for the Ion Storage Group at NIST.

It uses MiSoC with custom realtime I/O gateware and a Python static
compiler to provide both high expressivity and good timing performance.

This slideshow makes a good intro:
http://m-labs.hk/artiq/slides_taaccs.pdf

It's an open source project, and you are welcome to subscribe to the
mailing list to follow and participate in the discussions:
https://ssl.serverraum.org/lists/listinfo/artiq

Sébastien
_______________________________________________
M-Labs devel mailing list
https://ssl.serverraum.org/lists/listinfo/devel
Sébastien Bourdeauducq | 11 Oct 17:16 2014
Picon

[M-Labs devel] Fwd: [EHSM-public] FOSDEM 2015 EDA Devroom Call for Participation


---------- Forwarded message ----------
From: *Javier Serrano* <javier.serrano.pareja@...
<mailto:javier.serrano.pareja@...>>
Date: 11 October 2014 09:59
Subject: [Kicad-developers] FOSDEM 2015 EDA Devroom Call for Participation
To: KiCad Developers <kicad-developers@...
<mailto:kicad-developers@...>>

Dear all,

Here's the Call for Participation for the FOSS EDA Devroom in FOSDEM 2015:

http://www.ohwr.org/projects/ohr-meta/wiki/FOSDEM2015

Looking forward to meeting many of you there.

Javier

Guy Hutchison | 25 Sep 02:30 2014
Picon

[M-Labs devel] ECC generator/checker

Hamming code ECC generator/checker for SECDEC code.


<div><div dir="ltr">Hamming code ECC generator/checker for SECDEC code.<div><br></div>
<div><br></div>
</div></div>
Florent Kermarrec | 24 Sep 22:41 2014
Picon

[M-Labs devel] [PATCH] add generic CRCEngine, CRC32, CRCInserter and CRCChecker


<div><div dir="ltr"><br></div></div>
Florent Kermarrec | 24 Sep 22:12 2014
Picon

[M-Labs devel] [PATCH] update README with new Kintex-7 support


<div><div dir="ltr"><br></div></div>
Florent Kermarrec | 24 Sep 21:44 2014
Picon

[M-Labs devel] [PATCH] uart: split it and use dataflow


Attachment (0002-uart-split-it-and-use-dataflow.patch): application/octet-stream, 7744 bytes
<div><div dir="ltr"><br></div></div>
Florent Kermarrec | 24 Sep 21:44 2014
Picon

[M-Labs devel] [PATCH] targets: add simple design


<div><div dir="ltr"><br></div></div>
Michael Walle | 21 Sep 21:05 2014

[M-Labs devel] Milkymist One QEMU image

Hi all,

I've created a full disk image of the Milkymist One. It contains the BIOS, 
splash screen, flickernoise and the data files. Therefore, it should behave 
the same like the real milkymist hardware (spash screen is not working for 
some reason).

Start it with any recent qemu-system-lm32 binary:
  qemu-system-lm32 -M milkymist -pflash flash-2012-07-09.img

You can find it at http://milkymist.walle.cc/.

Additonally, i've mirrored the old update files/images, which used to be at 
http://www.milkymist.org/updates/.

--

-- 
-michael

Gmane