public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Russ Dill <russ.dill@gmail.com>
Cc: Charles Manning <manningc2@actrix.gen.nz>,
	linux-mtd@lists.infradead.org, yaffs@stoneboat.aleph1.co.uk
Subject: Re: [Yaffs] bit error rates --> a vendor speaks
Date: Thu, 23 Feb 2006 08:36:31 +0100	[thread overview]
Message-ID: <1140680191.5237.18.camel@localhost.localdomain> (raw)
In-Reply-To: <f9d2a5e10602221646h240ae399p88c88233e0fb3bb8@mail.gmail.com>

On Wed, 2006-02-22 at 17:46 -0700, Russ Dill wrote:
> > Depends. The 1bit correction/ 2bit detection Hamming ECC algorithm found
> > in the kernel is not too bad, but Reed Solomon is a quite conmputation
> > expensive algorithm. Look into the encoder / decoder code in
> > lib/reed_solomon.
> 
> 
> Do NAND errors tend to clump in sequences of bits (ie, something reed
> solomon is paticularly good at)?

In tests with AG-AND, which is known to be less reliable, I saw the bits
flip randomly in several consecutive bytes.

> > In general you have to iterate over the data buffer and compute on each
> > step. The performance penalty depends on the complexitiy of the
> > algortihm. If you have enough space in your FPGA then its definitely a
> > good idea to put some ECC calculation mechanism into it. There are
> > implementations for both ECC and Reed Solomon available.
> 
> Care to recommend any?

I dont remember where the Hamming ECC was from, but a Reed Solomon
encoder is available on opencores.org. And there are several generators
out there which produce RS encoder VHDL code from the given parameters.
Someone used this one with success
http://home.arcor.de/christianschuler/software/genenc_v1_2_tar.gz
You need to build the interfaces around though.

Parameters used back then:

-b 10	data width
-n 518	total length of code word
-k 512  number of information words
-m 10	symbol width
-p 10000001001	polynomial

Result below.

Some hints:

Expand the 8 bit data bus to 10 bits by setting the bit 8/9 hard to 1.
Before feeding the resulting 10 bit word into the generator invert them.
Also invert the resulting RS code. The reason is:
code for all data 0x00 is 0 0 0 0 0 0. Empty flash (0xff) expanded with
bit 8/9 feeds 0x3ff to the inverter, which results in 0x000 for the
generator input. Now you invert the resulting code and get 6 words of
0x3ff. That way you need no special checking for all empty flash as the
resulting code will be correct.

	tglx

-------------------------------------------------------------------------------
-- Parallel Reed-Solomon Encoder (ENTITY)
-- automatically generated by program 'genenc_solaris'
-- ./genenc_solaris -e 2 -b 10 -n 518 -k 512 -m 10 -p 10000001001 >
rs_ecc_nand1.vhdl
-- 
-- Date Thu Jun 23 08:07:57 2005
-- 
-------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY rs_enc IS
    PORT (
        clk     : IN    STD_LOGIC;
        enable  : IN    STD_LOGIC;
        reset   : IN    STD_LOGIC;
        out_enb : OUT   STD_LOGIC;
        d_in    : IN    STD_LOGIC_VECTOR(9 DOWNTO 0);
        d_out   : OUT   STD_LOGIC_VECTOR(9 DOWNTO 0)
    );
END rs_enc;
-------------------------------------------------------------------------------
-- Parallel Reed-Solomon Encoder (ARCHITECTURE)
-- automatically generated by program 'genenc_solaris'
-- 
-- Date Thu Jun 23 08:07:57 2005
-- 
-------------------------------------------------------------------------------

ARCHITECTURE rtl OF rs_enc IS

    CONSTANT nn:     INTEGER := 518;
        -- Number of code symbols

    CONSTANT kk:     INTEGER := 512;
        -- Number of information symbols

    CONSTANT bw:     INTEGER := 10;
        -- Bussize in bits

    CONSTANT mm:     INTEGER := 10;
        -- symbol size in bits

    CONSTANT last_in:  INTEGER := 512;
        -- Last input clock cycle

    CONSTANT last_out: INTEGER := 518;
        -- Last output clock cycle


-------------------------------------------------------------------------------

-- Galois field multiplier functions for Generator Polynomial
-- RS(518,512) encoder:

-- G(0):
    FUNCTION gf_mul_21 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(3) XOR bb(9);
            cc_next(1) := bb(0) XOR bb(4);
            cc_next(2) := bb(1) XOR bb(5);
            cc_next(3) := bb(2) XOR bb(3) XOR bb(6) XOR bb(9);
            cc_next(4) := bb(3) XOR bb(4) XOR bb(7);
            cc_next(5) := bb(4) XOR bb(5) XOR bb(8);
            cc_next(6) := bb(5) XOR bb(6) XOR bb(9);
            cc_next(7) := bb(0) XOR bb(6) XOR bb(7);
            cc_next(8) := bb(1) XOR bb(7) XOR bb(8);
            cc_next(9) := bb(2) XOR bb(8) XOR bb(9);
        RETURN cc_next;
    END gf_mul_21;

-- G(1):
    FUNCTION gf_mul_981 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(3) XOR bb(6) XOR bb(7) XOR bb(8) XOR bb(9);
            cc_next(1) := bb(0) XOR bb(4) XOR bb(7) XOR bb(8) XOR bb(9);
            cc_next(2) := bb(0) XOR bb(1) XOR bb(5) XOR bb(8) XOR bb(9);
            cc_next(3) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(7)
XOR 
                bb(8);
            cc_next(4) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(4)
XOR 
                bb(8) XOR bb(9);
            cc_next(5) := bb(1) XOR bb(2) XOR bb(3) XOR bb(4) XOR bb(5)
XOR 
                bb(9);
            cc_next(6) := bb(2) XOR bb(3) XOR bb(4) XOR bb(5) XOR bb(6);
            cc_next(7) := bb(0) XOR bb(3) XOR bb(4) XOR bb(5) XOR bb(6)
XOR 
                bb(7);
            cc_next(8) := bb(1) XOR bb(4) XOR bb(5) XOR bb(6) XOR bb(7)
XOR 
                bb(8);
            cc_next(9) := bb(2) XOR bb(5) XOR bb(6) XOR bb(7) XOR bb(8)
XOR 
                bb(9);
        RETURN cc_next;
    END gf_mul_981;

-- G(2):
    FUNCTION gf_mul_312 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(2) XOR bb(6) XOR bb(9);
            cc_next(1) := bb(3) XOR bb(7);
            cc_next(2) := bb(4) XOR bb(8);
            cc_next(3) := bb(2) XOR bb(5) XOR bb(6);
            cc_next(4) := bb(0) XOR bb(3) XOR bb(6) XOR bb(7);
            cc_next(5) := bb(1) XOR bb(4) XOR bb(7) XOR bb(8);
            cc_next(6) := bb(2) XOR bb(5) XOR bb(8) XOR bb(9);
            cc_next(7) := bb(3) XOR bb(6) XOR bb(9);
            cc_next(8) := bb(0) XOR bb(4) XOR bb(7);
            cc_next(9) := bb(1) XOR bb(5) XOR bb(8);
        RETURN cc_next;
    END gf_mul_312;

-- G(3):
    FUNCTION gf_mul_606 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(0) XOR bb(1) XOR bb(2) XOR bb(4) XOR bb(7);
            cc_next(1) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(5)
XOR 
                bb(8);
            cc_next(2) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(4)
XOR 
                bb(6) XOR bb(9);
            cc_next(3) := bb(0) XOR bb(3) XOR bb(5);
            cc_next(4) := bb(1) XOR bb(4) XOR bb(6);
            cc_next(5) := bb(2) XOR bb(5) XOR bb(7);
            cc_next(6) := bb(0) XOR bb(3) XOR bb(6) XOR bb(8);
            cc_next(7) := bb(1) XOR bb(4) XOR bb(7) XOR bb(9);
            cc_next(8) := bb(0) XOR bb(2) XOR bb(5) XOR bb(8);
            cc_next(9) := bb(0) XOR bb(1) XOR bb(3) XOR bb(6) XOR bb(9);
        RETURN cc_next;
    END gf_mul_606;

-- G(4):
    FUNCTION gf_mul_305 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(0) XOR bb(3) XOR bb(9);
            cc_next(1) := bb(0) XOR bb(1) XOR bb(4);
            cc_next(2) := bb(1) XOR bb(2) XOR bb(5);
            cc_next(3) := bb(2) XOR bb(6) XOR bb(9);
            cc_next(4) := bb(3) XOR bb(7);
            cc_next(5) := bb(4) XOR bb(8);
            cc_next(6) := bb(5) XOR bb(9);
            cc_next(7) := bb(0) XOR bb(6);
            cc_next(8) := bb(1) XOR bb(7);
            cc_next(9) := bb(2) XOR bb(8);
        RETURN cc_next;
    END gf_mul_305;

-- G(5):
    FUNCTION gf_mul_967 ( 
        bb: STD_LOGIC_VECTOR(9 DOWNTO 0))
        RETURN STD_LOGIC_VECTOR IS
        VARIABLE cc_next: STD_LOGIC_VECTOR(9 DOWNTO 0);
            BEGIN
            cc_next(0) := bb(4) XOR bb(5) XOR bb(6) XOR bb(7) XOR bb(8)
XOR 
                bb(9);
            cc_next(1) := bb(0) XOR bb(5) XOR bb(6) XOR bb(7) XOR bb(8)
XOR 
                bb(9);
            cc_next(2) := bb(0) XOR bb(1) XOR bb(6) XOR bb(7) XOR bb(8)
XOR 
                bb(9);
            cc_next(3) := bb(0) XOR bb(1) XOR bb(2) XOR bb(4) XOR bb(5)
XOR 
                bb(6);
            cc_next(4) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(5)
XOR 
                bb(6) XOR bb(7);
            cc_next(5) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(4)
XOR 
                bb(6) XOR bb(7) XOR bb(8);
            cc_next(6) := bb(0) XOR bb(1) XOR bb(2) XOR bb(3) XOR bb(4)
XOR 
                bb(5) XOR bb(7) XOR bb(8) XOR bb(9);
            cc_next(7) := bb(1) XOR bb(2) XOR bb(3) XOR bb(4) XOR bb(5)
XOR 
                bb(6) XOR bb(8) XOR bb(9);
            cc_next(8) := bb(2) XOR bb(3) XOR bb(4) XOR bb(5) XOR bb(6)
XOR 
                bb(7) XOR bb(9);
            cc_next(9) := bb(3) XOR bb(4) XOR bb(5) XOR bb(6) XOR bb(7)
XOR 
                bb(8);
        RETURN cc_next;
    END gf_mul_967;

-- G(6): input equals output !

-------------------------------------------------------------------------------

    TYPE bb_t IS ARRAY (0 TO nn-kk-1) OF STD_LOGIC_VECTOR(mm-1 DOWNTO
0);

    TYPE prod_t IS ARRAY (0 TO nn-kk-1) OF STD_LOGIC_VECTOR(mm-1 DOWNTO
0);

-------------------------------------------------------------------------------

    SIGNAL bb: bb_t;


    SIGNAL rs_calc :  STD_LOGIC;

    SIGNAL rs_ins  :  STD_LOGIC;


    BEGIN

    main:
    PROCESS (clk,bb,d_in,reset)

    VARIABLE feedback: STD_LOGIC_VECTOR(mm-1 DOWNTO 0);
    VARIABLE product: bb_t;

    BEGIN

        FOR i IN 0 TO mm - 1 LOOP
            feedback:= bb(0) XOR d_in;
        END LOOP;

        product(0) := gf_mul_967(feedback);
        product(1) := gf_mul_305(feedback);
        product(2) := gf_mul_606(feedback);
        product(3) := gf_mul_312(feedback);
        product(4) := gf_mul_981(feedback);
        product(5) := gf_mul_21(feedback);

        IF reset = '1' THEN

            FOR i IN 0 TO nn-kk-1 LOOP
                bb(i)    <= (others => '0');
            END LOOP;  

            out_enb <= '0';

        ELSIF clk = '1' AND clk'EVENT THEN

            IF enable = '1' THEN

                    out_enb <= '1';

                IF rs_ins = '0' AND rs_calc = '1' THEN

                        -- calculate:

                    FOR i IN 0 TO 4 LOOP
                        bb(i) <= bb(i+1) XOR product(i);
                    END LOOP;

                    bb(5) <= product(5); 
                    d_out <= d_in;

                ELSIF rs_ins = '1' AND rs_calc = '0' THEN

                        -- insert and shift:

                    d_out <= bb(0);

                    FOR i IN 0 TO nn-kk-2  LOOP
                        bb(i) <= bb(i+1);
                    END LOOP;

                    bb(nn-kk-1) <= (others =>'0');

                ELSIF rs_ins = '0' AND rs_calc = '0' THEN

                        -- bypass:

                    d_out <= d_in;

                END IF;

            ELSE
                out_enb <= '0';
            END IF;
        END IF;
    END PROCESS;  --main


    control:
    PROCESS (clk,reset)
    VARIABLE b_cnt : INTEGER RANGE 0 TO 518;
    BEGIN
        IF reset = '1' THEN
            rs_calc <= '1';
            rs_ins  <= '0';
            b_cnt   :=  0;
        ELSE
            IF clk = '1' AND clk'EVENT THEN
                IF enable = '1' THEN
                    IF b_cnt = 0 THEN
                        rs_calc <= '1';
                        rs_ins  <= '0';
                        b_cnt   := b_cnt + 1;
                    ELSIF b_cnt =  last_in - 1 THEN
                        rs_calc <= '0';
                        rs_ins  <= '1';
                        b_cnt   := b_cnt + 1;
                    ELSIF b_cnt = last_out - 1 THEN
                        rs_calc <= '1';
                        rs_ins  <= '0';
                        b_cnt   :=  0;
                    ELSE
                        b_cnt := b_cnt + 1;
                    END IF;
                END IF;
            END IF;
        END IF;
    END PROCESS;  -- ctrl

END rtl;  -- rs_enc

  reply	other threads:[~2006-02-23  7:35 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <43EB96DC.3030900@eptar.com>
     [not found] ` <35fb2e590602100558s2d868fa3o1752fbf3217439e4@mail.gmail.com>
     [not found]   ` <d97046180602151153g23064424x9e1ddf83a1d7ae4f@mail.gmail.com>
2006-02-16  1:32     ` [Yaffs] bit error rates --> a vendor speaks Charles Manning
2006-02-18  9:10       ` Thomas Gleixner
2006-02-18 16:31         ` Vitaly Wool
2006-02-19  8:22           ` Thomas Gleixner
2006-02-20 20:42             ` Charles Manning
2006-02-20 21:37               ` Thomas Gleixner
2006-02-20 22:40                 ` Charles Manning
2006-02-20 23:18                   ` Thomas Gleixner
2006-02-21  0:29                     ` Jon Masters
2006-02-21  8:26                       ` Thomas Gleixner
2006-02-21  9:35                         ` Jörn Engel
2006-02-21  1:08                     ` [Yaffs] bit error rates --> YAFFS for devices with no OOB Charles Manning
2006-02-21  2:12                       ` Jon Masters
2006-02-22  0:38                       ` Jamie Lokier
2006-02-21 12:14                   ` [Yaffs] bit error rates --> a vendor speaks Artem B. Bityutskiy
2006-02-21 13:50                     ` Josh Boyer
2006-02-21 14:36                       ` Artem B. Bityutskiy
2006-02-21 14:49                         ` Artem B. Bityutskiy
2006-02-21 11:59                 ` Artem B. Bityutskiy
2006-02-21 12:06                   ` Thomas Gleixner
2006-02-25 11:58                     ` Artem B. Bityutskiy
2006-02-27 13:27                       ` Josh Boyer
2006-02-27 16:01                         ` Artem B. Bityutskiy
2006-02-27 16:15                           ` Josh Boyer
2006-02-27 17:21                             ` Artem B. Bityutskiy
2006-02-27 17:40                               ` Josh Boyer
2006-02-18 18:11         ` Russ Dill
2006-02-19  0:29           ` Charles Manning
2006-02-19  5:08             ` Jon Masters
2006-02-19  8:29           ` Thomas Gleixner
2006-02-23  0:46             ` Russ Dill
2006-02-23  7:36               ` Thomas Gleixner [this message]
2006-02-23  8:31       ` Vitaly Wool
2006-02-24  9:51         ` Artem B. Bityutskiy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1140680191.5237.18.camel@localhost.localdomain \
    --to=tglx@linutronix.de \
    --cc=linux-mtd@lists.infradead.org \
    --cc=manningc2@actrix.gen.nz \
    --cc=russ.dill@gmail.com \
    --cc=yaffs@stoneboat.aleph1.co.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox