-- -- Copyright (c) 1999-2000 University of California, Riverside. -- Permission to copy is granted provided that this header remains -- intact. This software is provided with no warranties. -- -- Version : 1.0 -- ------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; ------------------------------------------------------------------------------- entity DCTC is generic(STAT_REG_ADDR : INTEGER := 65527; CMND_REG_ADDR : INTEGER := 65528; DATAI_REG_ADDR : INTEGER := 65530; DATAO_REG_ADDR : INTEGER := 65529); port(rst : in STD_LOGIC; clk : in STD_LOGIC; addr : in UNSIGNED (15 downto 0); in_data : in UNSIGNED (7 downto 0); out_data : out UNSIGNED (7 downto 0); rd : in STD_LOGIC; wr : in STD_LOGIC); end DCTC; ------------------------------------------------------------------------------- architecture BHV of DCTC is type S_TYPE is array (0 to 7) of SIGNED (23 downto 0); type COS_ROW_TYPE is array (0 to 7) of SIGNED (6 downto 0); type COS_BLOCK_TYPE is array (0 to 7) of COS_ROW_TYPE; type ROW_TYPE is array (0 to 7) of SIGNED (15 downto 0); type BLOCK_TYPE is array (0 to 7) of ROW_TYPE; type STATE_TYPE1 is (ST1_IDLE, ST1_WAIT, ST1_INCREMENT); type STATE_TYPE2 is (ST2_IDLE, ST2_COMPUTE, ST2_FINISH); constant CD_8 : UNSIGNED (7 downto 0) := "--------"; constant CD_16 : SIGNED (15 downto 0) := "----------------"; constant CD_24 : SIGNED (23 downto 0) := "------------------------"; constant C0_2 : SIGNED ( 1 downto 0) := "00"; constant C0_6 : SIGNED ( 5 downto 0) := "000000"; constant C0_7 : SIGNED ( 6 downto 0) := "0000000"; constant C0_8 : SIGNED ( 7 downto 0) := "00000000"; constant C0_13 : SIGNED (12 downto 0) := "0000000000000"; constant C0_17 : SIGNED (16 downto 0) := "00000000000000000"; constant C0_18 : SIGNED (17 downto 0) := "000000000000000000"; constant C0_24 : SIGNED (23 downto 0) := "000000000000000000000000"; constant C0_46 : SIGNED (45 downto 0) := "0000000000000000000000000000000000000000000000"; constant CZ_8 : UNSIGNED ( 7 downto 0) := "ZZZZZZZZ"; constant C1_8 : UNSIGNED ( 7 downto 0) := "00000001"; constant ONE_OVER_SQRT_TWO : SIGNED ( 5 downto 0 ) := "000101"; -- 0,6 constant SIXTYFOUR : SIGNED ( 12 downto 0 ) := "1000000000000"; -- 7,6 constant SIXTEEN : SIGNED ( 10 downto 0 ) := "10000000000"; -- 5,6 constant COS_TABLE : COS_BLOCK_TYPE := ( -- 1,6 ("1000000", "0111110", "0111011", "0110101", "0101101", "0100011", "0011000", "0001100"), ("1000000", "0110101", "0011000", "1110100", "1010011", "1000010", "1000101", "1011101"), ("1000000", "0100011", "1101000", "1000010", "1010011", "0001100", "0111011", "0110101"), ("1000000", "0001100", "1000101", "1011101", "0101101", "0110101", "1101000", "1000010"), ("1000000", "1110100", "1000101", "0100011", "0101101", "1001011", "1101000", "0111110"), ("1000000", "1011101", "1101000", "0111110", "1010011", "1110100", "0111011", "1001011"), ("1000000", "1001011", "0011000", "0001100", "1010011", "0111110", "1000101", "0100011"), ("1000000", "1000010", "0111011", "1001011", "0101101", "1011101", "0011000", "1110100") ); signal row : INTEGER range 0 to 7; signal col : INTEGER range 0 to 7; signal x : INTEGER range 0 to 8; signal s : S_TYPE; signal msb : std_logic; signal go : std_logic; signal done : std_logic; signal code_out : SIGNED (15 downto 0); signal busy : STD_LOGIC; signal block_i : BLOCK_TYPE; signal block_o : BLOCK_TYPE; signal state1 : STATE_TYPE1; signal state2 : STATE_TYPE2; begin process(rst, clk) variable v8 : SIGNED (7 downto 0); variable v10 : SIGNED (9 downto 0); variable v16 : SIGNED (15 downto 0); begin if( rst = '1' ) then row <= 0; col <= 0; msb <= '0'; go <= '0'; busy <= '0'; for i in 0 to 7 loop for j in 0 to 7 loop block_i(i)(j) <= CD_16; block_o(i)(j) <= CD_16; end loop; end loop; state1 <= ST1_IDLE; out_data <= CZ_8; elsif( clk'event and clk = '1' ) then out_data <= CZ_8; -- bus i/o if( wr = '1' and conv_integer(addr) = CMND_REG_ADDR ) then busy <= '1'; end if; if( wr = '1' and conv_integer(addr) = DATAI_REG_ADDR ) then v10 := (C0_2 & SIGNED(in_data)); v16 := (v10 & C0_6); block_i(row)(col) <= v16; if( col = 7 ) then col <= 0; if( row /= 7 ) then row <= row + 1; end if; else col <= col + 1; end if; end if; if( rd = '1' and conv_integer(addr) = STAT_REG_ADDR ) then out_data <= UNSIGNED(C0_7 & busy); end if; if( rd = '1' and conv_integer(addr) = DATAO_REG_ADDR ) then if ( msb = '0' ) then v16 := block_o(row)(col); v8 := v16(15 downto 8); out_data <= UNSIGNED(v8); msb <= '1'; else v16 := block_o(row)(col); v8 := v16(7 downto 0); out_data <= UNSIGNED(v8); if( col = 7 ) then col <= 0; if( row /= 7 ) then row <= row + 1; end if; else col <= col + 1; end if; msb <= '0'; end if; end if; -- compute case state1 is when ST1_IDLE => if( busy = '1' ) then row <= 0; col <= 0; go <= '1'; state1 <= ST1_WAIT; end if; when ST1_WAIT => go <= '0'; if( done = '1' ) then block_o(row)(col) <= code_out; col <= col + 1; state1 <= ST1_INCREMENT; end if; when ST1_INCREMENT => state1 <= ST1_WAIT; go <= '1'; if ( col = 7 ) then col <= 0; if( row = 7 ) then row <= 0; busy <= '0'; go <= '0'; state1 <= ST1_IDLE; else row <= row + 1; end if; end if; end case; end if; end process; process(rst, clk) variable v24_1, v24_2 : SIGNED ( 23 downto 0 ); variable v48 : SIGNED (47 downto 0); begin if( rst = '1' ) then x <= 0; for i in 0 to 7 loop s(i) <= CD_24; end loop; done <= '0'; code_out <= CD_16; state2 <= ST2_IDLE; elsif( clk'event and clk = '1' ) then case state2 is when ST2_IDLE => if( go = '1' ) then done <= '0'; x <= 0; state2 <= ST2_COMPUTE; end if; when ST2_COMPUTE => if( x = 8 ) then x <= 0; state2 <= ST2_FINISH; else v24_1 := C0_24; for i in 0 to 7 loop -- COS_TABLE(i)(col) * block_i(x)(i) v24_2 := C0_17 & COS_TABLE(i)(col); v48 := v24_2 * ( C0_8 & block_i(x)(i)); v24_2 := C0_6 & v48(23 downto 6); -- v24_1 += v24_2; v24_1 := v24_1 + v24_2; end loop; s(x) <= v24_1; x <= x + 1; end if; when ST2_FINISH => -- v24_1 = s(0) + s(1) . . . + s(7) v24_1 := C0_24; for i in 0 to 7 loop v24_1 := v24_1 + s(i); end loop; v24_2 := C0_13 & SIXTEEN; if ( row = 0 ) then -- v24_2 *= ONE_OVER_SQRT_TWO v48 := v24_2 * (C0_18 & ONE_OVER_SQRT_TWO); v24_2 := C0_6 & v48(23 downto 6); end if; if ( col = 0 ) then -- v24_2 *= ONE_OVER_SQRT_TWO v48 := v24_2 * (C0_18 & ONE_OVER_SQRT_TWO); v24_2 := C0_6 & v48(23 downto 6); end if; -- v24_1 *= v24_2 v48 := v24_1 * v24_2; v24_1 := C0_6 & v48(23 downto 6); -- convert from fixed to decimal code_out <= v24_1(22 downto 7); -- done done <= '1'; state2 <= ST2_IDLE; end case; end if; end process; end BHV;