
% We need layers to draw the block diagram
\pgfdeclarelayer{background} \pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

% Define a few styles and constants
\tikzstyle{sensor}=[draw, fill=blue!20, text width=5em,
    text centered, minimum height=2.5em]

\tikzstyle{empty}=[
    text centered]

\tikzstyle{op}=[draw, fill=green!20, text width=3em,
    text centered, minimum height=1.5em]

\tikzstyle{tmp}=[text width=0em,
 minimum height=0em]

\tikzstyle{ann} = [above, text width=5em, text centered]

\tikzstyle{rom} = [sensor, text width=6em, fill=red!20,
    minimum height=12em, rounded corners]
\tikzstyle{reg} = [sensor, text width=7em, fill=green!20,
    minimum height=4em, rounded corners]

\tikzstyle{carry} = [sensor, text width=2em, fill=red!20,
    minimum height=1.5em, rounded corners]

\tikzstyle{mux} = [sensor, text width=3em, fill=black!20,
    minimum height=7em, rounded corners]

\def\blockdist{2.3}
\def\edgedist{2.5}

\begin{tikzpicture}[scale=0.8]
\scriptsize
    \node (rom) [rom] {ROM Instructions};

    \path (rom.180)+(-1.6,0) node (counter) [sensor] {counter};
    \path [draw, ->] (counter) -- node [above] {}
        (rom.west |- counter);

    \path (counter.west)+(-\blockdist,0) node (reg) [reg] {add by one or change by jump};
    \path [draw, <-] (counter.west) -- node[above]{}
        (reg.east |-counter);
    \path (rom.55)+(+\blockdist,0) node (inst) [sensor] {Select};
    \path [draw, <-] (inst) -- node [above] {4 bits}
        (rom.east |- inst);

    \path (reg)+(3,-2.2) node (jump) [empty] {jump};
    \path (rom.25)+(+\blockdist,0) node (source1) [sensor] {Source1};
    \path [draw, <-] (source1) -- node [above] {4 bits}
        (rom.east |- source1);
    \path (rom.-25)+(+\blockdist,0) node (source2) [sensor] {Source2};
    \path [draw, <-] (source2) -- node [above] {4 bits}
        (rom.east |- source2);
    \path (rom.-55)+(+\blockdist,0) node (dest) [sensor] {Destination};
    \path [draw, <-] (dest) -- node [above] {4 bits}
        (rom.east |- dest);

    \path (source1.east)+(3,0) node (op1)[op] {addu};
    \path (op1.south)+(0,-0.5) node (op2)[op] {subu};
    \path (op2.south)+(0,-0.6) node (dots)[ann] {$\vdots$};
    \path (dots.south)+(0,-0.3) node (op3)[op] {xor};

    \path [draw, <-] (op1.west) -- node [above] {16 bits}
        (source1.0) ;
    \path [draw, <-] (op1.west)+(0,-0.1) -- node [above] {}
        (source2.0) ;
    \path [draw, <-] (op2.west) -- node [above] {}
        (source2.0) ;
    \path [draw, <-] (op2.west)+(0,+0.1) -- node [above] {}
        (source1.0) ;
    \path [draw, <-] (op3.west) -- node [above] {}
        (source1.0) ;
    \path [draw, <-] (op3.west)+(0,-0.1) -- node [below] {16 bits}
        (source2.0) ;

    \path (op1.east)+(2.7,-1) node (mux)[mux] {Mux};
    \path [draw, ->] (op1) -- node [above] {16 bits}
        (mux.west |- op1);
    \path [draw, ->] (op2) -- node [above] {16 bits}
        (mux.west |- op2);
    \path [draw, ->] (op3) -- node [above] {16 bits}
        (mux.west |- op3);

    \node (alu) [below of =op3] {ALU};

    \path (mux.south)+(0.6,-0.9) node (carry) [carry] {carry};
    \path [draw, ->] (mux.south)+(0.4,0) -- node [above] {}
        (carry.100);
    \path (mux.south)+(-0.6,-0.9) node (zero) [carry] {zero};
    \path [draw, ->] (mux.south)+(-0.4,0) -- node [above] {}
        (zero.80);
    \path (mux.east)+(0.5,0.7) node (tmp) [empty] {16 bits};
    \path (mux.south)+(-0.1,-1.5) node (illu) [empty] {1 bit registers};

    \path [draw, <-] (alu.east)+(0.6,0) -- node [above] {}
        (illu.north west);

    \path [draw, -] (inst.east) -- (10.8,1.67);
    \path [draw, ->] (10.8,1.67) -- (10.8,0.8);

    \path [draw, -] (11.5,0) -- (12.3,0);
    \path [draw, -] (12.3,0) -- (12.3,-4);
    \path [draw, -] (12.3,-4) -- (3.5,-4);
    \path [draw, ->] (3.5,-4) -- (3.5,-2.2);

    \path [draw, -] (0,-2.1)--(0,-2.5);
    \path [draw, -] (0,-2.5) -- (-5.5,-2.5);
    \path [draw, ->] (-5.5,-2.5) -- (-5.5,-0.8);

    \path [draw, -] (-3, 0.5)--(-3,1.5);
    \path [draw, -] (-3, 1.5)--(-6,1.5);
    \path [draw, ->] (-6,1.5)--(-6, 0.7);

    \path [draw, -] (9.7, -3.2)--(-6.7,-3.2);
    \path [draw, ->] (-6.7,-3.2)--(-6.7,-0.8);

    \begin{pgfonlayer}{background}
         \path (op1.north west)+(-0.5,0.3) node (a) {};
         \path (op3.south east)+(+0.4,-1.2) node (b) {};
         \path[fill=yellow!20,rounded corners, draw=black!50, dashed]
            (a) rectangle (b);

         \path (zero.north west)+(-0.1,0.2) node (a) {};
         \path (illu.south east)+(+0.2,-0.1) node (b) {};
         \path[fill=blue!20,rounded corners, draw=black!50, dashed]
            (a) rectangle (b);

    \end{pgfonlayer}
\end{tikzpicture}
