-- The Main State Machine
-- Woo-Hoo!

INPUTS	: HSE ZEROFLAG NEG ERROR RESTART INST0 INST1 INST2 INST3;
OUTPUTS	: ADWR3 ADWR2 ADWR1 ADWR0 ADRE3 ADRE2 ADRE1 ADRE0 ALUINST2 ALUINST1 ALUINST0 ROMA1 ROMA0 ACCW ACCEN SBWR INWR INEN RFWR RFRE IRWR OUTW ROMR COLWR ALWR MEMWRITE SCENG HSI FLIPW;

-- Yes, folks...that's 29 output signals and 9 input signals!

RESET on RESTART to IDLE;

IDLE	:	CASE (HSE)
			1 => RCOM1(HSI INWR);
		ENDCASE => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

RCOM1	:	CASE (HSE)
			0 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
		ENDCASE => RCOM2(INEN IRWR);

RCOM2	:	GOTO RCOM3;

RCOM3	:	CASE (INST3 INST2 INST1 INST0)
			0 0 0 0 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
			1 1 0 0 => IN1(HSI INWR);
			1 1 0 1 => OUT1(RFRE OUTW);
			1 0 0 0 => TRNN1(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
			1 0 0 1 => TRNS1(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST2=0 ALUINST1=0);
			1 0 1 0 => TRNE1(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
			1 0 1 1 => TRNW1(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
			1 1 1 0 => CLR1(ROMA1=0 ROMA0=0 ROMR COLWR);
			1 1 1 1 => DRW1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

IN1	:	CASE (HSE)
			0 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
		ENDCASE => IN2(INEN RFWR);

IN2	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

OUT1	:	CASE (HSE)
			0 => LOOP;
		ENDCASE => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

-- Initialize loop variables

CLR1	:	GOTO CLR2(ROMA1=1 ROMA0=1 ROMR RFWR ADWR3=1 ADWR2=0 ADWR1=0 ADWR0=0);

CLR2	:	GOTO CLR3(ROMA1=1 ROMA0=1 ROMR RFWR ADWR3=1 ADWR2=0 ADWR1=0 ADWR0=1);

CLR3	:	GOTO CLR4(RFRE OUTW ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0);

-- setup address values

CLR4	:	GOTO CLR5(ALWR);

CLR5	:	GOTO CLR6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=1 RFRE OUTW);

CLR6	:	GOTO CLR7(MEMWRITE ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- write to external memory, check for termination of inside loop

CLR7	:	CASE (ZEROFLAG)
			1 => CLRA1(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => CLR8(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=1);

-- loop not terminated, lcv--, jump back to top

CLR8	:	GOTO CLR9(RFWR ACCEN ADWR3=1 ADWR2=0 ADWR1=0 ADWR0=1);

CLR9	:	GOTO CLR6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=1 RFRE OUTW);

-- inside loop terminated, check for outside loop termination

CLRA1	:	GOTO CLRA2;

CLRA2	:	CASE (ZEROFLAG)
			1 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
		ENDCASE => CLRA3(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=1);

-- outside loop not terminated, lcv--, jump to top, reinit inner loop


CLRA3	:	GOTO CLRA4(ACCEN RFWR ADWR3=1 ADWR2=0 ADWR1=0 ADWR0=0);

CLRA4	:	GOTO CLR3(ROMA1=1 ROMA0=1 ROMR RFWR ADWR3=1 ADWR2=0 ADWR1=0 ADWR0=1);


-- Translate instructions.  One opcode per direction.  translated by value stored in ARG

-- translate north (Y1=Y1+ARG, Y2=Y2+ARG)

TRNN1   :	GOTO TRNN2(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

TRNN2	:	GOTO TRNN3;

TRNN3	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNN4(ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=1 RFWR ACCEN);

TRNN4	:	GOTO TRNN5(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

TRNN5	:	GOTO TRNN6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

TRNN6	:	GOTO TRNN7;

TRNN7	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNN8(ADWR3=0 ADWR2=0 ADWR1=1 ADWR0=1 RFWR ACCEN);

TRNN8	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

-- translate south (Y1=Y1-ARG, Y2=Y2-ARG)

TRNS1	:	GOTO TRNS2(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

TRNS2	:	GOTO TRNS3;

TRNS3	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNS4(ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=1 RFWR ACCEN);

TRNS4	:	GOTO TRNS5(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

TRNS5	:	GOTO TRNS6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

TRNS6	:	GOTO TRNS7;

TRNS7	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNS8(ADWR3=0 ADWR2=0 ADWR1=1 ADWR0=1 RFWR ACCEN);

TRNS8	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

-- translate east (X1=X1+ARG, X2=X2+ARG)

TRNE1	:	GOTO TRNE2(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

TRNE2	:	GOTO TRNE3;

TRNE3	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNE4(ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=0 RFWR ACCEN);

TRNE4	:	GOTO TRNE5(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

TRNE5	:	GOTO TRNE6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

TRNE6	:	GOTO TRNE7;

TRNE7	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNE8(ADWR3=0 ADWR2=0 ADWR1=1 ADWR0=0 RFWR ACCEN);

TRNE8	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);

-- translate west (X1=X1-ARG, X2=X2-ARG)

TRNW1	:	GOTO TRNW2(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

TRNW2	:	GOTO TRNW3;

TRNW3	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNW4(ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=0 RFWR ACCEN);

TRNW4	:	GOTO TRNW5(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

TRNW5	:	GOTO TRNW6(ADRE3=1 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

TRNW6	:	GOTO TRNW7;

TRNW7	:	CASE (ERROR)
			1 => TRNER1(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => TRNW8(ADWR3=0 ADWR2=0 ADWR1=1 ADWR0=0 RFWR ACCEN);

TRNW8	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);


-- Handle errors by marking error flag on object

TRNER1	:	GOTO TRNER2(ROMA1=1 ROMA0=0 ROMR ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

TRNER2	:	GOTO TRNER3(ADWR3=0 ADWR2=1 ADWR1=0 ADWR0=0 RFWR ACCEN);

TRNER3	:	GOTO IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);


--------------------
-- Line Draw Unit --
--------------------

-- check whether object drawable.  if not, abort.

DRW1	:	GOTO DRW2(ADRE3=0 ADRE2=1 ADRE1=0 ADRE0=0 RFRE COLWR ALUINST2=0 ALUINST1=0 ALUINST0=0);

DRW2	:	GOTO DRW3(ROMA1=1 ROMA0=0 ROMR ALUINST2=1 ALUINST1=1 ALUINST0=0);

DRW3	:	GOTO DRW4;

DRW4	:	CASE (ZEROFLAG)
			0 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
		ENDCASE => DRW5(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- Calculate DX

DRW5	:	GOTO DRW6(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

DRW6	:	GOTO DRW7(RFWR ACCEN SBWR ADWR3=1 ADWR2=1 ADWR1=0 ADWR0=0);

DRW7	:	GOTO DRW8(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST0=0 ALUINST1=0 ALUINST0=0);

-- Calculate DY

DRW8	:	GOTO DRW9(ADRE3=0 ADRE2=0 ADRE1=1 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

DRW9	:	GOTO DRW10(ACCEN RFWR SBWR ADWR3=1 ADWR2=1 ADWR1=0 ADWR0=1);

DRW10	:	GOTO DRW11(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

-- Decide whether X or Y is to be iterated across (set FLIP bit)

DRW11	:	GOTO DRW12;

DRW12	:	CASE (NEG)
			1 => DRWF1(FLIPW ROMR ROMA1=0 ROMA0=1);
		ENDCASE => DRW13(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=1);

-- Proceed with line draw initialization

DRW13	:	GOTO DRW14(ACCEN RFWR SBWR ADWR3=1 ADWR2=1 ADWR1=0 ADWR0=1);

DRW14	:	GOTO DRW15(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

DRW15	:	GOTO DRW16(ACCEN SBWR RFWR ADWR3=1 ADWR2=1 ADWR1=1 ADWR0=0);

DRW16	:	GOTO DRW17(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=0 RFRE RFWR ADWR3=1 ADWR2=1 ADWR1=1 ADWR0=1);

DRW17	:	GOTO DRW18(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=1);

DRW18	:	GOTO DRW19(ACCEN SBWR RFWR ADWR3=1 ADWR2=1 ADWR1=0 ADWR0=0);

DRW19	:	GOTO DRW20(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- Check terminate condition for linedraw

DRW20	:	GOTO DRW21;

DRW21	:	CASE (ZEROFLAG)
			1 => IDLE(SCENG FLIPW ROMR ROMA1=0 ROMA0=0);
		ENDCASE => DRW22(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE OUTW);

-- Plot value at (x1, y1)

DRW22	:	GOTO DRW23(ALWR);

DRW23	:	GOTO DRW24(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE OUTW);

DRW24	:	GOTO DRW25(MEMWRITE);

DRW25	:	GOTO DRW26(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- Check accumulated error, inc/decrement values

DRW26	:	GOTO DRW27;

DRW27	:	CASE (NEG)
			1 => DRW37(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);
		ENDCASE => DRW28(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- Path One (E > 0)

DRW28	:	GOTO DRW29;

DRW29	:	CASE (NEG)
			1 => DRW31(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=1);
		ENDCASE => DRW30(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=0);

DRW30	:	GOTO DRW31(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=1);

DRW31	:	GOTO DRW32(ACCEN RFWR ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=1);

DRW32	:	GOTO DRW33(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=0);

DRW33	:	GOTO DRW34(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

DRW34	:	GOTO DRW35(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=1);

DRW35	:	GOTO DRW36(ACCEN RFWR SBWR ADWR3=1 ADWR2=1 ADWR1=1 ADWR0=0);

DRW36	:	GOTO DRW40(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=0);

-- Path Two (E < 0)

DRW37	:	GOTO DRW38(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=1 ALUINST1=0 ALUINST0=0);

DRW38	:	GOTO DRW39(ACCEN RFWR SBWR ADWR3=1 ADWR2=1 ADWR1=0 ADWR0=1);

DRW39	:	GOTO DRW40(ADRE3=0 ADRE2=0 ADRE1=0 ADRE0=0 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=0);

-- Branches One and Two rejoin.  End of loop increment

DRW40	:	GOTO DRW41(ACCEN RFWR ADWR3=0 ADWR2=0 ADWR1=0 ADWR0=0);

DRW41	:	GOTO DRW42(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=1 ALUINST0=1);

DRW42	:	GOTO DRW43(ACCEN RFWR SBWR ADWR3=1 ADWR2=1 ADWR1=1 ADWR0=1);

-- Return to end-of-draw test condition

DRW43	:	GOTO DRW20(ADRE3=1 ADRE2=1 ADRE1=1 ADRE0=1 ACCW RFRE ALUINST2=0 ALUINST1=0 ALUINST0=0);

-- Enable address flip.

DRWF1	:	GOTO DRWF2;

DRWF2	:	GOTO DRW13(ADRE3=1 ADRE2=1 ADRE1=0 ADRE0=1 RFRE ACCW ALUINST2=0 ALUINST1=0 ALUINST0=1);