/* ====================================================================
   This is same as alu-reg.cc  BUT using  D-latch as memory element
   ==================================================================== */

#include "Sim.h"

/* ==================================================================
   D_Latch(): memory element
   ================================================================== */
void D_Latch(const SD &coord,
               const Signal &D, const Signal &Clk, const Signal &q0)
{
   Module( coord, "D-latch", (D, Clk), q0);

   Signal n_D, set, reset, n_q0;

   Not( SD(coord,"bc"), D, n_D);
   And( SD(coord,"ad"), (D, Clk),   set);
   And( SD(coord,"bd"), (n_D, Clk), reset);

   Nor( SD(coord,"ae"), (set,  q0),   n_q0);
   Nor( SD(coord,"be"), (reset,n_q0), q0);
}



/* ==================================================================
   MyRegister(D,Clk,Out): 4 D-latch to make a 4 bit memory
   ================================================================== */
void MyRegister( const SD &coord,
                 const Signal &D, const Signal & Clk, const Signal &Out)
{
   Module( coord, "MyReg", (D,Clk), Out );

   D_Latch( SD(coord,"ab"), D[3], Clk, Out[3] );
   D_Latch( SD(coord,"bb"), D[2], Clk, Out[2] );
   D_Latch( SD(coord,"cb"), D[1], Clk, Out[1] );
   D_Latch( SD(coord,"db"), D[0], Clk, Out[0] );
}




/* ==================================================================
   Decoder2x4():  2x4 decoder

   Input:    c:   c[1] c[0]
   Output:   One of s[3], s[2], s[1], s[0] is 1, all other = 0
   =================================================================== */
void Decoder2x4( const SD &coord,
                 const Signal &c, const Signal &s)
{

   Signal not_c0, not_c1;

   Module( coord, "Decoder", (c[1],c[0]), (s[3]-s[0]) );

   Not( SD(coord,"aa"), c[1], not_c1); 
   Not( SD(coord,"ba"), c[0], not_c0);

   And( SD(coord,"ba"), (c[1],   c[0]),   s[3]);
   And( SD(coord,"bb"), (c[1],   not_c0), s[2]);
   And( SD(coord,"bc"), (not_c1, c[0]),   s[1]);
   And( SD(coord,"bd"), (not_c1, not_c0), s[0]);
}


void simnet()
{
   Signal Data[4], sw0, sw1, sw2;
   Signal s0, s1, s2, s3;

   Sig(Clk0,1);            // Write (clock) signals for registers
   Sig(Clk1,1);
   Sig(Clk2,1);
   Sig(Clk3,1);

   Sig(R0,4);              // Registers outputs
   Sig(R1,4);
   Sig(R2,4);
   Sig(R3,4);

   /* The input */
   Switch("ba", Data[3], '3', Zero); 
   Switch("bb", Data[2], '2', Zero); 
   Switch("bc", Data[1], '1', Zero); 
   Switch("bd", Data[0], '0', Zero);
   
   /* The Registers & Their probes */
   MyRegister("bh-bk", (Data[3]-Data[0]), Clk3, (R3[3]-R3[0]) );
   ProbeH("ah-aj", R3);
   
   MyRegister("dh-dk", (Data[3]-Data[0]), Clk2, (R2[3]-R2[0]) );
   ProbeH("ch-cj", R2);
   
   MyRegister("fh-fk", (Data[3]-Data[0]), Clk1, (R1[3]-R1[0]) );
   ProbeH("eh-ej", R1);
   
   MyRegister("hh-hk", (Data[3]-Data[0]), Clk0, (R0[3]-R0[0]) );
   ProbeH("gh-gj", R0);
   
   Switch("ia", sw0, '9', Zero);
   Switch("ha", sw1, '8', Zero);
   
   Decoder2x4("fc-ic", (sw1,sw0), (s3,s2,s1,s0) );
   Probe("fd", s3); 
   Probe("gd", s2); 
   Probe("hd", s1); 
   Probe("id", s0);
   
   Switch("ma", sw2, 'a', Zero);
   And("fe", (s3,sw2), Clk3);
   And("ge", (s2,sw2), Clk2);
   And("he", (s1,sw2), Clk1);
   And("ie", (s0,sw2), Clk0);
   
   Probe("ff", Clk3); 
   Probe("gf", Clk2); 
   Probe("hf", Clk1); 
   Probe("if", Clk0);
}
