www.pudn.com > rs3228v11tar.gz > chien.vhd, change:1998-10-01,size:8128b


-------------------------------------------------------------------------
-- model:     ENTITY chien, ARCHITECTURE rtl
-- copyright: Christian Schuler, GMD-FOKUS, 12/2/1998
--
--
-- description: 
--   chien search algorithm for rs(32,28)-gf(256) decoder
--   1) chien search to find error locations
--   2) calculation of error values by forney algorithm
--   the division of the forney algorithm uses the nomalization circuit
--   via a tristate bus (inv_oe,inv_out, result in sigma_in)
--   3) error correction via ram access to the code word memory
--   generated by code generator genfec
--
-- modified: 
--
-------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

USE work.rs_pkg.ALL;

ENTITY chien IS
  PORT (
    clk        : IN    STD_ULOGIC;
    reset      : IN    STD_ULOGIC;
    dec_err    : OUT   STD_ULOGIC;
    chien_done : OUT   STD_ULOGIC;
    inv_oe     : INOUT STD_ULOGIC;
    inv_out_tri: OUT   STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
    sigma_enb  : IN    STD_ULOGIC;
    sigma_in   : IN    STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
    omega_enb  : IN    STD_ULOGIC;
    omega_in   : IN    STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
    
    ram_we     : OUT   STD_ULOGIC;
    ram_re     : OUT   STD_ULOGIC;
    ram_addr   : OUT   STD_ULOGIC_VECTOR(addr_width-1 DOWNTO 0);
    ram_d_in   : OUT   STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
    ram_d_out  : IN    STD_ULOGIC_VECTOR(mm-1 DOWNTO 0));
        
END chien;

-------------------------------------------------------------
ARCHITECTURE rtl OF chien IS

  TYPE o_type IS ARRAY (0 TO deg_omega) OF STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  TYPE s_type IS ARRAY (0 TO deg_sigma) OF STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  TYPE sd_type IS ARRAY (0 TO 0) OF STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  SIGNAL omega    : o_type;
  SIGNAL sigma    : s_type;
  SIGNAL sigma_der: sd_type;

  SIGNAL omega_sum     : STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  SIGNAL sigma_sum     : STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  SIGNAL sigma_der_sum : STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  SIGNAL omega_sum_save: STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);

  SIGNAL step_cnt : INTEGER RANGE 0 TO nn+1;
  SIGNAL root_cnt : INTEGER RANGE 0 TO tt;
  SIGNAL wait_cnt : INTEGER RANGE 0 TO mm+2; -- wait states for division
  SIGNAL deg_sigma_real: INTEGER RANGE 0 TO deg_sigma;

  TYPE state_t IS (idle,loading_sigma,wait_for_omega,loading_omega,
    chien_wait1,chien_wait2,chien,forney,done);
  SIGNAL state: state_t;

  SIGNAL inv_out   : STD_ULOGIC_VECTOR(mm-1 DOWNTO 0);
  SIGNAL chien_eval: STD_ULOGIC;

BEGIN

  main_fsm:
  PROCESS (clk)
  BEGIN
    IF clk'EVENT AND clk = '1' THEN
      IF reset = '1' THEN
        state <= idle;
        dec_err <= '0';
        chien_done <= '0';
        -- tristate the division bus:
        inv_oe <= '0';
        ram_re <= '0';
        ram_we <= '0';
        step_cnt <= 0;
        wait_cnt <= 0;
        chien_eval <= '0';
      ELSE
        CASE state IS
          WHEN idle =>
            step_cnt <= 0;
            IF sigma_enb = '1' THEN
              state <= loading_sigma;
            END IF;
          WHEN loading_sigma =>  
            IF step_cnt = deg_sigma THEN
              step_cnt <= 0;
              state <= wait_for_omega;
            ELSE                
              step_cnt <= step_cnt + 1;  
            END IF;
          WHEN wait_for_omega =>
            IF omega_enb = '1' THEN
              state <= loading_omega;
            END IF;
          WHEN loading_omega =>
            IF step_cnt = deg_omega THEN
              state <= chien_wait1;
              chien_eval <= '1';
              root_cnt <= 0;
              step_cnt <= 0;
            ELSE                
              step_cnt <= step_cnt + 1;  
            END IF;
          WHEN chien_wait1 =>
            state <= chien_wait2;
          WHEN chien_wait2 =>
            state <= chien;
          WHEN chien =>
            ram_we <= '0';
            IF sigma_sum = alpha_0 THEN -- root found
              -- read the errored symbol from code word memory:
              ram_addr <= int2suv(step_cnt,addr_width);
              ram_re <= '1';
              root_cnt <= root_cnt + 1;
              -- start the forney algorithm
              inv_oe <= '1';
              inv_out <= sigma_der_sum;
              omega_sum_save <= omega_sum; -- save omega_sum
              wait_cnt <= 0;
              chien_eval <= '0';
              state <= forney;
            ELSE
              IF step_cnt < nn-1 THEN
                step_cnt <= step_cnt + 1;
              ELSE
                chien_eval <= '0';
                state <= done;
              END IF;           
            END IF;           
          WHEN forney =>
            IF wait_cnt < mm+2 THEN       
              wait_cnt <= wait_cnt + 1;
            END IF;         
            IF wait_cnt = mm THEN       -- division omega_sum/sigma_der_sum
              inv_out <= omega_sum_save;
            ELSIF wait_cnt = mm+2 THEN
              -- sigma_in at this step is output of division, i.e. 
              -- the error value
              -- re-write the corrected symbol to the code word memory
              ram_d_in <= sigma_in XOR ram_d_out; 
              ram_re <= '0';
              ram_we <= '1';
              inv_oe <= '0';
              IF step_cnt < nn-1 THEN 
                step_cnt <= step_cnt + 1;
                chien_eval <= '1';
                state <= chien;
              ELSE 
                state <= done;
              END IF;           
            END IF;         
          WHEN done =>
            ram_we <= '0';
            chien_done <= '1';
            IF root_cnt < deg_sigma_real THEN
              dec_err <= '1';
            END IF;
        END CASE;
      END IF;
    END IF;
  END PROCESS; 


  ----------------------------------------------------------------------------
  sigma_ctrl:
  PROCESS (clk)
  BEGIN
    IF clk'EVENT AND clk = '1' THEN
      IF sigma_enb = '1' AND (state = idle OR state = loading_sigma) THEN
        -- caution: sigma_enb is output of division circuit
        sigma(0 TO deg_sigma-1) <= sigma(1 TO deg_sigma);
        sigma(deg_sigma) <= sigma_in;
        IF sigma_in /= alpha_0 THEN
          deg_sigma_real <= step_cnt+1;
        END IF;
        -- loading derivative:
        IF step_cnt = 0 THEN
          sigma_der(0) <= gf_mul_223(sigma_in);
          -- power of two, one location is saved by 'wrong' index !
        END IF;
      ELSIF state = loading_omega AND step_cnt = 0 THEN
        -- preload for shortenend code:
        sigma(0) <= gf_mul_223(sigma(0));
        sigma(1) <= gf_mul_191(sigma(1));
        sigma(2) <= gf_mul_159(sigma(2));

      ELSIF chien_eval = '1' THEN
 
        -- evaluate sigma, the normalized lambda:
        sigma(0) <= gf_mul_1(sigma(0));
        sigma(1) <= gf_mul_2(sigma(1));
        sigma(2) <= gf_mul_3(sigma(2));
        sigma_sum <= sigma(0) XOR sigma(1) XOR sigma(2);

        -- evaluate sigma derivative 
        -- (for error value calculation in the forney algorithm)
        sigma_der(0) <= gf_mul_1(sigma_der(0));
        sigma_der_sum <= sigma_der(0);
      ELSIF state = idle THEN
        deg_sigma_real <= 0;
      END IF;
    END IF;
  END PROCESS; 

  ----------------------------------------------------------------------------
  omega_ctrl:
  PROCESS (clk)
  BEGIN
    IF clk'EVENT AND clk = '1' THEN
      IF omega_enb = '1' AND (state = wait_for_omega OR state = loading_omega) THEN
        omega(0 TO deg_omega-1) <= omega(1 TO deg_omega);
        omega(deg_omega) <= omega_in;
      ELSIF chien_eval = '1' THEN
        -- evaluate omega 
        omega(0) <= gf_mul_1(omega(0));
        omega(1) <= gf_mul_2(omega(1));
        omega_sum <= omega(0) XOR omega(1);
      END IF;
    END IF;
  END PROCESS; 


  ---------------------------------------------------------------------------
  --tristate output to shared division circuit:
  inv_tristate_buf:
  PROCESS (inv_oe,inv_out)
  BEGIN
    IF inv_oe = '1' THEN
      inv_out_tri <= inv_out;    
    ELSE
      inv_out_tri <= (OTHERS => 'Z');
    END IF;
  END PROCESS;

END rtl; -- OF chien