------------------------------------------------------------------------------ -- Copyright (C) 2011, Kenichi Kurimoto -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----------------------------------------------------------------------------- -- Entity: idct1 -- File: idct1.vhd -- Author: Kenichi Kurimoto -- Description: 1st IDCT calculation for jpeg decode ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library grlib; use grlib.stdlib.all; entity idct1 is port ( rst : in std_ulogic; clk : in std_ulogic; ready1 : out std_logic; strobe1 : in std_logic; coeffin : in std_logic_vector (11 downto 0); quantin : in std_logic_vector (7 downto 0); outdata : out std_logic_vector (15 downto 0); ready2 : in std_logic; strobe2 : out std_logic; startgen : in std_logic ); end idct1; architecture rtl of idct1 is function mysigned_mul(a,b : std_logic_vector) return std_logic_vector is variable z : std_logic_vector(a'length + b'length -1 downto 0); begin z := std_logic_vector(signed(a) * signed(b)); return(z); end; function mysigned_add(a,b : std_logic_vector) return std_logic_vector is variable ex_a : std_logic_vector(a'length downto 0); variable ex_b : std_logic_vector(b'length downto 0); variable z1 : std_logic_vector(a'length downto 0); variable z2 : std_logic_vector(b'length downto 0); begin ex_a := a(a'left) & a; ex_b := b(b'left) & b; if( a'length > b'length)then z1 := std_logic_vector(signed(ex_a) + signed(ex_b)); return(z1); else z2 := std_logic_vector(signed(ex_a) + signed(ex_b)); return(z2); end if; end; function round1(indata : std_logic_vector(34 downto 0)) return std_logic_vector is variable judge :std_logic; variable z : std_logic_vector(22 downto 0); begin judge := indata(11); if (judge = '0') then z := indata(34 downto 12); else z := indata(34 downto 12) + 1; end if; return(z); end; function round2(indata : std_logic_vector(34 downto 0); pol : std_logic) return std_logic_vector is variable judge : std_logic; variable tmpdata : std_logic_vector(34 downto 0); variable z : std_logic_vector(22 downto 0); begin if (pol = '1') then tmpdata := (not indata) + 1 ; else tmpdata := indata; end if; judge := tmpdata(11); if (judge = '1') then z := tmpdata(34 downto 12) + 1; else z := tmpdata(34 downto 12); end if; return(z); end; function round3(indata : std_logic_vector(25 downto 0)) return std_logic_vector is variable judge : std_logic; variable z : std_logic_vector(15 downto 0); begin judge := indata(4); if (judge = '0') then z := indata(20 downto 5); else z := indata(20 downto 5) + 1; end if; return(z); end; subtype coeff23 is std_logic_vector(22 downto 0); type coeff_array1 is array(0 to 31) of coeff23; constant coeff_rom : coeff_array1 := ("01011010100000100111101","01011010100000100111101","01011010100000100111101","01011010100000100111101", "01111101100010100110000","01101010011011011001100","01000111000111001110110","00011000111110001011100", "01110110010000011011000","00110000111110111100011","11001111000001000011110","10001001101111100101001", "01101010011011011001100","11100111000001110100100","10000010011101011010001","10111000111000110001010", "01011010100000100111101","10100101011111011000100","10100101011111011000100","01011010100000100111101", "01000111000111001110110","10000010011101011010001","00011000111110001011100","01101010011011011001100", "00110000111110111100011","10001001101111100101001","01110110010000011011000","11001111000001000011110", "00011000111110001011100","10111000111000110001010","01101010011011011001100","10000010011101011010001"); type tablereg_type is array (0 to 3) of std_logic_vector(22 downto 0); type accumulator_type is array (0 to 7) of std_logic_vector(25 downto 0); type resultreg_type is array (0 to 7) of std_logic_vector(15 downto 0); type d_reg is record inreg : std_logic_vector(11 downto 0); accumulator : accumulator_type; result_reg : resultreg_type; end record; type c_reg is record counter : std_logic_vector(6 downto 0); end record; type all_reg is record data_reg : d_reg; control_reg : c_reg; end record; type node1_array is array (0 to 3) of std_logic_vector(22 downto 0); type node2_array is array (0 to 3) of std_logic_vector(34 downto 0); type node3_array is array (0 to 7) of std_logic_vector(22 downto 0); type node4_array is array (0 to 7) of std_logic_vector(25 downto 0); type node5_array is array (0 to 7) of std_logic_vector(26 downto 0); type node6_array is array (0 to 7) of std_logic_vector(15 downto 0); signal r, rin : all_reg; --signal sig_node1_0 : std_logic_vector(22 downto 0); --signal sig_node2_0 : std_logic_vector(34 downto 0); --signal sig_node3_0 : std_logic_vector(22 downto 0); --signal sig_node4_0 : std_logic_vector(25 downto 0); --signal sig_node5_0 : std_logic_vector(26 downto 0); --signal sig_node6_0 : std_logic_vector(15 downto 0); --signal sig_node1_1 : std_logic_vector(22 downto 0); --signal sig_node2_1 : std_logic_vector(34 downto 0); --signal sig_node3_6 : std_logic_vector(22 downto 0); --signal sig_node4_6 : std_logic_vector(25 downto 0); --signal sig_node5_6 : std_logic_vector(26 downto 0); --signal sig_node6_6 : std_logic_vector(15 downto 0); begin comb : process(r, rst, strobe1, ready2, coeffin, quantin, startgen) variable v : all_reg; variable node0 : std_logic_vector(20 downto 0); variable node1 : node1_array; variable node2 : node2_array; variable node3 : node3_array; variable node4 : node4_array; variable node5 : node5_array; variable node6 : node6_array; variable pol : std_logic; variable count_num : integer; variable vstrobe2 : std_logic; variable vready1 : std_logic; begin v := r; vstrobe2 := '0'; count_num := to_integer(unsigned(r.control_reg.counter)); node0 := mysigned_mul(coeffin, '0' & quantin); v.data_reg.inreg := node0(11 downto 0); case count_num is when 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => node1(0) := coeff_rom(4); node1(1) := coeff_rom(5); node1(2) := coeff_rom(6); node1(3) := coeff_rom(7); when 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => node1(0) := coeff_rom(8); node1(1) := coeff_rom(9); node1(2) := coeff_rom(10); node1(3) := coeff_rom(11); when 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => node1(0) := coeff_rom(12); node1(1) := coeff_rom(13); node1(2) := coeff_rom(14); node1(3) := coeff_rom(15); when 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => node1(0) := coeff_rom(16); node1(1) := coeff_rom(17); node1(2) := coeff_rom(18); node1(3) := coeff_rom(19); when 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => node1(0) := coeff_rom(20); node1(1) := coeff_rom(21); node1(2) := coeff_rom(22); node1(3) := coeff_rom(23); when 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => node1(0) := coeff_rom(24); node1(1) := coeff_rom(25); node1(2) := coeff_rom(26); node1(3) := coeff_rom(27); when 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 => node1(0) := coeff_rom(28); node1(1) := coeff_rom(29); node1(2) := coeff_rom(30); node1(3) := coeff_rom(31); when others => node1(0) := coeff_rom(0); node1(1) := coeff_rom(1); node1(2) := coeff_rom(2); node1(3) := coeff_rom(3); end case; for i in 0 to 3 loop node2(i) := mysigned_mul(node1(i), r.data_reg.inreg); node3(i) := round1(node2(i)); end loop; -- when 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | ..... | 65 -- when 2 4 6 8 10 12 14 16 18 20 22 64 if((count_num mod 2) = 0 and (count_num >= 2) and (count_num <= 64))then pol := '1'; else pol := '0'; end if; node3(4) := round2(node2(3), pol); node3(5) := round2(node2(2), pol); node3(6) := round2(node2(1), pol); node3(7) := round2(node2(0), pol); if((count_num = 1) or (count_num = 9) or (count_num = 17) or (count_num = 25) or (count_num = 33) or (count_num = 41) or (count_num = 49) or (count_num = 57)) then for i in 0 to 7 loop node4(i) := (others => '0'); end loop; else for i in 0 to 7 loop node4(i) := r.data_reg.accumulator(i); end loop; end if; for i in 0 to 7 loop node5(i) := mysigned_add(node3(i), node4(i)); v.data_reg.accumulator(i) := node5(i)(25 downto 0); node6(i) := round3(r.data_reg.accumulator(i)); end loop; if((count_num = 9) or (count_num = 17) or (count_num = 25) or (count_num = 33) or (count_num = 41) or (count_num = 49) or (count_num = 57) or (count_num = 65)) then for i in 0 to 7 loop v.data_reg.result_reg(i) := node6(i); end loop; else for i in 0 to 6 loop v.data_reg.result_reg(i) := r.data_reg.result_reg(i+1); end loop; v.data_reg.result_reg(7) := (others => '0'); end if; if((count_num >= 10) and (count_num <= 73))then vstrobe2 := '1'; end if; -- controller part if ((count_num = 0 and strobe1 = '1') or count_num /= 0) then v.control_reg.counter := std_logic_vector(to_unsigned(count_num + 1,7)); if(count_num = 73)then v.control_reg.counter := (others => '0'); end if; end if; vready1 := '0'; if(ready2 = '1' and count_num <= 63) then vready1 := '1'; end if; -- reset part if rst = '0' or startgen = '1' then v.data_reg.inreg := (others => '0'); for i in 0 to 7 loop v.data_reg.accumulator(i) := (others => '0'); v.data_reg.result_reg(i) := (others => '0'); end loop; v.control_reg.counter := (others => '0'); end if; -- signal outdata <= r.data_reg.result_reg(0); strobe2 <= vstrobe2; ready1 <= vready1; rin <= v; -- debug -- sig_node1_0 <= node1(0); -- sig_node2_0 <= node2(0); -- sig_node3_0 <= node3(0); -- sig_node4_0 <= node4(0); -- sig_node5_0 <= node5(0); -- sig_node6_0 <= node6(0); -- sig_node1_1 <= node1(1); -- sig_node2_1 <= node2(1); -- sig_node3_6 <= node3(6); -- sig_node4_6 <= node4(6); -- sig_node5_6 <= node5(6); -- sig_node6_6 <= node6(6); end process; -- registers reg : process(clk) begin if rising_edge(clk) then r <= rin; end if; end process; end rtl;