Vous êtes sur la page 1sur 8

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

-- Create Date: 06/23/2008


-- Design Name: ETC1 Texture Decoder.
-- Module Name: ETC1Decompressor
--
-- Description: Decoding module for ETC1 texture compression format.
--
-- Take a 64 bit chunk and coordinate (4x4) as input.
-- It outputs RGB 888 value as a result.
-- It also output the overflow for R,G,B component to allow external ETC2
-- decoder.
--
-- The decoder itself has NO register and is made of pure logic.
-- And can be put directly after a texture cache line inside the texture sampler.
-- Inside FPGA speed above 80 Mhz seems sustainable.
--
-- Revision:
-- Revision 0.01 - File Created
-- Revision 0.02 - Comment added, cleaning started. Implementation finished.
-- Additional Comments:
-- Seach for "OPTIMIZE" in source code to see where changes could be made
-- for trade off.
-- Search for "ETC2" in source code to modify the decoder as a pure ETC1
decoder.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

----------------------------------------------------------------------------------
-- Connectivity.
----------------------------------------------------------------------------------

entity ETC1Decompressor is
Port ( textureLine : in STD_LOGIC_VECTOR(63 downto 0);
PIX : in STD_LOGIC_VECTOR(3 downto 0);

R : out STD_LOGIC_VECTOR(7 downto 0);


G : out STD_LOGIC_VECTOR(7 downto 0);
B : out STD_LOGIC_VECTOR(7 downto 0);

-- ETC2
OverflowR : out STD_LOGIC;
OverflowG : out STD_LOGIC;
OverflowB : out STD_LOGIC

);
end ETC1Decompressor;

----------------------------------------------------------------------------------
-- Synthetizable logic.
----------------------------------------------------------------------------------

architecture BehavioralETC1Decompressor of ETC1Decompressor is


-- Macro to avoid reading directly in 64 bit input.
signal component1 : std_logic_vector(7 downto 0);
signal component2 : std_logic_vector(7 downto 0);
signal component3 : std_logic_vector(7 downto 0);
signal pixels : std_logic_vector(31 downto 0);
signal diffbit : std_logic;
signal flipbit : std_logic;

-- Working mode bits.


signal u : std_logic;
signal v : std_logic;
signal w : std_logic;

-- Temporary signal for each component (RGB)


signal lsbR : std_logic;
signal lsbG : std_logic;
signal lsbB : std_logic;

signal add_compR : std_logic_vector(2 downto 0);


signal add_compG : std_logic_vector(2 downto 0);
signal add_compB : std_logic_vector(2 downto 0);

signal tempCompR : std_logic_vector(7 downto 0);


signal tempCompG : std_logic_vector(7 downto 0);
signal tempCompB : std_logic_vector(7 downto 0);

signal tempCompR2 : std_logic_vector(8 downto 0);


signal tempCompG2 : std_logic_vector(8 downto 0);
signal tempCompB2 : std_logic_vector(8 downto 0);

-- ETC2 : Use this signals to add 5 bit + 5 bit.


-- Overflow NEVER occur normally except for ETC2 extensions.
-- So if you want to make a PURE ETC1 decoder,
-- modify "5 downto 0" -> "4 down 0"
signal add_compoutR : std_logic_vector(5 downto 0);
signal add_compoutG : std_logic_vector(5 downto 0);
signal add_compoutB : std_logic_vector(5 downto 0);
signal outcolR : std_logic_vector(5 downto 0);
signal outcolG : std_logic_vector(5 downto 0);
signal outcolB : std_logic_vector(5 downto 0);

signal tableCode : std_logic_vector(2 downto 0);


signal addCode : std_logic_vector(8 downto 0);

signal pixIdx : std_logic_vector(1 downto 0);

-- Used in Clipper.
signal Rs : std_logic;
signal Ro : std_logic;
signal Gs : std_logic;
signal Go : std_logic;
signal Bs : std_logic;
signal Bo : std_logic;

--ROM Modifier Table


--
--Adress on 5 bit : LSB 1..0 : PixelIndex value (see lower table)
--
-- pixel index value
-- ---------------
-- msb lsb resulting modifier value
-- ----- ----- -------------------------
-- 0 0 a (small positive value) -> Index 0
-- 0 1 b (large positive value) -> Index 1
-- 1 0 -a (small negative value) -> Index 2
-- 1 1 -b (large negative value) -> Index 3
--
-- MSB 4..2 : Table code word as directly
-- given from compressed block.
--
-- table codeword modifier table
-- ------------------ ----------------------
-- 0 2 8 -2 -8
-- 1 5 17 -5 -17
-- 2 9 29 -9 -29
-- 3 13 42 -13 -42
-- 4 18 60 -18 -60
-- 5 24 80 -24 -80
-- 6 33 106 -33 -106
-- 7 47 183 -47 -183

type RomType is array (0 to 31) of std_logic_vector(8 downto 0);


constant ROMTbl : RomType := (
--- Table 0
B"000000010",
B"000001000",
B"111111110",
B"111111000",
--- Table 1
B"000000101",
B"000010001",
B"111111011",
B"111101111",
--- Table 2
B"000001001",
B"000011101",
B"111110111",
B"111100011",
--- Table 3
B"000001101",
B"000101010",
B"111110011",
B"111010110",
--- Table 4
B"000010010",
B"000111100",
B"111101110",
B"111000100",
--- Table 5
B"000011000",
B"001010000",
B"111101000",
B"110110000",
--- Table 6
B"000100001",
B"001101010",
B"111011111",
B"110010110",
--- Table 7
B"000101111",
B"010110111",
B"111010001",
B"101001001",
others => "000000000"
) ;

begin
--
-- Stage 0 :
-- Init, cut the 64 bit chunk and assign to temp signals.
-- Perform u,v,w working bit calculation.
process (textureLine, PIX)
begin
-- Chunk cutting.
----------------------------------------------------
diffbit <= textureLine(33);
flipbit <= textureLine(32);
pixels <= textureLine(31 downto 0);

component1 <= textureLine(63 downto 56);


component2 <= textureLine(55 downto 48);
component3 <= textureLine(47 downto 40);

-- Stage Ctrl Logic ---


----------------------------------------------------
-- Process the first 2x4 block(0) or second 2x4 block(1)
w <= (flipbit and PIX(1)) or (not(flipbit) and PIX(3));
-- Perform differential mode only in second block AND when diff mode
activated.
-- 0 : Add 0, 1 : Add value.
u <= diffbit and w;
-- Use directly the second color in other mode.
-- 0 : Use second color directly.
-- 1 : Use differential color or direct first color.
v <= diffbit or not(w);
end process;

--
-- Stage 1A :
-- Select Base Color A, B or A+Delta for each component.
-- Perform at the same time a conversion from 555/444/
process (u,v,diffbit,component1, component2, component3)
begin
-- Stage U : Select Color
if (u = '0') then
add_compR <= "000";
add_compG <= "000";
add_compB <= "000";
else
add_compR <= component1(2 downto 0); -- 3 Bit delta extended to 5
bit.
add_compG <= component2(2 downto 0); -- 3 Bit delta extended to 5
bit.
add_compB <= component3(2 downto 0); -- 3 Bit delta extended to 5
bit.
end if;

if (diffbit = '0') then


-- Extenstion 444 -> 555
lsbR <= component1(7);
lsbG <= component2(7);
lsbB <= component3(7);
else
-- Get real 555 LSB info.
lsbR <= component1(3);
lsbG <= component2(3);
lsbB <= component3(3);
end if;

-- Add 5 bit original + 5 bit delta. (no overflow garantee)


add_compoutR <= ('0' & component1(7 downto 4) & lsbR) + ('0' &
add_compR(2) & add_compR(2) & add_compR(2 downto 0));
add_compoutG <= ('0' & component2(7 downto 4) & lsbG) + ('0' &
add_compG(2) & add_compG(2) & add_compG(2 downto 0));
add_compoutB <= ('0' & component3(7 downto 4) & lsbB) + ('0' &
add_compB(2) & add_compB(2) & add_compB(2 downto 0));
-- Pure ETC1 version. : remove the '0' headers.
--- add_compoutR <= component1(4 downto 0) + (add_compR(2 downto 0) &
add_compR(2 downto 1));

-- Stage V : Select Diff


if (v = '0') then
-- ETC2 : Can remove the first '0' if pure ETC1 decoder.
-- Extension 444 -> 555 done at the same time.
outcolR <= '0' & component1(3 downto 0) & component1(3); --
Direct second color.
outcolG <= '0' & component2(3 downto 0) & component2(3); --
Direct second color.
outcolB <= '0' & component3(3 downto 0) & component3(3); --
Direct second color.
else
outcolR <= add_compoutR; -- Differential color or direct first
color.
outcolG <= add_compoutG; -- Differential color or direct first
color.
outcolB <= add_compoutB; -- Differential color or direct first
color.
end if;
end process;

--
-- State 1B : Optionnal overflow detector for ETC2 extension.
--
-- ETC2 : Delete this block if pure ETC1 decoder.
process (v, outcolR, outcolG, outcolB)
begin
if (v='0') then
OverflowR <= '0';
OverflowG <= '0';
OverflowB <= '0';
else
OverflowR <= outcolR(5);
OverflowG <= outcolG(5);
OverflowB <= outcolB(5);
end if;
end process;

--
-- Stage 1C : Code book setup.
--
process (w,PIX, pixels, textureLine)
begin
if (w = '0') then
-- Sub block 1
tableCode <= textureLine(39 downto 37);
else
-- Sub block 2
tableCode <= textureLine(36 downto 34);
end if;

-- Pixel Layout.
-- --> U / Width
-- 0---- ---- ---- ----
-- |a |e |i |m |
-- | | | | |
-- ---- ---- ---- ----
-- |b |f |j |n |
-- | | | | |
-- ---- ---- ---- ----
-- |c |g |k |o |
-- | | | | |
-- ---- ---- ---- ----
-- |d |h |l |p |
-- | | | | |
-- ---- ---- ---- ----

case PIX is
-- As specified in Khronos Group documentation.
when "0000" => pixIdx <= pixels(16) & pixels(0); -- a
when "0001" => pixIdx <= pixels(17) & pixels(1); -- b
when "0010" => pixIdx <= pixels(18) & pixels(2); -- c
when "0011" => pixIdx <= pixels(19) & pixels(3); -- d
when "0100" => pixIdx <= pixels(20) & pixels(4); -- e
when "0101" => pixIdx <= pixels(21) & pixels(5);
when "0110" => pixIdx <= pixels(22) & pixels(6);
when "0111" => pixIdx <= pixels(23) & pixels(7);
when "1000" => pixIdx <= pixels(24) & pixels(8);
when "1001" => pixIdx <= pixels(25) & pixels(9);
when "1010" => pixIdx <= pixels(26) & pixels(10);
when "1011" => pixIdx <= pixels(27) & pixels(11);
when "1100" => pixIdx <= pixels(28) & pixels(12);
when "1101" => pixIdx <= pixels(29) & pixels(13);
when "1110" => pixIdx <= pixels(30) & pixels(14);
when others => pixIdx <= pixels(31) & pixels(15);
end case;

-- OPTIMIZE : divide rom table by 2, store positive value only.(A,B


only)
-- Use pixIdx(1) as selector for a
-- multiplexer to choose betwen value and -value (not(value)+1) from
ROM.
addCode <= ROMTbl(conv_integer(tableCode & pixIdx)) ;
end process;

--
-- logic.
--
process (outcolR, outcolG, outcolB, diffbit, addCode)
begin
tempCompR <= outcolR(4 downto 0) & outcolR(4 downto 2); -- 5 -> 8
tempCompG <= outcolG(4 downto 0) & outcolG(4 downto 2); -- 5 -> 8
tempCompB <= outcolB(4 downto 0) & outcolB(4 downto 2); -- 5 -> 8

tempCompR2 <= ('0' & tempCompR) + addCode;


tempCompG2 <= ('0' & tempCompG) + addCode;
tempCompB2 <= ('0' & tempCompB) + addCode;
end process;

--
-- Clamp Code.
--
process (tempCompR2, tempCompG2, tempCompB2, addCode)
begin
-- Clamp Code.
-- 255 if too positive, 0 if too negative.
-- * tempComp garanteed by encoder.
-- * sign of addCode then valid overflow/underflow.

-- Behaviour
-- Overflow / addcode Sign -> Operation.
-- 0 x -> Value
-- 1 / 0 -> 255
-- 1 / 1 -> 0
--
-- Logic : (val & not(Overflow)) | (Overflow & not(sign))
-- (Value if no overflow) | 0 if no overflow, 1 if
overflow and + value.
-- else 0
--
-- Demonstration.
-- O S V&(~O) (O&(~S)) Complete Formula
-- 0 0 V | 0 --> V
-- 0 1 V | 0 --> V
-- 1 0 0 | 1 --> 1
-- 1 1 0 | 0 --> 0
--
Ro <= not(tempCompR2(8));
Rs <= tempCompR2(8) and (not(addCode(8)));

Go <= not(tempCompG2(8));
Gs <= tempCompG2(8) and (not(addCode(8)));

Bo <= not(tempCompB2(8));
Bs <= tempCompB2(8) and (not(addCode(8)));

r <= (tempCompR2(7 downto 0) and (Ro&Ro&Ro&Ro&Ro&Ro&Ro&Ro)) or


(Rs&Rs&Rs&Rs&Rs&Rs&Rs&Rs);
g <= (tempCompG2(7 downto 0) and (Go&Go&Go&Go&Go&Go&Go&Go)) or
(Gs&Gs&Gs&Gs&Gs&Gs&Gs&Gs);
b <= (tempCompB2(7 downto 0) and (Bo&Bo&Bo&Bo&Bo&Bo&Bo&Bo)) or
(Bs&Bs&Bs&Bs&Bs&Bs&Bs&Bs);
end process;
end BehavioralETC1Decompressor;

Vous aimerez peut-être aussi