------------------------------------------------------------------------------ -- 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: yccmemcont -- File: yccmemcont.vhd -- Author: Kenichi Kurimoto -- Description: YCbCr memory + controller ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library grlib; --use grlib.amba.all; use grlib.stdlib.all; use grlib.devices.all; library techmap; use techmap.gencomp.all; entity yccmemcont is generic ( memtech : integer := DEFMEMTECH); port ( rst : in std_ulogic; clk : in std_ulogic; kready1 : out std_logic; kstrobe1 : in std_logic; kdata1 : in std_logic_vector(7 downto 0); kready2 : in std_logic; kstrobe2 : out std_logic; kdata2 : out std_logic_vector(23 downto 0); samp_fact : in std_logic; error : out std_logic; startgen : in std_logic ); end; -- samp_fact = 0 -> 4:1:1 -- samp_fact = 1 -> 4:2:2 architecture rtl of yccmemcont is type sstate_type is (mem0, mem1); type mstate_type is (empty, writing, full, reading, standby); type control_reg is record swf : sstate_type; swb : sstate_type; mem0state : mstate_type; mem1state : mstate_type; countf : std_logic_vector(8 downto 0); -- selectf : std_logic_vector(1 downto 0); countb : std_logic_vector(7 downto 0); stb2keep : std_logic; end record; signal r, rin : control_reg; signal y0address, y1address : std_logic_vector(7 downto 0); signal cb0address, cb1address, cr0address, cr1address : std_logic_vector(6 downto 0); signal y0datain, y1datain, cb0datain, cb1datain, cr0datain, cr1datain : std_logic_vector(7 downto 0); signal y0dataout, y1dataout, cb0dataout, cb1dataout, cr0dataout, cr1dataout : std_logic_vector(7 downto 0); signal y0enable, y1enable, cb0enable, cb1enable, cr0enable, cr1enable : std_logic; signal y0write, y1write, cb0write, cb1write, cr0write, cr1write : std_logic; begin yram0 : syncram generic map(tech => memtech, abits => 8, dbits => 8) port map( clk, y0address, y0datain, y0dataout, y0enable, y0write); yram1 : syncram generic map(tech => memtech, abits => 8, dbits => 8) port map( clk, y1address, y1datain, y1dataout, y1enable, y1write); cbram0 : syncram generic map(tech => memtech, abits => 7, dbits => 8) port map( clk, cb0address, cb0datain, cb0dataout, cb0enable, cb0write); cbram1 : syncram generic map(tech => memtech, abits => 7, dbits => 8) port map( clk, cb1address, cb1datain, cb1dataout, cb1enable, cb1write); crram0 : syncram generic map(tech => memtech, abits => 7, dbits => 8) port map( clk, cr0address, cr0datain, cr0dataout, cr0enable, cr0write); crram1 : syncram generic map(tech => memtech, abits => 7, dbits => 8) port map( clk, cr1address, cr1datain, cr1dataout, cr1enable, cr1write); comb : process (r, rst, kstrobe1, kdata1, kready2, samp_fact, y0dataout, y1dataout, cb0dataout, cb1dataout, cr0dataout, cr1dataout, startgen) variable v : control_reg; variable vkready1 : std_logic; variable verror : std_logic; variable vy0address, vy1address : std_logic_vector(7 downto 0); variable vcb0address, vcb1address, vcr0address, vcr1address : std_logic_vector(6 downto 0); variable vy0enable, vy1enable, vcb0enable, vcb1enable, vcr0enable, vcr1enable : std_logic; variable vy0write, vy1write, vcb0write, vcb1write, vcr0write, vcr1write : std_logic; variable fcountup, bcountup : std_logic; variable fcntint : integer; variable vstrobe : std_logic; variable outdata : std_logic_vector(23 downto 0); begin v := r; verror := '0'; vy0enable := '0'; vy1enable := '0'; vcb0enable := '0'; vcb1enable := '0'; vcr0enable := '0'; vcr1enable := '0'; vy0write := '0'; vy1write := '0'; vcb0write := '0'; vcb1write := '0'; vcr0write := '0'; vcr1write := '0'; fcountup := '0'; bcountup := '0'; vy0address := (others => '0'); vy1address := (others => '0'); vcb0address := (others => '0'); vcb1address := (others => '0'); vcr0address := (others => '0'); vcr1address := (others => '0'); -- forward part fcntint := to_integer(unsigned(r.countf)); if (kstrobe1 = '1') then if ((r.swf = mem0 and (r.mem0state = full or r.mem0state = reading))or (r.swf = mem1 and (r.mem1state = full or r.mem1state = reading)))then verror := '1'; end if; fcountup := '1'; if(r.swf = mem0) then if(samp_fact = '0') then if(fcntint < 256) then vy0enable := '1'; vy0write := '1'; vy0address := r.countf(7 downto 0); elsif(fcntint < 320) then vcb0enable := '1'; vcb0write := '1'; vcb0address := r.countf(6 downto 0); elsif(fcntint < 384) then vcr0enable := '1'; vcr0write := '1'; vcr0address := '0' & r.countf(5 downto 0); else verror := '1'; end if; else if(fcntint < 256) then vy0enable := '1'; vy0write := '1'; vy0address := r.countf(7 downto 0); elsif(fcntint < 384) then vcb0enable := '1'; vcb0write := '1'; vcb0address := r.countf(6 downto 0); elsif(fcntint < 512) then vcr0enable := '1'; vcr0write := '1'; vcr0address := r.countf(6 downto 0); else verror := '1'; end if; end if; else if(samp_fact = '0') then if(fcntint < 256) then vy1enable := '1'; vy1write := '1'; vy1address := r.countf(7 downto 0); elsif(fcntint < 320) then vcb1enable := '1'; vcb1write := '1'; vcb1address := r.countf(6 downto 0); elsif(fcntint < 384) then vcr1enable := '1'; vcr1write := '1'; vcr1address := '0' & r.countf(5 downto 0); else verror := '1'; end if; else if(fcntint < 256) then vy1enable := '1'; vy1write := '1'; vy1address := r.countf(7 downto 0); elsif(fcntint < 384) then vcb1enable := '1'; vcb1write := '1'; vcb1address := r.countf(6 downto 0); elsif(fcntint < 512) then vcr1enable := '1'; vcr1write := '1'; vcr1address := r.countf(6 downto 0); else verror := '1'; end if; end if; end if; end if; vkready1 := '0'; if (r.swf = mem0 and (r.mem0state = empty or r.mem0state = writing)) or (r.swf = mem1 and (r.mem1state = empty or r.mem1state = writing)) then vkready1 := '1'; end if; --backward part v.stb2keep := '0'; if (kready2 = '1') then if(r.swb = mem0 and (r.mem0state = full or r.mem0state = reading)) then bcountup := '1'; v.stb2keep := '1'; vy0enable := '1'; vcb0enable := '1'; vcr0enable := '1'; vy0address := r.countb(7) & r.countb(3) & r.countb(6 downto 4) & r.countb(2 downto 0); if(samp_fact = '0') then vcb0address := '0' & r.countb(7 downto 5) & r.countb(3 downto 1); vcr0address := '0' & r.countb(7 downto 5) & r.countb(3 downto 1); else vcb0address := r.countb(7 downto 1); vcr0address := r.countb(7 downto 1); end if; elsif(r.swb = mem1 and (r.mem1state = full or r.mem1state = reading))then bcountup := '1'; v.stb2keep := '1'; vy1enable := '1'; vcb1enable := '1'; vcr1enable := '1'; vy1address := r.countb(7) & r.countb(3) & r.countb(6 downto 4) & r.countb(2 downto 0); if(samp_fact = '0') then vcb1address := '0' & r.countb(7 downto 5) & r.countb(3 downto 1); vcr1address := '0' & r.countb(7 downto 5) & r.countb(3 downto 1); else vcb1address := r.countb(7 downto 1); vcr1address := r.countb(7 downto 1); end if; end if; end if; if(r.swb = mem0)then outdata := y0dataout & cb0dataout & cr0dataout; else outdata := y1dataout & cb1dataout & cr1dataout; end if; --state-machine --check empty case batting memory read write access case r.mem0state is when empty => if (r.swf = mem0 and fcountup = '1') then v.mem0state := writing; end if; when writing => if ((samp_fact = '0' and fcntint = 383 and fcountup = '1')or(samp_fact = '1' and fcntint = 511 and fcountup = '1')) then v.mem0state := full; v.swf := mem1; end if; when full => if (r.swb = mem0 and kready2 = '1') then v.mem0state := reading; end if; when reading => if (r.countb = "11111111") then v.mem0state := standby; end if; when standby => v.swb := mem1; v.mem0state := empty; when others => end case; case r.mem1state is when empty => if (r.swf = mem1 and fcountup = '1') then v.mem1state := writing; end if; when writing => if ((samp_fact = '0' and fcntint = 383 and fcountup = '1')or(samp_fact = '1' and fcntint = 511 and fcountup = '1')) then v.mem1state := full; v.swf := mem0; end if; when full => if (r.swb = mem1 and kready2 = '1') then v.mem1state := reading; end if; when reading => if (r.countb = "11111111") then v.mem1state := standby; end if; when standby => v.swb := mem0; v.mem1state := empty; when others => end case; -- counter if(fcountup = '1') then v.countf := r.countf + '1'; if (samp_fact = '0') and (fcntint = 383) then v.countf := "000000000"; elsif (samp_fact = '1') and (fcntint = 511) then v.countf := "000000000"; end if; end if; if (bcountup = '1') then v.countb := r.countb + '1'; end if; -- reset part if rst = '0' or startgen = '1' then v.swf := mem0; v.swb := mem0; v.mem0state := empty; v.mem1state := empty; v.countf := (others => '0'); v.countb := (others => '0'); v.stb2keep := '0'; end if; -- signal rin <= v; kready1 <= vkready1; kstrobe2 <= r.stb2keep; kdata2 <= outdata; error <= verror; y0address <= vy0address; y1address <= vy1address; cb0address <= vcb0address; cb1address <= vcb1address; cr0address <= vcr0address; cr1address <= vcr1address; y0enable <= vy0enable; y1enable <= vy1enable; cb0enable <= vcb0enable; cb1enable <= vcb1enable; cr0enable <= vcr0enable; cr1enable <= vcr1enable; y0write <= vy0write; y1write <= vy1write; cb0write <= vcb0write; cb1write <= vcb1write; cr0write <= vcr0write; cr1write <= vcr1write; end process; y0datain <= kdata1; y1datain <= kdata1; cb0datain <= kdata1; cb1datain <= kdata1; cr0datain <= kdata1; cr1datain <= kdata1; -- registers reg : process(clk) begin if rising_edge(clk) then r <= rin; end if; end process; end;