-------------------------------------------------------------------------------
--
-- COPYRIGHT (c) 2006 BY VERIEN DESIGN GROUP, LLC, CONCORD, MA 01742
--
-- ALL RIGHTS RESERVED
--
-- This software is furnished under a license and may be used and
-- copied only in accordance with the terms of such license and with
-- the inclusion of the above copyright notice. This software or any
-- other copies thereof, may not be provided or otherwise made
-- available to anyone other than the licensee. Title to and owner-
-- ship of this software remains with Verien Design Group.
--
-- The information in this document is subject to change without
-- notice and should not be construed as a commitment by Verien.
-------------------------------------------------------------------------------
-- Title : pci cycles file
-- Project :
-------------------------------------------------------------------------------
-- File : pcicycs.vhd
-- Author : David J. Matthews
-------------------------------------------------------------------------------
-- Description : This file is a "pci cycs" file; a package that gets
-- compiled into package design unit "pcicycs". It executes PCI bus
-- cycles through pci_initiator_model. This particular set of tests
-- are used to simulate acquisitions on the frame grabber.
--
-- This test is used for running subtests on different display formats
-- (8, 16, and 32 bit-per-pixel) and at different pixel and line
-- subsamples (1 through 16). These are specified by running either
-- the BASIC_ACQ test (which is 8 BPP), the DISPLAY_FORMAT_16BPP test
-- or the DISPLAY_FORMAT_32BPP test. The tests to run are specified
-- in the SUBTEST_LIST constant array below. Another array, the
-- SUBSAMPLE_ARRAY is associated with the SUBTEST_LIST array and used
-- to specify the sub-sample for the particular test. There is a
-- one-to-one correspondence between the SUBTEST_LIST entries and the
-- SUBSAMPLE_ARRAY entries.
--
-- A fourth test, the LUT_ACQ test fills a pattern in the lookup
-- table, performs an acquisition, and checks the data.
--
-- All of these tests enable "block mode" in the video chip which
-- muxes an 8-bit counter into the video data path. The data pattern
-- is calculated by the getcheckdata procedure and checked in a FOR
-- loop which is used for PCI burst reads.
-------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
USE IEEE.std_logic_arith.ALL;
USE WORK.papsubs.ALL;
USE WORK.pci_pack.ALL;
USE WORK.pcidefs.ALL;
USE WORK.fg_simpack.ALL;
USE WORK.scan_params.ALL;
USE WORK.camera_defs.ALL;
PACKAGE pcicycs IS
-- The following type declaration (SUBTESTS_TYPE) specifies all of the subtests within
-- this module. The constant SUBTESTS is an array of subtests to be executed in the
-- order that they are specified. Note that all tests are preceded by a call to pci_init
-- which is used to setup the BARs.
TYPE subtest_type IS (basic_acq, display_format_16bpp, display_format_32bpp, lut_acq); -- the subtests
TYPE subtest_array_type IS ARRAY (INTEGER RANGE <>) OF subtest_type;
-- Place any subtests (which are values of SUBTEST_TYPE) in the SUBTEST_LIST array. The
-- subtests specified here will be executed in order.
CONSTANT subtest_list : subtest_array_type := (basic_acq, basic_acq, basic_acq, basic_acq, basic_acq,
display_format_16bpp, display_format_16bpp,
display_format_16bpp, display_format_16bpp,
display_format_16bpp,
display_format_32bpp, display_format_32bpp,
display_format_32bpp, display_format_32bpp,
display_format_32bpp);
TYPE subsample_array_type IS ARRAY (subtest_list'RANGE) OF INTEGER RANGE 1 TO 16;
-- This list is for the pixel subsample factors. Each entry is
-- associated with a subtest entry in the SUBTEST_LIST array
-- above. Therefore, the number of entries in this array must
-- equal the numberof entries in SUBTEST_LIST. Valid values for
-- the subsample factors are 1-16 (this value gets adjusted down
-- by 1 before loading in the register).
CONSTANT subsample_array : subsample_array_type := (1, 2, 3, 14, 16,
1, 2, 3, 14, 16,
2, 3, 7, 14, 16);
PROCEDURE initcycs (SIGNAL cyc : INOUT cycrecord;
SIGNAL ctlin : IN ctlin_record; -- control bus in
CONSTANT readdata : IN slv32_array(0 TO 15));
END pcicycs;
PACKAGE BODY pcicycs IS
PROCEDURE initcycs (SIGNAL cyc : INOUT cycrecord;
SIGNAL ctlin : IN ctlin_record; -- control bus in
CONSTANT readdata : IN slv32_array(0 TO 15)) IS
VARIABLE debug : BOOLEAN := FALSE; -- set true for per pixel groups debug msgs
VARIABLE data : int := 0; -- temp storage
VARIABLE data_slv : slv32; -- temp storage
VARIABLE data_ptn : slv8; -- simply stores the data pattern locally
VARIABLE disp_control_reg : int; -- contents of display control register
VARIABLE control : control_record; -- controls the getcheckdata procedure
VARIABLE seed : int; -- random number seed (not used yet)
VARIABLE addr_offset1 : int := 0; -- temp address storage
VARIABLE addr_offset2 : int := 0; -- temp address storage
VARIABLE index_offset : int := 0;
VARIABLE pixgroups : int := 0; -- padded no of 4-pixel groups / scan line
VARIABLE real_pixgroups : int := 0; -- real no of 4-pixel groups / scan line
VARIABLE pixel : int := 0; -- pixel count within scan line
VARIABLE starttime : TIME := 0 ns;
VARIABLE burst_enable : BOOLEAN := TRUE; -- flag indicating whether to perform a burst op
CONSTANT timeout : TIME := 1.5 ms; -- timeout
VARIABLE pixmult : int := 1; -- pixel multiplier factor (for pixel
-- expansion in 16, 32 BPP modes)
VARIABLE firstime : BOOLEAN := TRUE;
VARIABLE subsample_factor : int; -- subsample factor
VARIABLE no_of_lines : int; -- adjusted no of lines
VARIABLE no_of_pixels : int; -- adjusted no of pixels which is stored in the h/w
-- (double-word aligned)
VARIABLE total_pixels : int; -- total programmed pixels
VARIABLE real_no_of_pixels : int; -- the real number of pixels (used to check the data)
-- The following record contains the timing in the form of SCAN lists and register values
-- which are loaded into the SCAN for the test. These are located in video_params.vhd.
VARIABLE video_timing : video_record_ptr := NEW video_record'(testni_timing);
BEGIN
---------------------------------------------------------------------------------------
-- CAMERA RESET, PCI INITIALIZATION
---------------------------------------------------------------------------------------
-- THIS SECTION PERFORMS A CAMERA RESET TO GET THE CAMERA PIXEL CLOCK RUNNING AND THEN
-- INITIALIZES THE PCI BUS.
-- Set up the basic model switches:
-- enable read data checking:
cyc.readcheck <= TRUE;
-- don't mask data during comparisons:
cyc.mask <= 16#FFFFFFFF#;
-- assert all byte enables from the bus model:
cyc.byte_enables <= (OTHERS => '0');
-- set the debug message level:
cyc.ctlout.pcimon_debug_level <= NOTE; -- turn on all pcimon debug messages
-- disable the camera pixel clock driver for this test (we don't use the camera model
-- here);
cyc.ctlout.enable_camera <= FALSE;
-- Initialize PCI config space:
init_pci(cyc);
---------------------------------------------------------------------------------------
-- SUBTEST SETUP
---------------------------------------------------------------------------------------
-- THIS SECTION SETS UP THE REQUESTED SUBTEST, EITHER 8 BPP (BASIC ACQ), 16 BPP, OR 32
-- BPP AND AT THE REQUESTED SUBSAMPLE.
FOR subtest IN subtest_list'RANGE LOOP
-- Note that these tests have much common code and so first
-- set up some variables and then run through the common stuff.
---------------------------------------------------------------------------------------
-- Basic Test Mode Acquisition Test
---------------------------------------------------------------------------------------
IF subtest_list(subtest) = basic_acq THEN
report_test("STARTING BASIC TEST MODE ACQUISITION");
pixmult := 1; -- set up the pixel multiplier factor for 1
-- load the display control register with the display format
-- and the value of the subsample from the subsample array:
ASSERT FALSE REPORT cr & " SUBSAMPLE SET TO " & INTEGER'image(subsample_array(subtest))
SEVERITY NOTE;
disp_control_reg := format_8bpp + (subsample_array(subtest)-1)*16;
control.display_format := fmt_8bpp;
control.pattern := incr;
END IF;
---------------------------------------------------------------------------------------
-- 16 Bit Per Pixel Display Format Acquisition Test
---------------------------------------------------------------------------------------
IF subtest_list(subtest) = display_format_16bpp THEN
report_test("STARTING 16BPP DISPLAY FORMAT ACQUISITION TEST");
pixmult := 2; -- set up the pixel multiplier factor for 1
-- load the display control register with the display format
-- and the value of the subsample from the subsample array:
disp_control_reg := format_16bpp + (subsample_array(subtest)-1)*16;
ASSERT FALSE REPORT " SUBSAMPLE SET TO " & INTEGER'image(subsample_array(subtest))
SEVERITY NOTE;
control.display_format := fmt_16bpp;
control.pattern := incr;
END IF;
---------------------------------------------------------------------------------------
-- 32 Bit Per Pixel Display Format Acquisition Test
---------------------------------------------------------------------------------------
IF subtest_list(subtest) = display_format_32bpp THEN
report_test("STARTING 32BPP DISPLAY FORMAT ACQUISITION TEST");
pixmult := 4; -- set up the pixel multiplier factor for 1
-- load the display control register with the display format
-- and the value of the subsample from the subsample array:
disp_control_reg := format_32bpp + (subsample_array(subtest)-1)*16;
ASSERT FALSE REPORT " SUBSAMPLE SET TO " & INTEGER'image(subsample_array(subtest))
SEVERITY NOTE;
control.display_format := fmt_32bpp;
control.pattern := incr;
END IF;
---------------------------------------------------------------------------------------
-- LUT Acquisition Test
---------------------------------------------------------------------------------------
-- This test programs the LUT with a pattern, performs an acquisition, then check
IF subtest_list(subtest) = lut_acq THEN
report_test("STARTING LOOKUP TABLE ACQUISITION TEST");
pixmult := 1; -- set up the pixel multiplier factor for 1
-- load the display control register with the display format
-- and the value of the subsample from the subsample array:
ASSERT FALSE REPORT cr & " SUBSAMPLE SET TO " & INTEGER'image(subsample_array(subtest))
SEVERITY NOTE;
disp_control_reg := format_8bpp + (subsample_array(subtest)-1)*16;
control.display_format := fmt_8bpp;
-- control.fixed_data is used to hold the data pattern and is passed to getcheckdata to
-- check the data against a fixed pattern. This pattern is programmed into the
-- LUT and so the entire image should consist of this pattern.
control.fixed_data := x"A55AA55A";
control.pattern := fixed;
-- initilialize the LUT with the pattern
FOR i IN 0 TO 127 LOOP
memwrite(fg_bar1_base + scan0_base + lut_base + i*4, control.fixed_data, cyc);
END LOOP;
END IF; -- lut acq test
-----------------------------------------------------------------------------------
-- REGISTER INITIALIZATION
-----------------------------------------------------------------------------------
-- IN THIS SECTION WE FIRST SETUP THE SCAN BY CALLING AN
-- EXTERNAL PROCEDURE init_scan_params. PART OF THIS
-- INITIALIZATION IS THE CALCULATION OF THE NUMBER OF SCAN
-- LINES AND NUMBER OF PIXELS TO TEST.
addr_offset1 := fg_bar1_base + scan0_base;
IF firstime THEN
init_scan_params(video_timing, addr_offset1, cyc);
-- set up the channel control register for test mode:
memwrite(fg_bar1_base + scan0_base + channel_control_reg,
(clken_clear_bit => '1', test_bit => '1',
acquire_enable_bit => '1', interlaced_bit => '0',
pad_enable_bit => '1', OTHERS => '0'), cyc);
-- set up the ADMA cmd reg for block mode DMA (start bit not written yet):
memwrite(fg_bar0_base + ch0_base + admacmd,
acquire_enable + even + dma_threshold, cyc);
firstime := FALSE;
END IF;
-- set up the Acq DMA PCI address reg
memwrite(fg_bar0_base + ch0_base + admapa, tar_data_base, cyc);
-- calculate the number of lines to program into the video chip and to check based
-- upon the subsampling. First we get the raw number of lines from the video
-- record. This is divided by 16 because it is in 1/16th line accuracy in the scan:
no_of_lines := (video_timing.vthresh(17) - video_timing.vthresh(16))/16;
-- Next we divide by the sub-sample factor. If it is not evenly divisible then we
-- have to round up (add 1):
IF no_of_lines REM subsample_array(subtest) = 0 THEN
no_of_lines := no_of_lines/subsample_array(subtest);
ELSE
no_of_lines := (no_of_lines/subsample_array(subtest)) + 1;
END IF;
ASSERT FALSE REPORT cr & " THIS TEST WILL ACQUIRE " & INTEGER'image(no_of_lines)
& " LINES" SEVERITY NOTE;
-- Calculate the number of pixels. Note that the image width is multiplied by 2 in
-- 16BPP display mode and 4 in 32 BPP mode, then is later divided by the subsample value.
-- This is stored away as the real number of pixels and used to check the data.
-- The no_of_pixels that is written to the video fpga must be double-word aligned
-- and this is calculated next.
real_no_of_pixels := ((video_timing.hthresh(11) - video_timing.hthresh(6)) * pixmult);
-- Next we divide by the sub-sample amount and determine
-- if we need to round up the number of pixels in a scan
-- line by 1 to form the "real" no of pixels, which is the
-- number of pixels that we check (not padded by the
-- hardware):
IF real_no_of_pixels REM subsample_array(subtest) = 0 THEN
real_no_of_pixels := real_no_of_pixels/subsample_array(subtest);
ELSE
real_no_of_pixels := (real_no_of_pixels/subsample_array(subtest)) + 1;
END IF;
-- Next we calculate the no of "programmed" pixels, which are the number of pixels
-- that we program into the hardware. The hardware must have them double-work
-- aligned and will pad out the extra pixels - those between no_of_pixels and
-- real_no_of_pixels. We enable padding in the video chips which will
-- pad out the remaining pixels with the previous value.
IF real_no_of_pixels REM 8 /= 0 THEN
no_of_pixels := real_no_of_pixels + 8 - real_no_of_pixels REM 8;
ELSE
no_of_pixels := real_no_of_pixels;
END IF;
ASSERT FALSE REPORT cr & " THIS TEST WILL ACQUIRE " & INTEGER'image(no_of_pixels)
& " PIXELS PER SCAN LINE" SEVERITY NOTE;
ASSERT FALSE REPORT cr & " THIS TEST WILL CHECK " & INTEGER'image(real_no_of_pixels)
& " PIXELS PER SCAN LINE" SEVERITY NOTE;
-- set up the image width reg.
total_pixels := no_of_pixels * no_of_lines;
data_slv := conv_std_logic_vector(total_pixels, 32) AND x"0000FFF8";
memwrite(fg_bar1_base + scan0_base + image_width_reg, data_slv, cyc);
-- set up the image height reg:
data_slv := conv_std_logic_vector(total_pixels/65536, 32) AND x"000003FF";
memwrite(fg_bar1_base + scan0_base + image_height_reg, data_slv, cyc);
-- set up the DMA size reg with total pixels:
memwrite(fg_bar0_base + ch0_base + admasz, total_pixels, cyc);
-- set up the display control register:
memwrite(fg_bar1_base + scan0_base + display_control_reg, disp_control_reg, cyc);
-----------------------------------------------------------------------------------
-- SET THE RUN BITS
-----------------------------------------------------------------------------------
-- THIS SECTION SET THE RUN BIT IN THE SCAN AND THE START_EVEN BIT IN THE VIDEO
-- FPGA TO START THE ACQUISITION. WE THEN POLL THE EVEN_BUSY BIT UNTIL WE ARE DONE
-- OR WE TIMEOUT.
-- set up the ADMA cmd reg for block mode DMA and with start even bit set
memwrite(fg_bar0_base + ch0_base + admacmd,
acquire_enable + even + dma_threshold + dma_start_even, cyc);
-- set the state machine in the SCAN
memwrite(fg_bar1_base + scan0_base + state_mach_reg, 16#0005#, cyc);
-- set the RUN bit in the SCAN
memwrite(fg_bar1_base + scan0_base + rev_sync_reg, 16#0040#, cyc);
-- poll the busy bit until either we are not busy or we time out:
starttime := NOW; -- capture time that we start polling
memread(fg_bar0_base + ch0_base + admast, cyc);
pause(20, cyc);
WHILE readdata(0)(even_done_bit) = '0' LOOP
memread(fg_bar0_base + ch0_base + admast, cyc);
IF NOW - starttime > timeout THEN
ASSERT FALSE REPORT "TIMEOUT IN BASIC TESTMODE ACQ TEST"
& cr & "WAITING FOR EVEN_BUSY TO GO INACTIVE (ACQ NEVER COMPLETED)"
SEVERITY ERROR;
EXIT;
END IF;
END LOOP;
-----------------------------------------------------------------------------------
-- ACQUISITION COMPLETE
-----------------------------------------------------------------------------------
-- WE ARRIVE HERE WHEN THE ACQUISITION COMPLETES. WE NOW CHECK THE VARIOUS STATUS
-- REGISTERS TO LOOK FOR HEALTHY STATUS.
REPORT "ACQUISITION COMPLETE (EVEN_BUSY WENT ACTIVE)" SEVERITY NOTE;
-- check the Acq DMA Status to ensure we ended without errors:
pause(20, cyc);
ASSERT (readdata(0) AND healthy_dma_status) = 0
REPORT "DMA STATUS REGISTER INDICATES "
& "UNHEALTHY STATUS AT END OF ACQUISITION" SEVERITY ERROR;
-- check the acquire fifo status:
memread(fg_bar1_base + scan0_base + acqfifo_status_reg, cyc);
pause(20, cyc);
ASSERT (readdata(0) AND healthy_acqfifo_status) = 0
REPORT "ACQ FIFO STATUS REGISTER INDICATES "
& "UNHEALTHY STATUS AT END OF ACQUISITION" SEVERITY ERROR;
-- check the even fifo status:
memread(fg_bar1_base + scan0_base + evenfifo_status_msbreg, cyc);
pause(20, cyc);
ASSERT (readdata(0) AND healthy_evenfifo_status) = 0
REPORT "EVEN FIFO STATUS REGISTER INDICATES "
& "UNHEALTHY STATUS AT END OF ACQUISITION" SEVERITY ERROR;
-- clear the even_done bit in the status register:
memwrite(fg_bar0_base + ch0_base + admast, (even_done_bit => '1', OTHERS => '0'), cyc);
-----------------------------------------------------------------------------------
-- DATA CHECKING
-----------------------------------------------------------------------------------
-- HERE WE CHECK THE DATA IN TARGET MEMORY. WE PERFORM PCI BURST READS IN THE
-- INNER FOR LOOP TO SPEED UP THE PROCESS. AT THE END WE GO BACK UP AND DO THE
-- NEXT SUBTEST IN LINE.
control.subsample := subsample_array(subtest); -- set up the subsample amount
addr_offset2 := 0;
pixgroups := no_of_pixels/4; -- adjusted number of 4 pix groups/scan line * pix expansion
real_pixgroups := real_no_of_pixels/4; -- real number of 4 pix groups/scan line * pix expansion
FOR lines IN 0 TO no_of_lines-1 LOOP
ASSERT FALSE REPORT " ...CHECKING DATA FROM SCAN LINE " & INTEGER'image(lines)
SEVERITY NOTE;
control.reset := TRUE; -- reset the data pattern at begin of line
pixel := 0; -- pixel # in scan line
WHILE pixel < pixgroups LOOP
IF pixel >= real_pixgroups THEN
-- when we are at the end of real pixels we increment the address past
-- the "padded pixels" - we don't check them
pixel := pixel + 1; -- increment pixel count
addr_offset2 := addr_offset2 + 4; -- increment the address
ELSE
-- set transfer burst size to the smaller of 14 or the number of pixel
-- groups left to check. The actual burst size will be 0 to 14+1
-- because of the burst end operation after the loop:
IF real_pixgroups-pixel <= 2 THEN
burst_enable := FALSE;
ELSIF real_pixgroups-pixel < 16 THEN
index_offset := real_pixgroups-pixel-2;
burst_enable := TRUE;
ELSE
burst_enable := TRUE;
index_offset := 14;
END IF;
IF burst_enable THEN
FOR i IN 0 TO index_offset LOOP
ASSERT NOT debug REPORT "starting pixel group " & INTEGER'image(pixel)
SEVERITY NOTE;
getcheckdata(data_ptn, control, data_slv, seed);
membread(tar_data_base + addr_offset2, data_slv, cyc);
pixel := pixel + 1; -- increment pixel count
addr_offset2 := addr_offset2 + 4; -- increment the address
control.reset := FALSE;
END LOOP;
END IF;
ASSERT NOT debug REPORT "starting pixel group " & INTEGER'image(pixel)
SEVERITY NOTE;
getcheckdata(data_ptn, control, data_slv, seed);
membreadend(tar_data_base + addr_offset2, data_slv, cyc);
control.reset := FALSE;
pixel := pixel + 1; -- increment pixel count
addr_offset2 := addr_offset2 + 4; -- increment the address
END IF;
END LOOP;
END LOOP;
ASSERT NOT (subtest_list(subtest) = basic_acq)
REPORT "BASIC TEST MODE ACQ FINISHED" SEVERITY NOTE;
ASSERT NOT (subtest_list(subtest) = display_format_16bpp)
REPORT "16BPP DISPLAY FORMAT ACQ TEST FINISHED" SEVERITY NOTE;
ASSERT NOT (subtest_list(subtest) = display_format_32bpp)
REPORT "32BPP DISPLAY FORMAT ACQ TEST FINISHED" SEVERITY NOTE;
pause(10, cyc);
END LOOP; -- loop for subtest_list
pause(20, cyc);
stop(cyc);
END initcycs;
END pcicycs;