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

Subversion Repositories dirac

[/] [dirac/] [trunk/] [src/] [testbench/] [ArithmeticCoderTestbench.vhd] - Rev 12

Compare with Previous | Blame | View Log

-- ***** BEGIN LICENSE BLOCK *****
-- 
-- $Id: ArithmeticCoderTestbench.vhd,v 1.5 2006-09-06 18:41:06 petebleackley Exp $ $Name: not supported by cvs2svn $
-- *
-- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-- *
-- * The contents of this file are subject to the Mozilla Public License
-- * Version 1.1 (the "License"); you may not use this file except in compliance
-- * with the License. You may obtain a copy of the License at
-- * http://www.mozilla.org/MPL/
-- *
-- * Software distributed under the License is distributed on an "AS IS" basis,
-- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
-- * the specific language governing rights and limitations under the License.
-- *
-- * The Original Code is BBC Research and Development code.
-- *
-- * The Initial Developer of the Original Code is the British Broadcasting
-- * Corporation.
-- * Portions created by the Initial Developer are Copyright (C) 2004.
-- * All Rights Reserved.
-- *
-- * Contributor(s): Peter Bleackley (Original author)
-- *
-- * Alternatively, the contents of this file may be used under the terms of
-- * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
-- * Public License Version 2.1 (the "LGPL"), in which case the provisions of
-- * the GPL or the LGPL are applicable instead of those above. If you wish to
-- * allow use of your version of this file only under the terms of the either
-- * the GPL or LGPL and not to allow others to use your version of this file
-- * under the MPL, indicate your decision by deleting the provisions above
-- * and replace them with the notice and other provisions required by the GPL
-- * or LGPL. If you do not delete the provisions above, a recipient may use
-- * your version of this file under the terms of any one of the MPL, the GPL
-- * or the LGPL.
-- * ***** END LICENSE BLOCK ***** */
 
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
use IEEE.std_logic_textio.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use STD.textio.all;
 
ENTITY arithmeticcoder_ArithmeticCoderTestbench_vhd_tb IS
END arithmeticcoder_ArithmeticCoderTestbench_vhd_tb;
 
ARCHITECTURE behavior OF arithmeticcoder_ArithmeticCoderTestbench_vhd_tb IS 
 
	COMPONENT arithmeticcoder
	PORT(
		ENABLE : IN std_logic;
		DATA_IN : IN std_logic;
		CONTEXT_ENABLE : in std_logic;
		CONTEXT_IN : in std_logic_vector (5 downto 0);
		HALVECOUNTS_IN : in std_logic;
		FLUSH : in std_logic;
		RESET : IN std_logic;
		CLOCK : IN std_logic;          
		SENDING : OUT std_logic;
		DATA_OUT : OUT std_logic;
		FLUSH_COMPLETE : out std_logic
		);
	END COMPONENT;
	component EXP_GOLOMB_COUNTER
	port( DATA_IN : in std_logic_vector (31 downto 0);
		TEST : in std_logic;
		RESET : in std_logic;
		CLOCK : in std_logic;
		COUNTING : out std_logic;
		DATA_OUT : out std_logic);
	end component EXP_GOLOMB_COUNTER;
 
	SIGNAL ENABLE :  std_logic;
	SIGNAL DATA_IN :  std_logic := '0';
	SIGNAL RESET :  std_logic := '1';
	SIGNAL CLOCK :  std_logic := '0';
	signal FLUSH : std_logic := '0';
	signal HALVECOUNTS : std_logic := '0';
	SIGNAL SENDING :  std_logic;
	SIGNAL DATA_OUT :  std_logic;
	signal TRANSMIT :	std_logic;
	signal DATA_TRANSFER :	std_logic;
	signal FLUSH_COMPLETE : std_logic;
	signal DATA_IN2 :	std_logic_vector (0 downto 0);
	signal BUFFERED2 : std_logic_vector (0 downto 0);
	signal FIFO_EMPTY : std_logic;
	signal BUFFERED : std_logic;
	constant PERIOD : time := 16 ns;
	signal CONTEXT_ENABLE : std_logic;
	signal DECODER_CONTEXT_ENABLE : std_logic;
	signal NUMBITS : std_logic_vector (31 downto 0) := "00000000000000000000000000000000";
	signal NEXTNUMBITS : std_logic_vector (31 downto 0);
	signal NUMBYTES : std_logic_vector (28 downto 0);
	signal CONTEXT_IN : std_logic_vector (5 downto 0) := "000000";
	signal DECODER_CONTEXT : std_logic_vector (5 downto 0) := "000000";
	signal BYTECOUNT : std_logic_vector (31 downto 0);
	signal EXP_GOLOMB_READY : std_logic;
	signal EXP_GOLOMB_DATA : std_logic;
	signal BYTE_INSERT : std_logic := '0';
	signal COMPVAL : character;
	signal SUPPRESS_READ : std_logic := '0';
	type ENCODER_STATUS is (INIT, INIT2, HEADERS, CODING, FLUSHING, EXP_GOLOMB, WRITE_DATA, FINISHED);
	signal STATE : ENCODER_STATUS := INIT;
	type RAM is array (65535 downto 0) of integer;
	signal STORAGE : RAM;
	type CHARFILE is file of character;
	file raw_data : CHARFILE open read_mode is "test1.dr0";
	file contexts : CHARFILE open read_mode is "test1.ctx";
	file coded_stream : CHARFILE open write_mode is "test1.drc";
	file comparison_data : CHARFILE open read_mode is "test1.dr1";
	type INTARRAY is array (7 downto 0) of integer;
	function CONTEXT_INTERPRET(CONTEXT : integer) return std_logic_vector is
	variable VALUE : std_logic_vector(5 downto 0);
	begin
		if CONTEXT >= 128 then
			VALUE(5) := '1';
		else
			VALUE(5) := '0';
		end if;
		if (CONTEXT mod 128) >= 64 then
			VALUE(4) := '1';
		else
			VALUE(4) := '0';
		end if;
		if (CONTEXT mod 64) >= 32 then
			VALUE(3) := '1';
		else
			VALUE(3) := '0';
		end if;
		if (CONTEXT mod 32) >= 16 then
			VALUE(2) := '1';
		else
			VALUE(2) := '0';
		end if;
		if (CONTEXT mod 16) >= 8 then
			VALUE(1) := '1';
		else
			VALUE(1) := '0';
		end if;
		if (CONTEXT mod 8) >= 4 then
			VALUE(0) := '1';
		else
			VALUE(0) := '0';
		end if;
		return VALUE;
	end function CONTEXT_INTERPRET;
BEGIN
 
	uut: arithmeticcoder 
	PORT MAP(
		ENABLE => ENABLE,
		DATA_IN => DATA_IN,
		CONTEXT_ENABLE => CONTEXT_ENABLE,
		CONTEXT_IN => CONTEXT_IN,
		HALVECOUNTS_IN => HALVECOUNTS,
		FLUSH => FLUSH,
		RESET => RESET,
		CLOCK => CLOCK,
		SENDING => TRANSMIT,
		DATA_OUT => DATA_TRANSFER,
		FLUSH_COMPLETE => FLUSH_COMPLETE
	);
 
	EGC: EXP_GOLOMB_COUNTER
	port map(
		DATA_IN => BYTECOUNT,
		TEST => FLUSH_COMPLETE,
		RESET => RESET,
		CLOCK => CLOCK,
		COUNTING => EXP_GOLOMB_READY,
		DATA_OUT => EXP_GOLOMB_DATA);
 
 
 
	CLOCK <= not CLOCK after PERIOD/2;
 
 --*** Test Bench - User Defined Section ***
   tb : PROCESS (CLOCK)
	variable POSITION : integer;
	variable EGPOSITION : integer;
	variable PLACE : integer;
	variable READVAL : character;
	variable WRITEVAL : integer;
	variable CONTEXT : integer;
	variable DATA : integer;
	variable COMPDATA : integer;
	variable THRESHOLD : integer;
	variable INDEX : integer range 0 to 536870911;
	variable READ_DATA : INTARRAY := (0,0,0,0,0,0,0,0); 
	variable DUMMY : character;
 
   BEGIN
		if CLOCK'event and CLOCK = '1' then
			if STATE = INIT then
				if READ_DATA = ( 16#4B#, 16#57#, 16#2D#, 16#44#, 16#49#, 16#52#, 16#41#, 16#43#) then
					STATE <= INIT2;
					RESET <= '0';
				else
					READ_DATA(7 downto 1) := READ_DATA(6 downto 0);
					read(raw_data,READVAL);
					READ_DATA(0) := character'pos(READVAL);
				end if;
			elsif STATE = INIT2 then
				if READ_DATA (7 downto 3) = ( 16#44#, 16#49#, 16#52#, 16#41#, 16#43#) then
					STATE <= HEADERS;
					WRITEVAL := 0;
					EGPOSITION := 128;
				else
					WRITEVAL := READ_DATA(7);
					write(coded_stream,character'val(WRITEVAL));
					READ_DATA(7 downto 1) := READ_DATA (6 downto 0);
				end if;
			elsif STATE = HEADERS then
				if READ_DATA (7 downto 3) = ( 16#42#, 16#42#, 16#43#, 16#44#, 16#AC# ) then
					STATE <= CODING;
					PLACE := 0;
					POSITION := 0;
					RESET <= '1';
					ENABLE <= '0';
					DATA_IN <= '0';
					CONTEXT_ENABLE <= '0';
					CONTEXT_IN <= "000000";
					HALVECOUNTS <= '0';
					FLUSH <= '0';
					if SUPPRESS_READ = '0' then
						read(comparison_data,DUMMY);
						COMPVAL <= DUMMY;
					end if;
				elsif READ_DATA (7 downto 3) = (16#42#, 16#42#, 16#43#, 16#44#, 16#D0# ) then
					STATE <= FINISHED;
				else
					if EGPOSITION = 128 then
						read(raw_data,READVAL);
						READ_DATA(2) := character'pos(READVAL);
					end if;
					if READ_DATA(7) > 127 then
						WRITEVAL := WRITEVAL + EGPOSITION;
					end if;
 
					for I in 7 downto 2 loop
						if READ_DATA(I) > 127 then
							READ_DATA(I) := (READ_DATA(I) -128) * 2;
						else
							READ_DATA(I) := READ_DATA(I) * 2;
						end if;
						if READ_DATA(I-1) > 127 then 
							READ_DATA(I) := READ_DATA(I) + 1;
						end if;
					end loop;
					if EGPOSITION = 1 then
						write(coded_stream,character'val(WRITEVAL));
						EGPOSITION := 128;
						WRITEVAL := 0;
					else
						EGPOSITION := EGPOSITION / 2;
					end if;
				end if;
			elsif STATE = CODING then
				if PLACE = 0 then
					RESET <= '0';
				end if;
				if PLACE mod 5 = 0 then
					read(contexts,READVAL);
					CONTEXT := character'pos(READVAL);
					CONTEXT_ENABLE <= '1';
					if CONTEXT mod 2 = 1 then
						CONTEXT_IN <= "000000";
						HALVECOUNTS <= '0';
						STATE <= FLUSHING;
						FLUSH <= '1';
					else 
						CONTEXT_IN <= CONTEXT_INTERPRET(CONTEXT); 
						if (CONTEXT mod 4) > 1 then
							HALVECOUNTS <= '1';
						else
							HALVECOUNTS <= '0';
						end if;
						FLUSH <= '0';
					end if;
				elsif PLACE mod 5 = 3 then
					if POSITION = 0 then
						POSITION := 128;
						READ(raw_data,READVAL);
						DATA := character'pos(READVAL);
					end if;
					if (DATA / POSITION) mod 2 = 1 then
						DATA_IN <= '1';
					else
						DATA_IN <= '0';
					end if;
					ENABLE <= '1';
					POSITION := POSITION / 2;
				else
					CONTEXT_ENABLE <= '0';
					ENABLE <= '0';
				end if;
				PLACE := PLACE + 1;
			elsif STATE = FLUSHING then
				if FLUSH = '1' then
					FLUSH <= '0';
					CONTEXT_ENABLE <= '0';
				end if;
				if FLUSH_COMPLETE = '1' then
					STATE <= EXP_GOLOMB;
					PLACE := 7;
					POSITION := 128;
					READ_DATA(7) := 0;
				end if;
			elsif STATE = EXP_GOLOMB then
				if EXP_GOLOMB_READY = '0' then
					STATE <= WRITE_DATA;
					INDEX := 0;
					if EGPOSITION /= 128 then
						write(coded_stream,character'val(WRITEVAL));
					end if;
					PLACE := 7;
				else
					if EXP_GOLOMB_DATA = '1' then
						WRITEVAL := WRITEVAL + EGPOSITION;
					end if;
					if EGPOSITION = 1 then
						EGPOSITION := 128;
						write(coded_stream,character'val(WRITEVAL));
						WRITEVAL := 0;
					else
						EGPOSITION := EGPOSITION / 2;
					end if;
				end if;
 
			elsif STATE  = WRITE_DATA then
				if INDEX = (conv_integer(NUMBYTES)-1) then
					STATE <= HEADERS;
					WRITEVAL := 0;
				else
					if PLACE < 3 then
						WRITEVAL := READ_DATA(7);
						write(coded_stream,character'val(WRITEVAL));
						READ_DATA (7 downto 3) := READ_DATA (6 downto 2);
						READ_DATA (2) := STORAGE(INDEX);
					else
						READ_DATA (PLACE) := STORAGE(INDEX);
						PLACE := PLACE - 1;
					end if;
					INDEX := INDEX + 1;
				end if;
			else --STATE = FINISHED
				if READ_DATA (7 downto 3) = (0, 0, 0, 0, 0) then
					report ("finished") severity failure;
				else
					WRITEVAL := READ_DATA(7);
					write(coded_stream,character'val(WRITEVAL));
					READ_DATA (7 downto 3) := READ_DATA (6 downto 3) & 0;
				end if;
			end if;
		end if;
 
 
 
   END PROCESS;
 
 
COUNT_BITS: process (CLOCK)
	begin
	if (CLOCK'event and CLOCK='1') then
		if RESET = '1' then
			NUMBITS <= "00000000000000000000000000000000";
		else
			if TRANSMIT = '1' then
				NUMBITS <= NUMBITS + "00000000000000000000000000000001";
			end if;
			if BYTE_INSERT = '1' then
				NUMBITS <= NUMBITS + "00000000000000000000000000001000";
			end if;
		end if;
	end if;
	end process;
 
NEXTNUMBITS <= NUMBITS + "00000000000000000000000000000111";
 
NUMBYTES <= NEXTNUMBITS (31 downto 3);
 
	BYTECOUNT <=  "0000000000000000" & NUMBYTES(15 downto 0);
 
 
WRITE_MEMORY: process(CLOCK)
	variable INCREMENT: integer;
	variable DATA : integer;
	variable COMPARISON : character;
	variable COMPDATA : integer;
	variable COMPDATA2 : integer;
begin
	if CLOCK'event and CLOCK = '1' then
		if RESET = '1' then
			INCREMENT := 128;
			BYTE_INSERT <= '0';
			if SUPPRESS_READ = '0' then
				COMPDATA := character'pos(COMPVAL);
			end if;
			COMPDATA2 := 0;
			DATA := 0;
		elsif TRANSMIT = '1' then
			if (COMPDATA rem (INCREMENT*2)) >= INCREMENT then
				COMPDATA2 := COMPDATA2 + INCREMENT;
			end if;
			if DATA_TRANSFER = '1' then
				DATA := DATA + INCREMENT;
			end if;
			assert COMPDATA2 = DATA report "ENCODER HAS DIVERGED" severity failure;
			if INCREMENT = 1 then
				STORAGE(conv_integer(NUMBYTES)-1) <= DATA;
				DATA := 0;
				INCREMENT := 128;
				read(comparison_data,COMPARISON);
				COMPDATA := character'pos(COMPARISON);
				COMPDATA2 := 0;
				if NUMBYTES >= "00000000000000000000000000100" then
					if STORAGE((conv_integer(NUMBYTES) -4) downto (conv_integer(NUMBYTES) - 1)) = (16#42#, 16#42#, 16#43#, 16#44#) then
						STORAGE(conv_integer(NUMBYTES)) <= 16#FF#;
						BYTE_INSERT <= '1';
					end if;
				end if;
			else
				INCREMENT := INCREMENT/2;
			end if;
		elsif FLUSH_COMPLETE = '1' then
			if INCREMENT /= 128 then 
				STORAGE(conv_integer(NUMBYTES)) <= DATA;
				if NUMBYTES >= "00000000000000000000000000100" then
					if STORAGE((conv_integer(NUMBYTES) -3) downto (conv_integer(NUMBYTES))) = (16#42#, 16#42#, 16#43#, 16#44#) then
						STORAGE(conv_integer(NUMBYTES)+1) <= 16#FF#;
						BYTE_INSERT <= '1';
					end if;
				end if;
				SUPPRESS_READ <= '0';
			else
				SUPPRESS_READ <= '1';
			end if;
		end if;
		if BYTE_INSERT = '1' then
			BYTE_INSERT <= '0';
		end if;
	end if;
end process WRITE_MEMORY;
 
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.