-------------------------------------------------------------
-- MSS copyright 2016
-- Filename:  LLR.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
-- Version: Rev 0
-- Last modified: 9/24/16

-- Inheritance: 	N/A
--
-- description:  Generate the log likelyhood ratio (LLR) from a(k), bm(s,s'), b(k+1)
-- see Matlab turbo.m
--     sum = max(sum,a(k,is+1) + bm(abyw+1) + b(k+1,os+1));  % note a(k) represents a index k-1, b(k) represents b index k-1

-------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity LLR is
	generic (
		NLLRBITS: integer := 11;
			-- LLR precision (for flexibility, even though NLLRBITS may end up being the same as NSMBITS, but could possibly be smaller)
		NSMBITS: integer := 22
			-- state metrics precision. 	
	);
    Port ( 
		--GLOBAL CLOCKS
		CLK: std_logic;
		SYNC_RESET: in std_logic;
		
		-- Inputs
		INPUT_VALID: in std_logic;
		
		-- Forward state metrics at time k
		A_IN0 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN1 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN2 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN3 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN4 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN5 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN6 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN7 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN8 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN9 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN10 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN11 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN12 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN13 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN14 : IN std_logic_vector((NSMBITS-1) downto 0);          
		A_IN15 : IN std_logic_vector((NSMBITS-1) downto 0);      

		-- branch metrics at time k
		-- The index I in BM(I) represents ABYW, where A is the LSb and W the MSb.
		-- (keeping it the same order as in /Matlab/turbo.m)
		BM0 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM1 : in std_logic_vector(NLLRBITS-1 downto 0);           
		BM2 : in std_logic_vector(NLLRBITS-1 downto 0);      
		BM3 : in std_logic_vector(NLLRBITS-1 downto 0);           
		BM4 : in std_logic_vector(NLLRBITS-1 downto 0);           
		BM5 : in std_logic_vector(NLLRBITS-1 downto 0);         
		BM6 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM7 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM8 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM9 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM10 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM11 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM12 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM13 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM14 : in std_logic_vector(NLLRBITS-1 downto 0);          
		BM15 : in std_logic_vector(NLLRBITS-1 downto 0);
		
		-- Backward state metrics at time k+1
		B_IN0 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN1: IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN2 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN3 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN4 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN5 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN6 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN7 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN8 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN9 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN10 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN11 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN12 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN13 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN14 : IN std_logic_vector((NSMBITS-1) downto 0);          
		B_IN15 : IN std_logic_vector((NSMBITS-1) downto 0);

		-- output = LLR_k(delta)  
		-- Latency: 4 CLKs
		LLR00: out std_logic_vector((NLLRBITS-1) downto 0);
		LLR01: out std_logic_vector((NLLRBITS-1) downto 0);
		LLR10: out std_logic_vector((NLLRBITS-1) downto 0);
		LLR11: out std_logic_vector((NLLRBITS-1) downto 0);
		
		DECODED_DATA_OUT: out std_logic_vector(1 downto 0)
			-- decoded symbol

  );
end entity;

architecture Behavioral of LLR is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one CLK delayed version of the net with the same name
-- Suffix _X indicates an extended precision version of the net with the same name
-- Suffix _N indicates an inverted version of the net with the same name

-- Table td2 generated in Matlab file /matlab/turbo.m
-- columns: input state, ab, output state, yw, abyw		
-- ordered by information ab and input state
--     0     0     0     0     0
--     1     0     8     0     0
--     2     0     9     1     4
--     3     0     1     1     4
--     4     0     2     3    12
--     5     0    10     3    12
--     6     0    11     2     8
--     7     0     3     2     8
--     8     0     4     1     4
--     9     0    12     1     4
--    10     0    13     0     0
--    11     0     5     0     0
--    12     0     6     2     8
--    13     0    14     2     8
--    14     0    15     3    12
--    15     0     7     3    12

--     0     1     8     3    13
--     1     1     0     3    13
--     2     1     1     2     9
--     3     1     9     2     9
--     4     1    10     0     1
--     5     1     2     0     1
--     6     1     3     1     5
--     7     1    11     1     5
--     8     1    12     2     9
--     9     1     4     2     9
--    10     1     5     3    13
--    11     1    13     3    13
--    12     1    14     1     5
--    13     1     6     1     5
--    14     1     7     0     1
--    15     1    15     0     1

--     0     2    13     3    14
--     1     2     5     3    14
--     2     2     4     2    10
--     3     2    12     2    10
--     4     2    15     0     2
--     5     2     7     0     2
--     6     2     6     1     6
--     7     2    14     1     6
--     8     2     9     2    10
--     9     2     1     2    10
--    10     2     0     3    14
--    11     2     8     3    14
--    12     2    11     1     6
--    13     2     3     1     6
--    14     2     2     0     2
--    15     2    10     0     2

--     0     3     5     0     3
--     1     3    13     0     3
--     2     3    12     1     7
--     3     3     4     1     7
--     4     3     7     3    15
--     5     3    15     3    15
--     6     3    14     2    11
--     7     3     6     2    11
--     8     3     1     1     7
--     9     3     9     1     7
--    10     3     8     0     3
--    11     3     0     0     3
--    12     3     3     2    11
--    13     3    11     2    11
--    14     3    10     3    15
--    15     3     2     3    15
signal AB0_AS0: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS1: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS2: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS3: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS4: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS5: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS6: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS7: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS8: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS9: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS10: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS11: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS12: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS13: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS14: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB0_AS15: signed((NSMBITS-1) downto 0) := (others => '0');    

signal AB1_AS0: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS1: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS2: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS3: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS4: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS5: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS6: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS7: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS8: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS9: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS10: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS11: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS12: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS13: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS14: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB1_AS15: signed((NSMBITS-1) downto 0) := (others => '0');    

signal AB2_AS0: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS1: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS2: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS3: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS4: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS5: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS6: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS7: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS8: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS9: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS10: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS11: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS12: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS13: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS14: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB2_AS15: signed((NSMBITS-1) downto 0) := (others => '0');    

signal AB3_AS0: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS1: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS2: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS3: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS4: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS5: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS6: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS7: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS8: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS9: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS10: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS11: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS12: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS13: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS14: signed((NSMBITS-1) downto 0) := (others => '0');    
signal AB3_AS15: signed((NSMBITS-1) downto 0) := (others => '0');    

signal AB0_M01: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M23: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M45: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M67: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M89: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M1011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M1213: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M1415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M0123: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M4567: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M891011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M12131415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M0_7: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M8_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M0_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB0_M0_15_D: signed((NSMBITS-1) downto 0) := (others => '0');  

signal AB1_M01: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M23: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M45: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M67: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M89: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M1011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M1213: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M1415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M0123: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M4567: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M891011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M12131415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M0_7: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M8_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M0_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB1_M0_15_D: signed((NSMBITS-1) downto 0) := (others => '0');  

signal AB2_M01: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M23: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M45: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M67: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M89: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M1011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M1213: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M1415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M0123: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M4567: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M891011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M12131415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M0_7: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M8_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M0_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB2_M0_15_D: signed((NSMBITS-1) downto 0) := (others => '0');  

signal AB3_M01: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M23: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M45: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M67: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M89: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M1011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M1213: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M1415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M0123: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M4567: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M891011: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M12131415: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M0_7: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M8_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M0_15: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB3_M0_15_D: signed((NSMBITS-1) downto 0) := (others => '0');  

signal AB01_MAX: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB23_MAX: signed((NSMBITS-1) downto 0) := (others => '0');  
signal AB_MAX: signed((NSMBITS-1) downto 0) := (others => '0');  
signal LLR00_X: signed((NSMBITS-1) downto 0) := (others => '0');  
signal LLR01_X: signed((NSMBITS-1) downto 0) := (others => '0');  
signal LLR10_X: signed((NSMBITS-1) downto 0) := (others => '0');  
signal LLR11_X: signed((NSMBITS-1) downto 0) := (others => '0');  

signal DATA_OUT01: std_logic_vector(1 downto 0) := "00";
signal DATA_OUT23: std_logic_vector(1 downto 0) := "00";

-- simulation test code to confirm the selection of NLLRBITS
signal MSB10: std_logic := '0';
signal MSB11: std_logic := '0';
signal MSB12: std_logic := '0';
signal MSB13: std_logic := '0';
signal MSB20: std_logic := '0';
signal MSB21: std_logic := '0';
signal MSB22: std_logic := '0';
signal MSB23: std_logic := '0';

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

RECLOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(INPUT_VALID = '1') then
			AB0_AS0 <= signed(A_IN0) + resize(signed(BM0),NSMBITS) + signed(B_IN0);
			AB0_AS1 <= signed(A_IN1) + resize(signed(BM0),NSMBITS) + signed(B_IN8);
			AB0_AS2 <= signed(A_IN2) + resize(signed(BM4),NSMBITS) + signed(B_IN9);
			AB0_AS3 <= signed(A_IN3) + resize(signed(BM4),NSMBITS) + signed(B_IN1);
			AB0_AS4 <= signed(A_IN4) + resize(signed(BM12),NSMBITS) + signed(B_IN2);
			AB0_AS5 <= signed(A_IN5) + resize(signed(BM12),NSMBITS) + signed(B_IN10);
			AB0_AS6 <= signed(A_IN6) + resize(signed(BM8),NSMBITS) + signed(B_IN11);
			AB0_AS7 <= signed(A_IN7) + resize(signed(BM8),NSMBITS) + signed(B_IN3);
			AB0_AS8 <= signed(A_IN8) + resize(signed(BM4),NSMBITS) + signed(B_IN4);
			AB0_AS9 <= signed(A_IN9) + resize(signed(BM4),NSMBITS) + signed(B_IN12);
			AB0_AS10 <= signed(A_IN10) + resize(signed(BM0),NSMBITS) + signed(B_IN13);
			AB0_AS11 <= signed(A_IN11) + resize(signed(BM0),NSMBITS) + signed(B_IN5);
			AB0_AS12 <= signed(A_IN12) + resize(signed(BM8),NSMBITS) + signed(B_IN6);
			AB0_AS13 <= signed(A_IN13) + resize(signed(BM8),NSMBITS) + signed(B_IN14);
			AB0_AS14 <= signed(A_IN14) + resize(signed(BM12),NSMBITS) + signed(B_IN15);
			AB0_AS15 <= signed(A_IN15) + resize(signed(BM12),NSMBITS) + signed(B_IN7);

			AB1_AS0 <= signed(A_IN0) + resize(signed(BM13),NSMBITS) + signed(B_IN8);
			AB1_AS1 <= signed(A_IN1) + resize(signed(BM13),NSMBITS) + signed(B_IN0);
			AB1_AS2 <= signed(A_IN2) + resize(signed(BM9),NSMBITS) + signed(B_IN1);
			AB1_AS3 <= signed(A_IN3) + resize(signed(BM9),NSMBITS) + signed(B_IN9);
			AB1_AS4 <= signed(A_IN4) + resize(signed(BM1),NSMBITS) + signed(B_IN10);
			AB1_AS5 <= signed(A_IN5) + resize(signed(BM1),NSMBITS) + signed(B_IN2);
			AB1_AS6 <= signed(A_IN6) + resize(signed(BM5),NSMBITS) + signed(B_IN3);
			AB1_AS7 <= signed(A_IN7) + resize(signed(BM5),NSMBITS) + signed(B_IN11);
			AB1_AS8 <= signed(A_IN8) + resize(signed(BM9),NSMBITS) + signed(B_IN12);
			AB1_AS9 <= signed(A_IN9) + resize(signed(BM9),NSMBITS) + signed(B_IN4);
			AB1_AS10 <= signed(A_IN10) + resize(signed(BM13),NSMBITS) + signed(B_IN5);
			AB1_AS11 <= signed(A_IN11) + resize(signed(BM13),NSMBITS) + signed(B_IN13);
			AB1_AS12 <= signed(A_IN12) + resize(signed(BM5),NSMBITS) + signed(B_IN14);
			AB1_AS13 <= signed(A_IN13) + resize(signed(BM5),NSMBITS) + signed(B_IN6);
			AB1_AS14 <= signed(A_IN14) + resize(signed(BM1),NSMBITS) + signed(B_IN7);
			AB1_AS15 <= signed(A_IN15) + resize(signed(BM1),NSMBITS) + signed(B_IN15);

			AB2_AS0 <= signed(A_IN0) + resize(signed(BM14),NSMBITS) + signed(B_IN13);
			AB2_AS1 <= signed(A_IN1) + resize(signed(BM14),NSMBITS) + signed(B_IN5);
			AB2_AS2 <= signed(A_IN2) + resize(signed(BM10),NSMBITS) + signed(B_IN4); -- *092116
			AB2_AS3 <= signed(A_IN3) + resize(signed(BM10),NSMBITS) + signed(B_IN12);
			AB2_AS4 <= signed(A_IN4) + resize(signed(BM2),NSMBITS) + signed(B_IN15);
			AB2_AS5 <= signed(A_IN5) + resize(signed(BM2),NSMBITS) + signed(B_IN7);
			AB2_AS6 <= signed(A_IN6) + resize(signed(BM6),NSMBITS) + signed(B_IN6);
			AB2_AS7 <= signed(A_IN7) + resize(signed(BM6),NSMBITS) + signed(B_IN14);
			AB2_AS8 <= signed(A_IN8) + resize(signed(BM10),NSMBITS) + signed(B_IN9);
			AB2_AS9 <= signed(A_IN9) + resize(signed(BM10),NSMBITS) + signed(B_IN1);
			AB2_AS10 <= signed(A_IN10) + resize(signed(BM14),NSMBITS) + signed(B_IN0);
			AB2_AS11 <= signed(A_IN11) + resize(signed(BM14),NSMBITS) + signed(B_IN8);
			AB2_AS12 <= signed(A_IN12) + resize(signed(BM6),NSMBITS) + signed(B_IN11);
			AB2_AS13 <= signed(A_IN13) + resize(signed(BM6),NSMBITS) + signed(B_IN3);
			AB2_AS14 <= signed(A_IN14) + resize(signed(BM2),NSMBITS) + signed(B_IN2);
			AB2_AS15 <= signed(A_IN15) + resize(signed(BM2),NSMBITS) + signed(B_IN10);

			AB3_AS0 <= signed(A_IN0) + resize(signed(BM3),NSMBITS) + signed(B_IN5);
			AB3_AS1 <= signed(A_IN1) + resize(signed(BM3),NSMBITS) + signed(B_IN13);
			AB3_AS2 <= signed(A_IN2) + resize(signed(BM7),NSMBITS) + signed(B_IN12);
			AB3_AS3 <= signed(A_IN3) + resize(signed(BM7),NSMBITS) + signed(B_IN4);
			AB3_AS4 <= signed(A_IN4) + resize(signed(BM15),NSMBITS) + signed(B_IN7);
			AB3_AS5 <= signed(A_IN5) + resize(signed(BM15),NSMBITS) + signed(B_IN15);
			AB3_AS6 <= signed(A_IN6) + resize(signed(BM11),NSMBITS) + signed(B_IN14);
			AB3_AS7 <= signed(A_IN7) + resize(signed(BM11),NSMBITS) + signed(B_IN6);
			AB3_AS8 <= signed(A_IN8) + resize(signed(BM7),NSMBITS) + signed(B_IN1);
			AB3_AS9 <= signed(A_IN9) + resize(signed(BM7),NSMBITS) + signed(B_IN9);
			AB3_AS10 <= signed(A_IN10) + resize(signed(BM3),NSMBITS) + signed(B_IN8);
			AB3_AS11 <= signed(A_IN11) + resize(signed(BM3),NSMBITS) + signed(B_IN0);
			AB3_AS12 <= signed(A_IN12) + resize(signed(BM11),NSMBITS) + signed(B_IN3);
			AB3_AS13 <= signed(A_IN13) + resize(signed(BM11),NSMBITS) + signed(B_IN11);
			AB3_AS14 <= signed(A_IN14) + resize(signed(BM15),NSMBITS) + signed(B_IN10);
			AB3_AS15 <= signed(A_IN15) + resize(signed(BM15),NSMBITS) + signed(B_IN2);
		end if;
	end if;
end process;

-- find the max for each AB
-- MAX for AB = 00 ---------------------------------------
MAX_AB0_01: process(AB0_AS0, AB0_AS1)
begin
	if(AB0_AS0 > AB0_AS1) then
		AB0_M01 <= AB0_AS0;
	else
		AB0_M01 <= AB0_AS1;
	end if;
end process;
MAX_AB0_23: process(AB0_AS2, AB0_AS3)
begin
	if(AB0_AS2 > AB0_AS3) then
		AB0_M23 <= AB0_AS2;
	else
		AB0_M23 <= AB0_AS3;
	end if;
end process;
MAX_AB0_45: process(AB0_AS4, AB0_AS5)
begin
	if(AB0_AS4 > AB0_AS5) then
		AB0_M45 <= AB0_AS4;
	else
		AB0_M45 <= AB0_AS5;
	end if;
end process;
MAX_AB0_67: process(AB0_AS6, AB0_AS7)
begin
	if(AB0_AS6 > AB0_AS7) then
		AB0_M67 <= AB0_AS6;
	else
		AB0_M67 <= AB0_AS7;
	end if;
end process;
MAX_AB0_89: process(AB0_AS8, AB0_AS9)
begin
	if(AB0_AS8 > AB0_AS9) then
		AB0_M89 <= AB0_AS8;
	else
		AB0_M89 <= AB0_AS9;
	end if;
end process;
MAX_AB0_1011: process(AB0_AS10, AB0_AS11)
begin
	if(AB0_AS10 > AB0_AS11) then
		AB0_M1011 <= AB0_AS10;
	else
		AB0_M1011 <= AB0_AS11;
	end if;
end process;
MAX_AB0_1213: process(AB0_AS12, AB0_AS13)
begin
	if(AB0_AS12 > AB0_AS13) then
		AB0_M1213 <= AB0_AS12;
	else
		AB0_M1213 <= AB0_AS13;
	end if;
end process;
MAX_AB0_1415: process(AB0_AS14, AB0_AS15)
begin
	if(AB0_AS14 > AB0_AS15) then
		AB0_M1415 <= AB0_AS14;
	else
		AB0_M1415 <= AB0_AS15;
	end if;
end process;
MAX_AB0_0123: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB0_M01 > AB0_M23) then
			AB0_M0123 <= AB0_M01;
		else
			AB0_M0123 <= AB0_M23;
		end if;
	end if;
end process;
MAX_AB0_4567: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB0_M45 > AB0_M67) then
			AB0_M4567 <= AB0_M45;
		else
			AB0_M4567 <= AB0_M67;
		end if;
	end if;
end process;
MAX_AB0_891011: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB0_M89 > AB0_M1011) then
			AB0_M891011 <= AB0_M89;
		else
			AB0_M891011 <= AB0_M1011;
		end if;
	end if;
end process;
MAX_AB0_12131415: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB0_M1213 > AB0_M1415) then
			AB0_M12131415 <= AB0_M1213;
		else
			AB0_M12131415 <= AB0_M1415;
		end if;
	end if;
end process;
MAX_AB0_0_7: process(AB0_M0123, AB0_M4567)
begin
	if(AB0_M0123 > AB0_M4567) then
		AB0_M0_7 <= AB0_M0123;
	else
		AB0_M0_7 <= AB0_M4567;
	end if;
end process;
MAX_AB0_8_15: process(AB0_M891011, AB0_M12131415)
begin
	if(AB0_M891011 > AB0_M12131415) then
		AB0_M8_15 <= AB0_M891011;
	else
		AB0_M8_15 <= AB0_M12131415;
	end if;
end process;
MAX_AB0_ALL: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB0_M0_7 > AB0_M8_15) then
			AB0_M0_15 <= AB0_M0_7;
		else
			AB0_M0_15 <= AB0_M8_15;
		end if;
	end if;
end process;

-- MAX for AB = 01 ---------------------------------------
MAX_AB1_01: process(AB1_AS0, AB1_AS1)
begin
	if(AB1_AS0 > AB1_AS1) then
		AB1_M01 <= AB1_AS0;
	else
		AB1_M01 <= AB1_AS1;
	end if;
end process;
MAX_AB1_23: process(AB1_AS2, AB1_AS3)
begin
	if(AB1_AS2 > AB1_AS3) then
		AB1_M23 <= AB1_AS2;
	else
		AB1_M23 <= AB1_AS3;
	end if;
end process;
MAX_AB1_45: process(AB1_AS4, AB1_AS5)
begin
	if(AB1_AS4 > AB1_AS5) then
		AB1_M45 <= AB1_AS4;
	else
		AB1_M45 <= AB1_AS5;
	end if;
end process;
MAX_AB1_67: process(AB1_AS6, AB1_AS7)
begin
	if(AB1_AS6 > AB1_AS7) then
		AB1_M67 <= AB1_AS6;
	else
		AB1_M67 <= AB1_AS7;
	end if;
end process;
MAX_AB1_89: process(AB1_AS8, AB1_AS9)
begin
	if(AB1_AS8 > AB1_AS9) then
		AB1_M89 <= AB1_AS8;
	else
		AB1_M89 <= AB1_AS9;
	end if;
end process;
MAX_AB1_1011: process(AB1_AS10, AB1_AS11)
begin
	if(AB1_AS10 > AB1_AS11) then
		AB1_M1011 <= AB1_AS10;
	else
		AB1_M1011 <= AB1_AS11;
	end if;
end process;
MAX_AB1_1213: process(AB1_AS12, AB1_AS13)
begin
	if(AB1_AS12 > AB1_AS13) then
		AB1_M1213 <= AB1_AS12;
	else
		AB1_M1213 <= AB1_AS13;
	end if;
end process;
MAX_AB1_1415: process(AB1_AS14, AB1_AS15)
begin
	if(AB1_AS14 > AB1_AS15) then
		AB1_M1415 <= AB1_AS14;
	else
		AB1_M1415 <= AB1_AS15;
	end if;
end process;
MAX_AB1_0123: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB1_M01 > AB1_M23) then
			AB1_M0123 <= AB1_M01;
		else
			AB1_M0123 <= AB1_M23;
		end if;
	end if;
end process;
MAX_AB1_4567: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB1_M45 > AB1_M67) then
			AB1_M4567 <= AB1_M45;
		else
			AB1_M4567 <= AB1_M67;
		end if;
	end if;
end process;
MAX_AB1_891011: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB1_M89 > AB1_M1011) then
			AB1_M891011 <= AB1_M89;
		else
			AB1_M891011 <= AB1_M1011;
		end if;
	end if;
end process;
MAX_AB1_12131415: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB1_M1213 > AB1_M1415) then
			AB1_M12131415 <= AB1_M1213;
		else
			AB1_M12131415 <= AB1_M1415;
		end if;
	end if;
end process;
MAX_AB1_0_7: process(AB1_M0123, AB1_M4567)
begin
	if(AB1_M0123 > AB1_M4567) then
		AB1_M0_7 <= AB1_M0123;
	else
		AB1_M0_7 <= AB1_M4567;
	end if;
end process;
MAX_AB1_8_15: process(AB1_M891011, AB1_M12131415)
begin
	if(AB1_M891011 > AB1_M12131415) then
		AB1_M8_15 <= AB1_M891011;
	else
		AB1_M8_15 <= AB1_M12131415;
	end if;
end process;
MAX_AB1_ALL: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB1_M0_7 > AB1_M8_15) then
			AB1_M0_15 <= AB1_M0_7;
		else
			AB1_M0_15 <= AB1_M8_15;
		end if;
	end if;
end process;

-- MAX for AB = 10 ---------------------------------------
MAX_AB2_01: process(AB2_AS0, AB2_AS1)
begin
	if(AB2_AS0 > AB2_AS1) then
		AB2_M01 <= AB2_AS0;
	else
		AB2_M01 <= AB2_AS1;
	end if;
end process;
MAX_AB2_23: process(AB2_AS2, AB2_AS3)
begin
	if(AB2_AS2 > AB2_AS3) then
		AB2_M23 <= AB2_AS2;
	else
		AB2_M23 <= AB2_AS3;
	end if;
end process;
MAX_AB2_45: process(AB2_AS4, AB2_AS5)
begin
	if(AB2_AS4 > AB2_AS5) then
		AB2_M45 <= AB2_AS4;
	else
		AB2_M45 <= AB2_AS5;
	end if;
end process;
MAX_AB2_67: process(AB2_AS6, AB2_AS7)
begin
	if(AB2_AS6 > AB2_AS7) then
		AB2_M67 <= AB2_AS6;
	else
		AB2_M67 <= AB2_AS7;
	end if;
end process;
MAX_AB2_89: process(AB2_AS8, AB2_AS9)
begin
	if(AB2_AS8 > AB2_AS9) then
		AB2_M89 <= AB2_AS8;
	else
		AB2_M89 <= AB2_AS9;
	end if;
end process;
MAX_AB2_1011: process(AB2_AS10, AB2_AS11)
begin
	if(AB2_AS10 > AB2_AS11) then
		AB2_M1011 <= AB2_AS10;
	else
		AB2_M1011 <= AB2_AS11;
	end if;
end process;
MAX_AB2_1213: process(AB2_AS12, AB2_AS13)
begin
	if(AB2_AS12 > AB2_AS13) then
		AB2_M1213 <= AB2_AS12;
	else
		AB2_M1213 <= AB2_AS13;
	end if;
end process;
MAX_AB2_1415: process(AB2_AS14, AB2_AS15)
begin
	if(AB2_AS14 > AB2_AS15) then
		AB2_M1415 <= AB2_AS14;
	else
		AB2_M1415 <= AB2_AS15;
	end if;
end process;
MAX_AB2_0123: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB2_M01 > AB2_M23) then
			AB2_M0123 <= AB2_M01;
		else
			AB2_M0123 <= AB2_M23;
		end if;
	end if;
end process;
MAX_AB2_4567: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB2_M45 > AB2_M67) then
			AB2_M4567 <= AB2_M45;
		else
			AB2_M4567 <= AB2_M67;
		end if;
	end if;
end process;
MAX_AB2_891011: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB2_M89 > AB2_M1011) then
			AB2_M891011 <= AB2_M89;
		else
			AB2_M891011 <= AB2_M1011;
		end if;
	end if;
end process;
MAX_AB2_12131415: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB2_M1213 > AB2_M1415) then
			AB2_M12131415 <= AB2_M1213;
		else
			AB2_M12131415 <= AB2_M1415;
		end if;
	end if;
end process;
MAX_AB2_0_7: process(AB2_M0123, AB2_M4567)
begin
	if(AB2_M0123 > AB2_M4567) then
		AB2_M0_7 <= AB2_M0123;
	else
		AB2_M0_7 <= AB2_M4567;
	end if;
end process;
MAX_AB2_8_15: process(AB2_M891011, AB2_M12131415)
begin
	if(AB2_M891011 > AB2_M12131415) then
		AB2_M8_15 <= AB2_M891011;
	else
		AB2_M8_15 <= AB2_M12131415;
	end if;
end process;
MAX_AB2_ALL: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB2_M0_7 > AB2_M8_15) then
			AB2_M0_15 <= AB2_M0_7;
		else
			AB2_M0_15 <= AB2_M8_15;
		end if;
	end if;
end process;

-- MAX for AB = 11 ---------------------------------------
MAX_AB3_01: process(AB3_AS0, AB3_AS1)
begin
	if(AB3_AS0 > AB3_AS1) then
		AB3_M01 <= AB3_AS0;
	else
		AB3_M01 <= AB3_AS1;
	end if;
end process;
MAX_AB3_23: process(AB3_AS2, AB3_AS3)
begin
	if(AB3_AS2 > AB3_AS3) then
		AB3_M23 <= AB3_AS2;
	else
		AB3_M23 <= AB3_AS3;
	end if;
end process;
MAX_AB3_45: process(AB3_AS4, AB3_AS5)
begin
	if(AB3_AS4 > AB3_AS5) then
		AB3_M45 <= AB3_AS4;
	else
		AB3_M45 <= AB3_AS5;
	end if;
end process;
MAX_AB3_67: process(AB3_AS6, AB3_AS7)
begin
	if(AB3_AS6 > AB3_AS7) then
		AB3_M67 <= AB3_AS6;
	else
		AB3_M67 <= AB3_AS7;
	end if;
end process;
MAX_AB3_89: process(AB3_AS8, AB3_AS9)
begin
	if(AB3_AS8 > AB3_AS9) then
		AB3_M89 <= AB3_AS8;
	else
		AB3_M89 <= AB3_AS9;
	end if;
end process;
MAX_AB3_1011: process(AB3_AS10, AB3_AS11)
begin
	if(AB3_AS10 > AB3_AS11) then
		AB3_M1011 <= AB3_AS10;
	else
		AB3_M1011 <= AB3_AS11;
	end if;
end process;
MAX_AB3_1213: process(AB3_AS12, AB3_AS13)
begin
	if(AB3_AS12 > AB3_AS13) then
		AB3_M1213 <= AB3_AS12;
	else
		AB3_M1213 <= AB3_AS13;
	end if;
end process;
MAX_AB3_1415: process(AB3_AS14, AB3_AS15)
begin
	if(AB3_AS14 > AB3_AS15) then
		AB3_M1415 <= AB3_AS14;
	else
		AB3_M1415 <= AB3_AS15;
	end if;
end process;
MAX_AB3_0123: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB3_M01 > AB3_M23) then
			AB3_M0123 <= AB3_M01;
		else
			AB3_M0123 <= AB3_M23;
		end if;
	end if;
end process;
MAX_AB3_4567: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB3_M45 > AB3_M67) then
			AB3_M4567 <= AB3_M45;
		else
			AB3_M4567 <= AB3_M67;
		end if;
	end if;
end process;
MAX_AB3_891011: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB3_M89 > AB3_M1011) then
			AB3_M891011 <= AB3_M89;
		else
			AB3_M891011 <= AB3_M1011;
		end if;
	end if;
end process;
MAX_AB3_12131415: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB3_M1213 > AB3_M1415) then
			AB3_M12131415 <= AB3_M1213;
		else
			AB3_M12131415 <= AB3_M1415;
		end if;
	end if;
end process;
MAX_AB3_0_7: process(AB3_M0123, AB3_M4567)
begin
	if(AB3_M0123 > AB3_M4567) then
		AB3_M0_7 <= AB3_M0123;
	else
		AB3_M0_7 <= AB3_M4567;
	end if;
end process;
MAX_AB3_8_15: process(AB3_M891011, AB3_M12131415)
begin
	if(AB3_M891011 > AB3_M12131415) then
		AB3_M8_15 <= AB3_M891011;
	else
		AB3_M8_15 <= AB3_M12131415;
	end if;
end process;
MAX_AB3_ALL: process(CLK)
begin
	if rising_edge(CLK) then
		if(AB3_M0_7 > AB3_M8_15) then
			AB3_M0_15 <= AB3_M0_7;
		else
			AB3_M0_15 <= AB3_M8_15;
		end if;
	end if;
end process;

-- find lambda_max
MAX_AB01: process(AB0_M0_15, AB1_M0_15)
begin
	if(AB0_M0_15 > AB1_M0_15) then
		AB01_MAX <= AB0_M0_15;
		DATA_OUT01 <= "00";
	else
		AB01_MAX <= AB1_M0_15;
		DATA_OUT01 <= "01";
	end if;
end process;
MAX_AB23: process(AB2_M0_15, AB3_M0_15)
begin
	if(AB2_M0_15 > AB3_M0_15) then
		AB23_MAX <= AB2_M0_15;
		DATA_OUT23 <= "10";
	else
		AB23_MAX <= AB3_M0_15;
		DATA_OUT23 <= "11";
	end if;
end process;

MAX_ABALL: process(CLK)
begin
	if rising_edge(CLK) then
		AB0_M0_15_D <= AB0_M0_15;
		AB1_M0_15_D <= AB1_M0_15;
		AB2_M0_15_D <= AB2_M0_15;
		AB3_M0_15_D <= AB3_M0_15;
		
		if(AB01_MAX > AB23_MAX) then
			AB_MAX <= AB01_MAX;
			DECODED_DATA_OUT <= DATA_OUT01;
		else
			AB_MAX <= AB23_MAX;
			DECODED_DATA_OUT <= DATA_OUT23;
		end if;
	end if;
end process;

-- LLR(delta) = lambda(delta) - lambda_max
LLR00_X <= AB0_M0_15_D  - AB_MAX;
LLR01_X <= AB1_M0_15_D  - AB_MAX;
LLR10_X <= AB2_M0_15_D  - AB_MAX;
LLR11_X <= AB3_M0_15_D  - AB_MAX;

-- Clamp
-- drop MSbs. Scaled by 1/2
-- leave 1 extra bit room to add BM without any overflow
CLAMP_LLR00: process(CLK)
begin
	if rising_edge(CLK) then
		if(LLR00_X(NSMBITS-1) = '0') and (LLR00_X(NSMBITS-2 downto NLLRBITS-1) /= 0) then
			-- positive saturation
			LLR00(NLLRBITS-1 downto NLLRBITS-2) <= (others => '0');
			LLR00(NLLRBITS-3 downto 0) <= (others => '1');
		elsif(LLR00_X(NSMBITS-1) = '1') and ((not LLR00_X(NSMBITS-2 downto NLLRBITS -1)) /= 0) then
			-- negative saturation
			LLR00(NLLRBITS-1 downto NLLRBITS-2) <= (others => '1');
			LLR00(NLLRBITS-3 downto 0) <= (others => '0');
		else
			LLR00(NLLRBITS-1) <= LLR00_X(NLLRBITS -1);
			LLR00(NLLRBITS-2 downto 0) <= std_logic_vector(LLR00_X(NLLRBITS -1 downto 1));  -- Scaled by 1/2
		end if;
	end if;
end process;

CLAMP_LLR01: process(CLK)
begin
	if rising_edge(CLK) then
		if(LLR01_X(NSMBITS-1) = '0') and (LLR01_X(NSMBITS-2 downto NLLRBITS-1) /= 0) then
			-- positive saturation
			LLR01(NLLRBITS-1 downto NLLRBITS-2) <= (others => '0');
			LLR01(NLLRBITS-3 downto 0) <= (others => '1');
		elsif(LLR01_X(NSMBITS-1) = '1') and ((not LLR01_X(NSMBITS-2 downto NLLRBITS -1)) /= 0) then
			-- negative saturation
			LLR01(NLLRBITS-1 downto NLLRBITS-2) <= (others => '1');
			LLR01(NLLRBITS-3 downto 0) <= (others => '0');
		else
			LLR01(NLLRBITS-1) <= LLR01_X(NLLRBITS -1);
			LLR01(NLLRBITS-2 downto 0) <= std_logic_vector(LLR01_X(NLLRBITS -1 downto 1));  -- Scaled by 1/2
		end if;
	end if;
end process;

CLAMP_LLR10: process(CLK)
begin
	if rising_edge(CLK) then
		if(LLR10_X(NSMBITS-1) = '0') and (LLR10_X(NSMBITS-2 downto NLLRBITS-1) /= 0) then
			-- positive saturation
			LLR10(NLLRBITS-1 downto NLLRBITS-2) <= (others => '0');
			LLR10(NLLRBITS-3 downto 0) <= (others => '1');
		elsif(LLR10_X(NSMBITS-1) = '1') and ((not LLR10_X(NSMBITS-2 downto NLLRBITS -1)) /= 0) then
			-- negative saturation
			LLR10(NLLRBITS-1 downto NLLRBITS-2) <= (others => '1');
			LLR10(NLLRBITS-3 downto 0) <= (others => '0');
		else
			LLR10(NLLRBITS-1) <= LLR10_X(NLLRBITS -1);
			LLR10(NLLRBITS-2 downto 0) <= std_logic_vector(LLR10_X(NLLRBITS -1 downto 1));  -- Scaled by 1/2
		end if;
	end if;
end process;

CLAMP_LLR11: process(CLK)
begin
	if rising_edge(CLK) then
		if(LLR11_X(NSMBITS-1) = '0') and (LLR11_X(NSMBITS-2 downto NLLRBITS-1) /= 0) then
			-- positive saturation
			LLR11(NLLRBITS-1 downto NLLRBITS-2) <= (others => '0');
			LLR11(NLLRBITS-3 downto 0) <= (others => '1');
		elsif(LLR11_X(NSMBITS-1) = '1') and ((not LLR11_X(NSMBITS-2 downto NLLRBITS -1)) /= 0) then
			-- negative saturation
			LLR11(NLLRBITS-1 downto NLLRBITS-2) <= (others => '1');
			LLR11(NLLRBITS-3 downto 0) <= (others => '0');
		else
			LLR11(NLLRBITS-1) <= LLR11_X(NLLRBITS -1);
			LLR11(NLLRBITS-2 downto 0) <= std_logic_vector(LLR11_X(NLLRBITS -1 downto 1));  -- Scaled by 1/2
		end if;
	end if;
end process;

-- simulation test code to confirm the selection of NLLRBITS
--MSB10 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-1) else '0';
--MSB11 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-1) else '0';
--MSB12 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-1) else '0';
--MSB13 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-1) else '0';
--
--MSB20 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-2) else '0';
--MSB21 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-2) else '0';
--MSB22 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-2) else '0';
--MSB23 <= '1' when LLR00_X(NLLRBITS) /= LLR00_X(NLLRBITS-2) else '0';


end Behavioral;

