Library IEEE;
Use IEEE.STD_LOGIC_1164.ALL;
Use IEEE.STD_LOGIC_ARITH.ALL;
Use IEEE.STD_LOGIC_UNSIGNED.ALL;
---------------------------- Entity declaration  --------------------------------
entity interleaver is
  port(clk           : in  std_logic;   -- Processing clock 
       reset         : in  std_logic;   -- Asynchronous active high reset
       data_in       : in  std_logic;   -- Input data signal 
       start_sym_in  : in  std_logic_vector(10 downto 0);  -- Start symbol index
       no_of_sym_in  : in  std_logic_vector(10 downto 0);  -- Number of symbols in the burst
       code_rate     : in  std_logic_vector(3 downto 0);  -- code rate
       valid_in      : in  std_logic;   -- Input valid signal
       rd_en_in      : in  std_logic;   -- read enable signal
       data_out      : out std_logic;   -- Output data signal
       valid_out     : out std_logic;   -- Valid output signal
       start_sym_out : out std_logic_vector(10 downto 0);  -- Start symbol index
       no_of_sym_out : out std_logic_vector(10 downto 0);  -- Number of symbols for the burst
       rate_i        : out std_logic_vector(3 downto 0);  -- Code rate of outgoing fec block
       read_en_out   : out std_logic    -- when interleaving is ready to accept then read enable out will be generated
       );
end interleaver;
------------------ Architecture begins here  -----------------------------------------
architecture Behavioral of interleaver is
------------------------ RAM declaration  -----------------------------------------------
  type ram_type is array (0 to 4095) of std_logic;
  signal RAM           : ram_type;
  ----------------------- signals declaration  ------------------------------------------
  signal wr_add        : std_logic_vector(10 downto 0);
  signal wr_add1       : std_logic_vector(11 downto 0);
  signal wr_count      : std_logic_vector(1 downto 0);
  Signal Term_Count_s  : std_logic_vector(10 downto 0);
  Signal Term_Count_s1 : std_logic_vector(10 downto 0);
  Signal Term_Count_s2 : std_logic_vector(10 downto 0);
  Signal Term_Count_s3 : std_logic_vector(10 downto 0);
  Signal Count_s       : std_logic_vector(10 downto 0);
  Signal Count12_s     : std_logic_vector(6 downto 0);
  Signal Count_2nd_s   : std_logic_vector(3 downto 0);
  Signal TC            : std_logic_vector(6 downto 0);
  Signal TC1           : std_logic_vector(6 downto 0);
  Signal Index1_s      : std_logic_vector(10 downto 0);
  Signal Index2_s      : std_logic_vector(10 downto 0);
  Signal Index3_s      : std_logic_vector(10 downto 0);
  Signal Index4_s      : std_logic_vector(10 downto 0);
  Signal Temp1_s       : std_logic_vector(10 downto 0);
  Signal Temp2_s       : std_logic_vector(10 downto 0);
  Signal Temp3_s       : std_logic_vector(10 downto 0);
  Signal Temp4_s       : std_logic_vector(10 downto 0);
  Signal Temp5_s       : std_logic_vector(10 downto 0);
  Signal Temp6_s       : std_logic_vector(10 downto 0);
  Signal Index1_s_d    : std_logic_vector(10 downto 0);
  Signal Index2_s_d    : std_logic_vector(10 downto 0);
  Signal Index3_s_d    : std_logic_vector(10 downto 0);
  Signal Index4_s_d    : std_logic_vector(10 downto 0);
  Signal count_off1    : std_logic_vector(3 downto 0);
  Signal count_off2    : std_logic_vector(3 downto 0);
  Signal count_off3    : std_logic_vector(3 downto 0);
  Signal count_off4    : std_logic_vector(3 downto 0);
  Signal count_off1_d  : std_logic_vector(3 downto 0);
  signal code_rate_rd  : std_logic_vector(3 downto 0);
  signal start_sym_in1 : std_logic_vector(10 downto 0);
  signal start_sym_in2 : std_logic_vector(10 downto 0);
  signal no_of_sym_in1 : std_logic_vector(10 downto 0);
  signal no_of_sym_in2 : std_logic_vector(10 downto 0);
  signal rate1         : std_logic_vector(3 downto 0);
  signal rate2         : std_logic_vector(3 downto 0);
  signal rd_en         : std_logic;
  signal rd_en1        : std_logic;
  signal rd_en2        : std_logic;
  signal rd_en3        : std_logic;
  signal rd_en4        : std_logic;
  signal rd_count      : std_logic_vector(1 downto 0);
  signal rd_count1     : std_logic_vector(1 downto 0);
  signal rd_count2     : std_logic_vector(1 downto 0);
  signal rd_count3     : std_logic_vector(1 downto 0);
  signal rd_add1       : std_logic_vector(11 downto 0);
  signal Index_out_s1  : std_logic_vector(10 downto 0);
  signal valid_in1     : std_logic;
  signal count_read    : std_logic_vector(3 downto 0);
Begin

-- Based on the code rate assigning the number bits
  Term_Count_s <= "00010111111" when code_rate = "0000"                         else  -- 191 
                  "00101111111" when (code_rate = "0001" or code_rate = "0010") else  -- 383
                  "01011111111" when (code_rate = "0011" or code_rate = "0100") else  -- 767
                  "10001111111" when (code_rate = "0101" or code_rate = "0110") else  -- 1151
                  "00000000000";

  Term_Count_s1 <= "00010111111" when code_rate_rd = "0000"                            else  -- 191 
                   "00101111111" when (code_rate_rd = "0001" or code_rate_rd = "0010") else  -- 383
                   "01011111111" when (code_rate_rd = "0011" or code_rate_rd = "0100") else  -- 767
                   "10001111111" when (code_rate_rd = "0101" or code_rate_rd = "0110") else  -- 1151
                   "00000000000";

  TC <= "0001111" when code_rate_rd = "0000"                            else
        "0011111" when (code_rate_rd = "0001" or code_rate_rd = "0010") else
        "0111111" when (code_rate_rd = "0011" or code_rate_rd = "0100") else
        "1011111" when (code_rate_rd = "0101" or code_rate_rd = "0110") else
        "0000000";




  process(clk, reset)
  begin
    if reset = '1' then
      wr_add        <= (others => '0');
      wr_count      <= (others => '0');
      start_sym_in1 <= (others => '0');
      start_sym_in2 <= (others => '0');
      no_of_sym_in1 <= (others => '0');
      no_of_sym_in2 <= (others => '0');
      rate1         <= (others => '0');
      rate2         <= (others => '0');
      Term_Count_s2 <= (others => '0');
    elsif clk = '1' and clk'event then
      Term_Count_s2       <= Term_Count_s;
      if valid_in = '1' then
        if wr_Add = Term_Count_s2 then
          wr_Add          <= (others => '0');  -- Write counter is incrementing based on the write address and term count s2
          wr_count        <= wr_count+'1';
          if wr_count(0) = '0' then     -- signal switching depending on the write count pointint to which either half
            rate1         <= code_rate;
            start_sym_in1 <= start_sym_in;
            no_of_sym_in1 <= no_of_sym_in;  -- based on the write count lsb value assigning the start symbol, code rate and 
          else                          -- number of symbols into two different set of signals.
            start_sym_in2 <= start_sym_in;
            no_of_sym_in2 <= no_of_sym_in;
            rate2         <= code_rate;
          end if;
        else
          wr_add          <= wr_add+'1';  -- Incrementing the write address.
        end if;
      end if;
    end if;
  end process;

  wr_add1 <= wr_count(0)&wr_Add;
  
  process (clk)
  begin
    if (clk'event and clk = '1') then   -- In this process writing the data 
      if (valid_in = '1') then          -- into RAM  
        RAM(conv_integer(wr_add1)) <= data_in;
      end if;
    end if;
  end process;   

  Process(clk, reset)
  begin
    if reset = '1' then
      count12_s     <= ( others => '0' );
      count_2nd_s   <= ( others => '0' );  -- change to '0'
      count_s       <= ( others => '0' );
      start_sym_out <= ( others => '0' );
      no_of_sym_out <= ( others => '0' );
      rate_i        <= ( others => '0' );
      code_rate_rd  <= ( others => '0' );
      rd_en         <= '0';
      rd_count      <= (others  => '0');
      Term_Count_s3 <= (others  => '0');
      TC1           <= (others  => '0');
    elsif clk'event and clk = '1' then
      if rd_en_in = '1' and wr_count /= rd_count then
        if rd_count(0) = '0' then       -- selecting the signal correcponding to which half has read
          start_sym_out <= start_sym_in1;
          no_of_sym_out <= no_of_sym_in1;  -- Based on the write count and read count and read enable in
          rate_i        <= rate1;       -- assigning the values to the output signals  
          code_rate_rd  <= rate1;
        else
          start_sym_out <= start_sym_in2;
          no_of_sym_out <= no_of_sym_in2;
          rate_i        <= rate2;
          code_rate_rd  <= rate1;
        end if;
      end if;
      Term_Count_s3     <= Term_Count_s1;
      TC1               <= TC;
      if rd_en = '1' then
        if(count_s = Term_Count_s3) then
          count_s  <= ( others => '0');
          rd_count <= rd_count+'1';
          rd_en    <= '0';
        else                            -- based on the read enable incrementing the read count 
          count_s  <= count_s + '1';    -- and count_s signals
        end if;
        if(count12_s = TC1) then
          count12_s     <= "0000000";
          if (count_2nd_s = "1011") then
            count_2nd_s <= "0000";
          else
            count_2nd_s <= count_2nd_s + '1';
          end if;
        else
          count12_s     <= count12_s + '1';
        end if;
      elsif rd_en_in = '1' and wr_count/=rd_count then  -- Generating the read enbale signal
        rd_en <= '1';
      end if;
    end if;
  end process;
  
  process(clk, reset)
  begin
    if reset = '1' then
      read_en_out   <= '0';
      count_read    <= "0000";
      valid_in1     <= '0';
    elsif clk = '1' and clk'event then
      valid_in1     <= valid_in;
      if (wr_count(0) = rd_count(0) and wr_count(1)/=rd_count(1)) or valid_in = '1' or valid_in1 = '1' then
        count_read  <= count_read;
      else                              -- Generating the count read signal
        count_read  <= count_Read+'1';
      end if;
      if count_read = 15 then
        read_en_out <= '1';
      else                              -- Generating the read enable out signal
        read_en_out <= '0';
      end if;
    end if;
  end process;

  
  -- Assigning the location values to the index1_s based on count12_s value
  Index1_s <= "00000000000" when Count12_s = "0000000" else  -- 0
              "00000001100" when Count12_s = "0000001" else  -- 12
              "00000011000" when Count12_s = "0000010" else  -- 24
              "00000100100" when Count12_s = "0000011" else  -- 36
              "00000110000" when Count12_s = "0000100" else  -- 48
              "00000111100" when Count12_s = "0000101" else  -- 60
              "00001001000" when Count12_s = "0000110" else  -- 72
              "00001010100" when Count12_s = "0000111" else  -- 84
              "00001100000" when Count12_s = "0001000" else  -- 96
              "00001101100" when Count12_s = "0001001" else  -- 108
              "00001111000" when Count12_s = "0001010" else  -- 120
              "00010000100" when Count12_s = "0001011" else  -- 132
              "00010010000" when Count12_s = "0001100" else  -- 144
              "00010011100" when Count12_s = "0001101" else  -- 156
              "00010101000" when Count12_s = "0001110" else  -- 168
              "00010110100" when Count12_s = "0001111" else  -- 180
              "00011000000" when Count12_s = "0010000" else  -- 192
              "00011001100" when Count12_s = "0010001" else  -- 204
              "00011011000" when Count12_s = "0010010" else  -- 216
              "00011100100" when Count12_s = "0010011" else  -- 228
              "00011110000" when Count12_s = "0010100" else  -- 240
              "00011111100" when Count12_s = "0010101" else  -- 252
              "00100001000" when Count12_s = "0010110" else  -- 264
              "00100010100" when Count12_s = "0010111" else  -- 276
              "00100100000" when Count12_s = "0011000" else  -- 288
              "00100101100" when Count12_s = "0011001" else  -- 300
              "00100111000" when Count12_s = "0011010" else  -- 312
              "00101000100" when Count12_s = "0011011" else  -- 324
              "00101010000" when Count12_s = "0011100" else  -- 336
              "00101011100" when Count12_s = "0011101" else  -- 348
              "00101101000" when Count12_s = "0011110" else  -- 360
              "00101110100" when Count12_s = "0011111" else  -- 372
              "00110000000" when Count12_s = "0100000" else  -- 384
              "00110001100" when Count12_s = "0100001" else  -- 396
              "00110011000" when Count12_s = "0100010" else  -- 408
              "00110100100" when Count12_s = "0100011" else  -- 420
              "00110110000" when Count12_s = "0100100" else  -- 432
              "00110111100" when Count12_s = "0100101" else  -- 444
              "00111001000" when Count12_s = "0100110" else  -- 456
              "00111010100" when Count12_s = "0100111" else  -- 468
              "00111100000" when Count12_s = "0101000" else  -- 480
              "00111101100" when Count12_s = "0101001" else  -- 492
              "00111111000" when Count12_s = "0101010" else  -- 504
              "01000000100" when Count12_s = "0101011" else  -- 516
              "01000010000" when Count12_s = "0101100" else  -- 528
              "01000011100" when Count12_s = "0101101" else  -- 540
              "01000101000" when Count12_s = "0101110" else  -- 552
              "01000110100" when Count12_s = "0101111" else  -- 564
              "01001000000" when Count12_s = "0110000" else  -- 576
              "01001001100" when Count12_s = "0110001" else  -- 588
              "01001011000" when Count12_s = "0110010" else  -- 600
              "01001100100" when Count12_s = "0110011" else  -- 612
              "01001110000" when Count12_s = "0110100" else  -- 624
              "01001111100" when Count12_s = "0110101" else  -- 636
              "01010001000" when Count12_s = "0110110" else  -- 648
              "01010010100" when Count12_s = "0110111" else  -- 660
              "01010100000" when Count12_s = "0111000" else  -- 672
              "01010101100" when Count12_s = "0111001" else  -- 684
              "01010111000" when Count12_s = "0111010" else  -- 696
              "01011000100" when Count12_s = "0111011" else  -- 708
              "01011010000" when Count12_s = "0111100" else  -- 720
              "01011011100" when Count12_s = "0111101" else  -- 732
              "01011101000" when Count12_s = "0111110" else  -- 744
              "01011110100" when Count12_s = "0111111" else  -- 756
              "01100000000" when Count12_s = "1000000" else  -- 768
              "01100001100" when Count12_s = "1000001" else  -- 780
              "01100011000" when Count12_s = "1000010" else  -- 792
              "01100100100" when Count12_s = "1000011" else  -- 804
              "01100110000" when Count12_s = "1000100" else  -- 816
              "01100111100" when Count12_s = "1000101" else  -- 828
              "01101001000" when Count12_s = "1000110" else  -- 840
              "01101010100" when Count12_s = "1000111" else  -- 852
              "01101100000" when Count12_s = "1001000" else  -- 864
              "01101101100" when Count12_s = "1001001" else  -- 876
              "01101111000" when Count12_s = "1001010" else  -- 888
              "01110000100" when Count12_s = "1001011" else  -- 900
              "01110010000" when Count12_s = "1001100" else  -- 912
              "01110011100" when Count12_s = "1001101" else  -- 924
              "01110101000" when Count12_s = "1001110" else  -- 936
              "01110110100" when Count12_s = "1001111" else  -- 948
              "01111000000" when Count12_s = "1010000" else  -- 960
              "01111001100" when Count12_s = "1010001" else  -- 972
              "01111011000" when Count12_s = "1010010" else  -- 984
              "01111100100" when Count12_s = "1010011" else  -- 996
              "01111110000" when Count12_s = "1010100" else  -- 1008
              "01111111100" when Count12_s = "1010101" else  -- 1020
              "10000001000" when Count12_s = "1010110" else  -- 1032
              "10000010100" when Count12_s = "1010111" else  -- 1044
              "10000100000" when Count12_s = "1011000" else  -- 1056
              "10000101100" when Count12_s = "1011001" else  -- 1068
              "10000111000" when Count12_s = "1011010" else  -- 1080
              "10001000100" when Count12_s = "1011011" else  -- 1092
              "10001010000" when Count12_s = "1011100" else  -- 1104
              "10001011100" when Count12_s = "1011101" else  -- 1116
              "10001101000" when Count12_s = "1011110" else  -- 1128
              "10001110100" when Count12_s = "1011111" else  -- 1140
              "00000000000";
-- Assigning the locations values to the index2_s based on count12_s value				  
  Index2_s <= "00000001101" when count12_s = "0000000" else  -- 13
              "00000011001" when count12_s = "0000001" else  -- 25
              "00000000001" when count12_s = "0000010" else  -- 1
              "00000110001" when count12_s = "0000011" else  -- 49
              "00000111101" when count12_s = "0000100" else  -- 61
              "00000100101" when count12_s = "0000101" else  -- 37
              "00001010101" when count12_s = "0000110" else  -- 85
              "00001100001" when count12_s = "0000111" else  -- 97
              "00001001001" when count12_s = "0001000" else  -- 73
              "00001111001" when count12_s = "0001001" else  -- 121
              "00010000101" when count12_s = "0001010" else  -- 133
              "00001101101" when count12_s = "0001011" else  -- 109
              "00010011101" when count12_s = "0001100" else  -- 157
              "00010101001" when count12_s = "0001101" else  -- 169
              "00010010001" when count12_s = "0001110" else  -- 145
              "00011000001" when count12_s = "0001111" else  -- 193
              "00011001101" when count12_s = "0010000" else  -- 205
              "00010110101" when count12_s = "0010001" else  -- 181
              "00011100101" when count12_s = "0010010" else  -- 229
              "00011110001" when count12_s = "0010011" else  -- 241
              "00011011001" when count12_s = "0010100" else  -- 217
              "00100001001" when count12_s = "0010101" else  -- 265
              "00100010101" when count12_s = "0010110" else  -- 277
              "00011111101" when count12_s = "0010111" else  -- 253
              "00100101101" when count12_s = "0011000" else  -- 301
              "00100111001" when count12_s = "0011001" else  -- 313
              "00100100001" when count12_s = "0011010" else  -- 289
              "00101010001" when count12_s = "0011011" else  -- 337
              "00101011101" when count12_s = "0011100" else  -- 349
              "00101000101" when count12_s = "0011101" else  -- 325
              "00101110101" when count12_s = "0011110" else  -- 373
              "00110000001" when count12_s = "0011111" else  -- 385
              "00101101001" when count12_s = "0100000" else  -- 361
              "00110011001" when count12_s = "0100001" else  -- 409
              "00110100101" when count12_s = "0100010" else  -- 421
              "00110001101" when count12_s = "0100011" else  -- 397
              "00110111101" when count12_s = "0100100" else  -- 445
              "00111001001" when count12_s = "0100101" else  -- 457
              "00110110001" when count12_s = "0100110" else  -- 433
              "00111100001" when count12_s = "0100111" else  -- 481
              "00111101101" when count12_s = "0101000" else  -- 493
              "00111010101" when count12_s = "0101001" else  -- 469
              "01000000101" when count12_s = "0101010" else  -- 517
              "01000010001" when count12_s = "0101011" else  -- 529
              "00111111001" when count12_s = "0101100" else  -- 505
              "01000101001" when count12_s = "0101101" else  -- 553
              "01000110101" when count12_s = "0101110" else  -- 565
              "01000011101" when count12_s = "0101111" else  -- 541
              "01001001101" when count12_s = "0110000" else  -- 589
              "01001011001" when count12_s = "0110001" else  -- 601
              "01001000001" when count12_s = "0110010" else  -- 577
              "01001110001" when count12_s = "0110011" else  -- 625
              "01001111101" when count12_s = "0110100" else  -- 637
              "01001100101" when count12_s = "0110101" else  -- 613
              "01010010101" when count12_s = "0110110" else  -- 661
              "01010100001" when count12_s = "0110111" else  -- 673
              "01010001001" when count12_s = "0111000" else  -- 649
              "01010111001" when count12_s = "0111001" else  -- 697
              "01011000101" when count12_s = "0111010" else  -- 709
              "01010101101" when count12_s = "0111011" else  -- 685
              "01011011101" when count12_s = "0111100" else  -- 733
              "01011101001" when count12_s = "0111101" else  -- 745
              "01011010001" when count12_s = "0111110" else  -- 721
              "01100000001" when count12_s = "0111111" else  -- 769
              "01100001101" when count12_s = "1000000" else  -- 781
              "01011110101" when count12_s = "1000001" else  -- 757
              "01100100101" when count12_s = "1000010" else  -- 805
              "01100110001" when count12_s = "1000011" else  -- 817
              "01100011001" when count12_s = "1000100" else  -- 793
              "01101001001" when count12_s = "1000101" else  -- 841
              "01101010101" when count12_s = "1000110" else  -- 853
              "01100111101" when count12_s = "1000111" else  -- 829
              "01101101101" when count12_s = "1001000" else  -- 877
              "01101111001" when count12_s = "1001001" else  -- 889
              "01101100001" when count12_s = "1001010" else  -- 865
              "01110010001" when count12_s = "1001011" else  -- 913
              "01110011101" when count12_s = "1001100" else  -- 925
              "01110000101" when count12_s = "1001101" else  -- 901
              "01110110101" when count12_s = "1001110" else  -- 949
              "01111000001" when count12_s = "1001111" else  -- 961
              "01110101001" when count12_s = "1010000" else  -- 937
              "01111011001" when count12_s = "1010001" else  -- 985
              "01111100101" when count12_s = "1010010" else  -- 997
              "01111001101" when count12_s = "1010011" else  -- 973
              "01111111101" when count12_s = "1010100" else  -- 1021
              "10000001001" when count12_s = "1010101" else  -- 1033
              "01111110001" when count12_s = "1010110" else  -- 1009
              "10000100001" when count12_s = "1010111" else  -- 1057
              "10000101101" when count12_s = "1011000" else  -- 1069
              "10000010101" when count12_s = "1011001" else  -- 1045
              "10001000101" when count12_s = "1011010" else  -- 1093
              "10001010001" when count12_s = "1011011" else  -- 1105
              "10000111001" when count12_s = "1011100" else  -- 1081
              "10001101001" when count12_s = "1011101" else  -- 1129
              "10001110101" when count12_s = "1011110" else  -- 1141
              "10001011101" when count12_s = "1011111" else  -- 1117
              "00000000000";
-- Assigning the location values to the index3_s based on count12_s value				  
  Index3_s <= "00000011010" when count12_s = "0000000" else  -- 26
              "00000000010" when count12_s = "0000001" else  -- 2
              "00000001110" when count12_s = "0000010" else  -- 14
              "00000111110" when count12_s = "0000011" else  -- 62
              "00000100110" when count12_s = "0000100" else  -- 38
              "00000110010" when count12_s = "0000101" else  -- 50
              "00001100010" when count12_s = "0000110" else  -- 98
              "00001001010" when count12_s = "0000111" else  -- 74
              "00001010110" when count12_s = "0001000" else  -- 86
              "00010000110" when count12_s = "0001001" else  -- 134
              "00001101110" when count12_s = "0001010" else  -- 110
              "00001111010" when count12_s = "0001011" else  -- 122
              "00010101010" when count12_s = "0001100" else  -- 170
              "00010010010" when count12_s = "0001101" else  -- 146
              "00010011110" when count12_s = "0001110" else  -- 158
              "00011001110" when count12_s = "0001111" else  -- 206
              "00010110110" when count12_s = "0010000" else  -- 182
              "00011000010" when count12_s = "0010001" else  -- 194
              "00011110010" when count12_s = "0010010" else  -- 242
              "00011011010" when count12_s = "0010011" else  -- 218
              "00011100110" when count12_s = "0010100" else  -- 230
              "00100010110" when count12_s = "0010101" else  -- 278
              "00011111110" when count12_s = "0010110" else  -- 254
              "00100001010" when count12_s = "0010111" else  -- 266
              "00100111010" when count12_s = "0011000" else  -- 314
              "00100100010" when count12_s = "0011001" else  -- 290
              "00100101110" when count12_s = "0011010" else  -- 302
              "00101011110" when count12_s = "0011011" else  -- 350
              "00101000110" when count12_s = "0011100" else  -- 326
              "00101010010" when count12_s = "0011101" else  -- 338
              "00110000010" when count12_s = "0011110" else  -- 386
              "00101101010" when count12_s = "0011111" else  -- 362
              "00101110110" when count12_s = "0100000" else  -- 374
              "00110100110" when count12_s = "0100001" else  -- 422
              "00110001110" when count12_s = "0100010" else  -- 398
              "00110011010" when count12_s = "0100011" else  -- 410
              "00111001010" when count12_s = "0100100" else  -- 458
              "00110110010" when count12_s = "0100101" else  -- 434
              "00110111110" when count12_s = "0100110" else  -- 446
              "00111101110" when count12_s = "0100111" else  -- 494
              "00111010110" when count12_s = "0101000" else  -- 470
              "00111100010" when count12_s = "0101001" else  -- 482
              "01000010010" when count12_s = "0101010" else  -- 530
              "00111111010" when count12_s = "0101011" else  -- 506
              "01000000110" when count12_s = "0101100" else  -- 518
              "01000110110" when count12_s = "0101101" else  -- 566
              "01000011110" when count12_s = "0101110" else  -- 542
              "01000101010" when count12_s = "0101111" else  -- 554
              "01001011010" when count12_s = "0110000" else  -- 602
              "01001000010" when count12_s = "0110001" else  -- 578
              "01001001110" when count12_s = "0110010" else  -- 590
              "01001111110" when count12_s = "0110011" else  -- 638
              "01001100110" when count12_s = "0110100" else  -- 614
              "01001110010" when count12_s = "0110101" else  -- 626
              "01010100010" when count12_s = "0110110" else  -- 674
              "01010001010" when count12_s = "0110111" else  -- 650
              "01010010110" when count12_s = "0111000" else  -- 662
              "01011000110" when count12_s = "0111001" else  -- 710
              "01010101110" when count12_s = "0111010" else  -- 686
              "01010111010" when count12_s = "0111011" else  -- 698
              "01011101010" when count12_s = "0111100" else  -- 746
              "01011010010" when count12_s = "0111101" else  -- 722
              "01011011110" when count12_s = "0111110" else  -- 734
              "01100001110" when count12_s = "0111111" else  -- 782
              "01011110110" when count12_s = "1000000" else  -- 758
              "01100000010" when count12_s = "1000001" else  -- 770
              "01100110010" when count12_s = "1000010" else  -- 818
              "01100011010" when count12_s = "1000011" else  -- 794
              "01100100110" when count12_s = "1000100" else  -- 806
              "01101010110" when count12_s = "1000101" else  -- 854
              "01100111110" when count12_s = "1000110" else  -- 830
              "01101001010" when count12_s = "1000111" else  -- 842
              "01101111010" when count12_s = "1001000" else  -- 890
              "01101100010" when count12_s = "1001001" else  -- 866
              "01101101110" when count12_s = "1001010" else  -- 878
              "01110011110" when count12_s = "1001011" else  -- 926
              "01110000110" when count12_s = "1001100" else  -- 902
              "01110010010" when count12_s = "1001101" else  -- 914
              "01111000010" when count12_s = "1001110" else  -- 962
              "01110101010" when count12_s = "1001111" else  -- 938
              "01110110110" when count12_s = "1010000" else  -- 950
              "01111100110" when count12_s = "1010001" else  -- 998
              "01111001110" when count12_s = "1010010" else  -- 974
              "01111011010" when count12_s = "1010011" else  -- 986
              "10000001010" when count12_s = "1010100" else  -- 1034
              "01111110010" when count12_s = "1010101" else  -- 1010
              "01111111110" when count12_s = "1010110" else  -- 1022
              "10000101110" when count12_s = "1010111" else  -- 1070
              "10000010110" when count12_s = "1011000" else  -- 1046
              "10000100010" when count12_s = "1011001" else  -- 1058
              "10001010010" when count12_s = "1011010" else  -- 1106
              "10000111010" when count12_s = "1011011" else  -- 1082
              "10001000110" when count12_s = "1011100" else  -- 1094
              "10001110110" when count12_s = "1011101" else  -- 1142
              "10001011110" when count12_s = "1011110" else  -- 1118
              "10001101010" when count12_s = "1011111" else  -- 1130
              "00000000000";
-- Assigning the location values to the index4_s based on count12_s value				  
  Index4_s  <= "00000001101" when count12_s = "0000000" else  -- 13
             "00000000001"  when count12_s = "0000001" else  -- 1
             "00000100101"  when count12_s = "0000010" else  -- 37
             "00000011001"  when count12_s = "0000011" else  -- 25
             "00000111101"  when count12_s = "0000100" else  -- 61
             "00000110001"  when count12_s = "0000101" else  -- 49
             "00001010101"  when count12_s = "0000110" else  -- 85
             "00001001001"  when count12_s = "0000111" else  -- 73
             "00001101101"  when count12_s = "0001000" else  -- 109
             "00001100001"  when count12_s = "0001001" else  -- 97
             "00010000101"  when count12_s = "0001010" else  -- 133
             "00001111001"  when count12_s = "0001011" else  -- 121
             "00010011101"  when count12_s = "0001100" else  -- 157
             "00010010001"  when count12_s = "0001101" else  -- 145
             "00010110101"  when count12_s = "0001110" else  -- 181
             "00010101001"  when count12_s = "0001111" else  -- 169
             "00011001101"  when count12_s = "0010000" else  -- 205
             "00011000001"  when count12_s = "0010001" else  -- 193
             "00011100101"  when count12_s = "0010010" else  -- 229
             "00011011001"  when count12_s = "0010011" else  -- 217
             "00011111101"  when count12_s = "0010100" else  -- 253
             "00011110001"  when count12_s = "0010101" else  -- 241
             "00100010101"  when count12_s = "0010110" else  -- 277
             "00100001001"  when count12_s = "0010111" else  -- 265
             "00100101101"  when count12_s = "0011000" else  -- 301
             "00100100001"  when count12_s = "0011001" else  -- 289
             "00101000101"  when count12_s = "0011010" else  -- 325
             "00100111001"  when count12_s = "0011011" else  -- 313
             "00101011101"  when count12_s = "0011100" else  -- 349
             "00101010001"  when count12_s = "0011101" else  -- 337
             "00101110101"  when count12_s = "0011110" else  -- 373
             "00101101001"  when count12_s = "0011111" else  -- 361
             "00110001101"  when count12_s = "0100000" else  -- 397
             "00110000001"  when count12_s = "0100001" else  -- 385
             "00110100101"  when count12_s = "0100010" else  -- 421
             "00110011001"  when count12_s = "0100011" else  -- 409
             "00110111101"  when count12_s = "0100100" else  -- 445
             "00110110001"  when count12_s = "0100101" else  -- 433
             "00111010101"  when count12_s = "0100110" else  -- 469
             "00111001001"  when count12_s = "0100111" else  -- 457
             "00111101101"  when count12_s = "0101000" else  -- 493
             "00111100001"  when count12_s = "0101001" else  -- 481
             "01000000101"  when count12_s = "0101010" else  -- 517
             "00111111001"  when count12_s = "0101011" else  -- 505
             "01000011101"  when count12_s = "0101100" else  -- 541
             "01000010001"  when count12_s = "0101101" else  -- 529
             "01000110101"  when count12_s = "0101110" else  -- 565
             "01000101001"  when count12_s = "0101111" else  -- 553
             "01001001101"  when count12_s = "0110000" else  -- 589
             "01001000001"  when count12_s = "0110001" else  -- 577
             "01001100101"  when count12_s = "0110010" else  -- 613
             "01001011001"  when count12_s = "0110011" else  -- 601
             "01001111101"  when count12_s = "0110100" else  -- 637
             "01001110001"  when count12_s = "0110101" else  -- 625
             "01010010101"  when count12_s = "0110110" else  -- 661
             "01010001001"  when count12_s = "0110111" else  -- 649
             "01010101101"  when count12_s = "0111000" else  -- 685
             "01010100001"  when count12_s = "0111001" else  -- 673
             "01011000101"  when count12_s = "0111010" else  -- 709
             "01010111001"  when count12_s = "0111011" else  -- 697
             "01011011101"  when count12_s = "0111100" else  -- 733
             "01011010001"  when count12_s = "0111101" else  -- 721
             "01011110101"  when count12_s = "0111110" else  -- 757
             "01011101001"  when count12_s = "0111111" else  -- 745
             "00000000000";


  process(clk, reset)
  begin
    if reset = '1' then
      Index1_s_d <= (others => '0');
      Index2_s_d <= (others => '0');
      Index3_s_d <= (others => '0');
      Index4_s_d <= (others => '0');
      count_off1 <= (others => '0');
      count_off2 <= (others => '0');
      count_off3 <= (others => '0');
      count_off4 <= (others => '0');
      Temp1_s    <= (others => '0');
      Temp2_s    <= (others => '0');
      Temp3_s    <= (others => '0');
      Temp5_s    <= (others => '0');
      rd_add1    <= (others => '0');
      rd_count1  <= (others => '0');
      rd_count2  <= (others => '0');
      rd_count3  <= (others => '0');
      rd_en1     <= '0';
      rd_en2     <= '0';
      rd_en3     <= '0';
      rd_en4     <= '0';
      valid_out  <= '0';
    elsif clk = '1' and clk'event then
      rd_count1    <= rd_count;
      rd_count2    <= rd_count1;
      rd_count3    <= rd_count2;
      rd_en1       <= rd_en;
      rd_en2       <= rd_en1;           -- Delayed the read enable signal by
      rd_en3       <= rd_en2;           -- 4 clocks  
      rd_en4       <= rd_en3;
      valid_out    <= rd_en3;
      rd_add1      <= rd_count2(0)&Index_out_s1;  -- Generating the read address  
      Index1_s_d   <= Index1_s;
      Index2_s_d   <= Index2_s;         -- Delayed the index_s signal by 4 clocks            
      Index3_s_d   <= Index3_s;
      Index4_s_d   <= Index4_s;
      count_off1_d <= count_off1;
      count_off1   <= Count_2nd_s;
      count_off2   <= Count_2nd_s - '1';
      count_off3   <= Count_2nd_s - "10";
      count_off4   <= Count_2nd_s - '1';
      Temp1_s      <= Index1_s_d + count_off1;
      Temp2_s      <= Index2_s_d + count_off2;
      Temp3_s      <= Index3_s_d + count_off3;
      Temp5_s      <= Index4_s_d + count_off4;
    end if;
  end process;

  -- Generating the temp4_s and temp5_s based on the count_off1_d value
  Temp4_s  <= Temp1_s when (count_off1_d = 0 or count_off1_d = 3 or count_off1_d = 6 or count_off1_d = 9) else
              Temp2_s when (count_off1_d = 1 or count_off1_d = 4 or count_off1_d = 7 or count_off1_d = 10) else
              Temp3_s when (count_off1_d = 2 or count_off1_d = 5 or count_off1_d = 8 or count_off1_d = 11) else
              "00000000000";
  
  Temp6_s <= Temp5_s when ( count_off1_d = 1 or count_off1_d = 3 or count_off1_d = 5 or count_off1_d = 7 or count_off1_d = 9 or count_off1_d = 11) else
             Temp1_s;

  -- Generating the concatination value for the read address
  Index_out_s1 <= Temp1_s when (code_rate_rd = "0000" or code_rate_rd = "0001" or code_rate_rd = "0010") else
                  Temp6_s when (code_rate_rd = "0011" or code_rate_rd = "0100") else
                  Temp4_s when (code_rate_rd = "0101" or code_rate_rd = "0110") else
                  (others => '0');
  
  process(clk)
  begin
    if clk = '1' and clk'event then     -- In this process reading the data from the RAM
      data_out <= ram(conv_integer(rd_add1));
    end if;
  end process;

end behavioral;	
	    	
	              

	              
	              
	              
	
