OpenCores
URL https://opencores.org/ocsvn/mkjpeg/mkjpeg/trunk

Subversion Repositories mkjpeg

[/] [mkjpeg/] [trunk/] [design/] [mdct/] [FDCT.vhd] - Rev 63

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- File Name :  FDCT.vhd
--
-- Project   : JPEG_ENC
--
-- Module    : FDCT
--
-- Content   : FDCT
--
-- Description : 2D Discrete Cosine Transform
--
-- Spec.     : 
--
-- Author    : Michal Krepa
--
-------------------------------------------------------------------------------
-- History :
-- 20090301: (MK): Initial Creation.
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
----------------------------------- LIBRARY/PACKAGE ---------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-- generic packages/libraries:
-------------------------------------------------------------------------------
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;
 
-------------------------------------------------------------------------------
-- user packages/libraries:
-------------------------------------------------------------------------------
library work;
  use work.JPEG_PKG.all;
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
----------------------------------- ENTITY ------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
entity FDCT is
  port 
  (
        CLK                : in  std_logic;
        RST                : in  std_logic;
        -- CTRL
        start_pb           : in  std_logic;
        ready_pb           : out std_logic;
        fdct_sm_settings   : in  T_SM_SETTINGS;
 
        -- BUF_FIFO
        bf_fifo_rd         : out std_logic;
        bf_fifo_q          : in  std_logic_vector(23 downto 0);
        bf_fifo_hf_full    : in  std_logic;
 
        -- ZIG ZAG
        zz_buf_sel         : in  std_logic;
        zz_rd_addr         : in  std_logic_vector(5 downto 0);
        zz_data            : out std_logic_vector(11 downto 0);
        zz_rden            : in  std_logic;
 
        -- HOST
        img_size_x         : in  std_logic_vector(15 downto 0);
        img_size_y         : in  std_logic_vector(15 downto 0);
        sof                : in  std_logic        
    );
end entity FDCT;
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
----------------------------------- ARCHITECTURE ------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
architecture RTL of FDCT is
 
  constant C_Y_1       : signed(14 downto 0) := to_signed(4899,  15);
  constant C_Y_2       : signed(14 downto 0) := to_signed(9617,  15);
  constant C_Y_3       : signed(14 downto 0) := to_signed(1868,  15);
  constant C_Cb_1      : signed(14 downto 0) := to_signed(-2764, 15);
  constant C_Cb_2      : signed(14 downto 0) := to_signed(-5428, 15);
  constant C_Cb_3      : signed(14 downto 0) := to_signed(8192,  15);
  constant C_Cr_1      : signed(14 downto 0) := to_signed(8192,  15);
  constant C_Cr_2      : signed(14 downto 0) := to_signed(-6860, 15);
  constant C_Cr_3      : signed(14 downto 0) := to_signed(-1332, 15);
 
 
  signal mdct_data_in      : std_logic_vector(7 downto 0);
  signal mdct_idval        : std_logic;
  signal mdct_odval        : std_logic;
  signal mdct_data_out     : std_logic_vector(11 downto 0);
  signal odv1              : std_logic;
  signal dcto1             : std_logic_vector(11 downto 0);
  signal x_pixel_cnt       : unsigned(15 downto 0);
  signal y_line_cnt        : unsigned(15 downto 0);
  signal rd_addr           : std_logic_vector(31 downto 0);
  signal input_rd_cnt      : unsigned(6 downto 0);
  signal rd_en             : std_logic;
  signal rd_en_d1          : std_logic;
  signal rdaddr            : unsigned(31 downto 0);
  signal bf_dval           : std_logic;
  signal bf_dval_m1        : std_logic;
  signal bf_dval_m2        : std_logic;
  signal bf_dval_m3        : std_logic;
  signal wr_cnt            : unsigned(5 downto 0);
  signal dbuf_data         : std_logic_vector(11 downto 0);
  signal dbuf_q            : std_logic_vector(11 downto 0);
  signal dbuf_we           : std_logic;
  signal dbuf_waddr        : std_logic_vector(6 downto 0);
  signal dbuf_raddr        : std_logic_vector(6 downto 0);
  signal xw_cnt            : unsigned(2 downto 0);
  signal yw_cnt            : unsigned(2 downto 0);
 
  signal dbuf_q_z1         : std_logic_vector(11 downto 0);
  constant C_SIMA_ASZ      : integer := 9;
  signal sim_rd_addr       : unsigned(C_SIMA_ASZ-1 downto 0);
  signal Y_reg_1           : signed(23 downto 0);
  signal Y_reg_2           : signed(23 downto 0);
  signal Y_reg_3           : signed(23 downto 0);
  signal Cb_reg_1          : signed(23 downto 0);
  signal Cb_reg_2          : signed(23 downto 0);
  signal Cb_reg_3          : signed(23 downto 0);
  signal Cr_reg_1          : signed(23 downto 0);
  signal Cr_reg_2          : signed(23 downto 0);
  signal Cr_reg_3          : signed(23 downto 0);
  signal Y_reg             : signed(23 downto 0);
  signal Cb_reg            : signed(23 downto 0);
  signal Cr_reg            : signed(23 downto 0);
  signal R_s               : signed(8 downto 0);
  signal G_s               : signed(8 downto 0);
  signal B_s               : signed(8 downto 0);
  signal Y_8bit            : unsigned(7 downto 0);
  signal Cb_8bit           : unsigned(7 downto 0);
  signal Cr_8bit           : unsigned(7 downto 0);
  signal cmp_idx           : unsigned(2 downto 0);
  signal cur_cmp_idx       : unsigned(2 downto 0);
  signal cur_cmp_idx_d1    : unsigned(2 downto 0);
  signal cur_cmp_idx_d2    : unsigned(2 downto 0);
  signal cur_cmp_idx_d3    : unsigned(2 downto 0);
  signal cur_cmp_idx_d4    : unsigned(2 downto 0);
  signal cur_cmp_idx_d5    : unsigned(2 downto 0);
  signal cur_cmp_idx_d6    : unsigned(2 downto 0);
  signal cur_cmp_idx_d7    : unsigned(2 downto 0);
  signal cur_cmp_idx_d8    : unsigned(2 downto 0);
  signal cur_cmp_idx_d9    : unsigned(2 downto 0);
  signal fifo1_rd          : std_logic;
  signal fifo1_wr          : std_logic;
  signal fifo1_q           : std_logic_vector(11 downto 0);
  signal fifo1_full        : std_logic;
  signal fifo1_empty       : std_logic;
  signal fifo1_count       : std_logic_vector(9 downto 0);
  signal fifo1_rd_cnt      : unsigned(5 downto 0);
  signal fifo1_q_dval      : std_logic;
  signal fifo_data_in      : std_logic_vector(11 downto 0);
  signal fifo_rd_arm       : std_logic;
 
  signal eoi_fdct          : std_logic;
  signal bf_fifo_rd_s      : std_logic;
  signal start_int         : std_logic;
  signal start_int_d       : std_logic_vector(4 downto 0);
 
  signal fram1_data        : std_logic_vector(23 downto 0);
  signal fram1_q           : std_logic_vector(23 downto 0);
  signal fram1_we          : std_logic;
  signal fram1_waddr       : std_logic_vector(6 downto 0);
  signal fram1_raddr       : std_logic_vector(6 downto 0);
  signal fram1_rd_d        : std_logic_vector(8 downto 0);
  signal fram1_rd          : std_logic;  
  signal rd_started        : std_logic;
  signal writing_en        : std_logic;
  signal fram1_q_vld       : std_logic;
 
  signal fram1_line_cnt    : unsigned(2 downto 0);
  signal fram1_pix_cnt     : unsigned(2 downto 0);
 
 
-------------------------------------------------------------------------------
-- Architecture: begin
-------------------------------------------------------------------------------
begin
 
  zz_data      <= dbuf_q;
 
  bf_fifo_rd   <= bf_fifo_rd_s;
 
  -------------------------------------------------------------------
  -- FRAM1
  -------------------------------------------------------------------
  U_FRAM1 : entity work.RAMZ
  generic map
  ( 
      RAMADDR_W     => 7,
      RAMDATA_W     => 24
  )
  port map
  (      
        d           => fram1_data,
        waddr       => fram1_waddr,
        raddr       => fram1_raddr,
        we          => fram1_we,
        clk         => CLK,
 
        q           => fram1_q
  );
 
  fram1_we   <= bf_dval;
  fram1_data <= bf_fifo_q;
 
  fram1_q_vld <= fram1_rd_d(5);
 
  -------------------------------------------------------------------
  -- FRAM1 process
  -------------------------------------------------------------------
  p_fram1_acc : process(CLK, RST)
  begin
    if RST = '1' then
      fram1_waddr <= (others => '0');
    elsif CLK'event and CLK = '1' then
      if fram1_we = '1' then
        fram1_waddr <= std_logic_vector(unsigned(fram1_waddr) + 1);
      end if;
    end if;
  end process;
 
  -------------------------------------------------------------------
  -- IRAM read process 
  -------------------------------------------------------------------
  p_counter1 : process(CLK, RST)
  begin
    if RST = '1' then
      rd_en           <= '0';
      rd_en_d1        <= '0';
      x_pixel_cnt     <= (others => '0');
      y_line_cnt     <= (others => '0');
      input_rd_cnt    <= (others => '0');
      cmp_idx         <= (others => '0');
      cur_cmp_idx     <= (others => '0');
      cur_cmp_idx_d1  <= (others => '0');
      cur_cmp_idx_d2  <= (others => '0');
      cur_cmp_idx_d3  <= (others => '0');
      cur_cmp_idx_d4  <= (others => '0');
      cur_cmp_idx_d5  <= (others => '0');
      cur_cmp_idx_d6  <= (others => '0');
      cur_cmp_idx_d7  <= (others => '0');
      cur_cmp_idx_d8  <= (others => '0');
      cur_cmp_idx_d9  <= (others => '0');
      eoi_fdct        <= '0';
      start_int       <= '0';
      bf_fifo_rd_s    <= '0';
      bf_dval         <= '0';
      bf_dval_m1      <= '0';
      bf_dval_m2      <= '0';
      fram1_rd        <= '0';
      fram1_rd_d      <= (others => '0');
      start_int_d     <= (others => '0');
      fram1_raddr     <= (others => '0');
      fram1_line_cnt  <= (others => '0');
      fram1_pix_cnt   <= (others => '0');
    elsif CLK'event and CLK = '1' then
      rd_en_d1 <= rd_en;
      cur_cmp_idx_d1 <= cur_cmp_idx;
      cur_cmp_idx_d2 <= cur_cmp_idx_d1;
      cur_cmp_idx_d3 <= cur_cmp_idx_d2;
      cur_cmp_idx_d4 <= cur_cmp_idx_d3;
      cur_cmp_idx_d5 <= cur_cmp_idx_d4;
      cur_cmp_idx_d6 <= cur_cmp_idx_d5;
      cur_cmp_idx_d7 <= cur_cmp_idx_d6;
      cur_cmp_idx_d8 <= cur_cmp_idx_d7;
      cur_cmp_idx_d9 <= cur_cmp_idx_d8;
      start_int      <= '0';
 
      bf_dval_m3     <= bf_fifo_rd_s;
      bf_dval_m2     <= bf_dval_m3;
      bf_dval_m1     <= bf_dval_m2;
      bf_dval        <= bf_dval_m1;
 
      fram1_rd_d     <= fram1_rd_d(fram1_rd_d'length-2 downto 0) & fram1_rd;
      start_int_d    <= start_int_d(start_int_d'length-2 downto 0) & start_int;
 
      -- SOF or internal self-start
      if (sof = '1' or start_int = '1') then
        input_rd_cnt <= (others => '0');
        -- enable BUF_FIFO/FRAM1 reading
        rd_started      <= '1'; 
 
        -- component index
        if cmp_idx = 4-1 then
          cmp_idx <= (others => '0');
          -- horizontal block counter
          if x_pixel_cnt = unsigned(img_size_x)-16 then
            x_pixel_cnt <= (others => '0');
            -- vertical block counter
            if y_line_cnt = unsigned(img_size_y)-8 then
              y_line_cnt <= (others => '0');
              -- set end of image flag
              eoi_fdct <= '1';    
            else
              y_line_cnt <= y_line_cnt + 8;
            end if;
          else
            x_pixel_cnt <= x_pixel_cnt + 16;
          end if;
        else
          cmp_idx <=cmp_idx + 1;
        end if;
 
        cur_cmp_idx     <= cmp_idx;
 
      end if;
 
      -- wait until FIFO becomes half full but only for component 0
      -- as we read buf FIFO only during component 0
      if rd_started = '1' and (bf_fifo_hf_full = '1' or cur_cmp_idx > 1) then
        rd_en      <= '1';
        rd_started <= '0';
      end if;
 
      bf_fifo_rd_s   <= '0';
      fram1_rd       <= '0';
      -- stall reading from input FIFO and writing to output FIFO 
      -- when output FIFO is almost full
      if rd_en = '1' and unsigned(fifo1_count) < 512-64 and 
         (bf_fifo_hf_full = '1' or cur_cmp_idx > 1) then
        -- read request goes to BUF_FIFO only for component 0. 
        if cur_cmp_idx < 2 then 
          bf_fifo_rd_s <= '1';
        end if;
 
        -- count number of samples read from input in one run
        if input_rd_cnt = 64-1 then
          rd_en        <= '0';
          -- internal restart
          start_int    <= '1' and not eoi_fdct;
          eoi_fdct     <= '0';
        else
          input_rd_cnt <= input_rd_cnt + 1;
        end if;
        -- FRAM read enable
        fram1_rd <= '1';
      end if;
 
      -- increment FRAM1 read address according to subsampling
      -- idea is to extract 8x8 from 16x8 block
      -- there are two luminance blocks left and right
      -- there is 2:1 subsampled Cb block
      -- there is 2:1 subsampled Cr block
      -- subsampling done as simple decimation by 2 wo/ averaging
      if sof = '1' then
        fram1_raddr     <= (others => '0');
        fram1_line_cnt  <= (others => '0');
        fram1_pix_cnt   <= (others => '0');
      elsif start_int_d(4) = '1' then
        fram1_line_cnt  <= (others => '0');
        fram1_pix_cnt   <= (others => '0');
        case cur_cmp_idx_d4 is
          -- Y1, Cr, Cb
          when "000" | "010" | "011" => 
            fram1_raddr <= (others => '0');
          -- Y2
          when "001" => 
            fram1_raddr <= std_logic_vector(to_unsigned(64, fram1_raddr'length));
          when others =>
            null;
        end case;
      elsif fram1_rd_d(4) = '1' then 
 
        if fram1_pix_cnt = 8-1 then
          fram1_pix_cnt <= (others => '0');
          if fram1_line_cnt = 8-1 then
            fram1_line_cnt <= (others => '0');
          else
            fram1_line_cnt <= fram1_line_cnt + 1;
          end if;
        else
          fram1_pix_cnt <= fram1_pix_cnt + 1;
        end if;
 
        case cur_cmp_idx_d6 is
          when "000" | "001" => 
            fram1_raddr <= std_logic_vector(unsigned(fram1_raddr) + 1);
          when "010" | "011" => 
            if fram1_pix_cnt = 4-1 then
              fram1_raddr <= std_logic_vector('1' & fram1_line_cnt & "000");
            elsif fram1_pix_cnt = 8-1 then
              if fram1_line_cnt = 8-1 then
                fram1_raddr <= '0' & "000" & "000";
              else
                fram1_raddr <= std_logic_vector('0' & (fram1_line_cnt+1) & "000");
              end if;
            else
              fram1_raddr <= std_logic_vector(unsigned(fram1_raddr) + 2);
            end if;
          when others =>
            null;
        end case;
 
      end if;
 
    end if;
  end process;
 
  -------------------------------------------------------------------
  -- FDCT with input level shift
  -------------------------------------------------------------------
  U_MDCT : entity work.MDCT
	port map
  (	  
		clk          => CLK,
		rst          => RST,
    dcti         => mdct_data_in,
    idv          => mdct_idval,
    odv          => mdct_odval,
    dcto         => mdct_data_out,
    odv1         => odv1,
    dcto1        => dcto1
	); 
 
  mdct_idval   <= fram1_rd_d(8);
 
  R_s <= signed('0' & fram1_q(7 downto 0));
  G_s <= signed('0' & fram1_q(15 downto 8));
  B_s <= signed('0' & fram1_q(23 downto 16));
 
  -------------------------------------------------------------------
  -- Mux1
  -------------------------------------------------------------------
  p_mux1 : process(CLK, RST)
  begin
    if RST = '1' then
      mdct_data_in <= (others => '0');
    elsif CLK'event and CLK = '1' then
      case cur_cmp_idx_d9 is
        when "000" | "001" => 
          mdct_data_in <= std_logic_vector(Y_8bit);
        when "010" => 
          mdct_data_in <= std_logic_vector(Cb_8bit);
        when "011" => 
          mdct_data_in <= std_logic_vector(Cr_8bit);
        when others =>
          null;
      end case;
    end if;
  end process;
 
 
  -------------------------------------------------------------------
  -- FIFO1
  -------------------------------------------------------------------
  U_FIFO1 : entity work.FIFO   
  generic map
  (
        DATA_WIDTH        => 12,
        ADDR_WIDTH        => 9
  )
  port map 
  (        
        rst               => RST,
        clk               => CLK,
        rinc              => fifo1_rd,
        winc              => fifo1_wr,
        datai             => fifo_data_in,
 
        datao             => fifo1_q,
        fullo             => fifo1_full,
        emptyo            => fifo1_empty,
        count             => fifo1_count
  );
 
  fifo1_wr     <= mdct_odval;
  fifo_data_in <= mdct_data_out;
 
 
 
  -------------------------------------------------------------------
  -- FIFO1 rd controller
  -------------------------------------------------------------------
  p_fifo_rd_ctrl : process(CLK, RST)
  begin
    if RST = '1' then
      fifo1_rd     <= '0';
      fifo_rd_arm  <= '0';
      fifo1_rd_cnt <= (others => '0');
      fifo1_q_dval <= '0';
    elsif CLK'event and CLK = '1' then
      fifo1_rd     <= '0';
 
      fifo1_q_dval <= fifo1_rd;
 
      if start_pb = '1' then
        fifo_rd_arm  <= '1';
        fifo1_rd_cnt <= (others => '0');
      end if;
 
      if fifo_rd_arm = '1' then
 
        if fifo1_rd_cnt = 64-1 then
          fifo_rd_arm  <= '0';
          fifo1_rd     <= '1';
        elsif fifo1_empty = '0' then
          fifo1_rd     <= '1';
          fifo1_rd_cnt <= fifo1_rd_cnt + 1;
        end if;
 
      end if;
    end if;
  end process;
 
  -------------------------------------------------------------------
  -- write counter
  -------------------------------------------------------------------
  p_wr_cnt : process(CLK, RST)
  begin
    if RST = '1' then
      wr_cnt   <= (others => '0');
      ready_pb <= '0';
      xw_cnt   <= (others => '0');
      yw_cnt   <= (others => '0');
      writing_en <= '0';
    elsif CLK'event and CLK = '1' then
      ready_pb <= '0';
 
      if start_pb = '1' then
        wr_cnt <= (others => '0');
        xw_cnt <= (others => '0');
        yw_cnt <= (others => '0');
        writing_en  <= '1';
      end if;
 
      if writing_en = '1' then
        if fifo1_q_dval = '1' then
          if wr_cnt = 64-1 then
            wr_cnt <= (others => '0');
            ready_pb <= '1';
            writing_en <= '0';
          else
            wr_cnt <= wr_cnt + 1;
          end if;
 
          if yw_cnt = 8-1 then
            yw_cnt <= (others => '0');
            xw_cnt <= xw_cnt+1;
          else
            yw_cnt <= yw_cnt+1;
          end if;
        end if;
      end if;
    end if;
  end process;
 
  -------------------------------------------------------------------
  -- RGB to YCbCr conversion
  -------------------------------------------------------------------
  p_rgb2ycbcr : process(CLK, RST)
  begin
    if RST = '1' then
      Y_Reg_1  <= (others => '0');
      Y_Reg_2  <= (others => '0');
      Y_Reg_3  <= (others => '0');
      Cb_Reg_1 <= (others => '0');
      Cb_Reg_2 <= (others => '0');
      Cb_Reg_3 <= (others => '0');
      Cr_Reg_1 <= (others => '0');
      Cr_Reg_2 <= (others => '0');
      Cr_Reg_3 <= (others => '0');
      Y_Reg    <= (others => '0');
      Cb_Reg   <= (others => '0');
      Cr_Reg   <= (others => '0');
    elsif CLK'event and CLK = '1' then
      -- RGB input
      if C_YUV_INPUT = '0' then
        Y_Reg_1  <= R_s*C_Y_1;
        Y_Reg_2  <= G_s*C_Y_2;
        Y_Reg_3  <= B_s*C_Y_3;
 
        Cb_Reg_1 <= R_s*C_Cb_1;
        Cb_Reg_2 <= G_s*C_Cb_2;
        Cb_Reg_3 <= B_s*C_Cb_3;
 
        Cr_Reg_1 <= R_s*C_Cr_1;
        Cr_Reg_2 <= G_s*C_Cr_2;
        Cr_Reg_3 <= B_s*C_Cr_3;
 
        Y_Reg  <= Y_Reg_1 + Y_Reg_2 + Y_Reg_3;
        Cb_Reg <= Cb_Reg_1 + Cb_Reg_2 + Cb_Reg_3 + to_signed(128*16384,Cb_Reg'length);
        Cr_Reg <= Cr_Reg_1 + Cr_Reg_2 + Cr_Reg_3 + to_signed(128*16384,Cr_Reg'length);
      -- YCbCr input
      -- R-G-B misused as Y-Cb-Cr
      else
        Y_Reg_1  <= '0' & R_s & "00000000000000";
        Cb_Reg_1 <= '0' & G_s & "00000000000000";
        Cr_Reg_1 <= '0' & B_s & "00000000000000";
 
        Y_Reg  <= Y_Reg_1; 
        Cb_Reg <= Cb_Reg_1;
        Cr_Reg <= Cr_Reg_1;
      end if;
    end if;
  end process;
 
  Y_8bit  <= unsigned(Y_Reg(21 downto 14));
  Cb_8bit <= unsigned(Cb_Reg(21 downto 14));
  Cr_8bit <= unsigned(Cr_Reg(21 downto 14));
 
 
  -------------------------------------------------------------------
  -- DBUF
  -------------------------------------------------------------------
  U_RAMZ : entity work.RAMZ
  generic map
  ( 
      RAMADDR_W     => 7,
      RAMDATA_W     => 12
  )
  port map
  (      
        d           => dbuf_data,
        waddr       => dbuf_waddr,
        raddr       => dbuf_raddr,
        we          => dbuf_we,
        clk         => CLK,
 
        q           => dbuf_q
  );
 
  dbuf_data  <= fifo1_q;
  dbuf_we    <= fifo1_q_dval;
  dbuf_waddr <= (not zz_buf_sel) & std_logic_vector(yw_cnt & xw_cnt);
  dbuf_raddr <= zz_buf_sel & zz_rd_addr;
 
end architecture RTL;
-------------------------------------------------------------------------------
-- Architecture: end
-------------------------------------------------------------------------------

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.