% 6.111 Final Project - Fall 1996 - "PIC-Cam" %
% Kenneth B. Russell <kbrussel@mit.edu> %

INCLUDE "lpm_counter.inc";
INCLUDE "pc_const.inc";

% Counter which implements required counting functions for %
% JPEG compression using the ZR36050. %
% Specifications: %
%    - 23-bit counter (NOTE this is dependent on the image size; %
%      a larger image size might overflow into the second half of %
%      the SIMM, necessitating a 24-bit counter) %
%    - Counts 8x8 blocks in raster-scan (left to right, top down) %
%      order. %
% Conceptual components: %
%      Vert block ctr.  Horiz block ctr.  Component ctr.   Intra-block ctr. %
%                       (Max. value = 19) (Y0, Y1, U, V)                    %
%         10 bits           5 bits           2 bits             6 bits      %
%    The above counters feed RCO from right to left. That is, the intra-block %
%    counter's bits are the least significant bits. %
% Row/column mapping: %
%    row_addr[10..1] = q[23..14] (Note high bit of row_addr should be grounded) %
%    col_addr[11..1] = q[13..3] %
%    q[2] is a 16-bit word counter. %
%    q[1] is a byte selector. %
% Mapping from the above counters into the output bits: %
%    q[23..14] = VBC[10..1]   (VBC == Vert block ctr) %
%    q[13..11] = IBC[6..4] %
%    q[10..6]  = HBC[5..1] %
%    q[5..3]   = IBC[3..1] %
%    q[2]      = CC[1] %
%    q[1]      = CC[2] %

% Notes: %
%    The DATA and SLOAD inputs have been commented out. In this application, %
%    this counter should never need to be loaded, and by removing them we %
%    might reduce the logic size when these inputs would otherwise be tied %
%    to ground. %

SUBDESIGN jpegctr
(
	% Inputs %
	clock		: INPUT;
	cnt_en		: INPUT;
	aclr		: INPUT;
%	sload		: INPUT; %
%	data[23..1]	: INPUT; %
	
	% Outputs %
	q[23..1]	: OUTPUT;
)
VARIABLE
	% Vertical Block Counter (VBC) %
	vbc			: lpm_counter WITH (
		LPM_WIDTH = 10,
		LPM_DIRECTION = "UP"
	);
	% Horizontal Block Counter (HBC) %
	hbc			: lpm_counter WITH (
		LPM_WIDTH = 5,
		LPM_DIRECTION = "UP"
	);
	% Component (i.e., Y0, Y1, U, V) Counter (CC) %
	cc			: lpm_counter WITH (
		LPM_WIDTH = 2,
		LPM_DIRECTION = "UP"
	);
	% Intra-Block Counter (IBC) %
	ibc			: lpm_counter WITH (
		LPM_WIDTH = 6,
		LPM_DIRECTION = "UP"
	);
BEGIN
	% Hook up the clocks %
	vbc.clock = clock;
	hbc.clock = clock;
	cc.clock = clock;
	ibc.clock = clock;
	
	% Hook up the clear inputs %
	vbc.aclr = aclr;
	hbc.aclr = aclr;
	cc.aclr = aclr;
	ibc.aclr = aclr;
	% Hook up the SYNCHRONOUS clear circuitry for the horizontal block counter %
	% so it loops from 0..19 (H"00"..H"13") %
	hbc.sclr = ((cnt_en == VCC) & (hbc.q[] == H"13") &
				(cc.q[] == H"3") & (ibc.q[] == H"3F"));
	
	% Hook up the load inputs %
%	vbc.sload = sload; %
%	hbc.sload = sload; %
%	cc.sload = sload; %
%	ibc.sload = sload; %
	
	% Hook up the outputs from the component counters %
	q[23..14] = vbc.q[9..0];
	q[13..11] = ibc.q[5..3];
	q[10..6]  = hbc.q[4..0];
	q[5..3]   = ibc.q[2..0];
	q[2]      = cc.q[0];
	q[1]      = cc.q[1];
    
	% Hook up the data inputs to the appropriate counters %
%	vbc.data[9..0] = data[23..14]; %
%	ibc.data[5..3]  = data[13..11]; %
%	hbc.data[4..0]  = data[10..6]; %
%	ibc.data[2..0]  = data[5..3]; %
%	cc.data[0]      = data[2]; %
%	cc.data[1]      = data[1]; %
    
	% Construct the counter enable circuitry %
	ibc.cnt_en = cnt_en;
	cc.cnt_en = ((cnt_en == VCC) & (ibc.q[] == H"3F"));
	hbc.cnt_en = ((cnt_en == VCC) & (cc.q[] == H"3") & (ibc.q[] == H"3F"));
	vbc.cnt_en = ((cnt_en == VCC) & (hbc.q[] == H"13") &
				  (cc.q[] == H"3") & (ibc.q[] == H"3F"));
END;