module top
  (
   clk_50,
   reset,
   aff_data, aff_addr,
   aff_cs, aff_we, aff_oe,
   switchs, boutons, bcod,
   probes, sclk, lclk,lcden,kclk,kdat
   );

   input        clk_50;			// horloge 50 MHz
   input        reset;			// bouton de remise à zéro
   output [7:0] aff_data;		// donnée à afficher
   output [5:0] aff_addr;		// adresse du périphérique d'affichage
   output       aff_cs,aff_we,aff_oe;	// signaux de contrôle de l'affichage
   input [7:0]  switchs;		// Les 8 interrupteurs
   input [5:0]  boutons;		// les 6 boutons non codés de A à F
   input [3:0]  bcod;			// les 10 boutons codés de 0 à 9, à F sans appui sur bouton
   output       sclk;			// horloge 50MHz/16 = 3,125 MHz
   output       lclk;			// horloge 50MHz/2^16= 762 Hz
   output [7:0] probes;			// signaux de sorties sur le connecteur A2
   output       lcden;			// sortie toujours à O 
   input 	kdat;			// entrée donnée clavier PS/2
   input 	kclk;			// entrée horloge clavier PS/2
   
	


   // Les signaux pour le module d'affichage (debug du processeur)
   wire [7:0]   dispsslo;
   wire [7:0]   dispsshi;
   wire [7:0]   displedslo;
   wire [7:0]   displedshi;
   reg [7:0] 	lcd_cmd;
   reg [7:0] 	lcd_data;
   reg 		n_en_cmd, n_en_data;
   wire		sync;
   
   // Les horloges et reset
   wire         clk_int;         
   wire         sclk;
   wire         lclk;
   wire         ramclk;
   wire         reset_n;
   
   // pour le test LCD
   reg 		sync_d;
   wire 	synchro;
   reg [3:0] 	state;
  
   // ne pas utiliser le lcden
   assign 	lcden = 0;
   
   // Instanciation des differents blocs
   
   div_horloge div1
     (
      .clk_50(clk_50),
      .reset_n(reset_n),
      .sclk(clk_int),
      .lclk(lclk),
      .ramclk(ramclk)
      );
   // assign       sclk = switchs[0] ? boutons[0] : clk_int; pour le test
   assign sclk = clk_int;
   assign reset_n = ~reset;
   
  
   affichage affichage
     (
      .lclk(lclk),
      .reset_n(reset_n),
      .ledslo(displedslo),
      .ledshi(displedshi),
      .sseglo(dispsslo),
      .sseghi(dispsshi),
      .lcd_cmd(lcd_cmd),
      .lcd_data(lcd_data),
      .sync(sync),
      .n_en_cmd(n_en_cmd),
      .n_en_data(n_en_data),
      .db(aff_data),
      .adr(aff_addr),
      .cs(aff_cs),
      .we(aff_we),
      .oe(aff_oe)
      );
  
// CODE A MODIFIER A PARTIR D'ICI

	  
// Sorties sur les afficheurs
// 
   assign 	dispsshi = switchs;     	// 
   assign 	dispsslo = switchs;     // 
   assign 	displedshi = {bcod,4'h0};
   assign 	displedslo = {boutons,2'h0};   //


   /* Exemple de machine à état pour piloter les signaux LCD : 
    
    Il faut détecter un front montant du signal sync, puis présenter de façon stable
      - soit une data (code ASCII d'un caractere à écrire) sur lcd_data, et mettre n_en_data à 0
      - soit une commande sur lcd_cmd, et mettre n_en_cmd à 0
      - soit les deux (la commande est alors exécutée AVANT l'écriture du caractère)

    Puis il faut laisser ces données là stables jusqu'au prochain front montant de sync.
    
    */

   // detection d'un front montant du signal de sync : synchro
   always @(posedge sclk or negedge reset_n)
     if (reset_n ==0)
       sync_d <= 0;
     else
       sync_d <= sync;
   assign 	synchro = sync & ~sync_d;


   // detection d'un appui sur un bouton poussoir d'une façon synchrone
   // avec le lcd

   reg t,t_d;
   reg [3:0] code;
   
   always @(posedge sclk or negedge reset_n)
     if (reset_n ==0)
       begin
	  t<=0;
	  t_d<=0;
       end
     else

       begin
   	  if (synchro)   
	    begin 
	       t_d <= t;
	       if (bcod !=15)
		 begin
		    t<= 1;
		    code <= bcod;
		 end
	       else
		 t <= 0;
	    end
       end
   
   assign synchro_char=(synchro & t & !t_d);


  
   always @(posedge sclk or negedge reset_n)
     if (reset_n ==0)
       begin
	  state <= 0;
	  lcd_cmd <= 0;
	  lcd_data <= 0;
	  n_en_cmd <= 1; 
	  n_en_data <= 1;
       end
     else
       begin
	  n_en_cmd <= 1; 
	  n_en_data <= 1;
	  lcd_cmd <= 0;
	  lcd_data <= 0;
	  
	  case(state)
	    0 : // c'est un cycle de start, pour rien, juste comme ca ! :)
	      state <= 1;

	    1 : // dans ce cycle, on attend un top de synchro
	      if(synchro)
		state <= 2;

	    2: // dans ce cycle, on présente le caractere H (code 72), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 72;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 3;
	      end

	    3: // dans ce cycle, on présente le caractere e (code 101), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 101;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 4;
	      end

	    4: // dans ce cycle, on présente le caractere l (code 108), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 108;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 5;
	      end

	    5: // dans ce cycle, on présente le caractere l (code 108), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 108;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 6;
	      end

	    6: // dans ce cycle, on présente le caractere o (code 111), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 111;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 7;
	      end

	    7: // dans ce cycle, on ne fait rien, juste comme ca :)
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 if(synchro)
		   state <= 8;
	      end

	    8: // dans ce cycle, on passe à la ligne du bas (commande 168), et on asserte le signal de commande
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_cmd <= 168;
		 n_en_cmd <= 0;
		 if(synchro)
		   state <= 9;
	      end

	    9: // dans ce cycle, on présente le caractere : (code 58), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 58;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 10;
	      end
	    
	    10: // dans ce cycle, on présente le caractere ) (code 41), et le signal de data au LCD
	      // et on attend le top de synchro pour passer au cycle suivant
	      begin
		 lcd_data <= 41;
		 n_en_data <= 0;
		 if(synchro)
		   state <= 11;
	      end

	    11: 
		begin
		   if(synchro_char)
		     state <= 12;
		end
	    12:
	      begin
		 case (code)
		   0: lcd_data <= 8'h30;
		   1: lcd_data <= 8'h31;
		   2: lcd_data <= 8'h32;
		   3: lcd_data <= 8'h33;
		   4: lcd_data <= 8'h34;
		   5: lcd_data <= 8'h35;
		   6: lcd_data <= 8'h36;
		   7: lcd_data <= 8'h37;
		   8: lcd_data <= 8'h38;
		   default: lcd_data <= 8'h39;
		 endcase		
		 n_en_data <= 0;	
		 if(synchro)
		   state <= 11;
	      end
	    

	    default: // on boucle indéfiniment dans cet état
	      state <= state;
	  endcase
       end	
      
endmodule // top
