`include	"defines.v"
// -------------------------------------------------------------------
//  7474 Dual D-type flip-flop with set and reset; positive edge-trigger
// -------------------------------------------------------------------
module ttl_7474(
    //input
    CP,           //  clock pulse
    PRES_n,       //  enable signal - ERRORE  doveva essere /PRESET
    CLR_n,        //  clear signal - ERRORE doveva essere /CLR
    D,            //  input   data
    Q,            //  output  data
    Q_n           //  output  data
    );
    input       CP;
    input       PRES_n;
    input       CLR_n;
    input       D;
    output reg  Q;
    output reg  Q_n;

    always@ (posedge CP)
    	if(~CLR_n)    
		begin
				// mah, mi sembrava errato, con CLR_n deve andare a zero (era il contrario)
	        Q <= 1'b0;
	        Q_n <= 1'b1;    
			//$display ("cleared");
		end else
		if(~PRES_n)
      begin
			Q <= 1'b1;
	      Q_n <= 1'b0;    
		end else if(~CLR_n)
      begin
			Q <= 1'b0;
         Q_n <= 1'b1;    
      end else
      begin
            Q <= D;
            Q_n <= ~D;
      end
endmodule

// -------------------------------------------------------------------
//  74151 - 8-input multiplexer
// -------------------------------------------------------------------
module ttl_74151X ( select, a,b,c,d,e,f,g,h, y);
	input a;
	input b;
	input c;
	input d;
	input e;
	input f;
	input g;
	input h;
	input [2:0] select;
	output reg y;

	always @( select,a,b,c,d,e,f,g,h)
	begin
	   case( select )
	       0 : y = a;
	       1 : y = b;
	       2 : y = c;
	       3 : y = d;
	       4 : y = e;
	       5 : y = f;
	       6 : y = g;
	       7 : y = h;
	   endcase
	end
endmodule

// -------------------------------------------------------------------
//  74151 - 8-input multiplexer
// -------------------------------------------------------------------
module ttl_74151 ( G_n, select, in, y);
	input G_n;
	input [7:0] in;
	input [2:0] select;
output y;
	assign	y = ~G_n & in [select];

/*	always @( select, in)
begin
	$display("151 G_n=%d select=%04d = %d", G_n, select, in [select]);
	if (G_n == 1'b1)
		y = 0;
	else 
		y = in [select];
end*/
endmodule

// -------------------------------------------------------------------
//  74163 - Synchronous Binary Counter with Synchronous Clear
// -------------------------------------------------------------------
module ttl_74163 (CLK, CLR_L, LD_L, ENP, ENT, D, Q, RCO);
	input CLK, CLR_L, LD_L, ENP, ENT;
	input [3:0] D;
	output RCO;
	output [3:0] Q;
	reg [3:0] Q;
	reg RCO;
	always @(posedge CLK)
	if (CLR_L == 0)
		Q <= 4'b0000;
	else if (LD_L == 0) Q <= D;
	else if (ENT & ENP) Q <= Q +1;
	always @(Q or ENT)
	if (Q == 15 && ENT == 1) RCO = 1;
	else RCO = 0;
endmodule

// -------------------------------------------------------------------
//  74175 - Quad D-type flip-flop with reset; positive-edge trigger
// -------------------------------------------------------------------
// There are four D flip-flops (ABCD) that are triggered on the positive edge of the clock.
// Each has one output (outQ) and one input (data) dependent on the clock. 
// There is a master reset (clear) that clears all registers.  
// There are two enable lines en0 and en1 that allow tristate buffered outputs.  
module ttl_74175 (Adata, Bdata, Cdata, Ddata,
		          AoutQ, BoutQ, CoutQ, DoutQ,
		          AinvQ, BinvQ, CinvQ, DinvQ,
                  clock, clear);
   
   input       Adata;
   input       Bdata;
   input       Cdata;
   input       Ddata;
   input       clock;
   input       clear;
   
   output      AoutQ;
   output      BoutQ;
   output      CoutQ;
   output      DoutQ;
   output      AinvQ;
   output      BinvQ;
   output      CinvQ;
   output      DinvQ;
   
   reg         Aout = 1'b0;
   reg         Bout = 1'b0;
   reg         Cout = 1'b0;
   reg         Dout = 1'b0;

   wire        AoutQ;
   wire        BoutQ;
   wire        CoutQ;
   wire        DoutQ;
   wire        AinvQ;
   wire        BinvQ;
   wire        CinvQ;
   wire        DinvQ;

   // Direct inversions
   assign AoutQ = clear ? Aout : 1'b0;
   assign BoutQ = clear ? Bout : 1'b0;
   assign CoutQ = clear ? Cout : 1'b0;
   assign DoutQ = clear ? Dout : 1'b0;
   assign AinvQ = ~AoutQ;
   assign BinvQ = ~BoutQ;
   assign CinvQ = ~CoutQ;
   assign DinvQ = ~DoutQ;
      
   // The data line is dependent on the clock to change the output but is overridden
   // by clear.
   always @(posedge clock or negedge clear) begin
      if (!clear) begin
         Aout <= 1'b0;
         Bout <= 1'b0;
         Cout <= 1'b0;
         Dout <= 1'b0;  
      end
      else if (clear) begin
         Aout <= Adata;
         Bout <= Bdata;
         Cout <= Cdata;
         Dout <= Ddata;        
      end
   end // always @ (posedge clock)
endmodule

/****************************************************************************
 *                                                                          *
 *  VERILOG HIGH-LEVEL DESCRIPTION OF THE TI 74181 CIRCUIT                  *
 *                                                                          *
 *  Function: 4-bit ALU/Function Generator                                  *
 *                                                                          *
 *  Written by: Mark C. Hansen                                              *
 *                                                                          *
 *  Last modified: Dec 11, 1997                                             *
 *                                                                          *
 ****************************************************************************/

module ttl_74181 (S, A, B, M, CNb, F, X, Y, CN4b, AEB);

  input [3:0] A, B, S;
  input CNb, M; 
  output [3:0] F;
  output AEB, X, Y, CN4b;
	
  TopLevel74181 Ckt74181 (S, A, B, M, CNb, F, X, Y, CN4b, AEB);

endmodule /* Circuit74181 */

/*************************************************************************/

module TopLevel74181 (S, A, B, M, CNb, F, X, Y, CN4b, AEB);

  input [3:0] A, B, S;
  input CNb, M; 
  output [3:0] F;
  output AEB, X, Y, CN4b;
  wire [3:0] E, D, C, Bb;
  
  Emodule Emod1 (A, B, S, E, Bb);
  Dmodule Dmod2 (A, B, Bb, S, D);
  CLAmodule CLAmod3(E, D, CNb, C, X, Y, CN4b);
  Summodule Summod4(E, D, C, M, F, AEB);

endmodule /* TopLevel74181 */

/*************************************************************************/

module Emodule (A, B, S, E, Bb);

  input [3:0] A, B, S;
  output [3:0] E, Bb;
  wire [3:0]  ABS3, ABbS2;

  not Bb0gate(Bb[0], B[0]);
  not Bb1gate(Bb[1], B[1]);
  not Bb2gate(Bb[2], B[2]);
  not Bb3gate(Bb[3], B[3]);

  and ABS30gate(ABS3[0], A[0], B[0], S[3]);
  and ABS31gate(ABS3[1], A[1], B[1], S[3]);
  and ABS32gate(ABS3[2], A[2], B[2], S[3]);
  and ABS33gate(ABS3[3], A[3], B[3], S[3]);

  and ABbS20gate(ABbS2[0], A[0], Bb[0], S[2]);
  and ABbS21gate(ABbS2[1], A[1], Bb[1], S[2]);
  and ABbS22gate(ABbS2[2], A[2], Bb[2], S[2]);
  and ABbS23gate(ABbS2[3], A[3], Bb[3], S[2]);

  nor E0gate(E[0], ABS3[0], ABbS2[0]);
  nor E1gate(E[1], ABS3[1], ABbS2[1]);
  nor E2gate(E[2], ABS3[2], ABbS2[2]);
  nor E3gate(E[3], ABS3[3], ABbS2[3]);

endmodule /* Emodule */

/*************************************************************************/

module Dmodule (A, B, Bb, S, D);

  input [3:0] A, B, Bb, S;
  output [3:0] D;
  wire [3:0]  BbS1, BS0;  

  and BbS10gate(BbS1[0], Bb[0], S[1]);
  and BbS11gate(BbS1[1], Bb[1], S[1]);
  and BbS12gate(BbS1[2], Bb[2], S[1]);
  and BbS13gate(BbS1[3], Bb[3], S[1]);

  and BS00gate(BS0[0], B[0], S[0]);
  and BS01gate(BS0[1], B[1], S[0]);
  and BS02gate(BS0[2], B[2], S[0]);
  and BS03gate(BS0[3], B[3], S[0]);

  nor D0gate(D[0], BbS1[0], BS0[0], A[0]);
  nor D1gate(D[1], BbS1[1], BS0[1], A[1]);
  nor D2gate(D[2], BbS1[2], BS0[2], A[2]);
  nor D3gate(D[3], BbS1[3], BS0[3], A[3]);

endmodule /* Dmodule */

/*************************************************************************/

module CLAmodule(Gb, Pb, CNb, C, X, Y, CN4b);

	// mancavano
	wire Pb0, CNbGb0;
	wire Pb1;
	wire Pb2;
	wire Pb3;
	wire Pb0Gb1;
	wire CNbGb01;
	wire XCNb;
	wire Pb0Gb12, CNbGb012, Pb2Gb3, Pb1Gb23, Pb0Gb123, Pb1Gb2;

  input [3:0] Gb, Pb;
  input CNb; 
  output [3:0] C;
  output X, Y, CN4b;

  not C0gate(C[0], CNb);

  buf Pb0gate(Pb0, Pb[0]);
  and CNbGb0gate(CNbGb0, CNb, Gb[0]);

  buf Pb1gate(Pb1, Pb[1]);
  and Pb0Gb1gate(Pb0Gb1, Pb[0], Gb[1]);
  and CNbGb01gate(CNbGb01, CNb, Gb[0], Gb[1]);

  buf Pb2gate(Pb2, Pb[2]);
  and Pb1Gb2gate(Pb1Gb2, Pb[1], Gb[2]);
  and Pb0Gb12gate(Pb0Gb12, Pb[0], Gb[1], Gb[2]);
  and CNbGb012gate(CNbGb012, CNb, Gb[0], Gb[1], Gb[2]);

  buf Pb3gate(Pb3, Pb[3]);
  and Pb2Gb3gate(Pb2Gb3, Pb[2], Gb[3]);
  and Pb1Gb23gate(Pb1Gb23, Pb[1], Gb[2], Gb[3]);
  and Pb0Gb123gate(Pb0Gb123, Pb[0], Gb[1], Gb[2], Gb[3]);

  nand Xgate(X, Gb[0], Gb[1], Gb[2], Gb[3]);

  nor Ygate(Y, Pb3,Pb2Gb3,Pb1Gb23,Pb0Gb123);
  nand XCNbgate(XCNb, Gb[0], Gb[1], Gb[2], Gb[3], CNb);

  nand CN4bgate(CN4b, Y, XCNb);

  nor C3gate(C[3], Pb2, Pb1Gb2, Pb0Gb12, CNbGb012);

  nor C2gate(C[2], Pb1, Pb0Gb1, CNbGb01);

  nor C1gate(C[1], Pb0, CNbGb0);

endmodule /* CLAmodule */

/*************************************************************************/

module Summodule(E, D, C, M, F, AEB);

  input [3:0] E, D, C;
  input M; 
  output [3:0] F;
  output AEB;
  wire [3:0] EXD, CM;

  xor EXD0gate(EXD[0], E[0], D[0]);
  xor EXD1gate(EXD[1], E[1], D[1]);
  xor EXD2gate(EXD[2], E[2], D[2]);
  xor EXD3gate(EXD[3], E[3], D[3]);

  or CM0gate(CM[0], C[0], M);
  or CM1gate(CM[1], C[1], M);
  or CM2gate(CM[2], C[2], M);
  or CM3gate(CM[3], C[3], M);

  xor F0gate(F[0], EXD[0], CM[0]);
  xor F1gate(F[1], EXD[1], CM[1]);
  xor F2gate(F[2], EXD[2], CM[2]);
  xor F3gate(F[3], EXD[3], CM[3]);

  and AEBgate(AEB, F[0], F[1], F[2], F[3]);

endmodule /* Summodule */


// -------------------------------------------------------------------
//  74194 - 
// -------------------------------------------------------------------
module	ttl_74194(	
				cr_n,
				m1,
				m0,
				clk,
				Dsl,
				Dsr,
				data_in,
				data_out
				);

	input				cr_n; //clear_n							
	input				m1;								
	input				m0;								
	input				clk;							
	input				Dsl; // serial data input (shift left)							
	input				Dsr; // serial data input (shift right)							
	input	[3:0]		data_in;						
	output	[3:0]		data_out;						
	
	reg		[3:0]		data_out;
	always@(posedge clk or negedge cr_n)
	begin
		if(!cr_n)										
			data_out	<=	4'b0000;
		else
		begin
			case({m1,m0})								
			2'b01:										
					if(Dsr==1)
					begin
						data_out	<=	data_out<<1;	
						data_out[0]	<=	1;				
					end
					else
					begin
						data_out	<=	data_out<<1;	
						data_out[0]	<=	0;				
					end
			2'b10:										
					if(Dsl==1)
					begin
						data_out	<=	data_out>>1;	
						data_out[3]	<=	1;				
					end
					else
					begin
						data_out	<=	data_out>>1;	
						data_out[3]	<=	0;				
					end
			2'b11:										
					data_out	<=	data_in;			
			default:
					data_out	<=	data_out;			//	±£³Ö
			endcase
		end
	end
endmodule