---------------------------------------------------------------------------------------------- -- -- Generated by X-HDL Verilog Translator - Version 4.0.0 Apr. 30, 2006 -- Wed Jun 17 2009 01:03:24 -- -- Input file : /home/samsonn/SandBox_LBranch_11.2/env/Databases/ip/src2/L/mig_v3_2/data/dlib/virtex6/ddr3_sdram/verilog/rtl/ecc/ecc_gen.v -- Component name : ecc_gen -- Author : -- Company : -- -- Description : -- -- ---------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; -- Generate the ecc code. Note that the synthesizer should -- generate this as a static logic. Code in this block should -- never run during simulation phase, or directly impact timing. -- -- The code generated is a single correct, double detect code. -- It is the classic Hamming code. Instead, the code is -- optimized for minimal/balanced tree depth and size. See -- Hsiao IBM Technial Journal 1970. -- -- The code is returned as a single bit vector, h_rows. This was -- the only way to "subroutinize" this with the restrictions of -- disallowed include files and that matrices cannot be passed -- in ports. -- -- Factorial and the combos functions are defined. Combos -- simply computes the number of combinations from the set -- size and elements at a time. -- -- The function next_combo computes the next combination in -- lexicographical order given the "current" combination. Its -- output is undefined if given the last combination in the -- lexicographical order. -- -- next_combo is insensitive to the number of elements in the -- combinations. -- -- An H transpose matrix is generated because that's the easiest -- way to do it. The H transpose matrix is generated by taking -- the one at a time combinations, then the 3 at a time, then -- the 5 at a time. The number combinations used is equal to -- the width of the code (CODE_WIDTH). The boundaries between -- the 1, 3 and 5 groups are hardcoded in the for loop. -- -- At the same time the h_rows vector is generated from the -- H transpose matrix. entity ecc_gen is generic ( CODE_WIDTH : integer := 72; ECC_WIDTH : integer := 8; DATA_WIDTH : integer := 64 ); port ( -- Outputs -- function next_combo -- Given a combination, return the next combo in lexicographical -- order. Scans from right to left. Assumes the first combination -- is k ones all of the way to the left. -- -- Upon entry, initialize seen0, trig1, and ones. "seen0" means -- that a zero has been observed while scanning from right to left. -- "trig1" means that a one have been observed _after_ seen0 is set. -- "ones" counts the number of ones observed while scanning the input. -- -- If trig1 is one, just copy the input bit to the output and increment -- to the next bit. Otherwise set the the output bit to zero, if the -- input is a one, increment ones. If the input bit is a one and seen0 -- is true, dump out the accumulated ones. Set seen0 to the complement -- of the input bit. Note that seen0 is not used subsequent to trig1 -- getting set. -- The stuff above leads to excessive XST execution times. For now, hardwire to 72/64 bit. h_rows : out std_logic_vector(CODE_WIDTH * ECC_WIDTH - 1 downto 0) ); end entity ecc_gen; architecture trans of ecc_gen is attribute DowngradeIPIdentifiedWarnings: string; attribute DowngradeIPIdentifiedWarnings of trans : architecture is "yes"; function factorial (ivar: integer) return integer is variable tmp : integer; begin if (ivar = 1) then return 1; else tmp := 1; for i in ivar downto 2 loop tmp := tmp * i; end loop; end if; return tmp; end function factorial; function combos ( n, k: integer) return integer is begin return factorial(n)/(factorial(k)*factorial(n-k)); end function combos; function next_combo (i: std_logic_vector) return std_logic_vector is variable seen0: std_logic; variable trig1: std_logic; variable ones: std_logic_vector (ECC_WIDTH-1 downto 0); variable tmp: std_logic_vector (ECC_WIDTH-1 downto 0); variable tmp_index : integer; begin seen0 := '0'; trig1 := '0'; ones := (others => '0'); for index in ECC_WIDTH -1 downto 0 loop tmp_index := ECC_WIDTH -1 - index; if (trig1 = '1') then tmp(tmp_index) := i(tmp_index); else tmp(tmp_index) := '0'; ones := ones + i(tmp_index); if ((i(tmp_index) = '1') and (seen0 = '1')) then trig1 := '1'; for dump_index in tmp_index-1 downto 0 loop if (dump_index >= (tmp_index- conv_integer(ones)) ) then tmp(dump_index) := '1'; end if; end loop; end if; seen0 := not(i(tmp_index)); end if; end loop; return tmp; end function next_combo; constant COMBOS_3 : integer := combos(ECC_WIDTH, 3); constant COMBOS_5 : integer := combos(ECC_WIDTH, 5); type twoDarray is array (CODE_WIDTH -1 downto 0) of std_logic_vector (ECC_WIDTH-1 downto 0); signal ht_matrix : twoDarray; begin columns: for n in CODE_WIDTH - 1 downto 0 generate column0: if (n = 0) generate ht_matrix(n) <= "111" & conv_std_logic_vector(0,ECC_WIDTH-3); end generate; column_combos3: if ((n = COMBOS_3) and ( n < DATA_WIDTH) ) generate ht_matrix(n) <= "11111" & conv_std_logic_vector(0,ECC_WIDTH-5); end generate; column_combos5: if ((n = COMBOS_3 + COMBOS_5) and ( n < DATA_WIDTH) ) generate ht_matrix(n) <= "1111111" & conv_std_logic_vector(0,ECC_WIDTH-7); end generate; column_datawidth: if (n = DATA_WIDTH) generate ht_matrix(n) <= "1" & conv_std_logic_vector(0,ECC_WIDTH-1); end generate; column_gen: if ( (n /= 0 ) and ((n /= COMBOS_3) or (n > DATA_WIDTH)) and ((n /= COMBOS_3+COMBOS_5) or (n > DATA_WIDTH)) and (n /= DATA_WIDTH) ) generate ht_matrix(n) <= next_combo(ht_matrix(n-1)); end generate; out_assign: for s in ECC_WIDTH-1 downto 0 generate h_rows(s*CODE_WIDTH+n) <= ht_matrix(n)(s); end generate; end generate; --h_row0 <= "100000000100100011101101001101001000110100100010000110100100010000100000"; --h_row1 <= "010000001010010011011010101010100100101010010001000101010010001000010000"; --h_row2 <= "001000001001001010110110010110010010011001001000100011001001000100001000"; --h_row3 <= "000100000111000101110001110001110001000111000100010000111000100010000100"; --h_row4 <= "000010000000111100001111110000001111000000111100001000000111100001000010"; --h_row5 <= "000001001111111100000000001111111111000000000011111000000000011111000001"; --h_row6 <= "000000101111111100000000000000000000111111111111111000000000000000111111"; --h_row7 <= "000000011111111100000000000000000000000000000000000111111111111111111111"; --h_rows <= (h_row7 & h_row6 & h_row5 & h_row4 & h_row3 & h_row2 & h_row1 & h_row0); end architecture trans;